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