1 /* 2 * Copyright 2000-2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.code; 26 27 import java.io.*; 28 import java.util.*; 29 30 import sun.jvm.hotspot.debugger.*; 31 import sun.jvm.hotspot.oops.*; 32 import sun.jvm.hotspot.runtime.*; 33 import sun.jvm.hotspot.utilities.*; 34 35 /** ScopeDescs contain the information that makes source-level 36 debugging of nmethods possible; each scopeDesc describes a method 37 activation */ 38 39 public class ScopeDesc { 40 /** NMethod information */ 41 private NMethod code; 42 private Method method; 43 private int bci; 44 private boolean reexecute; 45 /** Decoding offsets */ 46 private int decodeOffset; 47 private int senderDecodeOffset; 48 private int localsDecodeOffset; 49 private int expressionsDecodeOffset; 50 private int monitorsDecodeOffset; 51 /** Scalar replaced bjects pool */ 52 private List objects; // ArrayList<ScopeValue> 53 54 private ScopeDesc(NMethod code, int decodeOffset, List objects, boolean reexecute) { 55 this.code = code; 56 this.decodeOffset = decodeOffset; 57 this.objects = objects; 58 this.reexecute = reexecute; 59 60 // Decode header 61 DebugInfoReadStream stream = streamAt(decodeOffset); 62 63 senderDecodeOffset = stream.readInt(); 64 method = (Method) VM.getVM().getObjectHeap().newOop(stream.readOopHandle()); 65 bci = stream.readBCI(); 66 // Decode offsets for body and sender 67 localsDecodeOffset = stream.readInt(); 68 expressionsDecodeOffset = stream.readInt(); 69 monitorsDecodeOffset = stream.readInt(); 70 } 71 72 public ScopeDesc(NMethod code, int decodeOffset, int objectDecodeOffset, boolean reexecute) { 73 this.code = code; 74 this.decodeOffset = decodeOffset; 75 this.objects = decodeObjectValues(objectDecodeOffset); 76 this.reexecute = reexecute; 77 78 // Decode header 79 DebugInfoReadStream stream = streamAt(decodeOffset); 80 81 senderDecodeOffset = stream.readInt(); 82 method = (Method) VM.getVM().getObjectHeap().newOop(stream.readOopHandle()); 83 bci = stream.readBCI(); 84 // Decode offsets for body and sender 85 localsDecodeOffset = stream.readInt(); 86 expressionsDecodeOffset = stream.readInt(); 87 monitorsDecodeOffset = stream.readInt(); 88 } 89 90 public NMethod getNMethod() { return code; } 91 public Method getMethod() { return method; } 92 public int getBCI() { return bci; } 93 public boolean getReexecute() { return reexecute;} 94 95 /** Returns a List<ScopeValue> */ 96 public List getLocals() { 97 return decodeScopeValues(localsDecodeOffset); 98 } 99 100 /** Returns a List<ScopeValue> */ 101 public List getExpressions() { 102 return decodeScopeValues(expressionsDecodeOffset); 103 } 104 105 /** Returns a List<MonitorValue> */ 106 public List getMonitors() { 107 return decodeMonitorValues(monitorsDecodeOffset); 108 } 109 110 /** Returns a List<ObjectValue> */ 111 public List getObjects() { 112 return objects; 113 } 114 115 /** Stack walking. Returns null if this is the outermost scope. */ 116 public ScopeDesc sender() { 117 if (isTop()) { 118 return null; 119 } 120 121 return new ScopeDesc(code, senderDecodeOffset, objects, false); 122 } 123 124 /** Returns where the scope was decoded */ 125 public int getDecodeOffset() { 126 return decodeOffset; 127 } 128 129 /** Tells whether sender() returns null */ 130 public boolean isTop() { 131 return (senderDecodeOffset == DebugInformationRecorder.SERIALIZED_NULL); 132 } 133 134 public boolean equals(Object arg) { 135 if (arg == null) { 136 return false; 137 } 138 139 if (!(arg instanceof ScopeDesc)) { 140 return false; 141 } 142 143 ScopeDesc sd = (ScopeDesc) arg; 144 145 return (sd.method.equals(method) && (sd.bci == bci)); 146 } 147 148 public void printValue() { 149 printValueOn(System.out); 150 } 151 152 public void printValueOn(PrintStream tty) { 153 tty.print("ScopeDesc for "); 154 method.printValueOn(tty); 155 tty.print(" @bci " + bci); 156 tty.println(" reexecute=" + reexecute); 157 } 158 159 // FIXME: add more accessors 160 161 //-------------------------------------------------------------------------------- 162 // Internals only below this point 163 // 164 private DebugInfoReadStream streamAt(int decodeOffset) { 165 return new DebugInfoReadStream(code, decodeOffset, objects); 166 } 167 168 /** Returns a List<ScopeValue> or null if no values were present */ 169 private List decodeScopeValues(int decodeOffset) { 170 if (decodeOffset == DebugInformationRecorder.SERIALIZED_NULL) { 171 return null; 172 } 173 DebugInfoReadStream stream = streamAt(decodeOffset); 174 int length = stream.readInt(); 175 List res = new ArrayList(length); 176 for (int i = 0; i < length; i++) { 177 res.add(ScopeValue.readFrom(stream)); 178 } 179 return res; 180 } 181 182 /** Returns a List<MonitorValue> or null if no values were present */ 183 private List decodeMonitorValues(int decodeOffset) { 184 if (decodeOffset == DebugInformationRecorder.SERIALIZED_NULL) { 185 return null; 186 } 187 DebugInfoReadStream stream = streamAt(decodeOffset); 188 int length = stream.readInt(); 189 List res = new ArrayList(length); 190 for (int i = 0; i < length; i++) { 191 res.add(new MonitorValue(stream)); 192 } 193 return res; 194 } 195 196 /** Returns a List<ObjectValue> or null if no values were present */ 197 private List decodeObjectValues(int decodeOffset) { 198 if (decodeOffset == DebugInformationRecorder.SERIALIZED_NULL) { 199 return null; 200 } 201 List res = new ArrayList(); 202 DebugInfoReadStream stream = new DebugInfoReadStream(code, decodeOffset, res); 203 int length = stream.readInt(); 204 for (int i = 0; i < length; i++) { 205 // Objects values are pushed to 'res' array during read so that 206 // object's fields could reference it (OBJECT_ID_CODE). 207 ScopeValue.readFrom(stream); 208 // res.add(ScopeValue.readFrom(stream)); 209 } 210 Assert.that(res.size() == length, "inconsistent debug information"); 211 return res; 212 } 213 }