diff --git a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index af970215024e6262831f4d1c0e0caeff7b227a92..21cb47f9d9896be27dced604cb2df7fd1bba551a 100644 --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -388,6 +388,60 @@ int LIR_Assembler::emit_exception_handler() { } +// 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 @@ int LIR_Assembler::shift_amount(BasicType t) { } -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 @@ void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { 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(), diff --git a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index d88ce13e2c45ecf8839b6bf4c65229e986c3f2dd..966a01d8624da84113ac8db7911e79ba8a33cb99 100644 --- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -455,6 +455,60 @@ int LIR_Assembler::emit_exception_handler() { } +// 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::emit_static_call_stub() { } -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: diff --git a/src/share/vm/asm/codeBuffer.hpp b/src/share/vm/asm/codeBuffer.hpp index 8751fb6494d93fdc9ce48f397235ad3b4e241a05..3d61f875a6e215092516e7752cd62412e32dced4 100644 --- a/src/share/vm/asm/codeBuffer.hpp +++ b/src/share/vm/asm/codeBuffer.hpp @@ -40,6 +40,7 @@ public: 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 @@ public: _values[Exceptions ] = -1; _values[Deopt ] = -1; _values[DeoptMH ] = -1; + _values[UnwindHandler ] = -1; } int value(Entries e) { return _values[e]; } diff --git a/src/share/vm/c1/c1_Compilation.cpp b/src/share/vm/c1/c1_Compilation.cpp index e1df739770f1c58aa830e78883ef4cb7b6ada88d..5fd667cb7d0c014a8a3b08a28c1c2a816ad840cf 100644 --- a/src/share/vm/c1/c1_Compilation.cpp +++ b/src/share/vm/c1/c1_Compilation.cpp @@ -229,6 +229,10 @@ void Compilation::emit_code_epilog(LIR_Assembler* assembler) { 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(); } diff --git a/src/share/vm/c1/c1_GraphBuilder.cpp b/src/share/vm/c1/c1_GraphBuilder.cpp index 8fc646cca5516020adbfd35264bd94ec89dc2243..808adc78cf4b2e9add467284f0517e7859bde108 100644 --- a/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/src/share/vm/c1/c1_GraphBuilder.cpp @@ -829,12 +829,8 @@ void GraphBuilder::ScopeData::setup_jsr_xhandlers() { // 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 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) _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 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) } 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); diff --git a/src/share/vm/c1/c1_Instruction.hpp b/src/share/vm/c1/c1_Instruction.hpp index 92e020a873a9f6a3a5eeb77d16ba1a6b7360b5e0..eac937ad9e3a30d35c497cb1b6bc657c0059e863 100644 --- a/src/share/vm/c1/c1_Instruction.hpp +++ b/src/share/vm/c1/c1_Instruction.hpp @@ -1628,11 +1628,10 @@ LEAF(BlockBegin, StateSplit) 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; } diff --git a/src/share/vm/c1/c1_LIR.cpp b/src/share/vm/c1/c1_LIR.cpp index 4d9f6958a26099926da4402bb9439c991c1d8c7a..e6a3b314715d5e0fe05dcb8f28bff86f955e9c1a 100644 --- a/src/share/vm/c1/c1_LIR.cpp +++ b/src/share/vm/c1/c1_LIR.cpp @@ -626,8 +626,7 @@ void LIR_OpVisitState::visit(LIR_Op* op) { 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 @@ void LIR_OpVisitState::visit(LIR_Op* op) { 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: diff --git a/src/share/vm/c1/c1_LIR.hpp b/src/share/vm/c1/c1_LIR.hpp index 4ce123a176eca950d0b75a3b617e05e01f44ff6c..b0a56404502588000be1bafa2d9d16b085de8e21 100644 --- a/src/share/vm/c1/c1_LIR.hpp +++ b/src/share/vm/c1/c1_LIR.hpp @@ -801,6 +801,7 @@ enum LIR_Code { , lir_monaddr , lir_roundfp , lir_safepoint + , lir_unwind , end_op1 , begin_op2 , lir_cmp @@ -830,7 +831,6 @@ enum LIR_Code { , lir_ushr , lir_alloc_array , lir_throw - , lir_unwind , lir_compare_to , end_op2 , begin_op3 @@ -1827,8 +1827,12 @@ class LIR_List: public CompilationResourceObj { 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)); diff --git a/src/share/vm/c1/c1_LIRAssembler.cpp b/src/share/vm/c1/c1_LIRAssembler.cpp index 14c4485e3430425f194dfc79090b9c3177c13479..ab9c44625fe8185a56ef45fe85a654b6a2766e11 100644 --- a/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/src/share/vm/c1/c1_LIRAssembler.cpp @@ -552,6 +552,10 @@ void LIR_Assembler::emit_op1(LIR_Op1* op) { 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 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) { 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: diff --git a/src/share/vm/c1/c1_LIRAssembler.hpp b/src/share/vm/c1/c1_LIRAssembler.hpp index a7c1ecc869e0cf7a0189c921abbf3d31e3fa5945..d73a19fdbdbf88cd7141170af66837940620e726 100644 --- a/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/src/share/vm/c1/c1_LIRAssembler.hpp @@ -39,6 +39,8 @@ class LIR_Assembler: public CompilationResourceObj { 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 @@ class LIR_Assembler: public CompilationResourceObj { // 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 @@ class LIR_Assembler: public CompilationResourceObj { 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(); diff --git a/src/share/vm/c1/c1_LIRGenerator.cpp b/src/share/vm/c1/c1_LIRGenerator.cpp index 4d9b19882f1dd5c0a2547efe7a14c10e8609ffb6..ea2942d9b2cd3800ca8b5c4db56fcb6ecbaeee72 100644 --- a/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/src/share/vm/c1/c1_LIRGenerator.cpp @@ -1765,35 +1765,17 @@ void LIRGenerator::do_Throw(Throw* x) { __ 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); } diff --git a/src/share/vm/code/nmethod.cpp b/src/share/vm/code/nmethod.cpp index 7ffb0f57026536aaf1d908c8333683716da77a4b..946e5f67aed0215326ee96d75c49a8071cc1d813 100644 --- a/src/share/vm/code/nmethod.cpp +++ b/src/share/vm/code/nmethod.cpp @@ -685,6 +685,7 @@ nmethod::nmethod( _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 @@ nmethod::nmethod( _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); diff --git a/src/share/vm/code/nmethod.hpp b/src/share/vm/code/nmethod.hpp index f910efbd2246f8454a81767300dccb6cf772f081..05664fd97b43d32978cc3b08d6a8dfa27ef53cf7 100644 --- a/src/share/vm/code/nmethod.hpp +++ b/src/share/vm/code/nmethod.hpp @@ -154,6 +154,9 @@ class nmethod : public CodeBlob { // 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 @@ class nmethod : public CodeBlob { 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 ; } diff --git a/src/share/vm/runtime/sharedRuntime.cpp b/src/share/vm/runtime/sharedRuntime.cpp index b2c5c43c1b329fe8186516c9920e7d7b60ab32b5..06af4af32cd00562c3d114c06cdd6c6c7788ed98 100644 --- a/src/share/vm/runtime/sharedRuntime.cpp +++ b/src/share/vm/runtime/sharedRuntime.cpp @@ -473,6 +473,13 @@ address SharedRuntime::compute_compiled_exc_handler(nmethod* nm, address ret_pc, 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:");