--- /dev/null 2017-01-22 10:16:57.869617664 -0800 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/dumper/AbstractMethodScopeDumper.java 2017-02-15 17:09:26.228969584 -0800 @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +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 pathStack = new ArrayDeque<>(); + protected int pathCounter; + protected final Deque itemIdStack = new ArrayDeque<>(); + protected int itemIdCounter; + + protected void resolveMethodContext() throws IOException { + // Get all current JavaMethod instances in the context. + MethodContext methodContext = new MethodContext(); + // Reverse list such that inner method comes after outer method. + Collections.reverse(methodContext); + + int size = methodContext.size(); + int previousSize = previousMethodContext != null ? previousMethodContext.size() : 0; + // Check for method scopes that must be closed since the previous dump. + for (int i = 0; i < previousSize; ++i) { + if (i >= size || !methodContext.itemEquals(i, previousMethodContext)) { + for (int inlineDepth = previousSize - 1; inlineDepth >= i; --inlineDepth) { + closeScope(); + } + break; + } + } + // Check for method scopes that must be opened since the previous dump. + 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; + } + } + // Save inline context for next dump. + 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 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); + } +}