< prev index next >

src/hotspot/cpu/x86/frame_x86.cpp

Print this page
*** 29,10 ***
--- 29,11 ---
  #include "memory/universe.hpp"
  #include "oops/markWord.hpp"
  #include "oops/method.hpp"
  #include "oops/oop.inline.hpp"
  #include "prims/methodHandles.hpp"
+ #include "runtime/continuation.hpp"
  #include "runtime/frame.inline.hpp"
  #include "runtime/handles.inline.hpp"
  #include "runtime/javaCalls.hpp"
  #include "runtime/monitorChunk.hpp"
  #include "runtime/signature.hpp"

*** 144,10 ***
--- 145,13 ---
        sender_pc = (address) *(sender_sp-1);
        // Note: frame::sender_sp_offset is only valid for compiled frame
        saved_fp = (intptr_t*) *(sender_sp - frame::sender_sp_offset);
      }
  
+     if (Continuation::is_return_barrier_entry(sender_pc)) {	
+       Continuation::fix_continuation_bottom_sender(thread, *this, &sender_pc, &sender_sp);	
+     }
  
      // If the potential sender is the interpreter then we can do some more checking
      if (Interpreter::contains(sender_pc)) {
  
        // ebp is always saved in a recognizable place in any code we generate. However

*** 259,36 ***
  
  
  void frame::patch_pc(Thread* thread, address pc) {
    assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
    address* pc_addr = &(((address*) sp())[-1]);
    if (TracePcPatching) {
      tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]",
                    p2i(pc_addr), p2i(*pc_addr), p2i(pc));
    }
    // Either the return address is the original one or we are going to
    // patch in the same address that's already there.
!   assert(_pc == *pc_addr || pc == *pc_addr, "must be");
    *pc_addr = pc;
    address original_pc = CompiledMethod::get_deopt_original_pc(this);
    if (original_pc != NULL) {
!     assert(original_pc == _pc, "expected original PC to be stored before patching");
      _deopt_state = is_deoptimized;
!     // leave _pc as is
    } else {
      _deopt_state = not_deoptimized;
-     _pc = pc;
    }
! }
  
! bool frame::is_interpreted_frame() const  {
!   return Interpreter::contains(pc());
! }
! 
! int frame::frame_size(RegisterMap* map) const {
!   frame sender = this->sender(map);
!   return sender.sp() - sp();
  }
  
  intptr_t* frame::entry_frame_argument_at(int offset) const {
    // convert offset to index to deal with tsi
    int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
--- 263,43 ---
  
  
  void frame::patch_pc(Thread* thread, address pc) {
    assert(_cb == CodeCache::find_blob(pc), "unexpected pc");
    address* pc_addr = &(((address*) sp())[-1]);
+ 
    if (TracePcPatching) {
      tty->print_cr("patch_pc at address " INTPTR_FORMAT " [" INTPTR_FORMAT " -> " INTPTR_FORMAT "]",
                    p2i(pc_addr), p2i(*pc_addr), p2i(pc));
    }
    // Either the return address is the original one or we are going to
    // patch in the same address that's already there.
! 
+   assert(!Continuation::is_return_barrier_entry(*pc_addr), "return barrier");
+ 
+   assert(_pc == *pc_addr || pc == *pc_addr || *pc_addr == 0, "must be (pc: " INTPTR_FORMAT " _pc: " INTPTR_FORMAT " pc_addr: " INTPTR_FORMAT " *pc_addr: " INTPTR_FORMAT  " sp: " INTPTR_FORMAT ")", p2i(pc), p2i(_pc), p2i(pc_addr), p2i(*pc_addr), p2i(sp()));
+   DEBUG_ONLY(address old_pc = _pc;)
    *pc_addr = pc;
+   _pc = pc; // must be set before call to get_deopt_original_pc
    address original_pc = CompiledMethod::get_deopt_original_pc(this);
    if (original_pc != NULL) {
!     assert(original_pc == old_pc, "expected original PC to be stored before patching");
      _deopt_state = is_deoptimized;
!     _pc = original_pc;
    } else {
      _deopt_state = not_deoptimized;
    }
!   assert (!is_compiled_frame() || !_cb->as_compiled_method()->is_deopt_entry(_pc), "must be");
  
! #ifdef ASSERT
!   {
!     frame f(this->sp(), this->unextended_sp(), this->fp(), pc);
!     assert(f.is_deoptimized_frame() == this->is_deoptimized_frame() && f.pc() == this->pc() && f.raw_pc() == this->raw_pc(), 
!       "must be (f.is_deoptimized_frame(): %d this->is_deoptimized_frame(): %d "
!       "f.pc(): " INTPTR_FORMAT " this->pc(): " INTPTR_FORMAT " f.raw_pc(): " INTPTR_FORMAT " this->raw_pc(): " INTPTR_FORMAT ")", 
!       f.is_deoptimized_frame(), this->is_deoptimized_frame(), p2i(f.pc()), p2i(this->pc()), p2i(f.raw_pc()), p2i(this->raw_pc()));
+   }
+ #endif
  }
  
  intptr_t* frame::entry_frame_argument_at(int offset) const {
    // convert offset to index to deal with tsi
    int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);

*** 313,15 ***
  
  BasicObjectLock* frame::interpreter_frame_monitor_begin() const {
    return (BasicObjectLock*) addr_at(interpreter_frame_monitor_block_bottom_offset);
  }
  
  BasicObjectLock* frame::interpreter_frame_monitor_end() const {
!   BasicObjectLock* result = (BasicObjectLock*) *addr_at(interpreter_frame_monitor_block_top_offset);
    // make sure the pointer points inside the frame
    assert(sp() <= (intptr_t*) result, "monitor end should be above the stack pointer");
!   assert((intptr_t*) result < fp(),  "monitor end should be strictly below the frame pointer");
    return result;
  }
  
  void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
    *((BasicObjectLock**)addr_at(interpreter_frame_monitor_block_top_offset)) = value;
--- 324,19 ---
  
  BasicObjectLock* frame::interpreter_frame_monitor_begin() const {
    return (BasicObjectLock*) addr_at(interpreter_frame_monitor_block_bottom_offset);
  }
  
+ template BasicObjectLock* frame::interpreter_frame_monitor_end<true>() const;
+ template BasicObjectLock* frame::interpreter_frame_monitor_end<false>() const;
+ 
+ template <bool relative>
  BasicObjectLock* frame::interpreter_frame_monitor_end() const {
!   BasicObjectLock* result = (BasicObjectLock*) at<relative>(interpreter_frame_monitor_block_top_offset);
    // make sure the pointer points inside the frame
    assert(sp() <= (intptr_t*) result, "monitor end should be above the stack pointer");
!   assert((intptr_t*) result < fp(),  "monitor end should be strictly below the frame pointer: result: " INTPTR_FORMAT " fp: " INTPTR_FORMAT, p2i(result), p2i(fp()));
    return result;
  }
  
  void frame::interpreter_frame_set_monitor_end(BasicObjectLock* value) {
    *((BasicObjectLock**)addr_at(interpreter_frame_monitor_block_top_offset)) = value;

*** 403,11 ***
    // method anyway.
    fr._unextended_sp = unextended_sp;
  
    address original_pc = nm->get_original_pc(&fr);
    assert(nm->insts_contains_inclusive(original_pc),
!          "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
  }
  #endif
  
  //------------------------------------------------------------------------------
  // frame::adjust_unextended_sp
--- 418,11 ---
    // method anyway.
    fr._unextended_sp = unextended_sp;
  
    address original_pc = nm->get_original_pc(&fr);
    assert(nm->insts_contains_inclusive(original_pc),
!          "original PC must be in the main code section of the the compiled method (or must be immediately following it) original_pc: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " name: %s", p2i(original_pc), p2i(unextended_sp), nm->name());
  }
  #endif
  
  //------------------------------------------------------------------------------
  // frame::adjust_unextended_sp

*** 428,115 ***
      }
    }
  }
  #endif
  
- //------------------------------------------------------------------------------
- // frame::update_map_with_saved_link
- void frame::update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr) {
-   // The interpreter and compiler(s) always save EBP/RBP in a known
-   // location on entry. We must record where that location is
-   // so this if EBP/RBP was live on callout from c2 we can find
-   // the saved copy no matter what it called.
- 
-   // Since the interpreter always saves EBP/RBP if we record where it is then
-   // we don't have to always save EBP/RBP on entry and exit to c2 compiled
-   // code, on entry will be enough.
-   map->set_location(rbp->as_VMReg(), (address) link_addr);
- #ifdef AMD64
-   // this is weird "H" ought to be at a higher address however the
-   // oopMaps seems to have the "H" regs at the same address and the
-   // vanilla register.
-   // XXXX make this go away
-   if (true) {
-     map->set_location(rbp->as_VMReg()->next(), (address) link_addr);
-   }
- #endif // AMD64
- }
- 
- 
  //------------------------------------------------------------------------------
  // frame::sender_for_interpreter_frame
  frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
    // SP is the raw SP from the sender after adapter or interpreter
    // extension.
    intptr_t* sender_sp = this->sender_sp();
  
    // This is the sp before any possible extension (adapter/locals).
    intptr_t* unextended_sp = interpreter_frame_sender_sp();
  
  #if COMPILER2_OR_JVMCI
    if (map->update_map()) {
      update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset));
    }
  #endif // COMPILER2_OR_JVMCI
  
!   return frame(sender_sp, unextended_sp, link(), sender_pc());
- }
- 
- 
- //------------------------------------------------------------------------------
- // frame::sender_for_compiled_frame
- frame frame::sender_for_compiled_frame(RegisterMap* map) const {
-   assert(map != NULL, "map must be set");
- 
-   // frame owned by optimizing compiler
-   assert(_cb->frame_size() >= 0, "must have non-zero frame size");
-   intptr_t* sender_sp = unextended_sp() + _cb->frame_size();
-   intptr_t* unextended_sp = sender_sp;
- 
-   // On Intel the return_address is always the word on the stack
-   address sender_pc = (address) *(sender_sp-1);
  
!   // This is the saved value of EBP which may or may not really be an FP.
!   // It is only an FP if the sender is an interpreter frame (or C1?).
!   intptr_t** saved_fp_addr = (intptr_t**) (sender_sp - frame::sender_sp_offset);
! 
!   if (map->update_map()) {
-     // Tell GC to use argument oopmaps for some runtime stubs that need it.
-     // For C1, the runtime stub might not have oop maps, so set this flag
-     // outside of update_register_map.
-     map->set_include_argument_oops(_cb->caller_must_gc_arguments(map->thread()));
-     if (_cb->oop_maps() != NULL) {
-       OopMapSet::update_register_map(this, map);
      }
- 
-     // Since the prolog does the save and restore of EBP there is no oopmap
-     // for it so we must fill in its location as if there was an oopmap entry
-     // since if our caller was compiled code there could be live jvm state in it.
-     update_map_with_saved_link(map, saved_fp_addr);
    }
  
!   assert(sender_sp != sp(), "must have changed");
-   return frame(sender_sp, unextended_sp, *saved_fp_addr, sender_pc);
  }
  
  
  //------------------------------------------------------------------------------
! // frame::sender_raw
- frame frame::sender_raw(RegisterMap* map) const {
-   // Default is we done have to follow them. The sender_for_xxx will
-   // update it accordingly
-   map->set_include_argument_oops(false);
- 
-   if (is_entry_frame())        return sender_for_entry_frame(map);
-   if (is_optimized_entry_frame()) return sender_for_optimized_entry_frame(map);
-   if (is_interpreted_frame())  return sender_for_interpreter_frame(map);
-   assert(_cb == CodeCache::find_blob(pc()),"Must be the same");
- 
-   if (_cb != NULL) {
-     return sender_for_compiled_frame(map);
-   }
-   // Must be native-compiled frame, i.e. the marshaling code for native
-   // methods that exists in the core system.
-   return frame(sender_sp(), link(), sender_pc());
- }
  
  frame frame::sender(RegisterMap* map) const {
    frame result = sender_raw(map);
  
!   if (map->process_frames()) {
      StackWatermarkSet::on_iteration(map->thread(), result);
    }
  
    return result;
  }
--- 443,48 ---
      }
    }
  }
  #endif
  
  //------------------------------------------------------------------------------
  // frame::sender_for_interpreter_frame
  frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
    // SP is the raw SP from the sender after adapter or interpreter
    // extension.
    intptr_t* sender_sp = this->sender_sp();
  
    // This is the sp before any possible extension (adapter/locals).
    intptr_t* unextended_sp = interpreter_frame_sender_sp();
+   intptr_t* sender_fp = link();
  
  #if COMPILER2_OR_JVMCI
    if (map->update_map()) {
      update_map_with_saved_link(map, (intptr_t**) addr_at(link_offset));
    }
  #endif // COMPILER2_OR_JVMCI
  
!   address sender_pc = this->sender_pc();
  
!   if (Continuation::is_return_barrier_entry(sender_pc)) {
!     if (map->walk_cont()) { // about to walk into an h-stack	
!       return Continuation::top_frame(*this, map);	
!     } else {
!       Continuation::fix_continuation_bottom_sender(map->thread(), *this, &sender_pc, &unextended_sp);
      }
    }
  
!   return frame(sender_sp, unextended_sp, sender_fp, sender_pc);
  }
  
  
  //------------------------------------------------------------------------------
! // frame::sender
  
  frame frame::sender(RegisterMap* map) const {
    frame result = sender_raw(map);
  
!   if (map->process_frames() && !map->in_cont()) {
      StackWatermarkSet::on_iteration(map->thread(), result);
    }
  
    return result;
  }

*** 657,20 ***
    }
  
    return type;
  }
  
  
  intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
    int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
!   return &interpreter_frame_tos_address()[index];
  }
  
  #ifndef PRODUCT
  
  #define DESCRIBE_FP_OFFSET(name) \
!   values.describe(frame_no, fp() + frame::name##_offset, #name)
  
  void frame::describe_pd(FrameValues& values, int frame_no) {
    if (is_interpreted_frame()) {
      DESCRIBE_FP_OFFSET(interpreter_frame_sender_sp);
      DESCRIBE_FP_OFFSET(interpreter_frame_last_sp);
--- 605,23 ---
    }
  
    return type;
  }
  
+ template intptr_t* frame::interpreter_frame_tos_at<false>(jint offset) const;
+ template intptr_t* frame::interpreter_frame_tos_at<true >(jint offset) const;
  
+ template <bool relative>
  intptr_t* frame::interpreter_frame_tos_at(jint offset) const {
    int index = (Interpreter::expr_offset_in_bytes(offset)/wordSize);
!   return &interpreter_frame_tos_address<relative>()[index];
  }
  
  #ifndef PRODUCT
  
  #define DESCRIBE_FP_OFFSET(name) \
!   values.describe(frame_no, fp() + frame::name##_offset, #name, 1)
  
  void frame::describe_pd(FrameValues& values, int frame_no) {
    if (is_interpreted_frame()) {
      DESCRIBE_FP_OFFSET(interpreter_frame_sender_sp);
      DESCRIBE_FP_OFFSET(interpreter_frame_last_sp);

*** 689,31 ***
      for (int i = 0; i < entry_frame_after_call_words; i++) {
        values.describe(frame_no, fp() - i, err_msg("call_stub word fp - %d", i));
      }
  #endif // AMD64
    }
  }
  #endif // !PRODUCT
  
  intptr_t *frame::initial_deoptimization_info() {
    // used to reset the saved FP
    return fp();
  }
  
- intptr_t* frame::real_fp() const {
-   if (_cb != NULL) {
-     // use the frame size if valid
-     int size = _cb->frame_size();
-     if (size > 0) {
-       return unextended_sp() + size;
-     }
-   }
-   // else rely on fp()
-   assert(! is_compiled_frame(), "unknown compiled frame size");
-   return fp();
- }
- 
  #ifndef PRODUCT
  // This is a generic constructor which is only used by pns() in debug.cpp.
  frame::frame(void* sp, void* fp, void* pc) {
    init((intptr_t*)sp, (intptr_t*)fp, (address)pc);
  }
--- 640,30 ---
      for (int i = 0; i < entry_frame_after_call_words; i++) {
        values.describe(frame_no, fp() - i, err_msg("call_stub word fp - %d", i));
      }
  #endif // AMD64
    }
+ 
+   if (is_java_frame()) {
+     address ret_pc = *(address*)(real_fp() - return_addr_offset);
+     values.describe(frame_no, real_fp() - return_addr_offset, Continuation::is_return_barrier_entry(ret_pc) ? "return address (return barrier)" : "return address");
+     values.describe(-1, real_fp() - sender_sp_offset, "saved fp", 2);
+   }
+ }
+ 
+ void frame::describe_top_pd(FrameValues& values) {
+   address ret_pc_callee = *(address*)(sp() - return_addr_offset);
+   values.describe(-1, sp() - return_addr_offset, Continuation::is_return_barrier_entry(ret_pc_callee) ? "return address (return barrier)" : "return address");
+   values.describe(-1, sp() - sender_sp_offset, "saved fp", 2);
  }
  #endif // !PRODUCT
  
  intptr_t *frame::initial_deoptimization_info() {
    // used to reset the saved FP
    return fp();
  }
  
  #ifndef PRODUCT
  // This is a generic constructor which is only used by pns() in debug.cpp.
  frame::frame(void* sp, void* fp, void* pc) {
    init((intptr_t*)sp, (intptr_t*)fp, (address)pc);
  }
< prev index next >