package org.graalvm.compiler.salver.dumper;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.ArrayDeque;
import java.util.Collections;
import java.util.Deque;
import java.util.Iterator;
import org.graalvm.compiler.bytecode.BytecodeDisassembler;
import org.graalvm.compiler.salver.data.DataDict;
import org.graalvm.compiler.salver.data.DataList;
import org.graalvm.compiler.salver.util.MethodContext;
import jdk.vm.ci.meta.JavaMethod;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public abstract class AbstractMethodScopeDumper extends AbstractGraalDumper {
protected MethodContext previousMethodContext;
protected final Deque<Integer> pathStack = new ArrayDeque<>();
protected int pathCounter;
protected final Deque<Integer> itemIdStack = new ArrayDeque<>();
protected int itemIdCounter;
protected void resolveMethodContext() throws IOException {
MethodContext methodContext = new MethodContext();
Collections.reverse(methodContext);
int size = methodContext.size();
int previousSize = previousMethodContext != null ? previousMethodContext.size() : 0;
for (int i = 0; i < previousSize; ++i) {
if (i >= size || !methodContext.itemEquals(i, previousMethodContext)) {
for (int inlineDepth = previousSize - 1; inlineDepth >= i; --inlineDepth) {
closeScope();
}
break;
}
}
for (int i = 0; i < size; ++i) {
if (i >= previousSize || !methodContext.itemEquals(i, previousMethodContext)) {
for (int inlineDepth = i; inlineDepth < size; ++inlineDepth) {
openScope(methodContext.get(inlineDepth));
}
break;
}
}
previousMethodContext = methodContext;
}
protected void openScope(MethodContext.Item item) throws IOException {
int debugId = item.getDebugId();
int id = debugId != -1 ? debugId : pathCounter;
pathStack.push(id);
itemIdStack.push(itemIdCounter);
pathCounter = 0;
itemIdCounter = 0;
processMethod(item.getMethod(), id, item.getName());
}
@SuppressWarnings("unused")
protected void closeScope() throws IOException {
if (!pathStack.isEmpty()) {
pathCounter = pathStack.pop();
pathCounter++;
}
if (!itemIdStack.isEmpty()) {
itemIdCounter = itemIdStack.pop();
}
}
protected void processMethod(JavaMethod method, int id, String name) throws IOException {
DataDict dataDict = new DataDict();
dataDict.put("id", id);
dataDict.put("name", name);
if (method instanceof ResolvedJavaMethod) {
DataDict methodDict = new DataDict();
dataDict.put("method", methodDict);
ResolvedJavaMethod resolvedMethod = (ResolvedJavaMethod) method;
methodDict.put("modifiers", Modifier.toString(resolvedMethod.getModifiers()));
methodDict.put("code", new BytecodeDisassembler(false).disassemble(resolvedMethod));
}
serializeAndFlush(createEventDictWithId("method", dataDict, false));
}
protected int nextItemId() {
return itemIdCounter++;
}
protected DataDict createEventDictWithId(String name, boolean isItem) {
DataDict eventDict = createEventDict(name);
DataDict idDict = new DataDict();
eventDict.put("@id", idDict);
DataList pathList = new DataList();
idDict.put("path", pathList);
Iterator<Integer> i = pathStack.descendingIterator();
while (i.hasNext()) {
pathList.add(i.next());
}
if (isItem) {
pathList.add(pathCounter++);
}
return eventDict;
}
protected DataDict createEventDictWithId(String name, DataDict dataDict, boolean isItem) {
DataDict eventDict = createEventDictWithId(name, isItem);
eventDict.put("@data", dataDict);
return eventDict;
}
protected DataDict createEventDictWithId(String name) {
return createEventDictWithId(name, true);
}
protected DataDict createEventDictWithId(String name, DataDict dataDict) {
return createEventDictWithId(name, dataDict, true);
}
}