comparison agent/src/share/classes/sun/jvm/hotspot/runtime/CompiledVFrame.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children cecd8eb4e0ca
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2000-2006 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.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);
134 StackValue ownerSV = createStackValue(mv.owner()); // it is an oop
135 result.add(new MonitorInfo(ownerSV.getObject(), resolveMonitorLock(mv.basicLock())));
136 }
137 return result;
138 }
139
140 public int getBCI() {
141 int raw = getRawBCI();
142 return ((raw == DebugInformationRecorder.SYNCHRONIZATION_ENTRY_BCI) ? 0 : raw);
143 }
144
145 /** Returns SynchronizationEntryBCI or bci() (used for synchronization) */
146 public int getRawBCI() {
147 if (VM.getVM().isDebugging() && getScope() == null) {
148 return 0; // No debugging information!
149 }
150 return getScope().getBCI();
151 }
152
153 /** Returns the sender vframe */
154 public VFrame sender() {
155 if (Assert.ASSERTS_ENABLED) {
156 Assert.that(isTop(), "just checking");
157 }
158 return sender(false);
159 }
160
161 public VFrame sender(boolean mayBeImprecise) {
162 if (!VM.getVM().isDebugging()) {
163 if (Assert.ASSERTS_ENABLED) {
164 Assert.that(scope != null, "When new stub generator is in place, then scope can never be NULL");
165 }
166 }
167 Frame f = (Frame) getFrame().clone();
168 return (isTop()
169 ? super.sender(false)
170 : new CompiledVFrame(f, getRegisterMap(), getThread(), getScope().sender(), mayBeImprecise));
171 }
172
173 private StackValue createStackValue(ScopeValue sv) {
174 // FIXME: this code appears to be out-of-date with respect to the VM especially in 64-bit mode
175 if (sv.isLocation()) {
176 // Stack or register value
177 Location loc = ((LocationValue) sv).getLocation();
178
179 if (loc.isIllegal()) return new StackValue();
180
181 // First find address of value
182 Address valueAddr = loc.isRegister()
183 // Value was in a callee-save register
184 ? getRegisterMap().getLocation(new VMReg(loc.getRegisterNumber()))
185 // Else value was directly saved on the stack. The frame's original stack pointer,
186 // before any extension by its callee (due to Compiler1 linkage on SPARC), must be used.
187 : ((Address)fr.getUnextendedSP()).addOffsetTo(loc.getStackOffset());
188
189 // Then package it right depending on type
190 if (loc.holdsFloat()) { // Holds a float in a double register?
191 // The callee has no clue whether the register holds a float,
192 // double or is unused. He always saves a double. Here we know
193 // a double was saved, but we only want a float back. Narrow the
194 // saved double to the float that the JVM wants.
195 if (Assert.ASSERTS_ENABLED) {
196 Assert.that( loc.isRegister(), "floats always saved to stack in 1 word" );
197 }
198 float value = (float) valueAddr.getJDoubleAt(0);
199 return new StackValue(Float.floatToIntBits(value) & 0xFFFFFFFF); // 64-bit high half is stack junk
200 } else if (loc.holdsInt()) { // Holds an int in a long register?
201 // The callee has no clue whether the register holds an int,
202 // long or is unused. He always saves a long. Here we know
203 // a long was saved, but we only want an int back. Narrow the
204 // saved long to the int that the JVM wants.
205 if (Assert.ASSERTS_ENABLED) {
206 Assert.that( loc.isRegister(), "ints always saved to stack in 1 word" );
207 }
208 return new StackValue(valueAddr.getJLongAt(0) & 0xFFFFFFFF);
209 } else if( loc.holdsOop() ) { // Holds an oop?
210 return new StackValue(valueAddr.getOopHandleAt(0));
211 } else if( loc.holdsDouble() ) {
212 // Double value in a single stack slot
213 return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF);
214 } else if(loc.holdsAddr()) {
215 if (Assert.ASSERTS_ENABLED) {
216 Assert.that(!VM.getVM().isServerCompiler(), "No address type for locations with C2 (jsr-s are inlined)");
217 }
218 // FIXME: not yet implemented (no access to safepoint state yet)
219 return new StackValue(0);
220 // intptr_t return_addr_tmp = *(intptr_t *)value_addr;
221 // int bci = -1;
222 // // Get the bci of the jsr that generated this returnAddress value.
223 // // If the destination of a jsr is a block that ends with a return or throw, then
224 // // the GraphBuilder converts the jsr into a direct goto. This has the side effect that
225 // // the return address for the jsr gets emitted as a bci instead of as a real pc
226 // if (code()->contains((address)return_addr_tmp)) {
227 // ScopeDesc* scope = code()->scope_desc_at((address)(return_addr_tmp - jsr_call_offset), false);
228 // bci = scope->bci();
229 // } else {
230 // bci = (int)return_addr_tmp;
231 // }
232 // // no need to lock method as this happens at Safepoint
233 // assert (SafepointSynchronize::is_at_safepoint(), "must be at safepoint, otherwise lock method()");
234 // // make sure bci points to jsr
235 // Bytecode* bytecode = Bytecode_at(method()->bcp_from(bci));
236 // Bytecodes::Code bc = bytecode->code();
237 // assert (bc == Bytecodes::_jsr || bc == Bytecodes::_jsr_w, "must be jsr");
238 //
239 // // the real returnAddress is the bytecode following the jsr
240 // return new StackValue((intptr_t)(bci + Bytecodes::length_for(bc)));
241 } else if (VM.getVM().isLP64() && loc.holdsLong()) {
242 if ( loc.isRegister() ) {
243 // Long value in two registers, high half in the first, low in the second
244 return new StackValue(((valueAddr.getJLongAt(0) & 0xFFFFFFFF) << 32) |
245 ((valueAddr.getJLongAt(8) & 0xFFFFFFFF)));
246 } else {
247 // Long value in a single stack slot
248 return new StackValue(valueAddr.getJLongAt(0));
249 }
250 } else if( loc.isRegister() ) {
251 // At the moment, all non-oop values in registers are 4 bytes,
252 // including double and long halves (see Compile::FillLocArray() in
253 // opto/output.cpp). Haul them out as such and return a StackValue
254 // containing an image of the value as it appears in a stack slot.
255 // If this is a double or long half, the interpreter _must_ deal
256 // with doubles and longs as entities split across two stack slots.
257 // To change this so doubles and/or longs can live in one stack slot,
258 // a StackValue will have to understand that it can contain an
259 // undivided double or long, implying that a Location (and the debug
260 // info mechanism) and FillLocArray() will also have to understand it.
261 return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF);
262 } else {
263 return new StackValue(valueAddr.getJIntAt(0) & 0xFFFFFFFF);
264 }
265 } else if (sv.isConstantInt()) {
266 // Constant int: treat same as register int.
267 return new StackValue(((ConstantIntValue) sv).getValue() & 0xFFFFFFFF);
268 } else if (sv.isConstantOop()) {
269 // constant oop
270 return new StackValue(((ConstantOopReadValue) sv).getValue());
271 } else if (sv.isConstantDouble()) {
272 // Constant double in a single stack slot
273 double d = ((ConstantDoubleValue) sv).getValue();
274 return new StackValue(Double.doubleToLongBits(d) & 0xFFFFFFFF);
275 } else if (VM.getVM().isLP64() && sv.isConstantLong()) {
276 // Constant long in a single stack slot
277 return new StackValue(((ConstantLongValue) sv).getValue() & 0xFFFFFFFF);
278 }
279
280 // Unknown ScopeValue type
281 Assert.that(false, "Should not reach here");
282 return new StackValue(0); // dummy
283 }
284
285 private BasicLock resolveMonitorLock(Location location) {
286 if (Assert.ASSERTS_ENABLED) {
287 Assert.that(location.isStack(), "for now we only look at the stack");
288 }
289 int byteOffset = location.getStackOffset();
290 // (stack picture)
291 // high: [ ] byte_offset + wordSize
292 // low [ ] byte_offset
293 //
294 // sp-> [ ] 0
295 // the byte_offset is the distance from the stack pointer to the lowest address
296 // The frame's original stack pointer, before any extension by its callee
297 // (due to Compiler1 linkage on SPARC), must be used.
298 return new BasicLock(getFrame().getUnextendedSP().addOffsetTo(byteOffset));
299 }
300 }