author | never |
Mon, 05 Sep 2011 17:09:05 -0700 | |
changeset 10517 | f92c9ff3a15f |
parent 5547 | f4b087cbb361 |
permissions | -rw-r--r-- |
1 | 1 |
/* |
5547
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
3261
diff
changeset
|
2 |
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. |
1 | 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 |
* |
|
5547
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
3261
diff
changeset
|
19 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
3261
diff
changeset
|
20 |
* or visit www.oracle.com if you need additional information or have any |
f4b087cbb361
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
3261
diff
changeset
|
21 |
* questions. |
1 | 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() { |
|
10517
f92c9ff3a15f
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
5547
diff
changeset
|
96 |
if (getScope() == null) |
f92c9ff3a15f
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
5547
diff
changeset
|
97 |
return new StackValueCollection(); |
1 | 98 |
List scvList = getScope().getLocals(); |
99 |
if (scvList == null) |
|
100 |
return new StackValueCollection(); |
|
101 |
||
102 |
// scvList is the list of ScopeValues describing the JVM stack state. |
|
103 |
// There is one scv_list entry for every JVM stack state in use. |
|
104 |
int length = scvList.size(); |
|
105 |
StackValueCollection result = new StackValueCollection(length); |
|
106 |
for( int i = 0; i < length; i++ ) |
|
107 |
result.add( createStackValue((ScopeValue) scvList.get(i)) ); |
|
108 |
||
109 |
return result; |
|
110 |
} |
|
111 |
||
112 |
public StackValueCollection getExpressions() { |
|
10517
f92c9ff3a15f
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
5547
diff
changeset
|
113 |
if (getScope() == null) |
f92c9ff3a15f
7051798: SA-JDI: NPE in Frame.addressOfStackSlot(Frame.java:244)
never
parents:
5547
diff
changeset
|
114 |
return new StackValueCollection(); |
1 | 115 |
List scvList = getScope().getExpressions(); |
116 |
if (scvList == null) |
|
117 |
return new StackValueCollection(); |
|
118 |
||
119 |
// scvList is the list of ScopeValues describing the JVM stack state. |
|
120 |
// There is one scv_list entry for every JVM stack state in use. |
|
121 |
int length = scvList.size(); |
|
122 |
StackValueCollection result = new StackValueCollection(length); |
|
123 |
for( int i = 0; i < length; i++ ) |
|
124 |
result.add( createStackValue((ScopeValue) scvList.get(i)) ); |
|
125 |
||
126 |
return result; |
|
127 |
} |
|
128 |
||
129 |
/** Returns List<MonitorInfo> */ |
|
130 |
public List getMonitors() { |
|
131 |
List monitors = getScope().getMonitors(); |
|
132 |
if (monitors == null) { |
|
133 |
return new ArrayList(); |
|
134 |
} |
|
135 |
List result = new ArrayList(monitors.size()); |
|
136 |
for (int i = 0; i < monitors.size(); i++) { |
|
137 |
MonitorValue mv = (MonitorValue) monitors.get(i); |
|
3171
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
138 |
ScopeValue ov = mv.owner(); |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
139 |
StackValue ownerSV = createStackValue(ov); // it is an oop |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
140 |
if (ov.isObject()) { // The owner object was scalar replaced |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
141 |
Assert.that(mv.eliminated() && ownerSV.objIsScalarReplaced(), "monitor should be eliminated for scalar replaced object"); |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
142 |
// Put klass for scalar replaced object. |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
143 |
ScopeValue kv = ((ObjectValue)ov).getKlass(); |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
144 |
Assert.that(kv.isConstantOop(), "klass should be oop constant for scalar replaced object"); |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
145 |
OopHandle k = ((ConstantOopReadValue)kv).getValue(); |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
146 |
result.add(new MonitorInfo(k, resolveMonitorLock(mv.basicLock()), mv.eliminated(), true)); |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
147 |
} else { |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
148 |
result.add(new MonitorInfo(ownerSV.getObject(), resolveMonitorLock(mv.basicLock()), mv.eliminated(), false)); |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
149 |
} |
1 | 150 |
} |
151 |
return result; |
|
152 |
} |
|
153 |
||
154 |
public int getBCI() { |
|
155 |
int raw = getRawBCI(); |
|
156 |
return ((raw == DebugInformationRecorder.SYNCHRONIZATION_ENTRY_BCI) ? 0 : raw); |
|
157 |
} |
|
158 |
||
159 |
/** Returns SynchronizationEntryBCI or bci() (used for synchronization) */ |
|
160 |
public int getRawBCI() { |
|
161 |
if (VM.getVM().isDebugging() && getScope() == null) { |
|
162 |
return 0; // No debugging information! |
|
163 |
} |
|
164 |
return getScope().getBCI(); |
|
165 |
} |
|
166 |
||
167 |
/** Returns the sender vframe */ |
|
168 |
public VFrame sender() { |
|
169 |
if (Assert.ASSERTS_ENABLED) { |
|
170 |
Assert.that(isTop(), "just checking"); |
|
171 |
} |
|
172 |
return sender(false); |
|
173 |
} |
|
174 |
||
175 |
public VFrame sender(boolean mayBeImprecise) { |
|
176 |
if (!VM.getVM().isDebugging()) { |
|
177 |
if (Assert.ASSERTS_ENABLED) { |
|
178 |
Assert.that(scope != null, "When new stub generator is in place, then scope can never be NULL"); |
|
179 |
} |
|
180 |
} |
|
181 |
Frame f = (Frame) getFrame().clone(); |
|
182 |
return (isTop() |
|
183 |
? super.sender(false) |
|
184 |
: new CompiledVFrame(f, getRegisterMap(), getThread(), getScope().sender(), mayBeImprecise)); |
|
185 |
} |
|
186 |
||
187 |
private StackValue createStackValue(ScopeValue sv) { |
|
188 |
// FIXME: this code appears to be out-of-date with respect to the VM especially in 64-bit mode |
|
189 |
if (sv.isLocation()) { |
|
190 |
// Stack or register value |
|
191 |
Location loc = ((LocationValue) sv).getLocation(); |
|
192 |
||
193 |
if (loc.isIllegal()) return new StackValue(); |
|
194 |
||
195 |
// First find address of value |
|
196 |
Address valueAddr = loc.isRegister() |
|
197 |
// Value was in a callee-save register |
|
198 |
? getRegisterMap().getLocation(new VMReg(loc.getRegisterNumber())) |
|
199 |
// Else value was directly saved on the stack. The frame's original stack pointer, |
|
200 |
// before any extension by its callee (due to Compiler1 linkage on SPARC), must be used. |
|
201 |
: ((Address)fr.getUnextendedSP()).addOffsetTo(loc.getStackOffset()); |
|
202 |
||
203 |
// Then package it right depending on type |
|
204 |
if (loc.holdsFloat()) { // Holds a float in a double register? |
|
205 |
// The callee has no clue whether the register holds a float, |
|
206 |
// double or is unused. He always saves a double. Here we know |
|
207 |
// a double was saved, but we only want a float back. Narrow the |
|
208 |
// saved double to the float that the JVM wants. |
|
209 |
if (Assert.ASSERTS_ENABLED) { |
|
210 |
Assert.that( loc.isRegister(), "floats always saved to stack in 1 word" ); |
|
211 |
} |
|
212 |
float value = (float) valueAddr.getJDoubleAt(0); |
|
213 |
return new StackValue(Float.floatToIntBits(value) & 0xFFFFFFFF); // 64-bit high half is stack junk |
|
214 |
} else if (loc.holdsInt()) { // Holds an int in a long register? |
|
215 |
// The callee has no clue whether the register holds an int, |
|
216 |
// long or is unused. He always saves a long. Here we know |
|
217 |
// a long was saved, but we only want an int back. Narrow the |
|
218 |
// saved long to the int that the JVM wants. |
|
219 |
if (Assert.ASSERTS_ENABLED) { |
|
220 |
Assert.that( loc.isRegister(), "ints always saved to stack in 1 word" ); |
|
221 |
} |
|
222 |
return new StackValue(valueAddr.getJLongAt(0) & 0xFFFFFFFF); |
|
1135 | 223 |
} else if (loc.holdsNarrowOop()) { // Holds an narrow oop? |
224 |
if (loc.isRegister() && VM.getVM().isBigEndian()) { |
|
225 |
// The callee has no clue whether the register holds an narrow oop, |
|
226 |
// long or is unused. He always saves a long. Here we know |
|
227 |
// a long was saved, but we only want an narrow oop back. Narrow the |
|
228 |
// saved long to the narrow oop that the JVM wants. |
|
3171
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
229 |
return new StackValue(valueAddr.getCompOopHandleAt(VM.getVM().getIntSize()), 0); |
1135 | 230 |
} else { |
3171
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
231 |
return new StackValue(valueAddr.getCompOopHandleAt(0), 0); |
1135 | 232 |
} |
1 | 233 |
} else if( loc.holdsOop() ) { // Holds an oop? |
3171
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
234 |
return new StackValue(valueAddr.getOopHandleAt(0), 0); |
1 | 235 |
} else if( loc.holdsDouble() ) { |
236 |
// Double value in a single stack slot |
|
237 |
return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF); |
|
238 |
} else if(loc.holdsAddr()) { |
|
239 |
if (Assert.ASSERTS_ENABLED) { |
|
240 |
Assert.that(!VM.getVM().isServerCompiler(), "No address type for locations with C2 (jsr-s are inlined)"); |
|
241 |
} |
|
242 |
// FIXME: not yet implemented (no access to safepoint state yet) |
|
243 |
return new StackValue(0); |
|
244 |
// intptr_t return_addr_tmp = *(intptr_t *)value_addr; |
|
245 |
// int bci = -1; |
|
246 |
// // Get the bci of the jsr that generated this returnAddress value. |
|
247 |
// // If the destination of a jsr is a block that ends with a return or throw, then |
|
248 |
// // the GraphBuilder converts the jsr into a direct goto. This has the side effect that |
|
249 |
// // the return address for the jsr gets emitted as a bci instead of as a real pc |
|
250 |
// if (code()->contains((address)return_addr_tmp)) { |
|
251 |
// ScopeDesc* scope = code()->scope_desc_at((address)(return_addr_tmp - jsr_call_offset), false); |
|
252 |
// bci = scope->bci(); |
|
253 |
// } else { |
|
254 |
// bci = (int)return_addr_tmp; |
|
255 |
// } |
|
256 |
// // no need to lock method as this happens at Safepoint |
|
257 |
// assert (SafepointSynchronize::is_at_safepoint(), "must be at safepoint, otherwise lock method()"); |
|
258 |
// // make sure bci points to jsr |
|
259 |
// Bytecode* bytecode = Bytecode_at(method()->bcp_from(bci)); |
|
260 |
// Bytecodes::Code bc = bytecode->code(); |
|
261 |
// assert (bc == Bytecodes::_jsr || bc == Bytecodes::_jsr_w, "must be jsr"); |
|
262 |
// |
|
263 |
// // the real returnAddress is the bytecode following the jsr |
|
264 |
// return new StackValue((intptr_t)(bci + Bytecodes::length_for(bc))); |
|
265 |
} else if (VM.getVM().isLP64() && loc.holdsLong()) { |
|
266 |
if ( loc.isRegister() ) { |
|
267 |
// Long value in two registers, high half in the first, low in the second |
|
268 |
return new StackValue(((valueAddr.getJLongAt(0) & 0xFFFFFFFF) << 32) | |
|
269 |
((valueAddr.getJLongAt(8) & 0xFFFFFFFF))); |
|
270 |
} else { |
|
271 |
// Long value in a single stack slot |
|
272 |
return new StackValue(valueAddr.getJLongAt(0)); |
|
273 |
} |
|
274 |
} else if( loc.isRegister() ) { |
|
275 |
// At the moment, all non-oop values in registers are 4 bytes, |
|
276 |
// including double and long halves (see Compile::FillLocArray() in |
|
277 |
// opto/output.cpp). Haul them out as such and return a StackValue |
|
278 |
// containing an image of the value as it appears in a stack slot. |
|
279 |
// If this is a double or long half, the interpreter _must_ deal |
|
280 |
// with doubles and longs as entities split across two stack slots. |
|
281 |
// To change this so doubles and/or longs can live in one stack slot, |
|
282 |
// a StackValue will have to understand that it can contain an |
|
283 |
// undivided double or long, implying that a Location (and the debug |
|
284 |
// info mechanism) and FillLocArray() will also have to understand it. |
|
285 |
return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF); |
|
286 |
} else { |
|
287 |
return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF); |
|
288 |
} |
|
289 |
} else if (sv.isConstantInt()) { |
|
290 |
// Constant int: treat same as register int. |
|
291 |
return new StackValue(((ConstantIntValue) sv).getValue() & 0xFFFFFFFF); |
|
292 |
} else if (sv.isConstantOop()) { |
|
293 |
// constant oop |
|
3171
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
294 |
return new StackValue(((ConstantOopReadValue) sv).getValue(), 0); |
1 | 295 |
} else if (sv.isConstantDouble()) { |
296 |
// Constant double in a single stack slot |
|
297 |
double d = ((ConstantDoubleValue) sv).getValue(); |
|
298 |
return new StackValue(Double.doubleToLongBits(d) & 0xFFFFFFFF); |
|
299 |
} else if (VM.getVM().isLP64() && sv.isConstantLong()) { |
|
300 |
// Constant long in a single stack slot |
|
301 |
return new StackValue(((ConstantLongValue) sv).getValue() & 0xFFFFFFFF); |
|
3171
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
302 |
} else if (sv.isObject()) { |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
303 |
// Scalar replaced object in compiled frame |
aa289b22b577
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
kvn
parents:
1217
diff
changeset
|
304 |
return new StackValue(((ObjectValue)sv).getValue(), 1); |
1 | 305 |
} |
306 |
||
307 |
// Unknown ScopeValue type |
|
308 |
Assert.that(false, "Should not reach here"); |
|
309 |
return new StackValue(0); // dummy |
|
310 |
} |
|
311 |
||
312 |
private BasicLock resolveMonitorLock(Location location) { |
|
313 |
if (Assert.ASSERTS_ENABLED) { |
|
314 |
Assert.that(location.isStack(), "for now we only look at the stack"); |
|
315 |
} |
|
316 |
int byteOffset = location.getStackOffset(); |
|
317 |
// (stack picture) |
|
318 |
// high: [ ] byte_offset + wordSize |
|
319 |
// low [ ] byte_offset |
|
320 |
// |
|
321 |
// sp-> [ ] 0 |
|
322 |
// the byte_offset is the distance from the stack pointer to the lowest address |
|
323 |
// The frame's original stack pointer, before any extension by its callee |
|
324 |
// (due to Compiler1 linkage on SPARC), must be used. |
|
325 |
return new BasicLock(getFrame().getUnextendedSP().addOffsetTo(byteOffset)); |
|
326 |
} |
|
327 |
} |