60 private static int INTERPRETER_FRAME_INITIAL_SP_OFFSET; |
59 private static int INTERPRETER_FRAME_INITIAL_SP_OFFSET; |
61 private static int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET; |
60 private static int INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET; |
62 private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET; |
61 private static int INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET; |
63 |
62 |
64 // Entry frames |
63 // Entry frames |
65 private static final int ENTRY_FRAME_CALL_WRAPPER_OFFSET = 2; |
64 private static int ENTRY_FRAME_CALL_WRAPPER_OFFSET; |
66 |
65 |
67 // Native frames |
66 // Native frames |
68 private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2; |
67 private static final int NATIVE_FRAME_INITIAL_PARAM_OFFSET = 2; |
|
68 |
|
69 private static VMReg rbp; |
69 |
70 |
70 static { |
71 static { |
71 VM.registerVMInitializedObserver(new Observer() { |
72 VM.registerVMInitializedObserver(new Observer() { |
72 public void update(Observable o, Object data) { |
73 public void update(Observable o, Object data) { |
73 initialize(VM.getVM().getTypeDataBase()); |
74 initialize(VM.getVM().getTypeDataBase()); |
74 } |
75 } |
75 }); |
76 }); |
76 } |
77 } |
77 |
78 |
78 private static synchronized void initialize(TypeDataBase db) { |
79 private static synchronized void initialize(TypeDataBase db) { |
79 if (VM.getVM().isCore()) { |
80 INTERPRETER_FRAME_MDX_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; |
80 INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_METHOD_OFFSET - 1; |
81 INTERPRETER_FRAME_CACHE_OFFSET = INTERPRETER_FRAME_MDX_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; |
82 INTERPRETER_FRAME_LOCALS_OFFSET = INTERPRETER_FRAME_CACHE_OFFSET - 1; |
86 INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1; |
83 INTERPRETER_FRAME_BCX_OFFSET = INTERPRETER_FRAME_LOCALS_OFFSET - 1; |
87 INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; |
84 INTERPRETER_FRAME_INITIAL_SP_OFFSET = INTERPRETER_FRAME_BCX_OFFSET - 1; |
88 INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; |
85 INTERPRETER_FRAME_MONITOR_BLOCK_TOP_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; |
89 INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; |
86 INTERPRETER_FRAME_MONITOR_BLOCK_BOTTOM_OFFSET = INTERPRETER_FRAME_INITIAL_SP_OFFSET; |
90 } |
87 |
|
88 ENTRY_FRAME_CALL_WRAPPER_OFFSET = db.lookupIntConstant("frame::entry_frame_call_wrapper_offset"); |
|
89 if (VM.getVM().getAddressSize() == 4) { |
|
90 rbp = new VMReg(5); |
|
91 } else { |
|
92 rbp = new VMReg(5 << 1); |
|
93 } |
|
94 } |
|
95 |
91 |
96 |
92 // an additional field beyond sp and pc: |
97 // an additional field beyond sp and pc: |
93 Address raw_fp; // frame pointer |
98 Address raw_fp; // frame pointer |
94 private Address raw_unextendedSP; |
99 private Address raw_unextendedSP; |
95 |
100 |
132 public X86Frame(Address raw_sp, Address raw_fp) { |
138 public X86Frame(Address raw_sp, Address raw_fp) { |
133 this.raw_sp = raw_sp; |
139 this.raw_sp = raw_sp; |
134 this.raw_unextendedSP = raw_sp; |
140 this.raw_unextendedSP = raw_sp; |
135 this.raw_fp = raw_fp; |
141 this.raw_fp = raw_fp; |
136 this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); |
142 this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); |
|
143 adjustUnextendedSP(); |
137 |
144 |
138 // Frame must be fully constructed before this call |
145 // Frame must be fully constructed before this call |
139 adjustForDeopt(); |
146 adjustForDeopt(); |
140 |
147 |
141 if (DEBUG) { |
148 if (DEBUG) { |
142 System.out.println("X86Frame(sp, fp): " + this); |
149 System.out.println("X86Frame(sp, fp): " + this); |
143 dumpStack(); |
150 dumpStack(); |
144 } |
151 } |
145 } |
152 } |
146 |
153 |
147 // This constructor should really take the unextended SP as an arg |
154 public X86Frame(Address raw_sp, Address raw_unextendedSp, Address raw_fp, Address pc) { |
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; |
155 this.raw_sp = raw_sp; |
152 if (raw_sp == null) { |
156 this.raw_unextendedSP = raw_unextendedSp; |
153 this.raw_unextendedSP = null; |
|
154 } else { |
|
155 this.raw_unextendedSP = raw_sp.addOffsetTo(extension); |
|
156 } |
|
157 this.raw_fp = raw_fp; |
157 this.raw_fp = raw_fp; |
158 this.pc = raw_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); |
158 this.pc = pc; |
|
159 adjustUnextendedSP(); |
159 |
160 |
160 // Frame must be fully constructed before this call |
161 // Frame must be fully constructed before this call |
161 adjustForDeopt(); |
162 adjustForDeopt(); |
162 |
163 |
163 if (DEBUG) { |
164 if (DEBUG) { |
164 System.out.println("X86Frame(sp, fp): " + this); |
165 System.out.println("X86Frame(sp, unextendedSP, fp, pc): " + this); |
165 dumpStack(); |
166 dumpStack(); |
166 } |
167 } |
167 |
168 |
168 } |
169 } |
169 |
170 |
170 public Object clone() { |
171 public Object clone() { |
171 X86Frame frame = new X86Frame(); |
172 X86Frame frame = new X86Frame(); |
172 frame.raw_sp = raw_sp; |
173 frame.raw_sp = raw_sp; |
173 frame.raw_unextendedSP = raw_unextendedSP; |
174 frame.raw_unextendedSP = raw_unextendedSP; |
174 frame.raw_fp = raw_fp; |
175 frame.raw_fp = raw_fp; |
175 frame.raw_fp = raw_fp; |
|
176 frame.pc = pc; |
176 frame.pc = pc; |
177 frame.deoptimized = deoptimized; |
177 frame.deoptimized = deoptimized; |
178 return frame; |
178 return frame; |
179 } |
179 } |
180 |
180 |
267 // update it accordingly |
267 // update it accordingly |
268 map.setIncludeArgumentOops(false); |
268 map.setIncludeArgumentOops(false); |
269 |
269 |
270 if (isEntryFrame()) return senderForEntryFrame(map); |
270 if (isEntryFrame()) return senderForEntryFrame(map); |
271 if (isInterpretedFrame()) return senderForInterpreterFrame(map); |
271 if (isInterpretedFrame()) return senderForInterpreterFrame(map); |
272 |
272 if (isRicochetFrame()) return senderForRicochetFrame(map); |
273 if (!VM.getVM().isCore()) { |
273 |
274 if(cb == null) { |
274 if(cb == null) { |
275 cb = VM.getVM().getCodeCache().findBlob(getPC()); |
275 cb = VM.getVM().getCodeCache().findBlob(getPC()); |
276 } else { |
276 } else { |
277 if (Assert.ASSERTS_ENABLED) { |
277 if (Assert.ASSERTS_ENABLED) { |
278 Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); |
278 Assert.that(cb.equals(VM.getVM().getCodeCache().findBlob(getPC())), "Must be the same"); |
279 } |
279 } |
280 } |
280 } |
281 |
281 |
282 if (cb != null) { |
282 if (cb != null) { |
283 return senderForCompiledFrame(map, cb); |
283 return senderForCompiledFrame(map, cb); |
284 } |
|
285 } |
284 } |
286 |
285 |
287 // Must be native-compiled frame, i.e. the marshaling code for native |
286 // Must be native-compiled frame, i.e. the marshaling code for native |
288 // methods that exists in the core system. |
287 // methods that exists in the core system. |
289 return new X86Frame(getSenderSP(), getLink(), getSenderPC()); |
288 return new X86Frame(getSenderSP(), getLink(), getSenderPC()); |
290 } |
289 } |
291 |
290 |
|
291 private Frame senderForRicochetFrame(X86RegisterMap map) { |
|
292 if (DEBUG) { |
|
293 System.out.println("senderForRicochetFrame"); |
|
294 } |
|
295 X86RicochetFrame f = X86RicochetFrame.fromFrame(this); |
|
296 if (map.getUpdateMap()) |
|
297 updateMapWithSavedLink(map, f.senderLinkAddress()); |
|
298 return new X86Frame(f.extendedSenderSP(), f.exactSenderSP(), f.senderLink(), f.senderPC()); |
|
299 } |
|
300 |
292 private Frame senderForEntryFrame(X86RegisterMap map) { |
301 private Frame senderForEntryFrame(X86RegisterMap map) { |
|
302 if (DEBUG) { |
|
303 System.out.println("senderForEntryFrame"); |
|
304 } |
293 if (Assert.ASSERTS_ENABLED) { |
305 if (Assert.ASSERTS_ENABLED) { |
294 Assert.that(map != null, "map must be set"); |
306 Assert.that(map != null, "map must be set"); |
295 } |
307 } |
296 // Java frame called from C; skip all C frames and return top C |
308 // Java frame called from C; skip all C frames and return top C |
297 // frame of that chunk as the sender |
309 // frame of that chunk as the sender |
311 Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); |
323 Assert.that(map.getIncludeArgumentOops(), "should be set by clear"); |
312 } |
324 } |
313 return fr; |
325 return fr; |
314 } |
326 } |
315 |
327 |
|
328 //------------------------------------------------------------------------------ |
|
329 // frame::adjust_unextended_sp |
|
330 private void adjustUnextendedSP() { |
|
331 // If we are returning to a compiled MethodHandle call site, the |
|
332 // saved_fp will in fact be a saved value of the unextended SP. The |
|
333 // simplest way to tell whether we are returning to such a call site |
|
334 // is as follows: |
|
335 |
|
336 CodeBlob cb = cb(); |
|
337 NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull(); |
|
338 if (senderNm != null) { |
|
339 // If the sender PC is a deoptimization point, get the original |
|
340 // PC. For MethodHandle call site the unextended_sp is stored in |
|
341 // saved_fp. |
|
342 if (senderNm.isDeoptMhEntry(getPC())) { |
|
343 // DEBUG_ONLY(verifyDeoptMhOriginalPc(senderNm, getFP())); |
|
344 raw_unextendedSP = getFP(); |
|
345 } |
|
346 else if (senderNm.isDeoptEntry(getPC())) { |
|
347 // DEBUG_ONLY(verifyDeoptOriginalPc(senderNm, raw_unextendedSp)); |
|
348 } |
|
349 else if (senderNm.isMethodHandleReturn(getPC())) { |
|
350 raw_unextendedSP = getFP(); |
|
351 } |
|
352 } |
|
353 } |
|
354 |
316 private Frame senderForInterpreterFrame(X86RegisterMap map) { |
355 private Frame senderForInterpreterFrame(X86RegisterMap map) { |
|
356 if (DEBUG) { |
|
357 System.out.println("senderForInterpreterFrame"); |
|
358 } |
317 Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); |
359 Address unextendedSP = addressOfStackSlot(INTERPRETER_FRAME_SENDER_SP_OFFSET).getAddressAt(0); |
318 Address sp = addressOfStackSlot(SENDER_SP_OFFSET); |
360 Address sp = addressOfStackSlot(SENDER_SP_OFFSET); |
319 // We do not need to update the callee-save register mapping because above |
361 // 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 |
362 // us is either another interpreter frame or a converter-frame, but never |
321 // directly a compiled frame. |
363 // directly a compiled frame. |
322 // 11/24/04 SFG. With the removal of adapter frames this is no longer true. |
364 // 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 |
365 // However c2 no longer uses callee save register for java calls so there |
324 // are no callee register to find. |
366 // are no callee register to find. |
325 |
367 |
326 return new X86Frame(sp, getLink(), unextendedSP.minus(sp)); |
368 if (map.getUpdateMap()) |
|
369 updateMapWithSavedLink(map, addressOfStackSlot(LINK_OFFSET)); |
|
370 |
|
371 return new X86Frame(sp, unextendedSP, getLink(), getSenderPC()); |
|
372 } |
|
373 |
|
374 private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) { |
|
375 map.setLocation(rbp, savedFPAddr); |
327 } |
376 } |
328 |
377 |
329 private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) { |
378 private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) { |
|
379 if (DEBUG) { |
|
380 System.out.println("senderForCompiledFrame"); |
|
381 } |
|
382 |
330 // |
383 // |
331 // NOTE: some of this code is (unfortunately) duplicated in X86CurrentFrameGuess |
384 // NOTE: some of this code is (unfortunately) duplicated in X86CurrentFrameGuess |
332 // |
385 // |
333 |
386 |
334 if (Assert.ASSERTS_ENABLED) { |
387 if (Assert.ASSERTS_ENABLED) { |
335 Assert.that(map != null, "map must be set"); |
388 Assert.that(map != null, "map must be set"); |
336 } |
389 } |
337 |
390 |
338 // frame owned by optimizing compiler |
391 // frame owned by optimizing compiler |
339 Address sender_sp = null; |
392 if (Assert.ASSERTS_ENABLED) { |
340 |
393 Assert.that(cb.getFrameSize() >= 0, "must have non-zero frame size"); |
341 if (VM.getVM().isClientCompiler()) { |
394 } |
342 sender_sp = addressOfStackSlot(SENDER_SP_OFFSET); |
395 Address senderSP = getUnextendedSP().addOffsetTo(cb.getFrameSize()); |
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 |
396 |
350 // On Intel the return_address is always the word on the stack |
397 // On Intel the return_address is always the word on the stack |
351 Address sender_pc = sender_sp.getAddressAt(-1 * VM.getVM().getAddressSize()); |
398 Address senderPC = senderSP.getAddressAt(-1 * VM.getVM().getAddressSize()); |
352 |
399 |
353 if (map.getUpdateMap() && cb.getOopMaps() != null) { |
400 // This is the saved value of EBP which may or may not really be an FP. |
354 OopMapSet.updateRegisterMap(this, cb, map, true); |
401 // It is only an FP if the sender is an interpreter frame (or C1?). |
355 } |
402 Address savedFPAddr = senderSP.addOffsetTo(- SENDER_SP_OFFSET * VM.getVM().getAddressSize()); |
356 |
403 |
357 if (VM.getVM().isClientCompiler()) { |
404 if (map.getUpdateMap()) { |
358 // Move this here for C1 and collecting oops in arguments (According to Rene) |
405 // Tell GC to use argument oopmaps for some runtime stubs that need it. |
359 map.setIncludeArgumentOops(cb.callerMustGCArguments(map.getThread())); |
406 // For C1, the runtime stub might not have oop maps, so set this flag |
360 } |
407 // outside of update_register_map. |
361 |
408 map.setIncludeArgumentOops(cb.callerMustGCArguments()); |
362 Address saved_fp = null; |
409 |
363 if (VM.getVM().isClientCompiler()) { |
410 if (cb.getOopMaps() != null) { |
364 saved_fp = getFP().getAddressAt(0); |
411 OopMapSet.updateRegisterMap(this, cb, map, true); |
365 } else if (VM.getVM().isServerCompiler() && |
412 } |
366 (VM.getVM().getInterpreter().contains(sender_pc) || |
413 |
367 VM.getVM().getStubRoutines().returnsToCallStub(sender_pc))) { |
414 // Since the prolog does the save and restore of EBP there is no oopmap |
368 // C2 prologue saves EBP in the usual place. |
415 // for it so we must fill in its location as if there was an oopmap entry |
369 // however only use it if the sender had link infomration in it. |
416 // since if our caller was compiled code there could be live jvm state in it. |
370 saved_fp = sender_sp.getAddressAt(-2 * VM.getVM().getAddressSize()); |
417 updateMapWithSavedLink(map, savedFPAddr); |
371 } |
418 } |
372 |
419 |
373 return new X86Frame(sender_sp, saved_fp, sender_pc); |
420 return new X86Frame(senderSP, savedFPAddr.getAddressAt(0), senderPC); |
374 } |
421 } |
375 |
422 |
376 protected boolean hasSenderPD() { |
423 protected boolean hasSenderPD() { |
377 // FIXME |
424 // FIXME |
378 // Check for null ebp? Need to do some tests. |
425 // Check for null ebp? Need to do some tests. |