1
|
1 |
/*
|
|
2 |
* Copyright 2001-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.x86;
|
|
26 |
|
|
27 |
import java.util.*;
|
|
28 |
import sun.jvm.hotspot.asm.x86.*;
|
|
29 |
import sun.jvm.hotspot.code.*;
|
|
30 |
import sun.jvm.hotspot.compiler.*;
|
|
31 |
import sun.jvm.hotspot.debugger.*;
|
|
32 |
import sun.jvm.hotspot.oops.*;
|
|
33 |
import sun.jvm.hotspot.runtime.*;
|
|
34 |
import sun.jvm.hotspot.types.*;
|
|
35 |
import sun.jvm.hotspot.utilities.*;
|
|
36 |
|
|
37 |
/** Specialization of and implementation of abstract methods of the
|
|
38 |
Frame class for the x86 family of CPUs. */
|
|
39 |
|
|
40 |
public class X86Frame extends Frame {
|
|
41 |
private static final boolean DEBUG;
|
|
42 |
static {
|
|
43 |
DEBUG = System.getProperty("sun.jvm.hotspot.runtime.x86.X86Frame.DEBUG") != null;
|
|
44 |
}
|
|
45 |
|
|
46 |
// All frames
|
|
47 |
private static final int LINK_OFFSET = 0;
|
|
48 |
private static final int RETURN_ADDR_OFFSET = 1;
|
|
49 |
private static final int SENDER_SP_OFFSET = 2;
|
|
50 |
|
|
51 |
// Interpreter frames
|
|
52 |
private static final int INTERPRETER_FRAME_MIRROR_OFFSET = 2; // for native calls only
|
|
53 |
private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1;
|
|
54 |
private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1;
|
|
55 |
private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET - 1;
|
|
56 |
private static int INTERPRETER_FRAME_MDX_OFFSET; // Non-core builds only
|
|
57 |
private static int INTERPRETER_FRAME_CACHE_OFFSET;
|
|
58 |
private static int INTERPRETER_FRAME_LOCALS_OFFSET;
|
|
59 |
private static int INTERPRETER_FRAME_BCX_OFFSET;
|
|
60 |
private static int INTERPRETER_FRAME_INITIAL_SP_OFFSET;
|
|
61 |
private static int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET;
|
|
62 |
private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET;
|
|
63 |
|
|
64 |
// Entry frames
|
|
65 |
private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET = 2;
|
|
66 |
|
|
67 |
// Native frames
|
|
68 |
private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2;
|
|
69 |
|
|
70 |
static {
|
|
71 |
VM.registerVMInitializedObserver(new Observer() {
|
|
72 |
public void update(Observable o, Object data) {
|
|
73 |
initialize(VM.getVM().getTypeDataBase());
|
|
74 |
}
|
|
75 |
});
|
|
76 |
}
|
|
77 |
|
|
78 |
private static synchronized void initialize(TypeDataBase db) {
|
|
79 |
if (VM.getVM().isCore()) {
|
|
80 |
INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1;
|
|
81 |
} else {
|
|
82 |
INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1;
|
|
83 |
INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1;
|
|
84 |
}
|
|
85 |
INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1;
|
|
86 |
INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
|
|
87 |
INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1;
|
|
88 |
INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
|
|
89 |
INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
|
|
90 |
}
|
|
91 |
|
|
92 |
// an additional field beyond sp and pc:
|
|
93 |
Address raw_fp; // frame pointer
|
|
94 |
private Address raw_unextendedSP;
|
|
95 |
|
|
96 |
private X86Frame() {
|
|
97 |
}
|
|
98 |
|
|
99 |
private void adjustForDeopt() {
|
|
100 |
if ( pc != null) {
|
|
101 |
// Look for a deopt pc and if it is deopted convert to original pc
|
|
102 |
CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
|
|
103 |
if (cb != null && cb.isJavaMethod()) {
|
|
104 |
NMethod nm = (NMethod) cb;
|
|
105 |
if (pc.equals(nm.deoptBegin())) {
|
|
106 |
if (Assert.ASSERTS_ENABLED) {
|
|
107 |
Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
|
|
108 |
}
|
|
109 |
// adjust pc if frame is deoptimized.
|
|
110 |
pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
|
|
111 |
deoptimized = true;
|
|
112 |
}
|
|
113 |
}
|
|
114 |
}
|
|
115 |
}
|
|
116 |
|
|
117 |
public X86Frame(Address raw_sp, Address raw_fp, Address pc) {
|
|
118 |
this.raw_sp = raw_sp;
|
|
119 |
this.raw_unextendedSP = raw_sp;
|
|
120 |
this.raw_fp = raw_fp;
|
|
121 |
this.pc = pc;
|
|
122 |
|
|
123 |
// Frame must be fully constructed before this call
|
|
124 |
adjustForDeopt();
|
|
125 |
|
|
126 |
if (DEBUG) {
|
|
127 |
System.out.println("X86Frame(sp, fp, pc): " + this);
|
|
128 |
dumpStack();
|
|
129 |
}
|
|
130 |
}
|
|
131 |
|
|
132 |
public X86Frame(Address raw_sp, Address raw_fp) {
|
|
133 |
this.raw_sp = raw_sp;
|
|
134 |
this.raw_unextendedSP = raw_sp;
|
|
135 |
this.raw_fp = raw_fp;
|
|
136 |
this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
|
|
137 |
|
|
138 |
// Frame must be fully constructed before this call
|
|
139 |
adjustForDeopt();
|
|
140 |
|
|
141 |
if (DEBUG) {
|
|
142 |
System.out.println("X86Frame(sp, fp): " + this);
|
|
143 |
dumpStack();
|
|
144 |
}
|
|
145 |
}
|
|
146 |
|
|
147 |
// This constructor should really take the unextended SP as an arg
|
|
148 |
// but then the constructor is ambiguous with constructor that takes
|
|
149 |
// a PC so take an int and convert it.
|
|
150 |
public X86Frame(Address raw_sp, Address raw_fp, long extension) {
|
|
151 |
this.raw_sp = raw_sp;
|
|
152 |
if (raw_sp == null) {
|
|
153 |
this.raw_unextendedSP = null;
|
|
154 |
} else {
|
|
155 |
this.raw_unextendedSP = raw_sp.addOffsetTo(extension);
|
|
156 |
}
|
|
157 |
this.raw_fp = raw_fp;
|
|
158 |
this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
|
|
159 |
|
|
160 |
// Frame must be fully constructed before this call
|
|
161 |
adjustForDeopt();
|
|
162 |
|
|
163 |
if (DEBUG) {
|
|
164 |
System.out.println("X86Frame(sp, fp): " + this);
|
|
165 |
dumpStack();
|
|
166 |
}
|
|
167 |
|
|
168 |
}
|
|
169 |
|
|
170 |
public Object clone() {
|
|
171 |
X86Frame frame = new X86Frame();
|
|
172 |
frame.raw_sp = raw_sp;
|
|
173 |
frame.raw_unextendedSP = raw_unextendedSP;
|
|
174 |
frame.raw_fp = raw_fp;
|
|
175 |
frame.raw_fp = raw_fp;
|
|
176 |
frame.pc = pc;
|
|
177 |
frame.deoptimized = deoptimized;
|
|
178 |
return frame;
|
|
179 |
}
|
|
180 |
|
|
181 |
public boolean equals(Object arg) {
|
|
182 |
if (arg == null) {
|
|
183 |
return false;
|
|
184 |
}
|
|
185 |
|
|
186 |
if (!(arg instanceof X86Frame)) {
|
|
187 |
return false;
|
|
188 |
}
|
|
189 |
|
|
190 |
X86Frame other = (X86Frame) arg;
|
|
191 |
|
|
192 |
return (AddressOps.equal(getSP(), other.getSP()) &&
|
|
193 |
AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) &&
|
|
194 |
AddressOps.equal(getFP(), other.getFP()) &&
|
|
195 |
AddressOps.equal(getPC(), other.getPC()));
|
|
196 |
}
|
|
197 |
|
|
198 |
public int hashCode() {
|
|
199 |
if (raw_sp == null) {
|
|
200 |
return 0;
|
|
201 |
}
|
|
202 |
|
|
203 |
return raw_sp.hashCode();
|
|
204 |
}
|
|
205 |
|
|
206 |
public String toString() {
|
|
207 |
return "sp: " + (getSP() == null? "null" : getSP().toString()) +
|
|
208 |
", unextendedSP: " + (getUnextendedSP() == null? "null" : getUnextendedSP().toString()) +
|
|
209 |
", fp: " + (getFP() == null? "null" : getFP().toString()) +
|
|
210 |
", pc: " + (pc == null? "null" : pc.toString());
|
|
211 |
}
|
|
212 |
|
|
213 |
// accessors for the instance variables
|
|
214 |
public Address getFP() { return raw_fp; }
|
|
215 |
public Address getSP() { return raw_sp; }
|
|
216 |
public Address getID() { return raw_sp; }
|
|
217 |
|
|
218 |
// FIXME: not implemented yet (should be done for Solaris/X86)
|
|
219 |
public boolean isSignalHandlerFrameDbg() { return false; }
|
|
220 |
public int getSignalNumberDbg() { return 0; }
|
|
221 |
public String getSignalNameDbg() { return null; }
|
|
222 |
|
|
223 |
public boolean isInterpretedFrameValid() {
|
|
224 |
if (Assert.ASSERTS_ENABLED) {
|
|
225 |
Assert.that(isInterpretedFrame(), "Not an interpreted frame");
|
|
226 |
}
|
|
227 |
|
|
228 |
// These are reasonable sanity checks
|
|
229 |
if (getFP() == null || getFP().andWithMask(0x3) != null) {
|
|
230 |
return false;
|
|
231 |
}
|
|
232 |
|
|
233 |
if (getSP() == null || getSP().andWithMask(0x3) != null) {
|
|
234 |
return false;
|
|
235 |
}
|
|
236 |
|
|
237 |
if (getFP().addOffsetTo(INTERPRETER_FRAME_INITIAL_SP_OFFSET * VM.getVM().getAddressSize()).lessThan(getSP())) {
|
|
238 |
return false;
|
|
239 |
}
|
|
240 |
|
|
241 |
// These are hacks to keep us out of trouble.
|
|
242 |
// The problem with these is that they mask other problems
|
|
243 |
if (getFP().lessThanOrEqual(getSP())) {
|
|
244 |
// this attempts to deal with unsigned comparison above
|
|
245 |
return false;
|
|
246 |
}
|
|
247 |
|
|
248 |
if (getFP().minus(getSP()) > 4096 * VM.getVM().getAddressSize()) {
|
|
249 |
// stack frames shouldn't be large.
|
|
250 |
return false;
|
|
251 |
}
|
|
252 |
|
|
253 |
return true;
|
|
254 |
}
|
|
255 |
|
|
256 |
// FIXME: not applicable in current system
|
|
257 |
// void patch_pc(Thread* thread, address pc);
|
|
258 |
|
|
259 |
public Frame sender(RegisterMap regMap, CodeBlob cb) {
|
|
260 |
X86RegisterMap map = (X86RegisterMap) regMap;
|
|
261 |
|
|
262 |
if (Assert.ASSERTS_ENABLED) {
|
|
263 |
Assert.that(map != null, "map must be set");
|
|
264 |
}
|
|
265 |
|
|
266 |
// Default is we done have to follow them. The sender_for_xxx will
|
|
267 |
// update it accordingly
|
|
268 |
map.setIncludeArgumentOops(false);
|
|
269 |
|
|
270 |
if (isEntryFrame()) return senderForEntryFrame(map);
|
|
271 |
if (isInterpretedFrame()) return senderForInterpreterFrame(map);
|
|
272 |
|
|
273 |
if (!VM.getVM().isCore()) {
|
|
274 |
if(cb == null) {
|
|
275 |
cb = VM.getVM().getCodeCache().findBlob(getPC());
|
|
276 |
} else {
|
|
277 |
if (Assert.ASSERTS_ENABLED) {
|
|
278 |
Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
|
|
279 |
}
|
|
280 |
}
|
|
281 |
|
|
282 |
if (cb != null) {
|
|
283 |
return senderForCompiledFrame(map, cb);
|
|
284 |
}
|
|
285 |
}
|
|
286 |
|
|
287 |
// Must be native-compiled frame, i.e. the marshaling code for native
|
|
288 |
// methods that exists in the core system.
|
|
289 |
return new X86Frame(getSenderSP(), getLink(), getSenderPC());
|
|
290 |
}
|
|
291 |
|
|
292 |
private Frame senderForEntryFrame(X86RegisterMap map) {
|
|
293 |
if (Assert.ASSERTS_ENABLED) {
|
|
294 |
Assert.that(map != null, "map must be set");
|
|
295 |
}
|
|
296 |
// Java frame called from C; skip all C frames and return top C
|
|
297 |
// frame of that chunk as the sender
|
|
298 |
X86JavaCallWrapper jcw = (X86JavaCallWrapper) getEntryFrameCallWrapper();
|
|
299 |
if (Assert.ASSERTS_ENABLED) {
|
|
300 |
Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
|
|
301 |
Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
|
|
302 |
}
|
|
303 |
X86Frame fr;
|
|
304 |
if (jcw.getLastJavaPC() != null) {
|
|
305 |
fr = new X86Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC());
|
|
306 |
} else {
|
|
307 |
fr = new X86Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP());
|
|
308 |
}
|
|
309 |
map.clear();
|
|
310 |
if (Assert.ASSERTS_ENABLED) {
|
|
311 |
Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
|
|
312 |
}
|
|
313 |
return fr;
|
|
314 |
}
|
|
315 |
|
|
316 |
private Frame senderForInterpreterFrame(X86RegisterMap map) {
|
|
317 |
Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
|
|
318 |
Address sp = addressOfStackSlot(SENDER_SP_OFFSET);
|
|
319 |
// We do not need to update the callee-save register mapping because above
|
|
320 |
// us is either another interpreter frame or a converter-frame, but never
|
|
321 |
// directly a compiled frame.
|
|
322 |
// 11/24/04 SFG. With the removal of adapter frames this is no longer true.
|
|
323 |
// However c2 no longer uses callee save register for java calls so there
|
|
324 |
// are no callee register to find.
|
|
325 |
|
|
326 |
return new X86Frame(sp, getLink(), unextendedSP.minus(sp));
|
|
327 |
}
|
|
328 |
|
|
329 |
private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) {
|
|
330 |
//
|
|
331 |
// NOTE: some of this code is (unfortunately) duplicated in X86CurrentFrameGuess
|
|
332 |
//
|
|
333 |
|
|
334 |
if (Assert.ASSERTS_ENABLED) {
|
|
335 |
Assert.that(map != null, "map must be set");
|
|
336 |
}
|
|
337 |
|
|
338 |
// frame owned by optimizing compiler
|
|
339 |
Address sender_sp = null;
|
|
340 |
|
|
341 |
if (VM.getVM().isClientCompiler()) {
|
|
342 |
sender_sp = addressOfStackSlot(SENDER_SP_OFFSET);
|
|
343 |
} else {
|
|
344 |
if (Assert.ASSERTS_ENABLED) {
|
|
345 |
Assert.that(cb.getFrameSize() >= 0, "Compiled by Compiler1: do not use");
|
|
346 |
}
|
|
347 |
sender_sp = getUnextendedSP().addOffsetTo(cb.getFrameSize());
|
|
348 |
}
|
|
349 |
|
|
350 |
// On Intel the return_address is always the word on the stack
|
|
351 |
Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
|
|
352 |
|
|
353 |
if (map.getUpdateMap() && cb.getOopMaps() != null) {
|
|
354 |
OopMapSet.updateRegisterMap(this, cb, map, true);
|
|
355 |
}
|
|
356 |
|
|
357 |
if (VM.getVM().isClientCompiler()) {
|
|
358 |
// Move this here for C1 and collecting oops in arguments (According to Rene)
|
|
359 |
map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread()));
|
|
360 |
}
|
|
361 |
|
|
362 |
Address saved_fp = null;
|
|
363 |
if (VM.getVM().isClientCompiler()) {
|
|
364 |
saved_fp = getFP().getAddressAt(0);
|
|
365 |
} else if (VM.getVM().isServerCompiler() &&
|
|
366 |
(VM.getVM().getInterpreter().contains(sender_pc) ||
|
|
367 |
VM.getVM().getStubRoutines().returnsToCallStub(sender_pc))) {
|
|
368 |
// C2 prologue saves EBP in the usual place.
|
|
369 |
// however only use it if the sender had link infomration in it.
|
|
370 |
saved_fp = sender_sp.getAddressAt(-2 * VM.getVM().getAddressSize());
|
|
371 |
}
|
|
372 |
|
|
373 |
return new X86Frame(sender_sp, saved_fp, sender_pc);
|
|
374 |
}
|
|
375 |
|
|
376 |
protected boolean hasSenderPD() {
|
|
377 |
// FIXME
|
|
378 |
// Check for null ebp? Need to do some tests.
|
|
379 |
return true;
|
|
380 |
}
|
|
381 |
|
|
382 |
public long frameSize() {
|
|
383 |
return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize());
|
|
384 |
}
|
|
385 |
|
|
386 |
public Address getLink() {
|
|
387 |
return addressOfStackSlot(LINK_OFFSET).getAddressAt(0);
|
|
388 |
}
|
|
389 |
|
|
390 |
// FIXME: not implementable yet
|
|
391 |
//inline void frame::set_link(intptr_t* addr) { *(intptr_t **)addr_at(link_offset) = addr; }
|
|
392 |
|
|
393 |
public Address getUnextendedSP() { return raw_unextendedSP; }
|
|
394 |
|
|
395 |
// Return address:
|
|
396 |
public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); }
|
|
397 |
public Address getSenderPC() { return getSenderPCAddr().getAddressAt(0); }
|
|
398 |
|
|
399 |
// return address of param, zero origin index.
|
|
400 |
public Address getNativeParamAddr(int idx) {
|
|
401 |
return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx);
|
|
402 |
}
|
|
403 |
|
|
404 |
public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); }
|
|
405 |
|
|
406 |
public Address compiledArgumentToLocationPD(VMReg reg, RegisterMap regMap, int argSize) {
|
|
407 |
if (VM.getVM().isCore() || VM.getVM().isClientCompiler()) {
|
|
408 |
throw new RuntimeException("Should not reach here");
|
|
409 |
}
|
|
410 |
|
|
411 |
return oopMapRegToLocation(reg, regMap);
|
|
412 |
}
|
|
413 |
|
|
414 |
public Address addressOfInterpreterFrameLocals() {
|
|
415 |
return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
|
|
416 |
}
|
|
417 |
|
|
418 |
private Address addressOfInterpreterFrameBCX() {
|
|
419 |
return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET);
|
|
420 |
}
|
|
421 |
|
|
422 |
public int getInterpreterFrameBCI() {
|
|
423 |
// FIXME: this is not atomic with respect to GC and is unsuitable
|
|
424 |
// for use in a non-debugging, or reflective, system. Need to
|
|
425 |
// figure out how to express this.
|
|
426 |
Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
|
|
427 |
OopHandle methodHandle = addressOfInterpreterFrameMethod().getOopHandleAt(0);
|
|
428 |
Method method = (Method) VM.getVM().getObjectHeap().newOop(methodHandle);
|
|
429 |
return bcpToBci(bcp, method);
|
|
430 |
}
|
|
431 |
|
|
432 |
public Address addressOfInterpreterFrameMDX() {
|
|
433 |
return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET);
|
|
434 |
}
|
|
435 |
|
|
436 |
// FIXME
|
|
437 |
//inline int frame::interpreter_frame_monitor_size() {
|
|
438 |
// return BasicObjectLock::size();
|
|
439 |
//}
|
|
440 |
|
|
441 |
// expression stack
|
|
442 |
// (the max_stack arguments are used by the GC; see class FrameClosure)
|
|
443 |
|
|
444 |
public Address addressOfInterpreterFrameExpressionStack() {
|
|
445 |
Address monitorEnd = interpreterFrameMonitorEnd().address();
|
|
446 |
return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize());
|
|
447 |
}
|
|
448 |
|
|
449 |
public int getInterpreterFrameExpressionStackDirection() { return -1; }
|
|
450 |
|
|
451 |
// top of expression stack
|
|
452 |
public Address addressOfInterpreterFrameTOS() {
|
|
453 |
return getSP();
|
|
454 |
}
|
|
455 |
|
|
456 |
/** Expression stack from top down */
|
|
457 |
public Address addressOfInterpreterFrameTOSAt(int slot) {
|
|
458 |
return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
|
|
459 |
}
|
|
460 |
|
|
461 |
public Address getInterpreterFrameSenderSP() {
|
|
462 |
if (Assert.ASSERTS_ENABLED) {
|
|
463 |
Assert.that(isInterpretedFrame(), "interpreted frame expected");
|
|
464 |
}
|
|
465 |
return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
|
|
466 |
}
|
|
467 |
|
|
468 |
// Monitors
|
|
469 |
public BasicObjectLock interpreterFrameMonitorBegin() {
|
|
470 |
return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET));
|
|
471 |
}
|
|
472 |
|
|
473 |
public BasicObjectLock interpreterFrameMonitorEnd() {
|
|
474 |
Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0);
|
|
475 |
if (Assert.ASSERTS_ENABLED) {
|
|
476 |
// make sure the pointer points inside the frame
|
|
477 |
Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer");
|
|
478 |
Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer");
|
|
479 |
}
|
|
480 |
return new BasicObjectLock(result);
|
|
481 |
}
|
|
482 |
|
|
483 |
public int interpreterFrameMonitorSize() {
|
|
484 |
return BasicObjectLock.size();
|
|
485 |
}
|
|
486 |
|
|
487 |
// Method
|
|
488 |
public Address addressOfInterpreterFrameMethod() {
|
|
489 |
return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET);
|
|
490 |
}
|
|
491 |
|
|
492 |
// Constant pool cache
|
|
493 |
public Address addressOfInterpreterFrameCPCache() {
|
|
494 |
return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET);
|
|
495 |
}
|
|
496 |
|
|
497 |
// Entry frames
|
|
498 |
public JavaCallWrapper getEntryFrameCallWrapper() {
|
|
499 |
return new X86JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0));
|
|
500 |
}
|
|
501 |
|
|
502 |
protected Address addressOfSavedOopResult() {
|
|
503 |
// offset is 2 for compiler2 and 3 for compiler1
|
|
504 |
return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) *
|
|
505 |
VM.getVM().getAddressSize());
|
|
506 |
}
|
|
507 |
|
|
508 |
protected Address addressOfSavedReceiver() {
|
|
509 |
return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
|
|
510 |
}
|
|
511 |
|
|
512 |
private void dumpStack() {
|
|
513 |
if (getFP() != null) {
|
|
514 |
for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
|
|
515 |
AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize()));
|
|
516 |
addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
|
|
517 |
System.out.println(addr + ": " + addr.getAddressAt(0));
|
|
518 |
}
|
|
519 |
} else {
|
|
520 |
for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
|
|
521 |
AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize()));
|
|
522 |
addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
|
|
523 |
System.out.println(addr + ": " + addr.getAddressAt(0));
|
|
524 |
}
|
|
525 |
}
|
|
526 |
}
|
|
527 |
}
|