changeset 55791:d19dc5b10fbb

8209626: [JVMCI] Use implicit exception table for dispatch and printing Reviewed-by: kvn
author never
date Fri, 07 Jun 2019 10:26:21 -0700
parents f4b2d5b83ebf
children 3493c1bc59fd
files src/hotspot/share/aot/aotCompiledMethod.hpp src/hotspot/share/code/compiledMethod.cpp src/hotspot/share/code/compiledMethod.hpp src/hotspot/share/code/exceptionHandlerTable.cpp src/hotspot/share/code/exceptionHandlerTable.hpp src/hotspot/share/code/nmethod.cpp src/hotspot/share/code/nmethod.hpp src/hotspot/share/jvmci/jvmciCodeInstaller.cpp src/hotspot/share/jvmci/jvmciCodeInstaller.hpp src/hotspot/share/jvmci/jvmciCompilerToVM.cpp src/hotspot/share/jvmci/jvmciJavaClasses.hpp src/hotspot/share/jvmci/jvmciRuntime.cpp src/hotspot/share/jvmci/jvmciRuntime.hpp src/hotspot/share/runtime/sharedRuntime.cpp src/hotspot/share/runtime/sharedRuntime.hpp src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java
diffstat 17 files changed, 192 insertions(+), 97 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/aot/aotCompiledMethod.hpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/aot/aotCompiledMethod.hpp	Fri Jun 07 10:26:21 2019 -0700
@@ -51,6 +51,7 @@
   int _scopes_begin;
   int _reloc_begin;
   int _exception_table_begin;
+  int _nul_chk_table_begin;
   int _oopmap_begin;
   address at_offset(size_t offset) const { return ((address) this) + offset; }
 public:
@@ -63,9 +64,9 @@
   relocInfo* relocation_begin() const { return (relocInfo*) at_offset(_reloc_begin); }
   relocInfo* relocation_end() const { return (relocInfo*) at_offset(_exception_table_begin); }
   address handler_table_begin   () const { return at_offset(_exception_table_begin); }
-  address handler_table_end() const { return at_offset(_oopmap_begin); }
+  address handler_table_end() const { return at_offset(_nul_chk_table_begin); }
 
-  address nul_chk_table_begin() const { return at_offset(_oopmap_begin); }
+  address nul_chk_table_begin() const { return at_offset(_nul_chk_table_begin); }
   address nul_chk_table_end() const { return at_offset(_oopmap_begin); }
 
   ImmutableOopMapSet* oopmap_set() const { return (ImmutableOopMapSet*) at_offset(_oopmap_begin); }
--- a/src/hotspot/share/code/compiledMethod.cpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/code/compiledMethod.cpp	Fri Jun 07 10:26:21 2019 -0700
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "code/compiledIC.hpp"
 #include "code/compiledMethod.inline.hpp"
+#include "code/exceptionHandlerTable.hpp"
 #include "code/scopeDesc.hpp"
 #include "code/codeCache.hpp"
 #include "code/icBuffer.hpp"
@@ -37,8 +38,10 @@
 #include "oops/methodData.hpp"
 #include "oops/method.inline.hpp"
 #include "prims/methodHandles.hpp"
+#include "runtime/deoptimization.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/sharedRuntime.hpp"
 
 CompiledMethod::CompiledMethod(Method* method, const char* name, CompilerType type, const CodeBlobLayout& layout,
                                int frame_complete_offset, int frame_size, ImmutableOopMapSet* oop_maps,
@@ -638,6 +641,46 @@
          os::is_readable_pointer(method->signature());
 }
 
+address CompiledMethod::continuation_for_implicit_exception(address pc, bool for_div0_check) {
+  // Exception happened outside inline-cache check code => we are inside
+  // an active nmethod => use cpc to determine a return address
+  int exception_offset = pc - code_begin();
+  int cont_offset = ImplicitExceptionTable(this).continuation_offset( exception_offset );
+#ifdef ASSERT
+  if (cont_offset == 0) {
+    Thread* thread = Thread::current();
+    ResetNoHandleMark rnm; // Might be called from LEAF/QUICK ENTRY
+    HandleMark hm(thread);
+    ResourceMark rm(thread);
+    CodeBlob* cb = CodeCache::find_blob(pc);
+    assert(cb != NULL && cb == this, "");
+    ttyLocker ttyl;
+    tty->print_cr("implicit exception happened at " INTPTR_FORMAT, p2i(pc));
+    print();
+    method()->print_codes();
+    print_code();
+    print_pcs();
+  }
+#endif
+  if (cont_offset == 0) {
+    // Let the normal error handling report the exception
+    return NULL;
+  }
+  if (cont_offset == exception_offset) {
+#if INCLUDE_JVMCI
+    Deoptimization::DeoptReason deopt_reason = for_div0_check ? Deoptimization::Reason_div0_check : Deoptimization::Reason_null_check;
+    JavaThread *thread = JavaThread::current();
+    thread->set_jvmci_implicit_exception_pc(pc);
+    thread->set_pending_deoptimization(Deoptimization::make_trap_request(deopt_reason,
+                                                                         Deoptimization::Action_reinterpret));
+    return (SharedRuntime::deopt_blob()->implicit_exception_uncommon_trap());
+#else
+    ShouldNotReachHere();
+#endif
+  }
+  return code_begin() + cont_offset;
+}
+
 class HasEvolDependency : public MetadataClosure {
   bool _has_evol_dependency;
  public:
--- a/src/hotspot/share/code/compiledMethod.hpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/code/compiledMethod.hpp	Fri Jun 07 10:26:21 2019 -0700
@@ -350,7 +350,8 @@
   void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map, OopClosure* f);
 
   // implicit exceptions support
-  virtual address continuation_for_implicit_exception(address pc) { return NULL; }
+  address continuation_for_implicit_div0_exception(address pc) { return continuation_for_implicit_exception(pc, true); }
+  address continuation_for_implicit_null_exception(address pc) { return continuation_for_implicit_exception(pc, false); }
 
   static address get_deopt_original_pc(const frame* fr);
 
@@ -358,6 +359,8 @@
  private:
   bool cleanup_inline_caches_impl(bool unloading_occurred, bool clean_all);
 
+  address continuation_for_implicit_exception(address pc, bool for_div0_check);
+
  public:
   // Serial version used by sweeper and whitebox test
   void cleanup_inline_caches(bool clean_all);
--- a/src/hotspot/share/code/exceptionHandlerTable.cpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/code/exceptionHandlerTable.cpp	Fri Jun 07 10:26:21 2019 -0700
@@ -176,7 +176,7 @@
   _len = l+1;
 };
 
-uint ImplicitExceptionTable::at( uint exec_off ) const {
+uint ImplicitExceptionTable::continuation_offset( uint exec_off ) const {
   uint l = len();
   for( uint i=0; i<l; i++ )
     if( *adr(i) == exec_off )
@@ -205,7 +205,7 @@
   }
 }
 
-ImplicitExceptionTable::ImplicitExceptionTable(const nmethod* nm) {
+ImplicitExceptionTable::ImplicitExceptionTable(const CompiledMethod* nm) {
   if (nm->nul_chk_table_size() == 0) {
     _len = 0;
     _data = NULL;
@@ -221,9 +221,13 @@
 }
 
 void ImplicitExceptionTable::copy_to( nmethod* nm ) {
-  assert(size_in_bytes() <= nm->nul_chk_table_size(), "size of space allocated in nmethod incorrect");
+  copy_bytes_to(nm->nul_chk_table_begin(), nm->nul_chk_table_size());
+}
+
+void ImplicitExceptionTable::copy_bytes_to(address addr, int size) {
+  assert(size_in_bytes() <= size, "size of space allocated in nmethod incorrect");
   if (len() != 0) {
-    implicit_null_entry* nmdata = (implicit_null_entry*)nm->nul_chk_table_begin();
+    implicit_null_entry* nmdata = (implicit_null_entry*)addr;
     // store the length in the first uint
     nmdata[0] = _len;
     nmdata++;
@@ -232,7 +236,7 @@
   } else {
     // zero length table takes zero bytes
     assert(size_in_bytes() == 0, "bad size");
-    assert(nm->nul_chk_table_size() == 0, "bad size");
+    assert(size == 0, "bad size");
   }
 }
 
--- a/src/hotspot/share/code/exceptionHandlerTable.hpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/code/exceptionHandlerTable.hpp	Fri Jun 07 10:26:21 2019 -0700
@@ -146,19 +146,36 @@
   implicit_null_entry *_data;
   implicit_null_entry *adr( uint idx ) const { return &_data[2*idx]; }
   ReallocMark          _nesting;  // assertion check for reallocations
+
 public:
   ImplicitExceptionTable( ) :  _size(0), _len(0), _data(0) { }
   // (run-time) construction from nmethod
-  ImplicitExceptionTable( const nmethod *nm );
+  ImplicitExceptionTable( const CompiledMethod *nm );
 
   void set_size( uint size );
   void append( uint exec_off, uint cont_off );
-  uint at( uint exec_off ) const;
+
+#if INCLUDE_JVMCI
+  void add_deoptimize(uint exec_off) {
+    // Use the same offset as a marker value for deoptimization
+    append(exec_off, exec_off);
+  }
+#endif
+
+  // Returns the offset to continue execution at.  If the returned
+  // value equals exec_off then the dispatch is expected to be a
+  // deoptimization instead.
+  uint continuation_offset( uint exec_off ) const;
 
   uint len() const { return _len; }
+
+  uint get_exec_offset(uint i) { assert(i < _len, "oob"); return *adr(i); }
+  uint get_cont_offset(uint i) { assert(i < _len, "oob"); return *(adr(i) + 1); }
+
   int size_in_bytes() const { return len() == 0 ? 0 : ((2 * len() + 1) * sizeof(implicit_null_entry)); }
 
   void copy_to(nmethod* nm);
+  void copy_bytes_to(address addr, int size);
   void print(address base) const;
   void verify(nmethod *nm) const;
 };
--- a/src/hotspot/share/code/nmethod.cpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/code/nmethod.cpp	Fri Jun 07 10:26:21 2019 -0700
@@ -923,6 +923,7 @@
   ttyLocker ttyl;  // keep the following output all in one block
   if (xtty != NULL) {
     xtty->begin_head("print_nmethod");
+    log_identity(xtty);
     xtty->stamp();
     xtty->end_head();
   }
@@ -2093,34 +2094,6 @@
 }
 
 
-address nmethod::continuation_for_implicit_exception(address pc) {
-  // Exception happened outside inline-cache check code => we are inside
-  // an active nmethod => use cpc to determine a return address
-  int exception_offset = pc - code_begin();
-  int cont_offset = ImplicitExceptionTable(this).at( exception_offset );
-#ifdef ASSERT
-  if (cont_offset == 0) {
-    Thread* thread = Thread::current();
-    ResetNoHandleMark rnm; // Might be called from LEAF/QUICK ENTRY
-    HandleMark hm(thread);
-    ResourceMark rm(thread);
-    CodeBlob* cb = CodeCache::find_blob(pc);
-    assert(cb != NULL && cb == this, "");
-    ttyLocker ttyl;
-    tty->print_cr("implicit exception happened at " INTPTR_FORMAT, p2i(pc));
-    // Print all available nmethod info.
-    print_nmethod(true);
-    method()->print_codes();
-  }
-#endif
-  if (cont_offset == 0) {
-    // Let the normal error handling report the exception
-    return NULL;
-  }
-  return code_begin() + cont_offset;
-}
-
-
 void nmethod_init() {
   // make sure you didn't forget to adjust the filler fields
   assert(sizeof(nmethod) % oopSize == 0, "nmethod size must be multiple of a word");
@@ -2213,6 +2186,30 @@
     }
   }
 
+#ifdef ASSERT
+#if INCLUDE_JVMCI
+  {
+    // Verify that implicit exceptions that deoptimize have a PcDesc and OopMap
+    ImmutableOopMapSet* oms = oop_maps();
+    ImplicitExceptionTable implicit_table(this);
+    for (uint i = 0; i < implicit_table.len(); i++) {
+      int exec_offset = (int) implicit_table.get_exec_offset(i);
+      if (implicit_table.get_exec_offset(i) == implicit_table.get_cont_offset(i)) {
+        assert(pc_desc_at(code_begin() + exec_offset) != NULL, "missing PcDesc");
+        bool found = false;
+        for (int i = 0, imax = oms->count(); i < imax; i++) {
+          if (oms->pair_at(i)->pc_offset() == exec_offset) {
+            found = true;
+            break;
+          }
+        }
+        assert(found, "missing oopmap");
+      }
+    }
+  }
+#endif
+#endif
+
   VerifyOopsClosure voc(this);
   oops_do(&voc);
   assert(voc.ok(), "embedded oops must be OK");
@@ -3012,16 +3009,32 @@
   if (str != NULL) return true;
 
   // implicit exceptions?
-  int cont_offset = ImplicitExceptionTable(this).at(begin - code_begin());
+  int cont_offset = ImplicitExceptionTable(this).continuation_offset(begin - code_begin());
   if (cont_offset != 0) return true;
 
   return false;
 }
 
 void nmethod::print_code_comment_on(outputStream* st, int column, address begin, address end) {
-  // First, find an oopmap in (begin, end].
-  // We use the odd half-closed interval so that oop maps and scope descs
-  // which are tied to the byte after a call are printed with the call itself.
+  ImplicitExceptionTable implicit_table(this);
+  int pc_offset = begin - code_begin();
+  int cont_offset = implicit_table.continuation_offset(pc_offset);
+  bool oop_map_required = false;
+  if (cont_offset != 0) {
+    st->move_to(column, 6, 0);
+    if (pc_offset == cont_offset) {
+      st->print("; implicit exception: deoptimizes");
+      oop_map_required = true;
+    } else {
+      st->print("; implicit exception: dispatches to " INTPTR_FORMAT, p2i(code_begin() + cont_offset));
+    }
+  }
+
+  // Find an oopmap in (begin, end].  We use the odd half-closed
+  // interval so that oop maps and scope descs which are tied to the
+  // byte after a call are printed with the call itself.  OopMaps
+  // associated with implicit exceptions are printed with the implicit
+  // instruction.
   address base = code_begin();
   ImmutableOopMapSet* oms = oop_maps();
   if (oms != NULL) {
@@ -3029,16 +3042,25 @@
       const ImmutableOopMapPair* pair = oms->pair_at(i);
       const ImmutableOopMap* om = pair->get_from(oms);
       address pc = base + pair->pc_offset();
-      if (pc > begin) {
-        if (pc <= end) {
+      if (pc >= begin) {
+#if INCLUDE_JVMCI
+        bool is_implicit_deopt = implicit_table.continuation_offset(pair->pc_offset()) == (uint) pair->pc_offset();
+#else
+        bool is_implicit_deopt = false;
+#endif
+        if (is_implicit_deopt ? pc == begin : pc > begin && pc <= end) {
           st->move_to(column, 6, 0);
           st->print("; ");
           om->print_on(st);
+          oop_map_required = false;
         }
+      }
+      if (pc > end) {
         break;
       }
     }
   }
+  assert(!oop_map_required, "missed oopmap");
 
   // Print any debug info present at this pc.
   ScopeDesc* sd  = scope_desc_in(begin, end);
@@ -3128,12 +3150,6 @@
     st->move_to(column, 6, 0);
     st->print(";   {%s}", str);
   }
-  int cont_offset = ImplicitExceptionTable(this).at(begin - code_begin());
-  if (cont_offset != 0) {
-    st->move_to(column, 6, 0);
-    st->print("; implicit exception: dispatches to " INTPTR_FORMAT, p2i(code_begin() + cont_offset));
-  }
-
 }
 
 #endif
--- a/src/hotspot/share/code/nmethod.hpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/code/nmethod.hpp	Fri Jun 07 10:26:21 2019 -0700
@@ -424,9 +424,6 @@
   long  stack_traversal_mark()                    { return _stack_traversal_mark; }
   void  set_stack_traversal_mark(long l)          { _stack_traversal_mark = l; }
 
-  // implicit exceptions support
-  address continuation_for_implicit_exception(address pc);
-
   // On-stack replacement support
   int   osr_entry_bci() const                     { assert(is_osr_method(), "wrong kind of nmethod"); return _entry_bci; }
   address  osr_entry() const                      { assert(is_osr_method(), "wrong kind of nmethod"); return _osr_entry_point; }
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp	Fri Jun 07 10:26:21 2019 -0700
@@ -562,6 +562,7 @@
   metadata.set_pc_desc(_debug_recorder->pcs(), _debug_recorder->pcs_length());
   metadata.set_scopes(_debug_recorder->stream()->buffer(), _debug_recorder->data_size());
   metadata.set_exception_table(&_exception_handler_table);
+  metadata.set_implicit_exception_table(&_implicit_exception_table);
 
   RelocBuffer* reloc_buffer = metadata.get_reloc_buffer();
 
@@ -637,7 +638,7 @@
     JVMCIObject mirror = installed_code;
     nmethod* nm = NULL;
     result = runtime()->register_method(jvmci_env(), method, nm, entry_bci, &_offsets, _orig_pc_offset, &buffer,
-                                        stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table,
+                                        stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, &_implicit_exception_table,
                                         compiler, _debug_recorder, _dependencies, id,
                                         has_unsafe_access, _has_wide_vector, compiled_code, mirror,
                                         failed_speculations, speculations, speculations_len);
@@ -870,6 +871,10 @@
         if (_orig_pc_offset < 0) {
           JVMCI_ERROR_OK("method contains safepoint, but has no deopt rescue slot");
         }
+        if (JVMCIENV->equals(reason, jvmci_env()->get_site_InfopointReason_IMPLICIT_EXCEPTION())) {
+          TRACE_jvmci_4("implicit exception at %i", pc_offset);
+          _implicit_exception_table.add_deoptimize(pc_offset);
+        }
       } else {
         TRACE_jvmci_4("infopoint at %i", pc_offset);
         site_Infopoint(buffer, pc_offset, site, JVMCI_CHECK_OK);
--- a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp	Fri Jun 07 10:26:21 2019 -0700
@@ -85,6 +85,8 @@
 
   ExceptionHandlerTable* get_exception_table() { return _exception_table; }
 
+  ImplicitExceptionTable* get_implicit_exception_table() { return _implicit_exception_table; }
+
   void set_pc_desc(PcDesc* desc, int count) {
     _pc_desc = desc;
     _nr_pc_desc = count;
@@ -105,6 +107,10 @@
     _exception_table = table;
   }
 
+  void set_implicit_exception_table(ImplicitExceptionTable* table) {
+    _implicit_exception_table = table;
+  }
+
 private:
   CodeBlob* _cb;
   PcDesc* _pc_desc;
@@ -118,6 +124,7 @@
   AOTOopRecorder* _oop_recorder;
 #endif
   ExceptionHandlerTable* _exception_table;
+  ImplicitExceptionTable* _implicit_exception_table;
 };
 
 /*
@@ -185,6 +192,7 @@
   DebugInformationRecorder* _debug_recorder;
   Dependencies*             _dependencies;
   ExceptionHandlerTable     _exception_handler_table;
+  ImplicitExceptionTable    _implicit_exception_table;
 
   bool _immutable_pic_compilation;  // Installer is called for Immutable PIC compilation.
 
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp	Fri Jun 07 10:26:21 2019 -0700
@@ -921,6 +921,14 @@
   }
   HotSpotJVMCI::HotSpotMetaData::set_exceptionBytes(JVMCIENV, metadata_handle, exceptionArray);
 
+  ImplicitExceptionTable* implicit = code_metadata.get_implicit_exception_table();
+  int implicit_table_size = implicit->size_in_bytes();
+  JVMCIPrimitiveArray implicitExceptionArray = JVMCIENV->new_byteArray(implicit_table_size, JVMCI_CHECK_(JVMCI::cache_full));
+  if (implicit_table_size > 0) {
+    implicit->copy_bytes_to((address) HotSpotJVMCI::resolve(implicitExceptionArray)->byte_at_addr(0), implicit_table_size);
+  }
+  HotSpotJVMCI::HotSpotMetaData::set_implicitExceptionBytes(JVMCIENV, metadata_handle, implicitExceptionArray);
+
   return result;
 #else
   JVMCI_THROW_MSG_0(InternalError, "unimplemented");
--- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp	Fri Jun 07 10:26:21 2019 -0700
@@ -334,6 +334,7 @@
     primarray_field(HotSpotMetaData, scopesDescBytes, "[B")                                                   \
     primarray_field(HotSpotMetaData, relocBytes, "[B")                                                        \
     primarray_field(HotSpotMetaData, exceptionBytes, "[B")                                                    \
+    primarray_field(HotSpotMetaData, implicitExceptionBytes, "[B")                                            \
     primarray_field(HotSpotMetaData, oopMaps, "[B")                                                           \
     object_field(HotSpotMetaData, metadata, "[Ljava/lang/Object;")                                            \
   end_class                                                                                                   \
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp	Fri Jun 07 10:26:21 2019 -0700
@@ -1425,6 +1425,7 @@
                                 int frame_words,
                                 OopMapSet* oop_map_set,
                                 ExceptionHandlerTable* handler_table,
+                                ImplicitExceptionTable* implicit_exception_table,
                                 AbstractCompiler* compiler,
                                 DebugInformationRecorder* debug_info,
                                 Dependencies* dependencies,
@@ -1494,7 +1495,6 @@
       // as in C2, then it must be freed.
       //code_buffer->free_blob();
     } else {
-      ImplicitExceptionTable implicit_tbl;
       nm =  nmethod::new_nmethod(method,
                                  compile_id,
                                  entry_bci,
@@ -1502,7 +1502,7 @@
                                  orig_pc_offset,
                                  debug_info, dependencies, code_buffer,
                                  frame_words, oop_map_set,
-                                 handler_table, &implicit_tbl,
+                                 handler_table, implicit_exception_table,
                                  compiler, comp_level,
                                  speculations, speculations_len,
                                  nmethod_mirror_index, nmethod_mirror_name, failed_speculations);
--- a/src/hotspot/share/jvmci/jvmciRuntime.hpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp	Fri Jun 07 10:26:21 2019 -0700
@@ -222,6 +222,7 @@
                        int                       frame_words,
                        OopMapSet*                oop_map_set,
                        ExceptionHandlerTable*    handler_table,
+                       ImplicitExceptionTable* implicit_exception_table,
                        AbstractCompiler*         compiler,
                        DebugInformationRecorder* debug_info,
                        Dependencies*             dependencies,
--- a/src/hotspot/share/runtime/sharedRuntime.cpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Fri Jun 07 10:26:21 2019 -0700
@@ -764,18 +764,9 @@
   throw_and_post_jvmti_exception(thread, exception);
 }
 
-#if INCLUDE_JVMCI
-address SharedRuntime::deoptimize_for_implicit_exception(JavaThread* thread, address pc, CompiledMethod* nm, int deopt_reason) {
-  assert(deopt_reason > Deoptimization::Reason_none && deopt_reason < Deoptimization::Reason_LIMIT, "invalid deopt reason");
-  thread->set_jvmci_implicit_exception_pc(pc);
-  thread->set_pending_deoptimization(Deoptimization::make_trap_request((Deoptimization::DeoptReason)deopt_reason, Deoptimization::Action_reinterpret));
-  return (SharedRuntime::deopt_blob()->implicit_exception_uncommon_trap());
-}
-#endif // INCLUDE_JVMCI
-
 address SharedRuntime::continuation_for_implicit_exception(JavaThread* thread,
                                                            address pc,
-                                                           SharedRuntime::ImplicitExceptionKind exception_kind)
+                                                           ImplicitExceptionKind exception_kind)
 {
   address target_pc = NULL;
 
@@ -876,19 +867,7 @@
 #ifndef PRODUCT
           _implicit_null_throws++;
 #endif
-#if INCLUDE_JVMCI
-          if (cm->is_compiled_by_jvmci() && cm->pc_desc_at(pc) != NULL) {
-            // If there's no PcDesc then we'll die way down inside of
-            // deopt instead of just getting normal error reporting,
-            // so only go there if it will succeed.
-            return deoptimize_for_implicit_exception(thread, pc, cm, Deoptimization::Reason_null_check);
-          } else {
-#endif // INCLUDE_JVMCI
-          assert (cm->is_nmethod(), "Expect nmethod");
-          target_pc = ((nmethod*)cm)->continuation_for_implicit_exception(pc);
-#if INCLUDE_JVMCI
-          }
-#endif // INCLUDE_JVMCI
+          target_pc = cm->continuation_for_implicit_null_exception(pc);
           // If there's an unexpected fault, target_pc might be NULL,
           // in which case we want to fall through into the normal
           // error handling code.
@@ -904,15 +883,7 @@
 #ifndef PRODUCT
         _implicit_div0_throws++;
 #endif
-#if INCLUDE_JVMCI
-        if (cm->is_compiled_by_jvmci() && cm->pc_desc_at(pc) != NULL) {
-          return deoptimize_for_implicit_exception(thread, pc, cm, Deoptimization::Reason_div0_check);
-        } else {
-#endif // INCLUDE_JVMCI
-        target_pc = cm->continuation_for_implicit_exception(pc);
-#if INCLUDE_JVMCI
-        }
-#endif // INCLUDE_JVMCI
+        target_pc = cm->continuation_for_implicit_div0_exception(pc);
         // If there's an unexpected fault, target_pc might be NULL,
         // in which case we want to fall through into the normal
         // error handling code.
--- a/src/hotspot/share/runtime/sharedRuntime.hpp	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/hotspot/share/runtime/sharedRuntime.hpp	Fri Jun 07 10:26:21 2019 -0700
@@ -204,9 +204,6 @@
   static address continuation_for_implicit_exception(JavaThread* thread,
                                                      address faulting_pc,
                                                      ImplicitExceptionKind exception_kind);
-#if INCLUDE_JVMCI
-  static address deoptimize_for_implicit_exception(JavaThread* thread, address pc, CompiledMethod* nm, int deopt_reason);
-#endif
 
   // Post-slow-path-allocation, pre-initializing-stores step for
   // implementing e.g. ReduceInitialCardMarks
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/MetadataBuilder.java	Fri Jun 07 10:26:21 2019 -0700
@@ -25,16 +25,20 @@
 
 package jdk.tools.jaotc;
 
+import static jdk.tools.jaotc.AOTCompiledClass.getType;
+import static jdk.tools.jaotc.AOTCompiledClass.metadataName;
+
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+
 import jdk.tools.jaotc.binformat.BinaryContainer;
 import jdk.tools.jaotc.binformat.ByteContainer;
 import jdk.tools.jaotc.binformat.GotSymbol;
 import jdk.tools.jaotc.utils.NativeOrderOutputStream;
-import org.graalvm.compiler.code.CompilationResult;
-import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
-
 import jdk.vm.ci.code.StackSlot;
 import jdk.vm.ci.code.site.DataPatch;
 import jdk.vm.ci.code.site.Infopoint;
@@ -42,9 +46,6 @@
 import jdk.vm.ci.hotspot.HotSpotCompiledCode;
 import jdk.vm.ci.hotspot.HotSpotMetaData;
 
-import static jdk.tools.jaotc.AOTCompiledClass.getType;
-import static jdk.tools.jaotc.AOTCompiledClass.metadataName;
-
 final class MetadataBuilder {
 
     private final DataBuilder dataBuilder;
@@ -81,6 +82,12 @@
         HotSpotGraalRuntimeProvider runtime = dataBuilder.getBackend().getRuntime();
         ByteContainer methodMetadataContainer = binaryContainer.getMethodMetadataContainer();
 
+        Method implicitExceptionsMethod = null;
+        try {
+            implicitExceptionsMethod = HotSpotMetaData.class.getDeclaredMethod("implicitExceptionBytes");
+        } catch (NoSuchMethodException e) {
+        }
+
         // For each of the compiled java methods, create records holding information about them.
         for (CompiledMethodInfo methodInfo : compiledClass.getCompiledMethods()) {
             // Get the current offset in the methodmetadata container.
@@ -141,6 +148,11 @@
                 NativeOrderOutputStream.PatchableInt scopeOffset = metadataStream.patchableInt();
                 NativeOrderOutputStream.PatchableInt relocationOffset = metadataStream.patchableInt();
                 NativeOrderOutputStream.PatchableInt exceptionOffset = metadataStream.patchableInt();
+                NativeOrderOutputStream.PatchableInt implictTableOFfset = null;
+
+                if (implicitExceptionsMethod != null) {
+                    implictTableOFfset = metadataStream.patchableInt();
+                }
                 NativeOrderOutputStream.PatchableInt oopMapOffset = metadataStream.patchableInt();
                 metadataStream.align(8);
 
@@ -156,6 +168,12 @@
                 exceptionOffset.set(metadataStream.position());
                 metadataStream.put(metaData.exceptionBytes()).align(8);
 
+                if (implicitExceptionsMethod != null) {
+                    implictTableOFfset.set(metadataStream.position());
+                    byte[] data = (byte[]) implicitExceptionsMethod.invoke(metaData);
+                    metadataStream.put(data).align(8);
+                }
+
                 // oopmaps should be last
                 oopMapOffset.set(metadataStream.position());
                 metadataStream.put(oopMapInfo).align(8);
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java	Fri Jun 07 09:16:11 2019 -0700
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaData.java	Fri Jun 07 10:26:21 2019 -0700
@@ -31,6 +31,7 @@
     private byte[] scopesDescBytes;
     private byte[] relocBytes;
     private byte[] exceptionBytes;
+    private byte[] implicitExceptionBytes;
     private byte[] oopMaps;
     private Object[] metadata;
 
@@ -62,6 +63,10 @@
         return exceptionBytes;
     }
 
+    public byte[] implicitExceptionBytes() {
+        return implicitExceptionBytes;
+    }
+
     public byte[] oopMaps() {
         return oopMaps;
     }