changeset 52081:a79d08d7b440 cont

imported patch excbarrier
author rpressler
date Thu, 18 Oct 2018 10:27:43 +0100
parents 01a6d46edf39
children f9ed3c3e6c19
files src/hotspot/cpu/x86/frame_x86.hpp src/hotspot/cpu/x86/frame_x86.inline.hpp src/hotspot/cpu/x86/stubGenerator_x86_64.cpp src/hotspot/share/aot/aotCompiledMethod.cpp src/hotspot/share/aot/aotCompiledMethod.hpp src/hotspot/share/code/compiledMethod.hpp src/hotspot/share/code/nmethod.cpp src/hotspot/share/code/nmethod.hpp src/hotspot/share/opto/library_call.cpp src/hotspot/share/runtime/continuation.cpp src/hotspot/share/runtime/continuation.hpp src/hotspot/share/runtime/sharedRuntime.cpp src/hotspot/share/runtime/stubRoutines.cpp src/hotspot/share/runtime/stubRoutines.hpp
diffstat 14 files changed, 107 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/cpu/x86/frame_x86.hpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/cpu/x86/frame_x86.hpp	Thu Oct 18 10:27:43 2018 +0100
@@ -139,6 +139,8 @@
 
   frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb);
 
+  frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb, bool deopt);
+
   frame(intptr_t* sp, intptr_t* fp);
 
   void init(intptr_t* sp, intptr_t* fp, address pc);
--- a/src/hotspot/cpu/x86/frame_x86.inline.hpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/cpu/x86/frame_x86.inline.hpp	Thu Oct 18 10:27:43 2018 +0100
@@ -73,6 +73,7 @@
   _pc = pc;
   assert(pc != NULL, "no pc?");
   _cb = cb;
+  _oop_map = NULL;
   setup(pc);
 }
 
@@ -83,28 +84,27 @@
   _pc = pc;
   assert(pc != NULL, "no pc?");
   _cb = CodeCache::find_blob(pc);
+  _oop_map = NULL;
   setup(pc);
 }
 
 inline void frame::setup(address pc) {
   adjust_unextended_sp();
 
+  assert(_cb != NULL, "");
   address original_pc = CompiledMethod::get_deopt_original_pc(this);
   if (original_pc != NULL) {
-    assert(_cb != NULL, "no cb 1 pc: " INTPTR_FORMAT " orig_pc: " INTPTR_FORMAT, p2i(pc), p2i(original_pc));
     _pc = original_pc;
     assert(_cb->as_compiled_method()->insts_contains_inclusive(_pc),
            "original PC must be in the main code section of the the compiled method (or must be immediately following it)");
     _deopt_state = is_deoptimized;
   } else {
-    assert(_cb != NULL, "no cb 2  sp: " INTPTR_FORMAT " usp: " INTPTR_FORMAT " fp: " INTPTR_FORMAT " pc: " INTPTR_FORMAT " orig_pc: " INTPTR_FORMAT, p2i(_sp), p2i(_unextended_sp), p2i(_fp), p2i(pc), p2i(original_pc));
     if (_cb->is_deoptimization_stub()) {
       _deopt_state = is_deoptimized;
     } else {
       _deopt_state = not_deoptimized;
     }
   }
-  _oop_map = NULL;
 }
 
 inline frame::frame(intptr_t* sp, intptr_t* fp) {
@@ -137,6 +137,16 @@
   }
 }
 
+inline frame::frame(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, address pc, CodeBlob* cb, bool deopt) {
+  _sp = sp;
+  _unextended_sp = unextended_sp;
+  _fp = fp;
+  _pc = pc;
+  assert(pc != NULL, "no pc?");
+  _cb = cb;
+  _deopt_state = deopt ? is_deoptimized : not_deoptimized;
+}
+
 // Accessors
 
 inline bool frame::equal(frame other) const {
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp	Thu Oct 18 10:27:43 2018 +0100
@@ -5633,7 +5633,7 @@
     return start;
   }
 
-  address generate_cont_thaw(bool return_barrier) {
+  address generate_cont_thaw(bool return_barrier, bool exception) {
     address start = __ pc();
 
     // TODO: Handle Valhalla return types. May require generating different return barriers.
@@ -5650,9 +5650,9 @@
     if (return_barrier) {
       __ push(rax); __ push_d(xmm0); // preserve possible return value from a method returning to the return barrier
     }
-    __ movl(c_rarg2, return_barrier);
+    __ movl(c_rarg1, return_barrier);
     push_FrameInfo(_masm, fi, fi, rbp, c_rarg3);
-    __ call_VM_leaf(CAST_FROM_FN_PTR(address, Continuation::prepare_thaw), fi, c_rarg2);
+    __ call_VM_leaf(CAST_FROM_FN_PTR(address, Continuation::prepare_thaw), fi, c_rarg1);
     __ testq(rax, rax);           // rax contains the size of the frames to thaw, 0 if overflow or no more frames
     __ jcc(Assembler::zero, thaw_fail);
 
@@ -5665,19 +5665,23 @@
     if (return_barrier) {
       __ push(rdx); __ push_d(xmm0); // save original return value -- again
     }
-    __ movl(c_rarg2, return_barrier);
     push_FrameInfo(_masm, fi, fi, rbp, c_rarg3);
-    __ call_VM_leaf(CAST_FROM_FN_PTR(address, Continuation::thaw), fi, c_rarg2);
+    __ movl(c_rarg1, return_barrier);
+    __ movl(c_rarg2, exception);
+    __ call_VM_leaf(CAST_FROM_FN_PTR(address, Continuation::thaw), fi, c_rarg1, c_rarg2);
     if (!return_barrier) {
       __ movl(rax, 0); // return 0 (success) from doYield
+    } 
+    if (exception) {
+      __ movptr(rdx, rax); // rdx must contain the original pc in the case of exception
     }
     __ bind(thaw_fail);
-    pop_FrameInfo(_masm, fi, rbp, rdx);
+    pop_FrameInfo(_masm, fi, rbp, rbx);
     if (return_barrier) {
       __ pop_d(xmm0); __ pop(rax); // restore return value (no safepoint in the call to thaw, so even an oop return value should be OK)
     }
     __ movptr(rsp, fi); // we're now on the yield frame (which is above us b/c rsp has been pushed down)
-    __ jmp(rdx);
+    __ jmp(rbx);
 
     return start;
   }
@@ -5685,7 +5689,7 @@
   address generate_cont_thaw() {
     StubCodeMark mark(this, "StubRoutines", "Cont thaw");
     address start = __ pc();
-    generate_cont_thaw(false);
+    generate_cont_thaw(false, false);
     return start;
   }
 
@@ -5697,7 +5701,19 @@
     if (CONT_FULL_STACK)
       __ stop("RETURN BARRIER -- UNREACHABLE 0");
 
-    generate_cont_thaw(true);
+    generate_cont_thaw(true, false);
+
+    return start;
+  }
+
+  address generate_cont_returnBarrier_exception() {
+    StubCodeMark mark(this, "StubRoutines", "cont return barrier exception handler");
+    address start = __ pc();
+
+    if (CONT_FULL_STACK)
+      __ stop("RETURN BARRIER -- UNREACHABLE 0");
+
+    generate_cont_thaw(true, true);
 
     return start;
   }
@@ -5968,6 +5984,7 @@
     // Continuation stubs:
     StubRoutines::_cont_thaw          = generate_cont_thaw();
     StubRoutines::_cont_returnBarrier = generate_cont_returnBarrier();
+    StubRoutines::_cont_returnBarrierExc = generate_cont_returnBarrier_exception();
     StubRoutines::_cont_doYield    = generate_cont_doYield();
     StubRoutines::_cont_jump       = generate_cont_jump();
     StubRoutines::_cont_getSP      = generate_cont_getSP();
--- a/src/hotspot/share/aot/aotCompiledMethod.cpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/share/aot/aotCompiledMethod.cpp	Thu Oct 18 10:27:43 2018 +0100
@@ -71,10 +71,6 @@
 }
 #endif
 
-address* AOTCompiledMethod::orig_pc_addr(const frame* fr) {
-  return (address*) ((address)fr->unextended_sp() + _meta->orig_pc_offset());
-}
-
 bool AOTCompiledMethod::do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive) {
   return false;
 }
--- a/src/hotspot/share/aot/aotCompiledMethod.hpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/share/aot/aotCompiledMethod.hpp	Thu Oct 18 10:27:43 2018 +0100
@@ -117,7 +117,6 @@
   const int _method_index;
   oop _oop;  // method()->method_holder()->klass_holder()
 
-  address* orig_pc_addr(const frame* fr);
   bool make_not_entrant_helper(int new_state);
 
  public:
@@ -234,12 +233,10 @@
   virtual oop* oop_addr_at(int index) const { ShouldNotReachHere(); return NULL; }
   virtual Metadata** metadata_addr_at(int index) const { ShouldNotReachHere(); return NULL; }
 
-  // Accessor/mutator for the original pc of a frame before a frame was deopted.
-  address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
-  void    set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
-
   virtual void metadata_do(void f(Metadata*));
 
+  int orig_pc_offset() { return _meta->orig_pc_offset(); }
+  
   bool metadata_got_contains(Metadata **p) {
     return p >= &_metadata_got[0] && p < &_metadata_got[_metadata_size];
   }
--- a/src/hotspot/share/code/compiledMethod.hpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/share/code/compiledMethod.hpp	Thu Oct 18 10:27:43 2018 +0100
@@ -304,7 +304,6 @@
 
   virtual oop* oop_addr_at(int index) const = 0;
   virtual Metadata** metadata_addr_at(int index) const = 0;
-  virtual void    set_original_pc(const frame* fr, address pc) = 0;
 
   // Exception cache support
   // Note: _exception_cache may be read concurrently. We rely on memory_order_consume here.
@@ -323,13 +322,21 @@
   address deopt_mh_handler_begin() const  { return _deopt_mh_handler_begin; }
 
   address deopt_handler_begin() const { return _deopt_handler_begin; }
-  virtual address get_original_pc(const frame* fr) = 0;
   // Deopt
   // Return true is the PC is one would expect if the frame is being deopted.
   inline bool is_deopt_pc(address pc);
   bool is_deopt_mh_entry(address pc) { return pc == deopt_mh_handler_begin(); }
   inline bool is_deopt_entry(address pc);
 
+  // Accessor/mutator for the original pc of a frame before a frame was deopted.
+  address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
+  void    set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
+
+ virtual int orig_pc_offset() = 0;
+private:
+  address* orig_pc_addr(const frame* fr) { return (address*) ((address)fr->unextended_sp() + orig_pc_offset()); };
+
+public:
   virtual bool can_convert_to_zombie() = 0;
   virtual const char* compile_kind() const = 0;
   virtual int get_state() const = 0;
--- a/src/hotspot/share/code/nmethod.cpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/share/code/nmethod.cpp	Thu Oct 18 10:27:43 2018 +0100
@@ -387,10 +387,6 @@
     nul_chk_table_size();
 }
 
-address* nmethod::orig_pc_addr(const frame* fr) {
-  return (address*) ((address)fr->unextended_sp() + _orig_pc_offset);
-}
-
 const char* nmethod::compile_kind() const {
   if (is_osr_method())     return "osr";
   if (method() != NULL && is_native_method())  return "c2n";
--- a/src/hotspot/share/code/nmethod.hpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/share/code/nmethod.hpp	Thu Oct 18 10:27:43 2018 +0100
@@ -512,16 +512,12 @@
  private:
   ScopeDesc* scope_desc_in(address begin, address end);
 
-  address* orig_pc_addr(const frame* fr);
-
  public:
   // copying of debugging information
   void copy_scopes_pcs(PcDesc* pcs, int count);
   void copy_scopes_data(address buffer, int size);
 
-  // Accessor/mutator for the original pc of a frame before a frame was deopted.
-  address get_original_pc(const frame* fr) { return *orig_pc_addr(fr); }
-  void    set_original_pc(const frame* fr, address pc) { *orig_pc_addr(fr) = pc; }
+  int orig_pc_offset() { return _orig_pc_offset; }
 
   // jvmti support:
   void post_compiled_method_load_event();
--- a/src/hotspot/share/opto/library_call.cpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/share/opto/library_call.cpp	Thu Oct 18 10:27:43 2018 +0100
@@ -6586,6 +6586,8 @@
   address call_addr = StubRoutines::cont_thaw();
   const TypeFunc* tf = OptoRuntime::void_void_Type();
   Node* call = make_runtime_call(RC_NO_LEAF, tf, call_addr, "doContinue", TypeRawPtr::BOTTOM);
+  assert (call->is_CallJava(), "");
+  Node* result = set_results_for_java_call((CallJavaNode*)call, false, /* deoptimize */ false);
   return true;
 }
 
--- a/src/hotspot/share/runtime/continuation.cpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/share/runtime/continuation.cpp	Thu Oct 18 10:27:43 2018 +0100
@@ -48,6 +48,7 @@
 #include "runtime/frame.inline.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/jniHandles.inline.hpp"
+#include "runtime/sharedRuntime.hpp"
 #include "runtime/vframe_hp.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/exceptions.hpp"
@@ -287,7 +288,7 @@
 
   Method* method(ContMirror& cont);
 
-  inline frame to_frame();
+  inline frame to_frame(ContMirror& cont);
 
   void print_on(ContMirror& cont, outputStream* st);
   void print(ContMirror& cont) { print_on(cont, tty); }
@@ -518,9 +519,25 @@
   template<typename Event> void post_jfr_event(Event *e);
 };
 
-inline frame hframe::to_frame() {
-  return frame(reinterpret_cast<intptr_t*>(_sp), reinterpret_cast<intptr_t*>(_sp), reinterpret_cast<intptr_t*>(_fp), _pc, 
-              _cb != NULL ? _cb : (_cb = CodeCache::find_blob(_pc)));
+inline frame hframe::to_frame(ContMirror& cont) {
+  bool deopt = false;
+  address pc = _pc;
+  if (!is_interpreted_frame()) {
+    CompiledMethod* cm = cb()->as_compiled_method_or_null();
+    if (cm != NULL && cm->is_deopt_pc(pc)) {
+      intptr_t* hsp = cont.stack_address(sp());
+      address orig_pc = *(address*) ((address)hsp + cm->orig_pc_offset());
+      assert (orig_pc != pc, "");
+      assert (orig_pc != NULL, "");
+
+      pc = orig_pc;
+      deopt = true;
+    }
+  }
+
+  return frame(reinterpret_cast<intptr_t*>(_sp), reinterpret_cast<intptr_t*>(_sp), reinterpret_cast<intptr_t*>(_fp), pc, 
+              _cb != NULL ? _cb : (_cb = CodeCache::find_blob(_pc)),
+              deopt);
 }
 
 void hframe::print_on(outputStream* st) {
@@ -2556,7 +2573,7 @@
 // fi->sp is the top of the stack after thaw
 // fi->fp current rbp
 // called after preparations (stack overflow check and making room)
-static inline void thaw1(JavaThread* thread, FrameInfo* fi, const bool return_barrier) {
+static inline void thaw1(JavaThread* thread, FrameInfo* fi, const bool return_barrier, const bool exception) {
   EventContinuationThaw event;
   ResourceMark rm(thread);
 
@@ -2594,7 +2611,7 @@
 
   // ResourceMark rm(cont.thread()); // apparently, oop-mapping may require resource allocation
 
-
+  // const address orig_top_pc = cont.pc();
   hframe hf = cont.last_frame();
   log_trace(jvmcont)("top_hframe before (thaw):");
   if (log_is_enabled(Trace, jvmcont)) hf.print_on(cont, tty);
@@ -2602,7 +2619,7 @@
   RegisterMap map(thread, false, false, false);
   map.set_include_argument_oops(false);
   map.set_update_link(true);
-  assert (map.update_map(), "RegisterMap not set to update");
+  // assert (map.update_map(), "RegisterMap not set to update");
 
   DEBUG_ONLY(int orig_num_frames = cont.num_frames();)
   int frame_count = 0;
@@ -2624,9 +2641,12 @@
   assert (cont.is_empty() <= (cont.num_interpreted_frames() == 0), "cont.is_empty: %d num_interpreted_frames: %d", cont.is_empty(), cont.num_interpreted_frames());
   assert (cont.num_frames() == orig_num_frames - frame_count, "cont.is_empty: %d num_frames: %d orig_num_frames: %d frame_count: %d", cont.is_empty(), cont.num_frames(), orig_num_frames, frame_count);
 
+  assert (!top.is_compiled_frame() || top.is_deoptimized_frame() == top.cb()->as_compiled_method()->is_deopt_pc(top.raw_pc()), "");
+  assert (!top.is_compiled_frame() || top.is_deoptimized_frame() == (top.pc() != top.raw_pc()), "");
+
   fi->sp = top.sp();
   fi->fp = top.fp();
-  fi->pc = top.pc(); // we'll jump to the current continuation pc // Interpreter::return_entry(vtos, 0, Bytecodes::_invokestatic, true); //
+  fi->pc = top.raw_pc(); // we'll jump to the current continuation pc // Interpreter::return_entry(vtos, 0, Bytecodes::_invokestatic, true); //
 
   log_trace(jvmcont)("thawed %d frames", frame_count);
 
@@ -2759,8 +2779,17 @@
 //      fi->fp = the FP " ...
 //      fi->pc = the PC " ...
 // JRT_ENTRY(void, Continuation::thaw(JavaThread* thread, FrameInfo* fi, int num_frames))
-JRT_LEAF(void, Continuation::thaw(FrameInfo* fi, bool return_barrier))
-  thaw1(JavaThread::current(), fi, return_barrier);
+JRT_LEAF(address, Continuation::thaw(FrameInfo* fi, bool return_barrier, bool exception))
+  thaw1(JavaThread::current(), fi, return_barrier, exception);
+
+  if (exception) {
+    // TODO: handle deopt. see TemplateInterpreterGenerator::generate_throw_exception, OptoRuntime::handle_exception_C, OptoRuntime::handle_exception_helper
+    // assert (!top.is_deoptimized_frame(), ""); -- seems to be handled
+    address ret = fi->pc;
+    fi->pc = SharedRuntime::raw_exception_handler_for_return_address(JavaThread::current(), fi->pc);
+    return ret;
+  } else
+    return NULL;
 JRT_END
 
 bool Continuation::is_continuation_entry_frame(const frame& f, const RegisterMap* map) {
@@ -2841,7 +2870,7 @@
   // tty->print_cr("continuation_top_frame");
   
   map->set_cont(map->thread(), contOop);
-  return hf.to_frame();
+  return hf.to_frame(cont);
 }
 
 static frame continuation_parent_frame(ContMirror& cont, RegisterMap* map) {
@@ -2872,7 +2901,7 @@
   hframe sender = hfcallee.sender(cont);
 
   if (!sender.is_empty())
-    return sender.to_frame();
+    return sender.to_frame(cont);
   return continuation_parent_frame(cont, map);
 }
 
--- a/src/hotspot/share/runtime/continuation.hpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/share/runtime/continuation.hpp	Thu Oct 18 10:27:43 2018 +0100
@@ -57,7 +57,7 @@
 public:
   static int freeze(JavaThread* thread, FrameInfo* fi);
   static int prepare_thaw(FrameInfo* fi, bool return_barrier);
-  static void thaw(FrameInfo* fi, bool return_barrier);
+  static address thaw(FrameInfo* fi, bool return_barrier, bool exception);
 
   static bool is_continuation_entry_frame(const frame& f, const RegisterMap* map);
   static bool is_cont_bottom_frame(const frame& f);
--- a/src/hotspot/share/runtime/sharedRuntime.cpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Thu Oct 18 10:27:43 2018 +0100
@@ -465,6 +465,10 @@
   thread->set_exception_pc(NULL);
 #endif // INCLUDE_JVMCI
 
+  if (Continuation::is_return_barrier_entry(return_address)) {
+    return StubRoutines::cont_returnBarrierExc();
+  }
+  
   // The fastest case first
   CodeBlob* blob = CodeCache::find_blob(return_address);
   CompiledMethod* nm = (blob != NULL) ? blob->as_compiled_method_or_null() : NULL;
@@ -699,13 +703,14 @@
 
   if (t == NULL) {
     ttyLocker ttyl;
-    tty->print_cr("MISSING EXCEPTION HANDLER for pc " INTPTR_FORMAT " and handler bci %d", p2i(ret_pc), handler_bci);
+    tty->print_cr("MISSING EXCEPTION HANDLER for pc " INTPTR_FORMAT " and handler bci %d, catch_pco: %d", p2i(ret_pc), handler_bci, catch_pco);
     tty->print_cr("   Exception:");
     exception->print();
     tty->cr();
     tty->print_cr(" Compiled exception table :");
     table.print();
-    nm->print_code();
+    nm->print();
+    // nm->print_code();
     guarantee(false, "missing exception handler");
     return NULL;
   }
--- a/src/hotspot/share/runtime/stubRoutines.cpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/share/runtime/stubRoutines.cpp	Thu Oct 18 10:27:43 2018 +0100
@@ -181,6 +181,7 @@
 address StubRoutines::_cont_jump          = NULL;
 address StubRoutines::_cont_thaw          = NULL;
 address StubRoutines::_cont_returnBarrier = NULL;
+address StubRoutines::_cont_returnBarrierExc = NULL;
 address StubRoutines::_cont_getSP         = NULL;
 address StubRoutines::_cont_getPC         = NULL;
 
--- a/src/hotspot/share/runtime/stubRoutines.hpp	Mon Oct 15 16:15:54 2018 +0100
+++ b/src/hotspot/share/runtime/stubRoutines.hpp	Thu Oct 18 10:27:43 2018 +0100
@@ -212,6 +212,7 @@
   static address _cont_jump;
   static address _cont_thaw;
   static address _cont_returnBarrier;
+  static address _cont_returnBarrierExc;  
   static address _cont_getSP;
   static address _cont_getPC;
 
@@ -396,6 +397,7 @@
   static address cont_jump()           { return _cont_jump; }
   static address cont_thaw()           { return _cont_thaw; }
   static address cont_returnBarrier()  { return _cont_returnBarrier; }
+  static address cont_returnBarrierExc(){return _cont_returnBarrierExc; }
   static address cont_getSP()          { return _cont_getSP; }
   static address cont_getPC()          { return _cont_getPC; }