src/cpu/x86/vm/frame_x86.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File 8068945-8u-patched Sdiff src/cpu/x86/vm

src/cpu/x86/vm/frame_x86.cpp

Print this page
rev 7386 : 8068945: Use RBP register as proper frame pointer in JIT compiled code on x86
Summary: Introduce the PreserveFramePointer flag to control if RBP is used as the frame pointer or as a general purpose register.
Reviewed-by: kvn, roland, dlong, enevill, shade


 199 
 200       if (!saved_fp_safe) {
 201         return false;
 202       }
 203 
 204       // construct the potential sender
 205 
 206       frame sender(sender_sp, saved_fp, sender_pc);
 207 
 208       // Validate the JavaCallWrapper an entry frame must have
 209       address jcw = (address)sender.entry_frame_call_wrapper();
 210 
 211       bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > (address)sender.fp());
 212 
 213       return jcw_safe;
 214     }
 215 
 216     if (sender_blob->is_nmethod()) {
 217         nmethod* nm = sender_blob->as_nmethod_or_null();
 218         if (nm != NULL) {
 219             if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc)) {

 220                 return false;
 221             }
 222         }
 223     }
 224 
 225     // If the frame size is 0 something (or less) is bad because every nmethod has a non-zero frame size
 226     // because the return address counts against the callee's frame.
 227 
 228     if (sender_blob->frame_size() <= 0) {
 229       assert(!sender_blob->is_nmethod(), "should count return address at least");
 230       return false;
 231     }
 232 
 233     // We should never be able to see anything here except an nmethod. If something in the
 234     // code cache (current frame) is called by an entity within the code cache that entity
 235     // should not be anything but the call stub (already covered), the interpreter (already covered)
 236     // or an nmethod.
 237 
 238     if (!sender_blob->is_nmethod()) {
 239         return false;


 366   assert(map != NULL, "map must be set");
 367   // Java frame called from C; skip all C frames and return top C
 368   // frame of that chunk as the sender
 369   JavaFrameAnchor* jfa = entry_frame_call_wrapper()->anchor();
 370   assert(!entry_frame_is_first(), "next Java fp must be non zero");
 371   assert(jfa->last_Java_sp() > sp(), "must be above this frame on stack");
 372   map->clear();
 373   assert(map->include_argument_oops(), "should be set by clear");
 374   if (jfa->last_Java_pc() != NULL ) {
 375     frame fr(jfa->last_Java_sp(), jfa->last_Java_fp(), jfa->last_Java_pc());
 376     return fr;
 377   }
 378   frame fr(jfa->last_Java_sp(), jfa->last_Java_fp());
 379   return fr;
 380 }
 381 
 382 //------------------------------------------------------------------------------
 383 // frame::verify_deopt_original_pc
 384 //
 385 // Verifies the calculated original PC of a deoptimization PC for the
 386 // given unextended SP.  The unextended SP might also be the saved SP
 387 // for MethodHandle call sites.
 388 #ifdef ASSERT
 389 void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return) {
 390   frame fr;
 391 
 392   // This is ugly but it's better than to change {get,set}_original_pc
 393   // to take an SP value as argument.  And it's only a debugging
 394   // method anyway.
 395   fr._unextended_sp = unextended_sp;
 396 
 397   address original_pc = nm->get_original_pc(&fr);
 398   assert(nm->insts_contains(original_pc), "original PC must be in nmethod");
 399   assert(nm->is_method_handle_return(original_pc) == is_method_handle_return, "must be");
 400 }
 401 #endif
 402 
 403 //------------------------------------------------------------------------------
 404 // frame::adjust_unextended_sp
 405 void frame::adjust_unextended_sp() {
 406   // If we are returning to a compiled MethodHandle call site, the
 407   // saved_fp will in fact be a saved value of the unextended SP.  The
 408   // simplest way to tell whether we are returning to such a call site
 409   // is as follows:
 410 
 411   nmethod* sender_nm = (_cb == NULL) ? NULL : _cb->as_nmethod_or_null();
 412   if (sender_nm != NULL) {
 413     // If the sender PC is a deoptimization point, get the original
 414     // PC.  For MethodHandle call site the unextended_sp is stored in
 415     // saved_fp.
 416     if (sender_nm->is_deopt_mh_entry(_pc)) {
 417       DEBUG_ONLY(verify_deopt_mh_original_pc(sender_nm, _fp));
 418       _unextended_sp = _fp;
 419     }
 420     else if (sender_nm->is_deopt_entry(_pc)) {
 421       DEBUG_ONLY(verify_deopt_original_pc(sender_nm, _unextended_sp));
 422     }
 423     else if (sender_nm->is_method_handle_return(_pc)) {
 424       _unextended_sp = _fp;
 425     }
 426   }
 427 }
 428 
 429 //------------------------------------------------------------------------------
 430 // frame::update_map_with_saved_link
 431 void frame::update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr) {
 432   // The interpreter and compiler(s) always save EBP/RBP in a known
 433   // location on entry. We must record where that location is
 434   // so this if EBP/RBP was live on callout from c2 we can find
 435   // the saved copy no matter what it called.
 436 
 437   // Since the interpreter always saves EBP/RBP if we record where it is then
 438   // we don't have to always save EBP/RBP on entry and exit to c2 compiled
 439   // code, on entry will be enough.
 440   map->set_location(rbp->as_VMReg(), (address) link_addr);
 441 #ifdef AMD64
 442   // this is weird "H" ought to be at a higher address however the
 443   // oopMaps seems to have the "H" regs at the same address and the
 444   // vanilla register.




 199 
 200       if (!saved_fp_safe) {
 201         return false;
 202       }
 203 
 204       // construct the potential sender
 205 
 206       frame sender(sender_sp, saved_fp, sender_pc);
 207 
 208       // Validate the JavaCallWrapper an entry frame must have
 209       address jcw = (address)sender.entry_frame_call_wrapper();
 210 
 211       bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > (address)sender.fp());
 212 
 213       return jcw_safe;
 214     }
 215 
 216     if (sender_blob->is_nmethod()) {
 217         nmethod* nm = sender_blob->as_nmethod_or_null();
 218         if (nm != NULL) {
 219             if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) ||
 220                 nm->method()->is_method_handle_intrinsic()) {
 221                 return false;
 222             }
 223         }
 224     }
 225 
 226     // If the frame size is 0 something (or less) is bad because every nmethod has a non-zero frame size
 227     // because the return address counts against the callee's frame.
 228 
 229     if (sender_blob->frame_size() <= 0) {
 230       assert(!sender_blob->is_nmethod(), "should count return address at least");
 231       return false;
 232     }
 233 
 234     // We should never be able to see anything here except an nmethod. If something in the
 235     // code cache (current frame) is called by an entity within the code cache that entity
 236     // should not be anything but the call stub (already covered), the interpreter (already covered)
 237     // or an nmethod.
 238 
 239     if (!sender_blob->is_nmethod()) {
 240         return false;


 367   assert(map != NULL, "map must be set");
 368   // Java frame called from C; skip all C frames and return top C
 369   // frame of that chunk as the sender
 370   JavaFrameAnchor* jfa = entry_frame_call_wrapper()->anchor();
 371   assert(!entry_frame_is_first(), "next Java fp must be non zero");
 372   assert(jfa->last_Java_sp() > sp(), "must be above this frame on stack");
 373   map->clear();
 374   assert(map->include_argument_oops(), "should be set by clear");
 375   if (jfa->last_Java_pc() != NULL ) {
 376     frame fr(jfa->last_Java_sp(), jfa->last_Java_fp(), jfa->last_Java_pc());
 377     return fr;
 378   }
 379   frame fr(jfa->last_Java_sp(), jfa->last_Java_fp());
 380   return fr;
 381 }
 382 
 383 //------------------------------------------------------------------------------
 384 // frame::verify_deopt_original_pc
 385 //
 386 // Verifies the calculated original PC of a deoptimization PC for the
 387 // given unextended SP.

 388 #ifdef ASSERT
 389 void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp) {
 390   frame fr;
 391 
 392   // This is ugly but it's better than to change {get,set}_original_pc
 393   // to take an SP value as argument.  And it's only a debugging
 394   // method anyway.
 395   fr._unextended_sp = unextended_sp;
 396 
 397   address original_pc = nm->get_original_pc(&fr);
 398   assert(nm->insts_contains(original_pc), "original PC must be in nmethod");

 399 }
 400 #endif
 401 
 402 //------------------------------------------------------------------------------
 403 // frame::adjust_unextended_sp
 404 void frame::adjust_unextended_sp() {
 405   // On x86, sites calling method handle intrinsics and lambda forms are treated
 406   // as any other call site. Therefore, no special action is needed when we are
 407   // returning to any of these call sites.

 408 
 409   nmethod* sender_nm = (_cb == NULL) ? NULL : _cb->as_nmethod_or_null();
 410   if (sender_nm != NULL) {
 411     // If the sender PC is a deoptimization point, get the original PC.
 412     if (sender_nm->is_deopt_entry(_pc) ||
 413         sender_nm->is_deopt_mh_entry(_pc)) {





 414       DEBUG_ONLY(verify_deopt_original_pc(sender_nm, _unextended_sp));



 415     }
 416   }
 417 }
 418 
 419 //------------------------------------------------------------------------------
 420 // frame::update_map_with_saved_link
 421 void frame::update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr) {
 422   // The interpreter and compiler(s) always save EBP/RBP in a known
 423   // location on entry. We must record where that location is
 424   // so this if EBP/RBP was live on callout from c2 we can find
 425   // the saved copy no matter what it called.
 426 
 427   // Since the interpreter always saves EBP/RBP if we record where it is then
 428   // we don't have to always save EBP/RBP on entry and exit to c2 compiled
 429   // code, on entry will be enough.
 430   map->set_location(rbp->as_VMReg(), (address) link_addr);
 431 #ifdef AMD64
 432   // this is weird "H" ought to be at a higher address however the
 433   // oopMaps seems to have the "H" regs at the same address and the
 434   // vanilla register.


src/cpu/x86/vm/frame_x86.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File