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

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children c18cbe5936b8
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2003-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.amd64;
26
27 import java.util.*;
28 import sun.jvm.hotspot.code.*;
29 import sun.jvm.hotspot.compiler.*;
30 import sun.jvm.hotspot.debugger.*;
31 import sun.jvm.hotspot.oops.*;
32 import sun.jvm.hotspot.runtime.*;
33 import sun.jvm.hotspot.types.*;
34 import sun.jvm.hotspot.utilities.*;
35
36 /** Specialization of and implementation of abstract methods of the
37 Frame class for the amd64 CPU. */
38
39 public class AMD64Frame extends Frame {
40 private static final boolean DEBUG;
41 static {
42 DEBUG = System.getProperty("sun.jvm.hotspot.runtime.amd64.AMD64Frame.DEBUG") != null;
43 }
44
45 // refer to frame_amd64.hpp
46 private static final int PC_RETURN_OFFSET = 0;
47 // All frames
48 private static final int LINK_OFFSET = 0;
49 private static final int RETURN_ADDR_OFFSET = 1;
50 private static final int SENDER_SP_OFFSET = 2;
51
52 // Interpreter frames
53 private static final int INTERPRETER_FRAME_MIRROR_OFFSET = 2; // for native calls only
54 private static final int INTERPRETER_FRAME_SENDER_SP_OFFSET = -1;
55 private static final int INTERPRETER_FRAME_LAST_SP_OFFSET = INTERPRETER_FRAME_SENDER_SP_OFFSET - 1;
56 private static final int INTERPRETER_FRAME_METHOD_OFFSET = INTERPRETER_FRAME_LAST_SP_OFFSET - 1;
57 private static int INTERPRETER_FRAME_MDX_OFFSET; // Non-core builds only
58 private static int INTERPRETER_FRAME_CACHE_OFFSET;
59 private static int INTERPRETER_FRAME_LOCALS_OFFSET;
60 private static int INTERPRETER_FRAME_BCX_OFFSET;
61 private static int INTERPRETER_FRAME_INITIAL_SP_OFFSET;
62 private static int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET;
63 private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET;
64
65 // Entry frames
66 private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET = -6;
67
68 // Native frames
69 private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2;
70
71 static {
72 VM.registerVMInitializedObserver(new Observer() {
73 public void update(Observable o, Object data) {
74 initialize(VM.getVM().getTypeDataBase());
75 }
76 });
77 }
78
79 private static synchronized void initialize(TypeDataBase db) {
80 if (VM.getVM().isCore()) {
81 INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1;
82 } else {
83 INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1;
84 INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_OFFSET - 1;
85 }
86 INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1;
87 INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1;
88 INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1;
89 INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
90 INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET;
91 }
92
93 // an additional field beyond sp and pc:
94 Address raw_fp; // frame pointer
95 private Address raw_unextendedSP;
96
97 private AMD64Frame() {
98 }
99
100 private void adjustForDeopt() {
101 if ( pc != null) {
102 // Look for a deopt pc and if it is deopted convert to original pc
103 CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
104 if (cb != null && cb.isJavaMethod()) {
105 NMethod nm = (NMethod) cb;
106 if (pc.equals(nm.deoptBegin())) {
107 // adjust pc if frame is deoptimized.
108 if (Assert.ASSERTS_ENABLED) {
109 Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
110 }
111 pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
112 deoptimized = true;
113 }
114 }
115 }
116 }
117
118 public AMD64Frame(Address raw_sp, Address raw_fp, Address pc) {
119 this.raw_sp = raw_sp;
120 this.raw_unextendedSP = raw_sp;
121 this.raw_fp = raw_fp;
122 this.pc = pc;
123
124 // Frame must be fully constructed before this call
125 adjustForDeopt();
126
127 if (DEBUG) {
128 System.out.println("AMD64Frame(sp, fp, pc): " + this);
129 dumpStack();
130 }
131 }
132
133 public AMD64Frame(Address raw_sp, Address raw_fp) {
134 this.raw_sp = raw_sp;
135 this.raw_unextendedSP = raw_sp;
136 this.raw_fp = raw_fp;
137 this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
138
139 // Frame must be fully constructed before this call
140 adjustForDeopt();
141
142 if (DEBUG) {
143 System.out.println("AMD64Frame(sp, fp): " + this);
144 dumpStack();
145 }
146 }
147
148 // This constructor should really take the unextended SP as an arg
149 // but then the constructor is ambiguous with constructor that takes
150 // a PC so take an int and convert it.
151 public AMD64Frame(Address raw_sp, Address raw_fp, long extension) {
152 this.raw_sp = raw_sp;
153 if ( raw_sp == null) {
154 this.raw_unextendedSP = null;
155 } else {
156 this.raw_unextendedSP = raw_sp.addOffsetTo(extension);
157 }
158 this.raw_fp = raw_fp;
159 this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
160
161 // Frame must be fully constructed before this call
162 adjustForDeopt();
163
164 if (DEBUG) {
165 System.out.println("AMD64Frame(sp, fp, extension): " + this);
166 dumpStack();
167 }
168
169 }
170
171 public Object clone() {
172 AMD64Frame frame = new AMD64Frame();
173 frame.raw_sp = raw_sp;
174 frame.raw_unextendedSP = raw_unextendedSP;
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 AMD64Frame)) {
187 return false;
188 }
189
190 AMD64Frame other = (AMD64Frame) arg;
191
192 return (AddressOps.equal(getSP(), other.getSP()) &&
193 AddressOps.equal(getFP(), other.getFP()) &&
194 AddressOps.equal(getUnextendedSP(), other.getUnextendedSP()) &&
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/AMD64)
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 AMD64RegisterMap map = (AMD64RegisterMap) 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
274 if (!VM.getVM().isCore()) {
275 if(cb == null) {
276 cb = VM.getVM().getCodeCache().findBlob(getPC());
277 } else {
278 if (Assert.ASSERTS_ENABLED) {
279 Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same");
280 }
281 }
282
283 if (cb != null) {
284 return senderForCompiledFrame(map, cb);
285 }
286 }
287
288 // Must be native-compiled frame, i.e. the marshaling code for native
289 // methods that exists in the core system.
290 return new AMD64Frame(getSenderSP(), getLink(), getSenderPC());
291 }
292
293 private Frame senderForEntryFrame(AMD64RegisterMap map) {
294 if (Assert.ASSERTS_ENABLED) {
295 Assert.that(map != null, "map must be set");
296 }
297 // Java frame called from C; skip all C frames and return top C
298 // frame of that chunk as the sender
299 AMD64JavaCallWrapper jcw = (AMD64JavaCallWrapper) getEntryFrameCallWrapper();
300 if (Assert.ASSERTS_ENABLED) {
301 Assert.that(!entryFrameIsFirst(), "next Java fp must be non zero");
302 Assert.that(jcw.getLastJavaSP().greaterThan(getSP()), "must be above this frame on stack");
303 }
304 AMD64Frame fr;
305 if (jcw.getLastJavaPC() != null) {
306 fr = new AMD64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP(), jcw.getLastJavaPC());
307 } else {
308 fr = new AMD64Frame(jcw.getLastJavaSP(), jcw.getLastJavaFP());
309 }
310 map.clear();
311 if (Assert.ASSERTS_ENABLED) {
312 Assert.that(map.getIncludeArgumentOops(), "should be set by clear");
313 }
314 return fr;
315 }
316
317 private Frame senderForInterpreterFrame(AMD64RegisterMap map) {
318 Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
319 Address sp = addressOfStackSlot(SENDER_SP_OFFSET);
320 // We do not need to update the callee-save register mapping because above
321 // us is either another interpreter frame or a converter-frame, but never
322 // directly a compiled frame.
323 // 11/24/04 SFG. This is no longer true after adapter were removed. However at the moment
324 // C2 no longer uses callee save register for java calls so there are no callee register
325 // to find.
326 return new AMD64Frame(sp, getLink(), unextendedSP.minus(sp));
327 }
328
329 private Frame senderForCompiledFrame(AMD64RegisterMap map, CodeBlob cb) {
330 //
331 // NOTE: some of this code is (unfortunately) duplicated in AMD64CurrentFrameGuess
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
342 if (VM.getVM().isClientCompiler()) {
343 sender_sp = addressOfStackSlot(SENDER_SP_OFFSET);
344 } else {
345 if (Assert.ASSERTS_ENABLED) {
346 Assert.that(cb.getFrameSize() >= 0, "Compiled by Compiler1: do not use");
347 }
348 sender_sp = getUnextendedSP().addOffsetTo(cb.getFrameSize());
349 }
350
351 // On Intel the return_address is always the word on the stack
352 Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize());
353
354 if (map.getUpdateMap() && cb.getOopMaps() != null) {
355 OopMapSet.updateRegisterMap(this, cb, map, true);
356 }
357
358 if (VM.getVM().isClientCompiler()) {
359 // Move this here for C1 and collecting oops in arguments (According to Rene)
360 map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread()));
361 }
362
363 Address saved_fp = null;
364 if (VM.getVM().isClientCompiler()) {
365 saved_fp = getFP().getAddressAt(0);
366 } else if (VM.getVM().isServerCompiler() &&
367 (VM.getVM().getInterpreter().contains(sender_pc) ||
368 VM.getVM().getStubRoutines().returnsToCallStub(sender_pc))) {
369 // C2 prologue saves EBP in the usual place.
370 // however only use it if the sender had link infomration in it.
371 saved_fp = sender_sp.getAddressAt(-2 * VM.getVM().getAddressSize());
372 }
373
374 return new AMD64Frame(sender_sp, saved_fp, sender_pc);
375 }
376
377 protected boolean hasSenderPD() {
378 // FIXME
379 // Check for null ebp? Need to do some tests.
380 return true;
381 }
382
383 public long frameSize() {
384 return (getSenderSP().minus(getSP()) / VM.getVM().getAddressSize());
385 }
386
387 public Address getLink() {
388 return addressOfStackSlot(LINK_OFFSET).getAddressAt(0);
389 }
390
391 // FIXME: not implementable yet
392 //inline void frame::set_link(intptr_t* addr) { *(intptr_t **)addr_at(link_offset) = addr; }
393
394 public Address getUnextendedSP() { return raw_unextendedSP; }
395
396 // Return address:
397 public Address getSenderPCAddr() { return addressOfStackSlot(RETURN_ADDR_OFFSET); }
398 public Address getSenderPC() { return getSenderPCAddr().getAddressAt(0); }
399
400 // return address of param, zero origin index.
401 public Address getNativeParamAddr(int idx) {
402 return addressOfStackSlot(NATIVE_FRAME_INITIAL_PARAM_OFFSET + idx);
403 }
404
405 public Address getSenderSP() { return addressOfStackSlot(SENDER_SP_OFFSET); }
406
407 public Address compiledArgumentToLocationPD(VMReg reg, RegisterMap regMap, int argSize) {
408 if (VM.getVM().isCore() || VM.getVM().isClientCompiler()) {
409 throw new RuntimeException("Should not reach here");
410 }
411
412 return oopMapRegToLocation(reg, regMap);
413 }
414
415 public Address addressOfInterpreterFrameLocals() {
416 return addressOfStackSlot(INTERPRETER_FRAME_LOCALS_OFFSET);
417 }
418
419 private Address addressOfInterpreterFrameBCX() {
420 return addressOfStackSlot(INTERPRETER_FRAME_BCX_OFFSET);
421 }
422
423 public int getInterpreterFrameBCI() {
424 // FIXME: this is not atomic with respect to GC and is unsuitable
425 // for use in a non-debugging, or reflective, system. Need to
426 // figure out how to express this.
427 Address bcp = addressOfInterpreterFrameBCX().getAddressAt(0);
428 OopHandle methodHandle = addressOfInterpreterFrameMethod().getOopHandleAt(0);
429 Method method = (Method) VM.getVM().getObjectHeap().newOop(methodHandle);
430 return (int) bcpToBci(bcp, method);
431 }
432
433 public Address addressOfInterpreterFrameMDX() {
434 return addressOfStackSlot(INTERPRETER_FRAME_MDX_OFFSET);
435 }
436
437 // FIXME
438 //inline int frame::interpreter_frame_monitor_size() {
439 // return BasicObjectLock::size();
440 //}
441
442 // expression stack
443 // (the max_stack arguments are used by the GC; see class FrameClosure)
444
445 public Address addressOfInterpreterFrameExpressionStack() {
446 Address monitorEnd = interpreterFrameMonitorEnd().address();
447 return monitorEnd.addOffsetTo(-1 * VM.getVM().getAddressSize());
448 }
449
450 public int getInterpreterFrameExpressionStackDirection() { return -1; }
451
452 // top of expression stack
453 public Address addressOfInterpreterFrameTOS() {
454 return getSP();
455 }
456
457 /** Expression stack from top down */
458 public Address addressOfInterpreterFrameTOSAt(int slot) {
459 return addressOfInterpreterFrameTOS().addOffsetTo(slot * VM.getVM().getAddressSize());
460 }
461
462 public Address getInterpreterFrameSenderSP() {
463 if (Assert.ASSERTS_ENABLED) {
464 Assert.that(isInterpretedFrame(), "interpreted frame expected");
465 }
466 return addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0);
467 }
468
469 // Monitors
470 public BasicObjectLock interpreterFrameMonitorBegin() {
471 return new BasicObjectLock(addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET));
472 }
473
474 public BasicObjectLock interpreterFrameMonitorEnd() {
475 Address result = addressOfStackSlot(INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET).getAddressAt(0);
476 if (Assert.ASSERTS_ENABLED) {
477 // make sure the pointer points inside the frame
478 Assert.that(AddressOps.gt(getFP(), result), "result must < than frame pointer");
479 Assert.that(AddressOps.lte(getSP(), result), "result must >= than stack pointer");
480 }
481 return new BasicObjectLock(result);
482 }
483
484 public int interpreterFrameMonitorSize() {
485 return BasicObjectLock.size();
486 }
487
488 // Method
489 public Address addressOfInterpreterFrameMethod() {
490 return addressOfStackSlot(INTERPRETER_FRAME_METHOD_OFFSET);
491 }
492
493 // Constant pool cache
494 public Address addressOfInterpreterFrameCPCache() {
495 return addressOfStackSlot(INTERPRETER_FRAME_CACHE_OFFSET);
496 }
497
498 // Entry frames
499 public JavaCallWrapper getEntryFrameCallWrapper() {
500 return new AMD64JavaCallWrapper(addressOfStackSlot(ENTRY_FRAME_CALL_WRAPPER_OFFSET).getAddressAt(0));
501 }
502
503 protected Address addressOfSavedOopResult() {
504 // offset is 2 for compiler2 and 3 for compiler1
505 return getSP().addOffsetTo((VM.getVM().isClientCompiler() ? 2 : 3) *
506 VM.getVM().getAddressSize());
507 }
508
509 protected Address addressOfSavedReceiver() {
510 return getSP().addOffsetTo(-4 * VM.getVM().getAddressSize());
511 }
512
513 private void dumpStack() {
514 if (getFP() != null) {
515 for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
516 AddressOps.lte(addr, getFP().addOffsetTo(5 * VM.getVM().getAddressSize()));
517 addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
518 System.out.println(addr + ": " + addr.getAddressAt(0));
519 }
520 } else {
521 for (Address addr = getSP().addOffsetTo(-5 * VM.getVM().getAddressSize());
522 AddressOps.lte(addr, getSP().addOffsetTo(20 * VM.getVM().getAddressSize()));
523 addr = addr.addOffsetTo(VM.getVM().getAddressSize())) {
524 System.out.println(addr + ": " + addr.getAddressAt(0));
525 }
526 }
527 }
528 }