Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java @ 2411:63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
Reviewed-by: kvn, dcubed
author | never |
---|---|
date | Wed, 30 Mar 2011 07:47:19 -0700 |
parents | c18cbe5936b8 |
children | 7588156f5cf9 |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
2 * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
844
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.runtime; | |
26 | |
27 import java.util.*; | |
28 import sun.jvm.hotspot.code.*; | |
29 import sun.jvm.hotspot.debugger.*; | |
30 import sun.jvm.hotspot.oops.*; | |
31 import sun.jvm.hotspot.utilities.*; | |
32 | |
33 /** FIXME: missing many accessors; all we have right now is the method | |
34 and BCI. NOTE that this has been modified from the VM's version to | |
35 handle NULL ScopeDescs for the debugging case. This simplifies | |
36 using code a great deal. */ | |
37 | |
38 public class CompiledVFrame extends JavaVFrame { | |
39 private ScopeDesc scope; | |
40 private boolean mayBeImprecise; | |
41 | |
42 public CompiledVFrame(Frame fr, RegisterMap regMap, JavaThread thread, ScopeDesc scope, boolean mayBeImprecise) { | |
43 super(fr, regMap, thread); | |
44 this.scope = scope; | |
45 this.mayBeImprecise = mayBeImprecise; | |
46 if (!VM.getVM().isDebugging()) { | |
47 Assert.that(scope != null, "scope must be present"); | |
48 } | |
49 } | |
50 | |
51 public boolean isTop() { | |
52 if (VM.getVM().isDebugging()) { | |
53 return (getScope() == null || getScope().isTop()); | |
54 } else { | |
55 return getScope().isTop(); | |
56 } | |
57 } | |
58 | |
59 public boolean isCompiledFrame() { | |
60 return true; | |
61 } | |
62 | |
63 public boolean isDeoptimized() { | |
64 return fr.isDeoptimized(); | |
65 } | |
66 | |
67 public boolean mayBeImpreciseDbg() { | |
68 return mayBeImprecise; | |
69 } | |
70 | |
71 /** Returns the active method */ | |
72 public NMethod getCode() { | |
73 return VM.getVM().getCodeCache().findNMethod(fr.getPC()); | |
74 } | |
75 | |
76 /** Returns the active method. Does not perform a guarantee | |
77 regarding unloaded methods -- more suitable for debugging | |
78 system. */ | |
79 public NMethod getCodeUnsafe() { | |
80 return VM.getVM().getCodeCache().findNMethodUnsafe(fr.getPC()); | |
81 } | |
82 | |
83 /** Returns the ScopeDesc */ | |
84 public ScopeDesc getScope() { | |
85 return scope; | |
86 } | |
87 | |
88 public Method getMethod() { | |
89 if (VM.getVM().isDebugging() && getScope() == null) { | |
90 return getCodeUnsafe().getMethod(); | |
91 } | |
92 return getScope().getMethod(); | |
93 } | |
94 | |
95 public StackValueCollection getLocals() { | |
96 List scvList = getScope().getLocals(); | |
97 if (scvList == null) | |
98 return new StackValueCollection(); | |
99 | |
100 // scvList is the list of ScopeValues describing the JVM stack state. | |
101 // There is one scv_list entry for every JVM stack state in use. | |
102 int length = scvList.size(); | |
103 StackValueCollection result = new StackValueCollection(length); | |
104 for( int i = 0; i < length; i++ ) | |
105 result.add( createStackValue((ScopeValue) scvList.get(i)) ); | |
106 | |
107 return result; | |
108 } | |
109 | |
110 public StackValueCollection getExpressions() { | |
111 List scvList = getScope().getExpressions(); | |
112 if (scvList == null) | |
113 return new StackValueCollection(); | |
114 | |
115 // scvList is the list of ScopeValues describing the JVM stack state. | |
116 // There is one scv_list entry for every JVM stack state in use. | |
117 int length = scvList.size(); | |
118 StackValueCollection result = new StackValueCollection(length); | |
119 for( int i = 0; i < length; i++ ) | |
120 result.add( createStackValue((ScopeValue) scvList.get(i)) ); | |
121 | |
122 return result; | |
123 } | |
124 | |
125 /** Returns List<MonitorInfo> */ | |
126 public List getMonitors() { | |
127 List monitors = getScope().getMonitors(); | |
128 if (monitors == null) { | |
129 return new ArrayList(); | |
130 } | |
131 List result = new ArrayList(monitors.size()); | |
132 for (int i = 0; i < monitors.size(); i++) { | |
133 MonitorValue mv = (MonitorValue) monitors.get(i); | |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
134 ScopeValue ov = mv.owner(); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
135 StackValue ownerSV = createStackValue(ov); // it is an oop |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
136 if (ov.isObject()) { // The owner object was scalar replaced |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
137 Assert.that(mv.eliminated() && ownerSV.objIsScalarReplaced(), "monitor should be eliminated for scalar replaced object"); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
138 // Put klass for scalar replaced object. |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
139 ScopeValue kv = ((ObjectValue)ov).getKlass(); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
140 Assert.that(kv.isConstantOop(), "klass should be oop constant for scalar replaced object"); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
141 OopHandle k = ((ConstantOopReadValue)kv).getValue(); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
142 result.add(new MonitorInfo(k, resolveMonitorLock(mv.basicLock()), mv.eliminated(), true)); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
143 } else { |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
144 result.add(new MonitorInfo(ownerSV.getObject(), resolveMonitorLock(mv.basicLock()), mv.eliminated(), false)); |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
145 } |
0 | 146 } |
147 return result; | |
148 } | |
149 | |
150 public int getBCI() { | |
151 int raw = getRawBCI(); | |
152 return ((raw == DebugInformationRecorder.SYNCHRONIZATION_ENTRY_BCI) ? 0 : raw); | |
153 } | |
154 | |
155 /** Returns SynchronizationEntryBCI or bci() (used for synchronization) */ | |
156 public int getRawBCI() { | |
157 if (VM.getVM().isDebugging() && getScope() == null) { | |
158 return 0; // No debugging information! | |
159 } | |
160 return getScope().getBCI(); | |
161 } | |
162 | |
163 /** Returns the sender vframe */ | |
164 public VFrame sender() { | |
165 if (Assert.ASSERTS_ENABLED) { | |
166 Assert.that(isTop(), "just checking"); | |
167 } | |
168 return sender(false); | |
169 } | |
170 | |
171 public VFrame sender(boolean mayBeImprecise) { | |
172 if (!VM.getVM().isDebugging()) { | |
173 if (Assert.ASSERTS_ENABLED) { | |
174 Assert.that(scope != null, "When new stub generator is in place, then scope can never be NULL"); | |
175 } | |
176 } | |
177 Frame f = (Frame) getFrame().clone(); | |
178 return (isTop() | |
179 ? super.sender(false) | |
180 : new CompiledVFrame(f, getRegisterMap(), getThread(), getScope().sender(), mayBeImprecise)); | |
181 } | |
182 | |
183 private StackValue createStackValue(ScopeValue sv) { | |
184 // FIXME: this code appears to be out-of-date with respect to the VM especially in 64-bit mode | |
185 if (sv.isLocation()) { | |
186 // Stack or register value | |
187 Location loc = ((LocationValue) sv).getLocation(); | |
188 | |
189 if (loc.isIllegal()) return new StackValue(); | |
190 | |
191 // First find address of value | |
192 Address valueAddr = loc.isRegister() | |
193 // Value was in a callee-save register | |
194 ? getRegisterMap().getLocation(new VMReg(loc.getRegisterNumber())) | |
195 // Else value was directly saved on the stack. The frame's original stack pointer, | |
196 // before any extension by its callee (due to Compiler1 linkage on SPARC), must be used. | |
197 : ((Address)fr.getUnextendedSP()).addOffsetTo(loc.getStackOffset()); | |
198 | |
199 // Then package it right depending on type | |
200 if (loc.holdsFloat()) { // Holds a float in a double register? | |
201 // The callee has no clue whether the register holds a float, | |
202 // double or is unused. He always saves a double. Here we know | |
203 // a double was saved, but we only want a float back. Narrow the | |
204 // saved double to the float that the JVM wants. | |
205 if (Assert.ASSERTS_ENABLED) { | |
206 Assert.that( loc.isRegister(), "floats always saved to stack in 1 word" ); | |
207 } | |
208 float value = (float) valueAddr.getJDoubleAt(0); | |
209 return new StackValue(Float.floatToIntBits(value) & 0xFFFFFFFF); // 64-bit high half is stack junk | |
210 } else if (loc.holdsInt()) { // Holds an int in a long register? | |
211 // The callee has no clue whether the register holds an int, | |
212 // long or is unused. He always saves a long. Here we know | |
213 // a long was saved, but we only want an int back. Narrow the | |
214 // saved long to the int that the JVM wants. | |
215 if (Assert.ASSERTS_ENABLED) { | |
216 Assert.that( loc.isRegister(), "ints always saved to stack in 1 word" ); | |
217 } | |
218 return new StackValue(valueAddr.getJLongAt(0) & 0xFFFFFFFF); | |
331 | 219 } else if (loc.holdsNarrowOop()) { // Holds an narrow oop? |
220 if (loc.isRegister() && VM.getVM().isBigEndian()) { | |
221 // The callee has no clue whether the register holds an narrow oop, | |
222 // long or is unused. He always saves a long. Here we know | |
223 // a long was saved, but we only want an narrow oop back. Narrow the | |
224 // saved long to the narrow oop that the JVM wants. | |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
225 return new StackValue(valueAddr.getCompOopHandleAt(VM.getVM().getIntSize()), 0); |
331 | 226 } else { |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
227 return new StackValue(valueAddr.getCompOopHandleAt(0), 0); |
331 | 228 } |
0 | 229 } else if( loc.holdsOop() ) { // Holds an oop? |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
230 return new StackValue(valueAddr.getOopHandleAt(0), 0); |
0 | 231 } else if( loc.holdsDouble() ) { |
232 // Double value in a single stack slot | |
233 return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF); | |
234 } else if(loc.holdsAddr()) { | |
235 if (Assert.ASSERTS_ENABLED) { | |
236 Assert.that(!VM.getVM().isServerCompiler(), "No address type for locations with C2 (jsr-s are inlined)"); | |
237 } | |
238 // FIXME: not yet implemented (no access to safepoint state yet) | |
239 return new StackValue(0); | |
240 // intptr_t return_addr_tmp = *(intptr_t *)value_addr; | |
241 // int bci = -1; | |
242 // // Get the bci of the jsr that generated this returnAddress value. | |
243 // // If the destination of a jsr is a block that ends with a return or throw, then | |
244 // // the GraphBuilder converts the jsr into a direct goto. This has the side effect that | |
245 // // the return address for the jsr gets emitted as a bci instead of as a real pc | |
246 // if (code()->contains((address)return_addr_tmp)) { | |
247 // ScopeDesc* scope = code()->scope_desc_at((address)(return_addr_tmp - jsr_call_offset), false); | |
248 // bci = scope->bci(); | |
249 // } else { | |
250 // bci = (int)return_addr_tmp; | |
251 // } | |
252 // // no need to lock method as this happens at Safepoint | |
253 // assert (SafepointSynchronize::is_at_safepoint(), "must be at safepoint, otherwise lock method()"); | |
254 // // make sure bci points to jsr | |
255 // Bytecode* bytecode = Bytecode_at(method()->bcp_from(bci)); | |
256 // Bytecodes::Code bc = bytecode->code(); | |
257 // assert (bc == Bytecodes::_jsr || bc == Bytecodes::_jsr_w, "must be jsr"); | |
258 // | |
259 // // the real returnAddress is the bytecode following the jsr | |
260 // return new StackValue((intptr_t)(bci + Bytecodes::length_for(bc))); | |
261 } else if (VM.getVM().isLP64() && loc.holdsLong()) { | |
262 if ( loc.isRegister() ) { | |
263 // Long value in two registers, high half in the first, low in the second | |
264 return new StackValue(((valueAddr.getJLongAt(0) & 0xFFFFFFFF) << 32) | | |
265 ((valueAddr.getJLongAt(8) & 0xFFFFFFFF))); | |
266 } else { | |
267 // Long value in a single stack slot | |
268 return new StackValue(valueAddr.getJLongAt(0)); | |
269 } | |
270 } else if( loc.isRegister() ) { | |
271 // At the moment, all non-oop values in registers are 4 bytes, | |
272 // including double and long halves (see Compile::FillLocArray() in | |
273 // opto/output.cpp). Haul them out as such and return a StackValue | |
274 // containing an image of the value as it appears in a stack slot. | |
275 // If this is a double or long half, the interpreter _must_ deal | |
276 // with doubles and longs as entities split across two stack slots. | |
277 // To change this so doubles and/or longs can live in one stack slot, | |
278 // a StackValue will have to understand that it can contain an | |
279 // undivided double or long, implying that a Location (and the debug | |
280 // info mechanism) and FillLocArray() will also have to understand it. | |
281 return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF); | |
282 } else { | |
283 return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF); | |
284 } | |
285 } else if (sv.isConstantInt()) { | |
286 // Constant int: treat same as register int. | |
287 return new StackValue(((ConstantIntValue) sv).getValue() & 0xFFFFFFFF); | |
288 } else if (sv.isConstantOop()) { | |
289 // constant oop | |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
290 return new StackValue(((ConstantOopReadValue) sv).getValue(), 0); |
0 | 291 } else if (sv.isConstantDouble()) { |
292 // Constant double in a single stack slot | |
293 double d = ((ConstantDoubleValue) sv).getValue(); | |
294 return new StackValue(Double.doubleToLongBits(d) & 0xFFFFFFFF); | |
295 } else if (VM.getVM().isLP64() && sv.isConstantLong()) { | |
296 // Constant long in a single stack slot | |
297 return new StackValue(((ConstantLongValue) sv).getValue() & 0xFFFFFFFF); | |
818
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
298 } else if (sv.isObject()) { |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
299 // Scalar replaced object in compiled frame |
b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
337
diff
changeset
|
300 return new StackValue(((ObjectValue)sv).getValue(), 1); |
0 | 301 } |
302 | |
303 // Unknown ScopeValue type | |
304 Assert.that(false, "Should not reach here"); | |
305 return new StackValue(0); // dummy | |
306 } | |
307 | |
308 private BasicLock resolveMonitorLock(Location location) { | |
309 if (Assert.ASSERTS_ENABLED) { | |
310 Assert.that(location.isStack(), "for now we only look at the stack"); | |
311 } | |
312 int byteOffset = location.getStackOffset(); | |
313 // (stack picture) | |
314 // high: [ ] byte_offset + wordSize | |
315 // low [ ] byte_offset | |
316 // | |
317 // sp-> [ ] 0 | |
318 // the byte_offset is the distance from the stack pointer to the lowest address | |
319 // The frame's original stack pointer, before any extension by its callee | |
320 // (due to Compiler1 linkage on SPARC), must be used. | |
321 return new BasicLock(getFrame().getUnextendedSP().addOffsetTo(byteOffset)); | |
322 } | |
323 } |