1 /* 2 * Copyright (c) 2002, 2005, 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 */ 24 25 package sun.jvm.hotspot.jdi; 26 27 import com.sun.jdi.*; 28 import sun.jvm.hotspot.oops.ObjectHeap; 29 import sun.jvm.hotspot.debugger.OopHandle; 30 import sun.jvm.hotspot.oops.Array; 31 import sun.jvm.hotspot.oops.ObjArray; 32 import sun.jvm.hotspot.oops.TypeArray; 33 import sun.jvm.hotspot.oops.Instance; 34 import sun.jvm.hotspot.runtime.BasicType; 35 import sun.jvm.hotspot.runtime.JavaVFrame; 36 import sun.jvm.hotspot.runtime.StackValue; 37 import sun.jvm.hotspot.runtime.StackValueCollection; 38 import sun.jvm.hotspot.utilities.Assert; 39 import java.util.List; 40 import java.util.Map; 41 import java.util.ArrayList; 42 import java.util.HashMap; 43 import java.util.Iterator; 44 import java.util.Collections; 45 46 public class StackFrameImpl extends MirrorImpl 47 implements StackFrame 48 { 49 /* Once false, frame should not be used. 50 * access synchronized on (vm.state()) 51 */ 52 private boolean isValid = true; 53 54 private final ThreadReferenceImpl thread; 55 private final JavaVFrame saFrame; 56 private final Location location; 57 private Map visibleVariables = null; 58 private ObjectReference thisObject = null; 59 StackFrameImpl(VirtualMachine vm, ThreadReferenceImpl thread, JavaVFrame jvf)60 StackFrameImpl(VirtualMachine vm, ThreadReferenceImpl thread, 61 JavaVFrame jvf) { 62 super(vm); 63 this.thread = thread; 64 this.saFrame = jvf; 65 66 sun.jvm.hotspot.oops.Method SAMethod = jvf.getMethod(); 67 68 ReferenceType rt = ((VirtualMachineImpl)vm).referenceType(SAMethod.getMethodHolder()); 69 70 this.location = new LocationImpl(vm, rt, SAMethod, (long)jvf.getBCI()); 71 } 72 validateStackFrame()73 private void validateStackFrame() { 74 if (!isValid) { 75 throw new InvalidStackFrameException("Thread has been resumed"); 76 } 77 } 78 getJavaVFrame()79 JavaVFrame getJavaVFrame() { 80 return saFrame; 81 } 82 83 /** 84 * Return the frame location. 85 * Need not be synchronized since it cannot be provably stale. 86 */ location()87 public Location location() { 88 validateStackFrame(); 89 return location; 90 } 91 92 /** 93 * Return the thread holding the frame. 94 * Need not be synchronized since it cannot be provably stale. 95 */ thread()96 public ThreadReference thread() { 97 validateStackFrame(); 98 return thread; 99 } 100 equals(Object obj)101 public boolean equals(Object obj) { 102 if ((obj != null) && (obj instanceof StackFrameImpl)) { 103 StackFrameImpl other = (StackFrameImpl)obj; 104 return (saFrame.equals(other.saFrame)); 105 } else { 106 return false; 107 } 108 } 109 hashCode()110 public int hashCode() { 111 return saFrame.hashCode(); 112 } 113 thisObject()114 public ObjectReference thisObject() { 115 validateStackFrame(); 116 MethodImpl currentMethod = (MethodImpl)location.method(); 117 if (currentMethod.isStatic() || currentMethod.isNative()) { 118 return null; 119 } 120 if (thisObject == null) { 121 StackValueCollection values = saFrame.getLocals(); 122 if (Assert.ASSERTS_ENABLED) { 123 Assert.that(values.size() > 0, "this is missing"); 124 } 125 // 'this' at index 0. 126 if (values.get(0).getType() == BasicType.getTConflict()) { 127 return null; 128 } 129 OopHandle handle = values.oopHandleAt(0); 130 ObjectHeap heap = vm.saObjectHeap(); 131 thisObject = vm.objectMirror(heap.newOop(handle)); 132 } 133 return thisObject; 134 } 135 136 /** 137 * Build the visible variable map. 138 * Need not be synchronized since it cannot be provably stale. 139 */ createVisibleVariables()140 private void createVisibleVariables() throws AbsentInformationException { 141 if (visibleVariables == null) { 142 List allVariables = location.method().variables(); 143 Map map = new HashMap(allVariables.size()); 144 145 Iterator iter = allVariables.iterator(); 146 while (iter.hasNext()) { 147 LocalVariableImpl variable = (LocalVariableImpl)iter.next(); 148 String name = variable.name(); 149 if (variable.isVisible(this)) { 150 LocalVariable existing = (LocalVariable)map.get(name); 151 if ((existing == null) || 152 variable.hides(existing)) { 153 map.put(name, variable); 154 } 155 } 156 } 157 visibleVariables = map; 158 } 159 } 160 161 /** 162 * Return the list of visible variable in the frame. 163 * Need not be synchronized since it cannot be provably stale. 164 */ visibleVariables()165 public List visibleVariables() throws AbsentInformationException { 166 validateStackFrame(); 167 createVisibleVariables(); 168 List mapAsList = new ArrayList(visibleVariables.values()); 169 Collections.sort(mapAsList); 170 return mapAsList; 171 } 172 173 /** 174 * Return a particular variable in the frame. 175 * Need not be synchronized since it cannot be provably stale. 176 */ visibleVariableByName(String name)177 public LocalVariable visibleVariableByName(String name) throws AbsentInformationException { 178 validateStackFrame(); 179 createVisibleVariables(); 180 return (LocalVariable)visibleVariables.get(name); 181 } 182 getValue(LocalVariable variable)183 public Value getValue(LocalVariable variable) { 184 List list = new ArrayList(1); 185 list.add(variable); 186 Map map = getValues(list); 187 return (Value)map.get(variable); 188 } 189 getValues(List variables)190 public Map getValues(List variables) { 191 validateStackFrame(); 192 StackValueCollection values = saFrame.getLocals(); 193 194 int count = variables.size(); 195 Map map = new HashMap(count); 196 for (int ii=0; ii<count; ++ii) { 197 LocalVariableImpl variable = (LocalVariableImpl)variables.get(ii); 198 if (!variable.isVisible(this)) { 199 throw new IllegalArgumentException(variable.name() + 200 " is not valid at this frame location"); 201 } 202 ValueImpl valueImpl; 203 int ss = variable.slot(); 204 char c = variable.signature().charAt(0); 205 BasicType variableType = BasicType.charToBasicType(c); 206 valueImpl = getSlotValue(values, variableType, ss); 207 map.put(variable, valueImpl); 208 } 209 return map; 210 } 211 getArgumentValues()212 public List getArgumentValues() { 213 validateStackFrame(); 214 StackValueCollection values = saFrame.getLocals(); 215 MethodImpl mmm = (MethodImpl)location.method(); 216 if (mmm.isNative()) 217 return null; 218 List argSigs = mmm.argumentSignatures(); 219 int count = argSigs.size(); 220 List res = new ArrayList(0); 221 222 int slot = mmm.isStatic()? 0 : 1; 223 for (int ii = 0; ii < count; ++slot, ++ii) { 224 char sigChar = ((String)argSigs.get(ii)).charAt(0); 225 BasicType variableType = BasicType.charToBasicType(sigChar); 226 res.add(getSlotValue(values, variableType, slot)); 227 if (sigChar == 'J' || sigChar == 'D') { 228 slot++; 229 } 230 } 231 return res; 232 } 233 getSlotValue(StackValueCollection values, BasicType variableType, int ss)234 private ValueImpl getSlotValue(StackValueCollection values, 235 BasicType variableType, int ss) { 236 ValueImpl valueImpl = null; 237 OopHandle handle = null; 238 ObjectHeap heap = vm.saObjectHeap(); 239 if (values.get(ss).getType() == BasicType.getTConflict()) { 240 // Dead locals, so just represent them as a zero of the appropriate type 241 if (variableType == BasicType.T_BOOLEAN) { 242 valueImpl = (BooleanValueImpl) vm.mirrorOf(false); 243 } else if (variableType == BasicType.T_CHAR) { 244 valueImpl = (CharValueImpl) vm.mirrorOf((char)0); 245 } else if (variableType == BasicType.T_FLOAT) { 246 valueImpl = (FloatValueImpl) vm.mirrorOf((float)0); 247 } else if (variableType == BasicType.T_DOUBLE) { 248 valueImpl = (DoubleValueImpl) vm.mirrorOf((double)0); 249 } else if (variableType == BasicType.T_BYTE) { 250 valueImpl = (ByteValueImpl) vm.mirrorOf((byte)0); 251 } else if (variableType == BasicType.T_SHORT) { 252 valueImpl = (ShortValueImpl) vm.mirrorOf((short)0); 253 } else if (variableType == BasicType.T_INT) { 254 valueImpl = (IntegerValueImpl) vm.mirrorOf((int)0); 255 } else if (variableType == BasicType.T_LONG) { 256 valueImpl = (LongValueImpl) vm.mirrorOf((long)0); 257 } else if (variableType == BasicType.T_OBJECT) { 258 // we may have an [Ljava/lang/Object; - i.e., Object[] with the 259 // elements themselves may be arrays because every array is an Object. 260 handle = null; 261 valueImpl = (ObjectReferenceImpl) vm.objectMirror(heap.newOop(handle)); 262 } else if (variableType == BasicType.T_ARRAY) { 263 handle = null; 264 valueImpl = vm.arrayMirror((Array)heap.newOop(handle)); 265 } else if (variableType == BasicType.T_VOID) { 266 valueImpl = new VoidValueImpl(vm); 267 } else { 268 throw new RuntimeException("Should not read here"); 269 } 270 } else { 271 if (variableType == BasicType.T_BOOLEAN) { 272 valueImpl = (BooleanValueImpl) vm.mirrorOf(values.booleanAt(ss)); 273 } else if (variableType == BasicType.T_CHAR) { 274 valueImpl = (CharValueImpl) vm.mirrorOf(values.charAt(ss)); 275 } else if (variableType == BasicType.T_FLOAT) { 276 valueImpl = (FloatValueImpl) vm.mirrorOf(values.floatAt(ss)); 277 } else if (variableType == BasicType.T_DOUBLE) { 278 valueImpl = (DoubleValueImpl) vm.mirrorOf(values.doubleAt(ss)); 279 } else if (variableType == BasicType.T_BYTE) { 280 valueImpl = (ByteValueImpl) vm.mirrorOf(values.byteAt(ss)); 281 } else if (variableType == BasicType.T_SHORT) { 282 valueImpl = (ShortValueImpl) vm.mirrorOf(values.shortAt(ss)); 283 } else if (variableType == BasicType.T_INT) { 284 valueImpl = (IntegerValueImpl) vm.mirrorOf(values.intAt(ss)); 285 } else if (variableType == BasicType.T_LONG) { 286 valueImpl = (LongValueImpl) vm.mirrorOf(values.longAt(ss)); 287 } else if (variableType == BasicType.T_OBJECT) { 288 // we may have an [Ljava/lang/Object; - i.e., Object[] with the 289 // elements themselves may be arrays because every array is an Object. 290 handle = values.oopHandleAt(ss); 291 valueImpl = (ObjectReferenceImpl) vm.objectMirror(heap.newOop(handle)); 292 } else if (variableType == BasicType.T_ARRAY) { 293 handle = values.oopHandleAt(ss); 294 valueImpl = vm.arrayMirror((Array)heap.newOop(handle)); 295 } else if (variableType == BasicType.T_VOID) { 296 valueImpl = new VoidValueImpl(vm); 297 } else { 298 throw new RuntimeException("Should not read here"); 299 } 300 } 301 302 return valueImpl; 303 } 304 setValue(LocalVariable variableIntf, Value valueIntf)305 public void setValue(LocalVariable variableIntf, Value valueIntf) 306 throws InvalidTypeException, ClassNotLoadedException { 307 308 vm.throwNotReadOnlyException("StackFrame.setValue()"); 309 } 310 toString()311 public String toString() { 312 return location.toString() + " in thread " + thread.toString(); 313 } 314 } 315