changeset 1676:9f5b60a14736

6939930: exception unwind changes in 6919934 hurts compilation speed Reviewed-by: twisti
author never
date Thu, 15 Apr 2010 18:14:49 -0700
parents ef74d6d1ac1e
children badea972a310
files src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp src/cpu/x86/vm/c1_LIRAssembler_x86.cpp src/share/vm/asm/codeBuffer.hpp src/share/vm/c1/c1_Compilation.cpp src/share/vm/c1/c1_GraphBuilder.cpp src/share/vm/c1/c1_Instruction.hpp src/share/vm/c1/c1_LIR.cpp src/share/vm/c1/c1_LIR.hpp src/share/vm/c1/c1_LIRAssembler.cpp src/share/vm/c1/c1_LIRAssembler.hpp src/share/vm/c1/c1_LIRGenerator.cpp src/share/vm/code/nmethod.cpp src/share/vm/code/nmethod.hpp src/share/vm/runtime/sharedRuntime.cpp
diffstat 14 files changed, 210 insertions(+), 103 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Thu Apr 15 18:14:49 2010 -0700
@@ -388,6 +388,60 @@
 }
 
 
+// Emit the code to remove the frame from the stack in the exception
+// unwind path.
+int LIR_Assembler::emit_unwind_handler() {
+#ifndef PRODUCT
+  if (CommentedAssembly) {
+    _masm->block_comment("Unwind handler");
+  }
+#endif
+
+  int offset = code_offset();
+
+  // Fetch the exception from TLS and clear out exception related thread state
+  __ ld_ptr(G2_thread, in_bytes(JavaThread::exception_oop_offset()), O0);
+  __ st_ptr(G0, G2_thread, in_bytes(JavaThread::exception_oop_offset()));
+  __ st_ptr(G0, G2_thread, in_bytes(JavaThread::exception_pc_offset()));
+
+  __ bind(_unwind_handler_entry);
+  __ verify_not_null_oop(O0);
+  if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) {
+    __ mov(O0, I0);  // Preserve the exception
+  }
+
+  // Preform needed unlocking
+  MonitorExitStub* stub = NULL;
+  if (method()->is_synchronized()) {
+    monitor_address(0, FrameMap::I1_opr);
+    stub = new MonitorExitStub(FrameMap::I1_opr, true, 0);
+    __ unlock_object(I3, I2, I1, *stub->entry());
+    __ bind(*stub->continuation());
+  }
+
+  if (compilation()->env()->dtrace_method_probes()) {
+    jobject2reg(method()->constant_encoding(), O0);
+    __ call(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), relocInfo::runtime_call_type);
+    __ delayed()->nop();
+  }
+
+  if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) {
+    __ mov(I0, O0);  // Restore the exception
+  }
+
+  // dispatch to the unwind logic
+  __ call(Runtime1::entry_for(Runtime1::unwind_exception_id), relocInfo::runtime_call_type);
+  __ delayed()->nop();
+
+  // Emit the slow path assembly
+  if (stub != NULL) {
+    stub->emit_code(this);
+  }
+
+  return offset;
+}
+
+
 int LIR_Assembler::emit_deopt_handler() {
   // if the last instruction is a call (typically to do a throw which
   // is coming at the end after block reordering) the return address
@@ -2050,26 +2104,29 @@
 }
 
 
-void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info, bool unwind) {
+void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) {
   assert(exceptionOop->as_register() == Oexception, "should match");
-  assert(unwind || exceptionPC->as_register() == Oissuing_pc, "should match");
+  assert(exceptionPC->as_register() == Oissuing_pc, "should match");
 
   info->add_register_oop(exceptionOop);
 
-  if (unwind) {
-    __ call(Runtime1::entry_for(Runtime1::unwind_exception_id), relocInfo::runtime_call_type);
-    __ delayed()->nop();
-  } else {
-    // reuse the debug info from the safepoint poll for the throw op itself
-    address pc_for_athrow  = __ pc();
-    int pc_for_athrow_offset = __ offset();
-    RelocationHolder rspec = internal_word_Relocation::spec(pc_for_athrow);
-    __ set(pc_for_athrow, Oissuing_pc, rspec);
-    add_call_info(pc_for_athrow_offset, info); // for exception handler
-
-    __ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type);
-    __ delayed()->nop();
-  }
+  // reuse the debug info from the safepoint poll for the throw op itself
+  address pc_for_athrow  = __ pc();
+  int pc_for_athrow_offset = __ offset();
+  RelocationHolder rspec = internal_word_Relocation::spec(pc_for_athrow);
+  __ set(pc_for_athrow, Oissuing_pc, rspec);
+  add_call_info(pc_for_athrow_offset, info); // for exception handler
+
+  __ call(Runtime1::entry_for(Runtime1::handle_exception_id), relocInfo::runtime_call_type);
+  __ delayed()->nop();
+}
+
+
+void LIR_Assembler::unwind_op(LIR_Opr exceptionOop) {
+  assert(exceptionOop->as_register() == Oexception, "should match");
+
+  __ br(Assembler::always, false, Assembler::pt, _unwind_handler_entry);
+  __ delayed()->nop();
 }
 
 
@@ -2358,7 +2415,7 @@
   if (UseSlowPath ||
       (!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) ||
       (!UseFastNewTypeArray   && (op->type() != T_OBJECT && op->type() != T_ARRAY))) {
-    __ br(Assembler::always, false, Assembler::pn, *op->stub()->entry());
+    __ br(Assembler::always, false, Assembler::pt, *op->stub()->entry());
     __ delayed()->nop();
   } else {
     __ allocate_array(op->obj()->as_register(),
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu Apr 15 18:14:49 2010 -0700
@@ -455,6 +455,60 @@
 }
 
 
+// Emit the code to remove the frame from the stack in the exception
+// unwind path.
+int LIR_Assembler::emit_unwind_handler() {
+#ifndef PRODUCT
+  if (CommentedAssembly) {
+    _masm->block_comment("Unwind handler");
+  }
+#endif
+
+  int offset = code_offset();
+
+  // Fetch the exception from TLS and clear out exception related thread state
+  __ get_thread(rsi);
+  __ movptr(rax, Address(rsi, JavaThread::exception_oop_offset()));
+  __ movptr(Address(rsi, JavaThread::exception_oop_offset()), (int32_t)NULL_WORD);
+  __ movptr(Address(rsi, JavaThread::exception_pc_offset()), (int32_t)NULL_WORD);
+
+  __ bind(_unwind_handler_entry);
+  __ verify_not_null_oop(rax);
+  if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) {
+    __ mov(rsi, rax);  // Preserve the exception
+  }
+
+  // Preform needed unlocking
+  MonitorExitStub* stub = NULL;
+  if (method()->is_synchronized()) {
+    monitor_address(0, FrameMap::rax_opr);
+    stub = new MonitorExitStub(FrameMap::rax_opr, true, 0);
+    __ unlock_object(rdi, rbx, rax, *stub->entry());
+    __ bind(*stub->continuation());
+  }
+
+  if (compilation()->env()->dtrace_method_probes()) {
+    __ movoop(Address(rsp, 0), method()->constant_encoding());
+    __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit)));
+  }
+
+  if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) {
+    __ mov(rax, rsi);  // Restore the exception
+  }
+
+  // remove the activation and dispatch to the unwind handler
+  __ remove_frame(initial_frame_size_in_bytes());
+  __ jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id)));
+
+  // Emit the slow path assembly
+  if (stub != NULL) {
+    stub->emit_code(this);
+  }
+
+  return offset;
+}
+
+
 int LIR_Assembler::emit_deopt_handler() {
   // if the last instruction is a call (typically to do a throw which
   // is coming at the end after block reordering) the return address
@@ -2795,42 +2849,43 @@
 }
 
 
-void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info, bool unwind) {
+void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) {
   assert(exceptionOop->as_register() == rax, "must match");
-  assert(unwind || exceptionPC->as_register() == rdx, "must match");
+  assert(exceptionPC->as_register() == rdx, "must match");
 
   // exception object is not added to oop map by LinearScan
   // (LinearScan assumes that no oops are in fixed registers)
   info->add_register_oop(exceptionOop);
   Runtime1::StubID unwind_id;
 
-  if (!unwind) {
-    // get current pc information
-    // pc is only needed if the method has an exception handler, the unwind code does not need it.
-    int pc_for_athrow_offset = __ offset();
-    InternalAddress pc_for_athrow(__ pc());
-    __ lea(exceptionPC->as_register(), pc_for_athrow);
-    add_call_info(pc_for_athrow_offset, info); // for exception handler
-
-    __ verify_not_null_oop(rax);
-    // search an exception handler (rax: exception oop, rdx: throwing pc)
-    if (compilation()->has_fpu_code()) {
-      unwind_id = Runtime1::handle_exception_id;
-    } else {
-      unwind_id = Runtime1::handle_exception_nofpu_id;
-    }
-    __ call(RuntimeAddress(Runtime1::entry_for(unwind_id)));
+  // get current pc information
+  // pc is only needed if the method has an exception handler, the unwind code does not need it.
+  int pc_for_athrow_offset = __ offset();
+  InternalAddress pc_for_athrow(__ pc());
+  __ lea(exceptionPC->as_register(), pc_for_athrow);
+  add_call_info(pc_for_athrow_offset, info); // for exception handler
+
+  __ verify_not_null_oop(rax);
+  // search an exception handler (rax: exception oop, rdx: throwing pc)
+  if (compilation()->has_fpu_code()) {
+    unwind_id = Runtime1::handle_exception_id;
   } else {
-    // remove the activation
-    __ remove_frame(initial_frame_size_in_bytes());
-    __ jump(RuntimeAddress(Runtime1::entry_for(Runtime1::unwind_exception_id)));
+    unwind_id = Runtime1::handle_exception_nofpu_id;
   }
+  __ call(RuntimeAddress(Runtime1::entry_for(unwind_id)));
 
   // enough room for two byte trap
   __ nop();
 }
 
 
+void LIR_Assembler::unwind_op(LIR_Opr exceptionOop) {
+  assert(exceptionOop->as_register() == rax, "must match");
+
+  __ jmp(_unwind_handler_entry);
+}
+
+
 void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr dest, LIR_Opr tmp) {
 
   // optimized version for linear scan:
--- a/src/share/vm/asm/codeBuffer.hpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/share/vm/asm/codeBuffer.hpp	Thu Apr 15 18:14:49 2010 -0700
@@ -40,6 +40,7 @@
                  Exceptions,     // Offset where exception handler lives
                  Deopt,          // Offset where deopt handler lives
                  DeoptMH,        // Offset where MethodHandle deopt handler lives
+                 UnwindHandler,  // Offset to default unwind handler
                  max_Entries };
 
   // special value to note codeBlobs where profile (forte) stack walking is
@@ -59,6 +60,7 @@
     _values[Exceptions    ] = -1;
     _values[Deopt         ] = -1;
     _values[DeoptMH       ] = -1;
+    _values[UnwindHandler ] = -1;
   }
 
   int value(Entries e) { return _values[e]; }
--- a/src/share/vm/c1/c1_Compilation.cpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/share/vm/c1/c1_Compilation.cpp	Thu Apr 15 18:14:49 2010 -0700
@@ -229,6 +229,10 @@
   code_offsets->set_value(CodeOffsets::DeoptMH, assembler->emit_deopt_handler());
   CHECK_BAILOUT();
 
+  // Emit the handler to remove the activation from the stack and
+  // dispatch to the caller.
+  offsets()->set_value(CodeOffsets::UnwindHandler, assembler->emit_unwind_handler());
+
   // done
   masm()->flush();
 }
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Apr 15 18:14:49 2010 -0700
@@ -829,12 +829,8 @@
     // should be left alone since there can be only one and all code
     // should dispatch to the same one.
     XHandler* h = handlers->handler_at(i);
-    if (h->handler_bci() != SynchronizationEntryBCI) {
-      h->set_entry_block(block_at(h->handler_bci()));
-    } else {
-      assert(h->entry_block()->is_set(BlockBegin::default_exception_handler_flag),
-             "should be the synthetic unlock block");
-    }
+    assert(h->handler_bci() != SynchronizationEntryBCI, "must be real");
+    h->set_entry_block(block_at(h->handler_bci()));
   }
   _jsr_xhandlers = handlers;
 }
@@ -2867,19 +2863,6 @@
   _initial_state = state_at_entry();
   start_block->merge(_initial_state);
 
-  // setup an exception handler to do the unlocking and/or
-  // notification and unwind the frame.
-  BlockBegin* sync_handler = new BlockBegin(-1);
-  sync_handler->set(BlockBegin::exception_entry_flag);
-  sync_handler->set(BlockBegin::is_on_work_list_flag);
-  sync_handler->set(BlockBegin::default_exception_handler_flag);
-
-  ciExceptionHandler* desc = new ciExceptionHandler(method()->holder(), 0, method()->code_size(), -1, 0);
-  XHandler* h = new XHandler(desc);
-  h->set_entry_block(sync_handler);
-  scope_data()->xhandlers()->append(h);
-  scope_data()->set_has_handler();
-
   // complete graph
   _vmap        = new ValueMap();
   scope->compute_lock_stack_size();
@@ -2930,19 +2913,6 @@
   }
   CHECK_BAILOUT();
 
-  if (sync_handler && sync_handler->state() != NULL) {
-    Value lock = NULL;
-    if (method()->is_synchronized()) {
-      lock = method()->is_static() ? new Constant(new InstanceConstant(method()->holder()->java_mirror())) :
-                                     _initial_state->local_at(0);
-
-      sync_handler->state()->unlock();
-      sync_handler->state()->lock(scope, lock);
-
-    }
-    fill_sync_handler(lock, sync_handler, true);
-  }
-
   _start = setup_start_block(osr_bci, start_block, _osr_entry, _initial_state);
 
   eliminate_redundant_phis(_start);
--- a/src/share/vm/c1/c1_Instruction.hpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/share/vm/c1/c1_Instruction.hpp	Thu Apr 15 18:14:49 2010 -0700
@@ -1628,11 +1628,10 @@
     backward_branch_target_flag   = 1 << 4,
     is_on_work_list_flag          = 1 << 5,
     was_visited_flag              = 1 << 6,
-    default_exception_handler_flag = 1 << 8, // identify block which represents the default exception handler
-    parser_loop_header_flag       = 1 << 9,  // set by parser to identify blocks where phi functions can not be created on demand
-    critical_edge_split_flag      = 1 << 10, // set for all blocks that are introduced when critical edges are split
-    linear_scan_loop_header_flag  = 1 << 11, // set during loop-detection for LinearScan
-    linear_scan_loop_end_flag     = 1 << 12  // set during loop-detection for LinearScan
+    parser_loop_header_flag       = 1 << 7,  // set by parser to identify blocks where phi functions can not be created on demand
+    critical_edge_split_flag      = 1 << 8, // set for all blocks that are introduced when critical edges are split
+    linear_scan_loop_header_flag  = 1 << 9, // set during loop-detection for LinearScan
+    linear_scan_loop_end_flag     = 1 << 10  // set during loop-detection for LinearScan
   };
 
   void set(Flag f)                               { _flags |= f; }
--- a/src/share/vm/c1/c1_LIR.cpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/share/vm/c1/c1_LIR.cpp	Thu Apr 15 18:14:49 2010 -0700
@@ -626,8 +626,7 @@
       break;
     }
 
-    case lir_throw:
-    case lir_unwind: {
+    case lir_throw: {
       assert(op->as_Op2() != NULL, "must be");
       LIR_Op2* op2 = (LIR_Op2*)op;
 
@@ -639,6 +638,17 @@
       break;
     }
 
+    case lir_unwind: {
+      assert(op->as_Op1() != NULL, "must be");
+      LIR_Op1* op1 = (LIR_Op1*)op;
+
+      assert(op1->_info == NULL, "no info");
+      assert(op1->_opr->is_valid(), "exception oop");         do_input(op1->_opr);
+      assert(op1->_result->is_illegal(), "no result");
+
+      break;
+    }
+
 
     case lir_tan:
     case lir_sin:
--- a/src/share/vm/c1/c1_LIR.hpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/share/vm/c1/c1_LIR.hpp	Thu Apr 15 18:14:49 2010 -0700
@@ -801,6 +801,7 @@
       , lir_monaddr
       , lir_roundfp
       , lir_safepoint
+      , lir_unwind
   , end_op1
   , begin_op2
       , lir_cmp
@@ -830,7 +831,6 @@
       , lir_ushr
       , lir_alloc_array
       , lir_throw
-      , lir_unwind
       , lir_compare_to
   , end_op2
   , begin_op3
@@ -1827,8 +1827,12 @@
   void logical_xor (LIR_Opr left, LIR_Opr right, LIR_Opr dst) { append(new LIR_Op2(lir_logic_xor,  left, right, dst)); }
 
   void null_check(LIR_Opr opr, CodeEmitInfo* info)         { append(new LIR_Op1(lir_null_check, opr, info)); }
-  void throw_exception(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) { append(new LIR_Op2(lir_throw, exceptionPC, exceptionOop, LIR_OprFact::illegalOpr, info)); }
-  void unwind_exception(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) { append(new LIR_Op2(lir_unwind, exceptionPC, exceptionOop, LIR_OprFact::illegalOpr, info)); }
+  void throw_exception(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) {
+    append(new LIR_Op2(lir_throw, exceptionPC, exceptionOop, LIR_OprFact::illegalOpr, info));
+  }
+  void unwind_exception(LIR_Opr exceptionOop) {
+    append(new LIR_Op1(lir_unwind, exceptionOop));
+  }
 
   void compare_to (LIR_Opr left, LIR_Opr right, LIR_Opr dst) {
     append(new LIR_Op2(lir_compare_to,  left, right, dst));
--- a/src/share/vm/c1/c1_LIRAssembler.cpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/share/vm/c1/c1_LIRAssembler.cpp	Thu Apr 15 18:14:49 2010 -0700
@@ -552,6 +552,10 @@
       monitor_address(op->in_opr()->as_constant_ptr()->as_jint(), op->result_opr());
       break;
 
+    case lir_unwind:
+      unwind_op(op->in_opr());
+      break;
+
     default:
       Unimplemented();
       break;
@@ -707,8 +711,7 @@
       break;
 
     case lir_throw:
-    case lir_unwind:
-      throw_op(op->in_opr1(), op->in_opr2(), op->info(), op->code() == lir_unwind);
+      throw_op(op->in_opr1(), op->in_opr2(), op->info());
       break;
 
     default:
--- a/src/share/vm/c1/c1_LIRAssembler.hpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/share/vm/c1/c1_LIRAssembler.hpp	Thu Apr 15 18:14:49 2010 -0700
@@ -39,6 +39,8 @@
   Instruction*       _pending_non_safepoint;
   int                _pending_non_safepoint_offset;
 
+  Label              _unwind_handler_entry;
+
 #ifdef ASSERT
   BlockList          _branch_target_blocks;
   void check_no_unbound_labels();
@@ -134,6 +136,7 @@
 
   // code patterns
   int  emit_exception_handler();
+  int  emit_unwind_handler();
   void emit_exception_entries(ExceptionInfoList* info_list);
   int  emit_deopt_handler();
 
@@ -217,7 +220,8 @@
 
   void build_frame();
 
-  void throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info, bool unwind);
+  void throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info);
+  void unwind_op(LIR_Opr exceptionOop);
   void monitor_address(int monitor_ix, LIR_Opr dst);
 
   void align_backward_branch_target();
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Apr 15 18:14:49 2010 -0700
@@ -1765,35 +1765,17 @@
     __ null_check(exception_opr, new CodeEmitInfo(info, true));
   }
 
-  if (compilation()->env()->jvmti_can_post_on_exceptions() &&
-      !block()->is_set(BlockBegin::default_exception_handler_flag)) {
+  if (compilation()->env()->jvmti_can_post_on_exceptions()) {
     // we need to go through the exception lookup path to get JVMTI
     // notification done
     unwind = false;
   }
 
-  assert(!block()->is_set(BlockBegin::default_exception_handler_flag) || unwind,
-         "should be no more handlers to dispatch to");
-
-  if (compilation()->env()->dtrace_method_probes() &&
-      block()->is_set(BlockBegin::default_exception_handler_flag)) {
-    // notify that this frame is unwinding
-    BasicTypeList signature;
-    signature.append(T_INT);    // thread
-    signature.append(T_OBJECT); // methodOop
-    LIR_OprList* args = new LIR_OprList();
-    args->append(getThreadPointer());
-    LIR_Opr meth = new_register(T_OBJECT);
-    __ oop2reg(method()->constant_encoding(), meth);
-    args->append(meth);
-    call_runtime(&signature, args, CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit), voidType, NULL);
-  }
-
   // move exception oop into fixed register
   __ move(exception_opr, exceptionOopOpr());
 
   if (unwind) {
-    __ unwind_exception(LIR_OprFact::illegalOpr, exceptionOopOpr(), info);
+    __ unwind_exception(exceptionOopOpr());
   } else {
     __ throw_exception(exceptionPcOpr(), exceptionOopOpr(), info);
   }
--- a/src/share/vm/code/nmethod.cpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/share/vm/code/nmethod.cpp	Thu Apr 15 18:14:49 2010 -0700
@@ -685,6 +685,7 @@
     _exception_offset        = 0;
     _deoptimize_offset       = 0;
     _deoptimize_mh_offset    = 0;
+    _unwind_handler_offset   = -1;
     _trap_offset             = offsets->value(CodeOffsets::Dtrace_trap);
     _orig_pc_offset          = 0;
     _stub_offset             = data_offset();
@@ -798,6 +799,11 @@
     _exception_offset        = _stub_offset + offsets->value(CodeOffsets::Exceptions);
     _deoptimize_offset       = _stub_offset + offsets->value(CodeOffsets::Deopt);
     _deoptimize_mh_offset    = _stub_offset + offsets->value(CodeOffsets::DeoptMH);
+    if (offsets->value(CodeOffsets::UnwindHandler) != -1) {
+      _unwind_handler_offset   = instructions_offset() + offsets->value(CodeOffsets::UnwindHandler);
+    } else {
+      _unwind_handler_offset   = -1;
+    }
     _consts_offset           = instructions_offset() + code_buffer->total_offset_of(code_buffer->consts()->start());
     _scopes_data_offset      = data_offset();
     _scopes_pcs_offset       = _scopes_data_offset   + round_to(debug_info->data_size         (), oopSize);
--- a/src/share/vm/code/nmethod.hpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/share/vm/code/nmethod.hpp	Thu Apr 15 18:14:49 2010 -0700
@@ -154,6 +154,9 @@
   // All deoptee's at a MethodHandle call site will resume execution
   // at this location described by this offset.
   int _deoptimize_mh_offset;
+  // Offset of the unwind handler if it exists
+  int _unwind_handler_offset;
+
 #ifdef HAVE_DTRACE_H
   int _trap_offset;
 #endif // def HAVE_DTRACE_H
@@ -341,6 +344,7 @@
   address exception_begin       () const          { return           header_begin() + _exception_offset     ; }
   address deopt_handler_begin   () const          { return           header_begin() + _deoptimize_offset    ; }
   address deopt_mh_handler_begin() const          { return           header_begin() + _deoptimize_mh_offset ; }
+  address unwind_handler_begin  () const          { return _unwind_handler_offset != -1 ? (header_begin() + _unwind_handler_offset) : NULL; }
   address stub_begin            () const          { return           header_begin() + _stub_offset          ; }
   address stub_end              () const          { return           header_begin() + _consts_offset        ; }
   address consts_begin          () const          { return           header_begin() + _consts_offset        ; }
--- a/src/share/vm/runtime/sharedRuntime.cpp	Wed Apr 14 15:30:13 2010 -0700
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Thu Apr 15 18:14:49 2010 -0700
@@ -473,6 +473,13 @@
     t = table.entry_for(catch_pco, -1, 0);
   }
 
+#ifdef COMPILER1
+  if (t == NULL && nm->is_compiled_by_c1()) {
+    assert(nm->unwind_handler_begin() != NULL, "");
+    return nm->unwind_handler_begin();
+  }
+#endif
+
   if (t == NULL) {
     tty->print_cr("MISSING EXCEPTION HANDLER for pc " INTPTR_FORMAT " and handler bci %d", ret_pc, handler_bci);
     tty->print_cr("   Exception:");