mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 06:45:07 +02:00
8141133: [JVMCI] crash during safepoint deopt if rethrow_exception is set
Reviewed-by: twisti
This commit is contained in:
parent
163e0435dc
commit
c4ce43c1ac
10 changed files with 114 additions and 36 deletions
|
@ -2384,6 +2384,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||||
}
|
}
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
__ mov(c_rarg0, rthread);
|
__ mov(c_rarg0, rthread);
|
||||||
|
__ mov(c_rarg1, rcpool);
|
||||||
__ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info)));
|
__ lea(rscratch1, RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info)));
|
||||||
__ blrt(rscratch1, 1, 0, 1);
|
__ blrt(rscratch1, 1, 0, 1);
|
||||||
__ bind(retaddr);
|
__ bind(retaddr);
|
||||||
|
@ -2397,6 +2398,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||||
// Load UnrollBlock* into rdi
|
// Load UnrollBlock* into rdi
|
||||||
__ mov(r5, r0);
|
__ mov(r5, r0);
|
||||||
|
|
||||||
|
__ ldrw(rcpool, Address(r5, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes()));
|
||||||
Label noException;
|
Label noException;
|
||||||
__ cmpw(rcpool, Deoptimization::Unpack_exception); // Was exception pending?
|
__ cmpw(rcpool, Deoptimization::Unpack_exception); // Was exception pending?
|
||||||
__ br(Assembler::NE, noException);
|
__ br(Assembler::NE, noException);
|
||||||
|
@ -2609,6 +2611,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||||
// n.b. 2 gp args, 0 fp args, integral return type
|
// n.b. 2 gp args, 0 fp args, integral return type
|
||||||
|
|
||||||
__ mov(c_rarg0, rthread);
|
__ mov(c_rarg0, rthread);
|
||||||
|
__ movw(c_rarg2, (unsigned)Deoptimization::Unpack_uncommon_trap);
|
||||||
__ lea(rscratch1,
|
__ lea(rscratch1,
|
||||||
RuntimeAddress(CAST_FROM_FN_PTR(address,
|
RuntimeAddress(CAST_FROM_FN_PTR(address,
|
||||||
Deoptimization::uncommon_trap)));
|
Deoptimization::uncommon_trap)));
|
||||||
|
@ -2628,6 +2631,16 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||||
// move UnrollBlock* into r4
|
// move UnrollBlock* into r4
|
||||||
__ mov(r4, r0);
|
__ mov(r4, r0);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
{ Label L;
|
||||||
|
__ ldrw(rscratch1, Address(r4, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes()));
|
||||||
|
__ cmpw(rscratch1, (unsigned)Deoptimization::Unpack_uncommon_trap);
|
||||||
|
__ br(Assembler::EQ, L);
|
||||||
|
__ stop("SharedRuntime::generate_deopt_blob: last_Java_fp not cleared");
|
||||||
|
__ bind(L);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Pop all the frames we must move/replace.
|
// Pop all the frames we must move/replace.
|
||||||
//
|
//
|
||||||
// Frame picture (youngest to oldest)
|
// Frame picture (youngest to oldest)
|
||||||
|
|
|
@ -2802,7 +2802,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||||
__ set_last_Java_frame(R1_SP, noreg);
|
__ set_last_Java_frame(R1_SP, noreg);
|
||||||
|
|
||||||
// With EscapeAnalysis turned on, this call may safepoint!
|
// With EscapeAnalysis turned on, this call may safepoint!
|
||||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info), R16_thread);
|
__ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info), R16_thread, exec_mode_reg);
|
||||||
address calls_return_pc = __ last_calls_return_pc();
|
address calls_return_pc = __ last_calls_return_pc();
|
||||||
// Set an oopmap for the call site that describes all our saved registers.
|
// Set an oopmap for the call site that describes all our saved registers.
|
||||||
oop_maps->add_gc_map(calls_return_pc - start, map);
|
oop_maps->add_gc_map(calls_return_pc - start, map);
|
||||||
|
@ -2815,6 +2815,8 @@ void SharedRuntime::generate_deopt_blob() {
|
||||||
// by save_volatile_registers(...).
|
// by save_volatile_registers(...).
|
||||||
RegisterSaver::restore_result_registers(masm, first_frame_size_in_bytes);
|
RegisterSaver::restore_result_registers(masm, first_frame_size_in_bytes);
|
||||||
|
|
||||||
|
// reload the exec mode from the UnrollBlock (it might have changed)
|
||||||
|
__ lwz(exec_mode_reg, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes(), unroll_block_reg);
|
||||||
// In excp_deopt_mode, restore and clear exception oop which we
|
// In excp_deopt_mode, restore and clear exception oop which we
|
||||||
// stored in the thread during exception entry above. The exception
|
// stored in the thread during exception entry above. The exception
|
||||||
// oop will be the return value of this stub.
|
// oop will be the return value of this stub.
|
||||||
|
@ -2945,8 +2947,9 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||||
__ set_last_Java_frame(/*sp*/R1_SP, /*pc*/R11_scratch1);
|
__ set_last_Java_frame(/*sp*/R1_SP, /*pc*/R11_scratch1);
|
||||||
|
|
||||||
__ mr(klass_index_reg, R3);
|
__ mr(klass_index_reg, R3);
|
||||||
|
__ li(R5, Deoptimization::Unpack_exception);
|
||||||
__ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap),
|
__ call_VM_leaf(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap),
|
||||||
R16_thread, klass_index_reg);
|
R16_thread, klass_index_reg, R5);
|
||||||
|
|
||||||
// Set an oopmap for the call site.
|
// Set an oopmap for the call site.
|
||||||
oop_maps->add_gc_map(gc_map_pc - start, map);
|
oop_maps->add_gc_map(gc_map_pc - start, map);
|
||||||
|
@ -2966,6 +2969,12 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||||
|
|
||||||
// stack: (caller_of_deoptee, ...).
|
// stack: (caller_of_deoptee, ...).
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
__ lwz(R22_tmp2, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes(), unroll_block_reg);
|
||||||
|
__ cmpdi(CCR0, R22_tmp2, (unsigned)Deoptimization::Unpack_uncommon_trap);
|
||||||
|
__ asm_assert_eq("SharedRuntime::generate_deopt_blob: expected Unpack_uncommon_trap", 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Allocate new interpreter frame(s) and possibly a c2i adapter
|
// Allocate new interpreter frame(s) and possibly a c2i adapter
|
||||||
// frame.
|
// frame.
|
||||||
push_skeleton_frames(masm, false/*deopt*/,
|
push_skeleton_frames(masm, false/*deopt*/,
|
||||||
|
|
|
@ -3036,6 +3036,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||||
|
|
||||||
__ mov((int32_t)Deoptimization::Unpack_reexecute, L0deopt_mode);
|
__ mov((int32_t)Deoptimization::Unpack_reexecute, L0deopt_mode);
|
||||||
__ mov(G2_thread, O0);
|
__ mov(G2_thread, O0);
|
||||||
|
__ mov(L0deopt_mode, O2);
|
||||||
__ call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap));
|
__ call(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap));
|
||||||
__ delayed()->nop();
|
__ delayed()->nop();
|
||||||
oop_maps->add_gc_map( __ offset()-start, map->deep_copy());
|
oop_maps->add_gc_map( __ offset()-start, map->deep_copy());
|
||||||
|
@ -3121,6 +3122,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||||
// do the call by hand so we can get the oopmap
|
// do the call by hand so we can get the oopmap
|
||||||
|
|
||||||
__ mov(G2_thread, L7_thread_cache);
|
__ mov(G2_thread, L7_thread_cache);
|
||||||
|
__ mov(L0deopt_mode, O1);
|
||||||
__ call(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info), relocInfo::runtime_call_type);
|
__ call(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info), relocInfo::runtime_call_type);
|
||||||
__ delayed()->mov(G2_thread, O0);
|
__ delayed()->mov(G2_thread, O0);
|
||||||
|
|
||||||
|
@ -3146,6 +3148,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||||
|
|
||||||
RegisterSaver::restore_result_registers(masm);
|
RegisterSaver::restore_result_registers(masm);
|
||||||
|
|
||||||
|
__ ld(O2UnrollBlock, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes(), G4deopt_mode);
|
||||||
Label noException;
|
Label noException;
|
||||||
__ cmp_and_br_short(G4deopt_mode, Deoptimization::Unpack_exception, Assembler::notEqual, Assembler::pt, noException);
|
__ cmp_and_br_short(G4deopt_mode, Deoptimization::Unpack_exception, Assembler::notEqual, Assembler::pt, noException);
|
||||||
|
|
||||||
|
@ -3269,7 +3272,8 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||||
__ save_frame(0);
|
__ save_frame(0);
|
||||||
__ set_last_Java_frame(SP, noreg);
|
__ set_last_Java_frame(SP, noreg);
|
||||||
__ mov(I0, O2klass_index);
|
__ mov(I0, O2klass_index);
|
||||||
__ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap), G2_thread, O2klass_index);
|
__ mov(Deoptimization::Unpack_uncommon_trap, O3); // exec mode
|
||||||
|
__ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap), G2_thread, O2klass_index, O3);
|
||||||
__ reset_last_Java_frame();
|
__ reset_last_Java_frame();
|
||||||
__ mov(O0, O2UnrollBlock->after_save());
|
__ mov(O0, O2UnrollBlock->after_save());
|
||||||
__ restore();
|
__ restore();
|
||||||
|
@ -3278,6 +3282,15 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||||
__ mov(O2UnrollBlock, O2UnrollBlock->after_save());
|
__ mov(O2UnrollBlock, O2UnrollBlock->after_save());
|
||||||
__ restore();
|
__ restore();
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
{ Label L;
|
||||||
|
__ ld(O2UnrollBlock, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes(), O1);
|
||||||
|
__ cmp_and_br_short(O1, Deoptimization::Unpack_uncommon_trap, Assembler::equal, Assembler::pt, L);
|
||||||
|
__ stop("SharedRuntime::generate_deopt_blob: expected Unpack_uncommon_trap");
|
||||||
|
__ bind(L);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Allocate new interpreter frame(s) and possible c2i adapter frame
|
// Allocate new interpreter frame(s) and possible c2i adapter frame
|
||||||
|
|
||||||
make_new_frames(masm, false);
|
make_new_frames(masm, false);
|
||||||
|
|
|
@ -2545,7 +2545,8 @@ void SharedRuntime::generate_deopt_blob() {
|
||||||
|
|
||||||
oop_maps->add_gc_map( __ pc()-start, map);
|
oop_maps->add_gc_map( __ pc()-start, map);
|
||||||
|
|
||||||
// Discard arg to fetch_unroll_info
|
// Discard args to fetch_unroll_info
|
||||||
|
__ pop(rcx);
|
||||||
__ pop(rcx);
|
__ pop(rcx);
|
||||||
|
|
||||||
__ get_thread(rcx);
|
__ get_thread(rcx);
|
||||||
|
@ -2558,9 +2559,8 @@ void SharedRuntime::generate_deopt_blob() {
|
||||||
// we are very short of registers
|
// we are very short of registers
|
||||||
|
|
||||||
Address unpack_kind(rdi, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes());
|
Address unpack_kind(rdi, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes());
|
||||||
// retrieve the deopt kind from where we left it.
|
// retrieve the deopt kind from the UnrollBlock.
|
||||||
__ pop(rax);
|
__ movl(rax, unpack_kind);
|
||||||
__ movl(unpack_kind, rax); // save the unpack_kind value
|
|
||||||
|
|
||||||
Label noException;
|
Label noException;
|
||||||
__ cmpl(rax, Deoptimization::Unpack_exception); // Was exception pending?
|
__ cmpl(rax, Deoptimization::Unpack_exception); // Was exception pending?
|
||||||
|
@ -2770,11 +2770,12 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||||
enum frame_layout {
|
enum frame_layout {
|
||||||
arg0_off, // thread sp + 0 // Arg location for
|
arg0_off, // thread sp + 0 // Arg location for
|
||||||
arg1_off, // unloaded_class_index sp + 1 // calling C
|
arg1_off, // unloaded_class_index sp + 1 // calling C
|
||||||
|
arg2_off, // exec_mode sp + 2
|
||||||
// The frame sender code expects that rbp will be in the "natural" place and
|
// The frame sender code expects that rbp will be in the "natural" place and
|
||||||
// will override any oopMap setting for it. We must therefore force the layout
|
// will override any oopMap setting for it. We must therefore force the layout
|
||||||
// so that it agrees with the frame sender code.
|
// so that it agrees with the frame sender code.
|
||||||
rbp_off, // callee saved register sp + 2
|
rbp_off, // callee saved register sp + 3
|
||||||
return_off, // slot for return address sp + 3
|
return_off, // slot for return address sp + 4
|
||||||
framesize
|
framesize
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2806,6 +2807,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||||
__ movptr(Address(rsp, arg0_off*wordSize), rdx);
|
__ movptr(Address(rsp, arg0_off*wordSize), rdx);
|
||||||
// argument already in ECX
|
// argument already in ECX
|
||||||
__ movl(Address(rsp, arg1_off*wordSize),rcx);
|
__ movl(Address(rsp, arg1_off*wordSize),rcx);
|
||||||
|
__ movl(Address(rsp, arg2_off*wordSize), Deoptimization::Unpack_uncommon_trap);
|
||||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
|
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
|
||||||
|
|
||||||
// Set an oopmap for the call site
|
// Set an oopmap for the call site
|
||||||
|
@ -2822,6 +2824,16 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||||
// Load UnrollBlock into EDI
|
// Load UnrollBlock into EDI
|
||||||
__ movptr(rdi, rax);
|
__ movptr(rdi, rax);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
{ Label L;
|
||||||
|
__ cmpptr(Address(rdi, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes()),
|
||||||
|
(int32_t)Deoptimization::Unpack_uncommon_trap);
|
||||||
|
__ jcc(Assembler::equal, L);
|
||||||
|
__ stop("SharedRuntime::generate_deopt_blob: expected Unpack_uncommon_trap");
|
||||||
|
__ bind(L);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Pop all the frames we must move/replace.
|
// Pop all the frames we must move/replace.
|
||||||
//
|
//
|
||||||
// Frame picture (youngest to oldest)
|
// Frame picture (youngest to oldest)
|
||||||
|
|
|
@ -2829,6 +2829,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||||
|
|
||||||
__ movl(r14, (int32_t)Deoptimization::Unpack_reexecute);
|
__ movl(r14, (int32_t)Deoptimization::Unpack_reexecute);
|
||||||
__ mov(c_rarg0, r15_thread);
|
__ mov(c_rarg0, r15_thread);
|
||||||
|
__ movl(c_rarg2, r14); // exec mode
|
||||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
|
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
|
||||||
oop_maps->add_gc_map( __ pc()-start, map->deep_copy());
|
oop_maps->add_gc_map( __ pc()-start, map->deep_copy());
|
||||||
|
|
||||||
|
@ -2915,6 +2916,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||||
}
|
}
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
__ mov(c_rarg0, r15_thread);
|
__ mov(c_rarg0, r15_thread);
|
||||||
|
__ movl(c_rarg1, r14); // exec_mode
|
||||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info)));
|
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::fetch_unroll_info)));
|
||||||
|
|
||||||
// Need to have an oopmap that tells fetch_unroll_info where to
|
// Need to have an oopmap that tells fetch_unroll_info where to
|
||||||
|
@ -2932,6 +2934,7 @@ void SharedRuntime::generate_deopt_blob() {
|
||||||
// Load UnrollBlock* into rdi
|
// Load UnrollBlock* into rdi
|
||||||
__ mov(rdi, rax);
|
__ mov(rdi, rax);
|
||||||
|
|
||||||
|
__ movl(r14, Address(rdi, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes()));
|
||||||
Label noException;
|
Label noException;
|
||||||
__ cmpl(r14, Deoptimization::Unpack_exception); // Was exception pending?
|
__ cmpl(r14, Deoptimization::Unpack_exception); // Was exception pending?
|
||||||
__ jcc(Assembler::notEqual, noException);
|
__ jcc(Assembler::notEqual, noException);
|
||||||
|
@ -3150,6 +3153,7 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||||
// UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index);
|
// UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index);
|
||||||
|
|
||||||
__ mov(c_rarg0, r15_thread);
|
__ mov(c_rarg0, r15_thread);
|
||||||
|
__ movl(c_rarg2, Deoptimization::Unpack_uncommon_trap);
|
||||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
|
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, Deoptimization::uncommon_trap)));
|
||||||
|
|
||||||
// Set an oopmap for the call site
|
// Set an oopmap for the call site
|
||||||
|
@ -3165,6 +3169,16 @@ void SharedRuntime::generate_uncommon_trap_blob() {
|
||||||
// Load UnrollBlock* into rdi
|
// Load UnrollBlock* into rdi
|
||||||
__ mov(rdi, rax);
|
__ mov(rdi, rax);
|
||||||
|
|
||||||
|
#ifdef ASSERT
|
||||||
|
{ Label L;
|
||||||
|
__ cmpptr(Address(rdi, Deoptimization::UnrollBlock::unpack_kind_offset_in_bytes()),
|
||||||
|
(int32_t)Deoptimization::Unpack_uncommon_trap);
|
||||||
|
__ jcc(Assembler::equal, L);
|
||||||
|
__ stop("SharedRuntime::generate_deopt_blob: expected Unpack_uncommon_trap");
|
||||||
|
__ bind(L);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Pop all the frames we must move/replace.
|
// Pop all the frames we must move/replace.
|
||||||
//
|
//
|
||||||
// Frame picture (youngest to oldest)
|
// Frame picture (youngest to oldest)
|
||||||
|
|
|
@ -1677,6 +1677,7 @@ public class HotSpotVMConfig {
|
||||||
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_caller_adjustment", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockCallerAdjustmentOffset;
|
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_caller_adjustment", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockCallerAdjustmentOffset;
|
||||||
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_number_of_frames", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockNumberOfFramesOffset;
|
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_number_of_frames", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockNumberOfFramesOffset;
|
||||||
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_total_frame_sizes", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockTotalFrameSizesOffset;
|
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_total_frame_sizes", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockTotalFrameSizesOffset;
|
||||||
|
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_unpack_kind", type = "int", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockUnpackKindOffset;
|
||||||
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_frame_sizes", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockFrameSizesOffset;
|
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_frame_sizes", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockFrameSizesOffset;
|
||||||
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_frame_pcs", type = "address*", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockFramePcsOffset;
|
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_frame_pcs", type = "address*", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockFramePcsOffset;
|
||||||
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_initial_info", type = "intptr_t", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockInitialInfoOffset;
|
@HotSpotVMField(name = "Deoptimization::UnrollBlock::_initial_info", type = "intptr_t", get = HotSpotVMField.Type.OFFSET) @Stable public int deoptimizationUnrollBlockInitialInfoOffset;
|
||||||
|
|
|
@ -68,7 +68,8 @@ Deoptimization::UnrollBlock::UnrollBlock(int size_of_deoptimized_frame,
|
||||||
int number_of_frames,
|
int number_of_frames,
|
||||||
intptr_t* frame_sizes,
|
intptr_t* frame_sizes,
|
||||||
address* frame_pcs,
|
address* frame_pcs,
|
||||||
BasicType return_type) {
|
BasicType return_type,
|
||||||
|
int exec_mode) {
|
||||||
_size_of_deoptimized_frame = size_of_deoptimized_frame;
|
_size_of_deoptimized_frame = size_of_deoptimized_frame;
|
||||||
_caller_adjustment = caller_adjustment;
|
_caller_adjustment = caller_adjustment;
|
||||||
_caller_actual_parameters = caller_actual_parameters;
|
_caller_actual_parameters = caller_actual_parameters;
|
||||||
|
@ -80,10 +81,11 @@ Deoptimization::UnrollBlock::UnrollBlock(int size_of_deoptimized_frame,
|
||||||
_initial_info = 0;
|
_initial_info = 0;
|
||||||
// PD (x86 only)
|
// PD (x86 only)
|
||||||
_counter_temp = 0;
|
_counter_temp = 0;
|
||||||
_unpack_kind = 0;
|
_unpack_kind = exec_mode;
|
||||||
_sender_sp_temp = 0;
|
_sender_sp_temp = 0;
|
||||||
|
|
||||||
_total_frame_sizes = size_of_frames();
|
_total_frame_sizes = size_of_frames();
|
||||||
|
assert(exec_mode >= 0 && exec_mode < Unpack_LIMIT, "Unexpected exec_mode");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -128,7 +130,7 @@ void Deoptimization::UnrollBlock::print() {
|
||||||
// ResetNoHandleMark and HandleMark were removed from it. The actual reallocation
|
// ResetNoHandleMark and HandleMark were removed from it. The actual reallocation
|
||||||
// of previously eliminated objects occurs in realloc_objects, which is
|
// of previously eliminated objects occurs in realloc_objects, which is
|
||||||
// called from the method fetch_unroll_info_helper below.
|
// called from the method fetch_unroll_info_helper below.
|
||||||
JRT_BLOCK_ENTRY(Deoptimization::UnrollBlock*, Deoptimization::fetch_unroll_info(JavaThread* thread))
|
JRT_BLOCK_ENTRY(Deoptimization::UnrollBlock*, Deoptimization::fetch_unroll_info(JavaThread* thread, int exec_mode))
|
||||||
// It is actually ok to allocate handles in a leaf method. It causes no safepoints,
|
// It is actually ok to allocate handles in a leaf method. It causes no safepoints,
|
||||||
// but makes the entry a little slower. There is however a little dance we have to
|
// but makes the entry a little slower. There is however a little dance we have to
|
||||||
// do in debug mode to get around the NoHandleMark code in the JRT_LEAF macro
|
// do in debug mode to get around the NoHandleMark code in the JRT_LEAF macro
|
||||||
|
@ -142,12 +144,12 @@ JRT_BLOCK_ENTRY(Deoptimization::UnrollBlock*, Deoptimization::fetch_unroll_info(
|
||||||
}
|
}
|
||||||
thread->inc_in_deopt_handler();
|
thread->inc_in_deopt_handler();
|
||||||
|
|
||||||
return fetch_unroll_info_helper(thread);
|
return fetch_unroll_info_helper(thread, exec_mode);
|
||||||
JRT_END
|
JRT_END
|
||||||
|
|
||||||
|
|
||||||
// This is factored, since it is both called from a JRT_LEAF (deoptimization) and a JRT_ENTRY (uncommon_trap)
|
// This is factored, since it is both called from a JRT_LEAF (deoptimization) and a JRT_ENTRY (uncommon_trap)
|
||||||
Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread* thread) {
|
Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread* thread, int exec_mode) {
|
||||||
|
|
||||||
// Note: there is a safepoint safety issue here. No matter whether we enter
|
// Note: there is a safepoint safety issue here. No matter whether we enter
|
||||||
// via vanilla deopt or uncommon trap we MUST NOT stop at a safepoint once
|
// via vanilla deopt or uncommon trap we MUST NOT stop at a safepoint once
|
||||||
|
@ -186,6 +188,19 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||||
assert(vf->is_compiled_frame(), "Wrong frame type");
|
assert(vf->is_compiled_frame(), "Wrong frame type");
|
||||||
chunk->push(compiledVFrame::cast(vf));
|
chunk->push(compiledVFrame::cast(vf));
|
||||||
|
|
||||||
|
ScopeDesc* trap_scope = chunk->at(0)->scope();
|
||||||
|
Handle exceptionObject;
|
||||||
|
if (trap_scope->rethrow_exception()) {
|
||||||
|
if (PrintDeoptimizationDetails) {
|
||||||
|
tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", trap_scope->method()->method_holder()->name()->as_C_string(), trap_scope->method()->name()->as_C_string(), trap_scope->bci());
|
||||||
|
}
|
||||||
|
GrowableArray<ScopeValue*>* expressions = trap_scope->expressions();
|
||||||
|
guarantee(expressions != NULL && expressions->length() > 0, "must have exception to throw");
|
||||||
|
ScopeValue* topOfStack = expressions->top();
|
||||||
|
exceptionObject = StackValue::create_stack_value(&deoptee, &map, topOfStack)->get_obj();
|
||||||
|
assert(exceptionObject() != NULL, "exception oop can not be null");
|
||||||
|
}
|
||||||
|
|
||||||
bool realloc_failures = false;
|
bool realloc_failures = false;
|
||||||
|
|
||||||
#if defined(COMPILER2) || INCLUDE_JVMCI
|
#if defined(COMPILER2) || INCLUDE_JVMCI
|
||||||
|
@ -474,13 +489,21 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||||
assert(CodeCache::find_blob_unsafe(frame_pcs[0]) != NULL, "bad pc");
|
assert(CodeCache::find_blob_unsafe(frame_pcs[0]) != NULL, "bad pc");
|
||||||
#endif // SHARK
|
#endif // SHARK
|
||||||
|
|
||||||
|
#ifdef INCLUDE_JVMCI
|
||||||
|
if (exceptionObject() != NULL) {
|
||||||
|
thread->set_exception_oop(exceptionObject());
|
||||||
|
exec_mode = Unpack_exception;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
UnrollBlock* info = new UnrollBlock(array->frame_size() * BytesPerWord,
|
UnrollBlock* info = new UnrollBlock(array->frame_size() * BytesPerWord,
|
||||||
caller_adjustment * BytesPerWord,
|
caller_adjustment * BytesPerWord,
|
||||||
caller_was_method_handle ? 0 : callee_parameters,
|
caller_was_method_handle ? 0 : callee_parameters,
|
||||||
number_of_frames,
|
number_of_frames,
|
||||||
frame_sizes,
|
frame_sizes,
|
||||||
frame_pcs,
|
frame_pcs,
|
||||||
return_type);
|
return_type,
|
||||||
|
exec_mode);
|
||||||
// On some platforms, we need a way to pass some platform dependent
|
// On some platforms, we need a way to pass some platform dependent
|
||||||
// information to the unpacking code so the skeletal frames come out
|
// information to the unpacking code so the skeletal frames come out
|
||||||
// correct (initial fp value, unextended sp, ...)
|
// correct (initial fp value, unextended sp, ...)
|
||||||
|
@ -1495,18 +1518,6 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* thread, jint tra
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Bytecodes::Code trap_bc = trap_method->java_code_at(trap_bci);
|
Bytecodes::Code trap_bc = trap_method->java_code_at(trap_bci);
|
||||||
|
|
||||||
if (trap_scope->rethrow_exception()) {
|
|
||||||
if (PrintDeoptimizationDetails) {
|
|
||||||
tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", trap_method->method_holder()->name()->as_C_string(), trap_method->name()->as_C_string(), trap_bci);
|
|
||||||
}
|
|
||||||
GrowableArray<ScopeValue*>* expressions = trap_scope->expressions();
|
|
||||||
guarantee(expressions != NULL, "must have exception to throw");
|
|
||||||
ScopeValue* topOfStack = expressions->top();
|
|
||||||
Handle topOfStackObj = StackValue::create_stack_value(&fr, ®_map, topOfStack)->get_obj();
|
|
||||||
THREAD->set_pending_exception(topOfStackObj(), NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Record this event in the histogram.
|
// Record this event in the histogram.
|
||||||
gather_statistics(reason, action, trap_bc);
|
gather_statistics(reason, action, trap_bc);
|
||||||
|
|
||||||
|
@ -1985,7 +1996,7 @@ Deoptimization::update_method_data_from_interpreter(MethodData* trap_mdo, int tr
|
||||||
ignore_maybe_prior_recompile);
|
ignore_maybe_prior_recompile);
|
||||||
}
|
}
|
||||||
|
|
||||||
Deoptimization::UnrollBlock* Deoptimization::uncommon_trap(JavaThread* thread, jint trap_request) {
|
Deoptimization::UnrollBlock* Deoptimization::uncommon_trap(JavaThread* thread, jint trap_request, jint exec_mode) {
|
||||||
if (TraceDeoptimization) {
|
if (TraceDeoptimization) {
|
||||||
tty->print("Uncommon trap ");
|
tty->print("Uncommon trap ");
|
||||||
}
|
}
|
||||||
|
@ -1994,7 +2005,7 @@ Deoptimization::UnrollBlock* Deoptimization::uncommon_trap(JavaThread* thread, j
|
||||||
// This enters VM and may safepoint
|
// This enters VM and may safepoint
|
||||||
uncommon_trap_inner(thread, trap_request);
|
uncommon_trap_inner(thread, trap_request);
|
||||||
}
|
}
|
||||||
return fetch_unroll_info_helper(thread);
|
return fetch_unroll_info_helper(thread, exec_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Local derived constants.
|
// Local derived constants.
|
||||||
|
|
|
@ -123,7 +123,8 @@ class Deoptimization : AllStatic {
|
||||||
Unpack_deopt = 0, // normal deoptimization, use pc computed in unpack_vframe_on_stack
|
Unpack_deopt = 0, // normal deoptimization, use pc computed in unpack_vframe_on_stack
|
||||||
Unpack_exception = 1, // exception is pending
|
Unpack_exception = 1, // exception is pending
|
||||||
Unpack_uncommon_trap = 2, // redo last byte code (C2 only)
|
Unpack_uncommon_trap = 2, // redo last byte code (C2 only)
|
||||||
Unpack_reexecute = 3 // reexecute bytecode (C1 only)
|
Unpack_reexecute = 3, // reexecute bytecode (C1 only)
|
||||||
|
Unpack_LIMIT = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
// Checks all compiled methods. Invalid methods are deleted and
|
// Checks all compiled methods. Invalid methods are deleted and
|
||||||
|
@ -179,13 +180,13 @@ JVMCI_ONLY(public:)
|
||||||
intptr_t _initial_info; // Platform dependent data for the sender frame (was FP on x86)
|
intptr_t _initial_info; // Platform dependent data for the sender frame (was FP on x86)
|
||||||
int _caller_actual_parameters; // The number of actual arguments at the
|
int _caller_actual_parameters; // The number of actual arguments at the
|
||||||
// interpreted caller of the deoptimized frame
|
// interpreted caller of the deoptimized frame
|
||||||
|
int _unpack_kind; // exec_mode that can be changed during fetch_unroll_info
|
||||||
|
|
||||||
// The following fields are used as temps during the unpacking phase
|
// The following fields are used as temps during the unpacking phase
|
||||||
// (which is tight on registers, especially on x86). They really ought
|
// (which is tight on registers, especially on x86). They really ought
|
||||||
// to be PD variables but that involves moving this class into its own
|
// to be PD variables but that involves moving this class into its own
|
||||||
// file to use the pd include mechanism. Maybe in a later cleanup ...
|
// file to use the pd include mechanism. Maybe in a later cleanup ...
|
||||||
intptr_t _counter_temp; // SHOULD BE PD VARIABLE (x86 frame count temp)
|
intptr_t _counter_temp; // SHOULD BE PD VARIABLE (x86 frame count temp)
|
||||||
intptr_t _unpack_kind; // SHOULD BE PD VARIABLE (x86 unpack kind)
|
|
||||||
intptr_t _sender_sp_temp; // SHOULD BE PD VARIABLE (x86 sender_sp)
|
intptr_t _sender_sp_temp; // SHOULD BE PD VARIABLE (x86 sender_sp)
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
|
@ -195,7 +196,8 @@ JVMCI_ONLY(public:)
|
||||||
int number_of_frames,
|
int number_of_frames,
|
||||||
intptr_t* frame_sizes,
|
intptr_t* frame_sizes,
|
||||||
address* frames_pcs,
|
address* frames_pcs,
|
||||||
BasicType return_type);
|
BasicType return_type,
|
||||||
|
int unpack_kind);
|
||||||
~UnrollBlock();
|
~UnrollBlock();
|
||||||
|
|
||||||
// Returns where a register is located.
|
// Returns where a register is located.
|
||||||
|
@ -205,6 +207,7 @@ JVMCI_ONLY(public:)
|
||||||
intptr_t* frame_sizes() const { return _frame_sizes; }
|
intptr_t* frame_sizes() const { return _frame_sizes; }
|
||||||
int number_of_frames() const { return _number_of_frames; }
|
int number_of_frames() const { return _number_of_frames; }
|
||||||
address* frame_pcs() const { return _frame_pcs ; }
|
address* frame_pcs() const { return _frame_pcs ; }
|
||||||
|
int unpack_kind() const { return _unpack_kind; }
|
||||||
|
|
||||||
// Returns the total size of frames
|
// Returns the total size of frames
|
||||||
int size_of_frames() const;
|
int size_of_frames() const;
|
||||||
|
@ -237,7 +240,7 @@ JVMCI_ONLY(public:)
|
||||||
// deoptimized frame.
|
// deoptimized frame.
|
||||||
// @argument thread. Thread where stub_frame resides.
|
// @argument thread. Thread where stub_frame resides.
|
||||||
// @see OptoRuntime::deoptimization_fetch_unroll_info_C
|
// @see OptoRuntime::deoptimization_fetch_unroll_info_C
|
||||||
static UnrollBlock* fetch_unroll_info(JavaThread* thread);
|
static UnrollBlock* fetch_unroll_info(JavaThread* thread, int exec_mode);
|
||||||
|
|
||||||
//** Unpacks vframeArray onto execution stack
|
//** Unpacks vframeArray onto execution stack
|
||||||
// Called by assembly stub after execution has returned to
|
// Called by assembly stub after execution has returned to
|
||||||
|
@ -262,7 +265,7 @@ JVMCI_ONLY(public:)
|
||||||
|
|
||||||
//** Performs an uncommon trap for compiled code.
|
//** Performs an uncommon trap for compiled code.
|
||||||
// The top most compiler frame is converted into interpreter frames
|
// The top most compiler frame is converted into interpreter frames
|
||||||
static UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index);
|
static UnrollBlock* uncommon_trap(JavaThread* thread, jint unloaded_class_index, jint exec_mode);
|
||||||
// Helper routine that enters the VM and may block
|
// Helper routine that enters the VM and may block
|
||||||
static void uncommon_trap_inner(JavaThread* thread, jint unloaded_class_index);
|
static void uncommon_trap_inner(JavaThread* thread, jint unloaded_class_index);
|
||||||
|
|
||||||
|
@ -423,7 +426,7 @@ JVMCI_ONLY(public:)
|
||||||
static void load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS);
|
static void load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS);
|
||||||
static void load_class_by_index(constantPoolHandle constant_pool, int index);
|
static void load_class_by_index(constantPoolHandle constant_pool, int index);
|
||||||
|
|
||||||
static UnrollBlock* fetch_unroll_info_helper(JavaThread* thread);
|
static UnrollBlock* fetch_unroll_info_helper(JavaThread* thread, int exec_mode);
|
||||||
|
|
||||||
static DeoptAction _unloaded_action; // == Action_reinterpret;
|
static DeoptAction _unloaded_action; // == Action_reinterpret;
|
||||||
static const char* _trap_reason_name[];
|
static const char* _trap_reason_name[];
|
||||||
|
|
|
@ -968,6 +968,7 @@ typedef CompactHashtable<Symbol*, char> SymbolCompactHashTable;
|
||||||
nonstatic_field(Deoptimization::UnrollBlock, _caller_adjustment, int) \
|
nonstatic_field(Deoptimization::UnrollBlock, _caller_adjustment, int) \
|
||||||
nonstatic_field(Deoptimization::UnrollBlock, _number_of_frames, int) \
|
nonstatic_field(Deoptimization::UnrollBlock, _number_of_frames, int) \
|
||||||
nonstatic_field(Deoptimization::UnrollBlock, _total_frame_sizes, int) \
|
nonstatic_field(Deoptimization::UnrollBlock, _total_frame_sizes, int) \
|
||||||
|
nonstatic_field(Deoptimization::UnrollBlock, _unpack_kind, int) \
|
||||||
nonstatic_field(Deoptimization::UnrollBlock, _frame_sizes, intptr_t*) \
|
nonstatic_field(Deoptimization::UnrollBlock, _frame_sizes, intptr_t*) \
|
||||||
nonstatic_field(Deoptimization::UnrollBlock, _frame_pcs, address*) \
|
nonstatic_field(Deoptimization::UnrollBlock, _frame_pcs, address*) \
|
||||||
nonstatic_field(Deoptimization::UnrollBlock, _register_block, intptr_t*) \
|
nonstatic_field(Deoptimization::UnrollBlock, _register_block, intptr_t*) \
|
||||||
|
|
|
@ -213,8 +213,9 @@ int SharkRuntime::uncommon_trap(JavaThread* thread, int trap_request) {
|
||||||
// Initiate the trap
|
// Initiate the trap
|
||||||
thread->set_last_Java_frame();
|
thread->set_last_Java_frame();
|
||||||
Deoptimization::UnrollBlock *urb =
|
Deoptimization::UnrollBlock *urb =
|
||||||
Deoptimization::uncommon_trap(thread, trap_request);
|
Deoptimization::uncommon_trap(thread, trap_request, Deoptimization::Unpack_uncommon_trap);
|
||||||
thread->reset_last_Java_frame();
|
thread->reset_last_Java_frame();
|
||||||
|
assert(urb->unpack_kind() == Deoptimization::Unpack_uncommon_trap, "expected Unpack_uncommon_trap");
|
||||||
|
|
||||||
// Pop our dummy frame and the frame being deoptimized
|
// Pop our dummy frame and the frame being deoptimized
|
||||||
thread->pop_zero_frame();
|
thread->pop_zero_frame();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue