1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.salver.dumper; 24 25 import java.io.IOException; 26 import java.lang.reflect.Modifier; 27 import java.util.ArrayDeque; 28 import java.util.Collections; 29 import java.util.Deque; 30 import java.util.Iterator; 31 32 import org.graalvm.compiler.bytecode.BytecodeDisassembler; 33 import org.graalvm.compiler.salver.data.DataDict; 34 import org.graalvm.compiler.salver.data.DataList; 35 import org.graalvm.compiler.salver.util.MethodContext; 36 37 import jdk.vm.ci.meta.JavaMethod; 38 import jdk.vm.ci.meta.ResolvedJavaMethod; 39 40 public abstract class AbstractMethodScopeDumper extends AbstractGraalDumper { 41 42 protected MethodContext previousMethodContext; 43 44 protected final Deque<Integer> pathStack = new ArrayDeque<>(); 45 protected int pathCounter; 46 protected final Deque<Integer> itemIdStack = new ArrayDeque<>(); 47 protected int itemIdCounter; 48 49 protected void resolveMethodContext() throws IOException { 50 // Get all current JavaMethod instances in the context. 51 MethodContext methodContext = new MethodContext(); 52 // Reverse list such that inner method comes after outer method. 53 Collections.reverse(methodContext); 54 55 int size = methodContext.size(); 56 int previousSize = previousMethodContext != null ? previousMethodContext.size() : 0; 57 // Check for method scopes that must be closed since the previous dump. 58 for (int i = 0; i < previousSize; ++i) { 59 if (i >= size || !methodContext.itemEquals(i, previousMethodContext)) { 60 for (int inlineDepth = previousSize - 1; inlineDepth >= i; --inlineDepth) { 61 closeScope(); 62 } 63 break; 64 } 65 } 66 // Check for method scopes that must be opened since the previous dump. 67 for (int i = 0; i < size; ++i) { 68 if (i >= previousSize || !methodContext.itemEquals(i, previousMethodContext)) { 69 for (int inlineDepth = i; inlineDepth < size; ++inlineDepth) { 70 openScope(methodContext.get(inlineDepth)); 71 } 72 break; 73 } 74 } 75 // Save inline context for next dump. 76 previousMethodContext = methodContext; 77 } 78 79 protected void openScope(MethodContext.Item item) throws IOException { 80 int debugId = item.getDebugId(); 81 int id = debugId != -1 ? debugId : pathCounter; 82 83 pathStack.push(id); 84 itemIdStack.push(itemIdCounter); 85 pathCounter = 0; 86 itemIdCounter = 0; 87 88 processMethod(item.getMethod(), id, item.getName()); 89 } 90 91 @SuppressWarnings("unused") 92 protected void closeScope() throws IOException { 93 if (!pathStack.isEmpty()) { 94 pathCounter = pathStack.pop(); 95 pathCounter++; 96 } 97 if (!itemIdStack.isEmpty()) { 98 itemIdCounter = itemIdStack.pop(); 99 } 100 } 101 102 protected void processMethod(JavaMethod method, int id, String name) throws IOException { 103 DataDict dataDict = new DataDict(); 104 dataDict.put("id", id); 105 dataDict.put("name", name); 106 107 if (method instanceof ResolvedJavaMethod) { 108 DataDict methodDict = new DataDict(); 109 dataDict.put("method", methodDict); 110 111 ResolvedJavaMethod resolvedMethod = (ResolvedJavaMethod) method; 112 113 methodDict.put("modifiers", Modifier.toString(resolvedMethod.getModifiers())); 114 methodDict.put("code", new BytecodeDisassembler(false).disassemble(resolvedMethod)); 115 } 116 serializeAndFlush(createEventDictWithId("method", dataDict, false)); 117 } 118 119 protected int nextItemId() { 120 return itemIdCounter++; 121 } 122 123 protected DataDict createEventDictWithId(String name, boolean isItem) { 124 DataDict eventDict = createEventDict(name); 125 126 DataDict idDict = new DataDict(); 127 eventDict.put("@id", idDict); 128 129 DataList pathList = new DataList(); 130 idDict.put("path", pathList); 131 132 Iterator<Integer> i = pathStack.descendingIterator(); 133 while (i.hasNext()) { 134 pathList.add(i.next()); 135 } 136 if (isItem) { 137 pathList.add(pathCounter++); 138 } 139 return eventDict; 140 } 141 142 protected DataDict createEventDictWithId(String name, DataDict dataDict, boolean isItem) { 143 DataDict eventDict = createEventDictWithId(name, isItem); 144 eventDict.put("@data", dataDict); 145 return eventDict; 146 } 147 148 protected DataDict createEventDictWithId(String name) { 149 return createEventDictWithId(name, true); 150 } 151 152 protected DataDict createEventDictWithId(String name, DataDict dataDict) { 153 return createEventDictWithId(name, dataDict, true); 154 } 155 }