mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-28 20:03:39 +00:00
8366461: Remove obsolete method handle invoke logic
Reviewed-by: vlivanov, mhaessig
This commit is contained in:
parent
fa6e884105
commit
da7121aff9
@ -2568,10 +2568,6 @@ RegMask Matcher::modL_proj_mask() {
|
||||
return RegMask();
|
||||
}
|
||||
|
||||
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||
return FP_REG_mask();
|
||||
}
|
||||
|
||||
bool size_fits_all_mem_uses(AddPNode* addp, int shift) {
|
||||
for (DUIterator_Fast imax, i = addp->fast_outs(imax); i < imax; i++) {
|
||||
Node* u = addp->fast_out(i);
|
||||
|
||||
@ -383,13 +383,6 @@ LIR_Opr FrameMap::stack_pointer() {
|
||||
return FrameMap::sp_opr;
|
||||
}
|
||||
|
||||
|
||||
// JSR 292
|
||||
LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
|
||||
return LIR_OprFact::illegalOpr; // Not needed on aarch64
|
||||
}
|
||||
|
||||
|
||||
bool FrameMap::validate_frame() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -228,8 +228,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
||||
|
||||
nmethod* nm = sender_blob->as_nmethod_or_null();
|
||||
if (nm != nullptr) {
|
||||
if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) ||
|
||||
nm->method()->is_method_handle_intrinsic()) {
|
||||
if (nm->is_deopt_entry(sender_pc) || nm->method()->is_method_handle_intrinsic()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -454,48 +453,6 @@ JavaThread** frame::saved_thread_address(const frame& f) {
|
||||
return thread_addr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::verify_deopt_original_pc
|
||||
//
|
||||
// Verifies the calculated original PC of a deoptimization PC for the
|
||||
// given unextended SP.
|
||||
#ifdef ASSERT
|
||||
void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp) {
|
||||
frame fr;
|
||||
|
||||
// This is ugly but it's better than to change {get,set}_original_pc
|
||||
// to take an SP value as argument. And it's only a debugging
|
||||
// method anyway.
|
||||
fr._unextended_sp = unextended_sp;
|
||||
|
||||
address original_pc = nm->get_original_pc(&fr);
|
||||
assert(nm->insts_contains_inclusive(original_pc),
|
||||
"original PC must be in the main code section of the compiled method (or must be immediately following it)");
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
#ifdef ASSERT
|
||||
void frame::adjust_unextended_sp() {
|
||||
// On aarch64, sites calling method handle intrinsics and lambda forms are treated
|
||||
// as any other call site. Therefore, no special action is needed when we are
|
||||
// returning to any of these call sites.
|
||||
|
||||
if (_cb != nullptr) {
|
||||
nmethod* sender_nm = _cb->as_nmethod_or_null();
|
||||
if (sender_nm != nullptr) {
|
||||
// If the sender PC is a deoptimization point, get the original PC.
|
||||
if (sender_nm->is_deopt_entry(_pc) ||
|
||||
sender_nm->is_deopt_mh_entry(_pc)) {
|
||||
verify_deopt_original_pc(sender_nm, _unextended_sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::sender_for_interpreter_frame
|
||||
frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -141,8 +141,6 @@
|
||||
int _offset_unextended_sp; // for use in stack-chunk frames
|
||||
};
|
||||
|
||||
void adjust_unextended_sp() NOT_DEBUG_RETURN;
|
||||
|
||||
// true means _sp value is correct and we can use it to get the sender's sp
|
||||
// of the compiled frame, otherwise, _sp value may be invalid and we can use
|
||||
// _fp to get the sender's sp if PreserveFramePointer is enabled.
|
||||
@ -152,11 +150,6 @@
|
||||
return (intptr_t*) addr_at(offset);
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
// Used in frame::sender_for_{interpreter,compiled}_frame
|
||||
static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp);
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
|
||||
|
||||
@ -116,8 +116,6 @@ inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
|
||||
}
|
||||
|
||||
inline void frame::setup(address pc) {
|
||||
adjust_unextended_sp();
|
||||
|
||||
address original_pc = get_deopt_original_pc();
|
||||
if (original_pc != nullptr) {
|
||||
_pc = original_pc;
|
||||
@ -223,7 +221,6 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) {
|
||||
// assert(_pc != nullptr, "no pc?");
|
||||
|
||||
_cb = CodeCache::find_blob(_pc);
|
||||
adjust_unextended_sp();
|
||||
|
||||
address original_pc = get_deopt_original_pc();
|
||||
if (original_pc != nullptr) {
|
||||
|
||||
@ -1154,10 +1154,6 @@ RegMask Matcher::modL_proj_mask() {
|
||||
return RegMask();
|
||||
}
|
||||
|
||||
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||
return FP_REGP_mask();
|
||||
}
|
||||
|
||||
bool maybe_far_call(const CallNode *n) {
|
||||
return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point());
|
||||
}
|
||||
@ -1248,23 +1244,6 @@ encode %{
|
||||
__ set_inst_mark(mark);
|
||||
%}
|
||||
|
||||
enc_class preserve_SP %{
|
||||
// preserve mark
|
||||
address mark = __ inst_mark();
|
||||
DEBUG_ONLY(int off0 = __ offset());
|
||||
// FP is preserved across all calls, even compiled calls.
|
||||
// Use it to preserve SP in places where the callee might change the SP.
|
||||
__ mov(Rmh_SP_save, SP);
|
||||
DEBUG_ONLY(int off1 = __ offset());
|
||||
assert(off1 - off0 == 4, "correct size prediction");
|
||||
// restore mark
|
||||
__ set_inst_mark(mark);
|
||||
%}
|
||||
|
||||
enc_class restore_SP %{
|
||||
__ mov(SP, Rmh_SP_save);
|
||||
%}
|
||||
|
||||
enc_class Java_Dynamic_Call (method meth) %{
|
||||
Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode());
|
||||
assert(R8_ic_reg == Ricklass, "should be");
|
||||
@ -8799,7 +8778,6 @@ instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{
|
||||
// Call Java Static Instruction
|
||||
instruct CallStaticJavaDirect( method meth ) %{
|
||||
match(CallStaticJava);
|
||||
predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke());
|
||||
effect(USE meth);
|
||||
|
||||
ins_cost(CALL_COST);
|
||||
@ -8808,20 +8786,6 @@ instruct CallStaticJavaDirect( method meth ) %{
|
||||
ins_pipe(simple_call);
|
||||
%}
|
||||
|
||||
// Call Java Static Instruction (method handle version)
|
||||
instruct CallStaticJavaHandle( method meth ) %{
|
||||
match(CallStaticJava);
|
||||
predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke());
|
||||
effect(USE meth);
|
||||
// FP is saved by all callees (for interpreter stack correction).
|
||||
// We use it here for a similar purpose, in {preserve,restore}_FP.
|
||||
|
||||
ins_cost(CALL_COST);
|
||||
format %{ "CALL,static/MethodHandle ==> " %}
|
||||
ins_encode( SetInstMark, preserve_SP, Java_Static_Call( meth ), restore_SP, call_epilog, ClearInstMark );
|
||||
ins_pipe(simple_call);
|
||||
%}
|
||||
|
||||
// Call Java Dynamic Instruction
|
||||
instruct CallDynamicJavaDirect( method meth ) %{
|
||||
match(CallDynamicJava);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
//
|
||||
// Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
// Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
//
|
||||
// This code is free software; you can redistribute it and/or modify it
|
||||
@ -432,8 +432,7 @@ OptoRegPair c2::return_value(int ideal_reg) {
|
||||
|
||||
int MachCallStaticJavaNode::ret_addr_offset() {
|
||||
bool far = (_method == nullptr) ? maybe_far_call(this) : !cache_reachable();
|
||||
return ((far ? 3 : 1) + (_method_handle_invoke ? 1 : 0)) *
|
||||
NativeInstruction::instruction_size;
|
||||
return (far ? 3 : 1) * NativeInstruction::instruction_size;
|
||||
}
|
||||
|
||||
int MachCallDynamicJavaNode::ret_addr_offset() {
|
||||
|
||||
@ -174,11 +174,6 @@ LIR_Opr FrameMap::stack_pointer() {
|
||||
return FrameMap::SP_opr;
|
||||
}
|
||||
|
||||
LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
|
||||
assert(Rmh_SP_save == FP, "Fix register used for saving SP for MethodHandle calls");
|
||||
return FP_opr;
|
||||
}
|
||||
|
||||
bool FrameMap::validate_frame() {
|
||||
int max_offset = in_bytes(framesize_in_bytes());
|
||||
int java_index = 0;
|
||||
|
||||
@ -275,14 +275,6 @@ OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address targe
|
||||
}
|
||||
|
||||
|
||||
static void restore_sp_for_method_handle(StubAssembler* sasm) {
|
||||
// Restore SP from its saved reg (FP) if the exception PC is a MethodHandle call site.
|
||||
__ ldr_s32(Rtemp, Address(Rthread, JavaThread::is_method_handle_return_offset()));
|
||||
__ cmp(Rtemp, 0);
|
||||
__ mov(SP, Rmh_SP_save, ne);
|
||||
}
|
||||
|
||||
|
||||
OopMapSet* Runtime1::generate_handle_exception(StubId id, StubAssembler* sasm) {
|
||||
__ block_comment("generate_handle_exception");
|
||||
|
||||
@ -339,7 +331,6 @@ OopMapSet* Runtime1::generate_handle_exception(StubId id, StubAssembler* sasm) {
|
||||
break;
|
||||
case StubId::c1_handle_exception_from_callee_id:
|
||||
restore_live_registers_without_return(sasm); // must not jump immediately to handler
|
||||
restore_sp_for_method_handle(sasm);
|
||||
__ ret();
|
||||
break;
|
||||
default: ShouldNotReachHere();
|
||||
@ -372,9 +363,6 @@ void Runtime1::generate_unwind_exception(StubAssembler* sasm) {
|
||||
// Jump to handler
|
||||
__ verify_not_null_oop(Rexception_obj);
|
||||
|
||||
// JSR292 extension
|
||||
restore_sp_for_method_handle(sasm);
|
||||
|
||||
__ jump(R0);
|
||||
}
|
||||
|
||||
|
||||
@ -329,56 +329,6 @@ JavaThread** frame::saved_thread_address(const frame& f) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::verify_deopt_original_pc
|
||||
//
|
||||
// Verifies the calculated original PC of a deoptimization PC for the
|
||||
// given unextended SP. The unextended SP might also be the saved SP
|
||||
// for MethodHandle call sites.
|
||||
#ifdef ASSERT
|
||||
void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return) {
|
||||
frame fr;
|
||||
|
||||
// This is ugly but it's better than to change {get,set}_original_pc
|
||||
// to take an SP value as argument. And it's only a debugging
|
||||
// method anyway.
|
||||
fr._unextended_sp = unextended_sp;
|
||||
|
||||
address original_pc = nm->get_original_pc(&fr);
|
||||
assert(nm->insts_contains_inclusive(original_pc),
|
||||
"original PC must be in the main code section of the compiled method (or must be immediately following it)");
|
||||
assert(nm->is_method_handle_return(original_pc) == is_method_handle_return, "must be");
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
void frame::adjust_unextended_sp() {
|
||||
// same as on x86
|
||||
|
||||
// If we are returning to a compiled MethodHandle call site, the
|
||||
// saved_fp will in fact be a saved value of the unextended SP. The
|
||||
// simplest way to tell whether we are returning to such a call site
|
||||
// is as follows:
|
||||
|
||||
nmethod* sender_nm = (_cb == nullptr) ? nullptr : _cb->as_nmethod_or_null();
|
||||
if (sender_nm != nullptr) {
|
||||
// If the sender PC is a deoptimization point, get the original
|
||||
// PC. For MethodHandle call site the unextended_sp is stored in
|
||||
// saved_fp.
|
||||
if (sender_nm->is_deopt_mh_entry(_pc)) {
|
||||
DEBUG_ONLY(verify_deopt_mh_original_pc(sender_nm, _fp));
|
||||
_unextended_sp = _fp;
|
||||
}
|
||||
else if (sender_nm->is_deopt_entry(_pc)) {
|
||||
DEBUG_ONLY(verify_deopt_original_pc(sender_nm, _unextended_sp));
|
||||
}
|
||||
else if (sender_nm->is_method_handle_return(_pc)) {
|
||||
_unextended_sp = _fp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::update_map_with_saved_link
|
||||
void frame::update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -85,20 +85,11 @@
|
||||
// original sp.
|
||||
|
||||
intptr_t* _unextended_sp;
|
||||
void adjust_unextended_sp();
|
||||
|
||||
intptr_t* ptr_at_addr(int offset) const {
|
||||
return (intptr_t*) addr_at(offset);
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
// Used in frame::sender_for_{interpreter,compiled}_frame
|
||||
static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return = false);
|
||||
static void verify_deopt_mh_original_pc(nmethod* nm, intptr_t* unextended_sp) {
|
||||
verify_deopt_original_pc(nm, unextended_sp, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -112,8 +112,6 @@ inline void frame::init(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, add
|
||||
}
|
||||
|
||||
inline void frame::setup(address pc) {
|
||||
adjust_unextended_sp();
|
||||
|
||||
address original_pc = get_deopt_original_pc();
|
||||
if (original_pc != nullptr) {
|
||||
_pc = original_pc;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -364,7 +364,6 @@ class VFPSystemRegisterImpl : public AbstractRegisterImpl {
|
||||
// This does not seem to conflict with Rexception_pc
|
||||
// In case of issues, R3 might be OK but adapters calling the runtime would have to save it
|
||||
#define R5_mh R5 // MethodHandle register, used during the call setup
|
||||
#define Rmh_SP_save FP // for C1
|
||||
|
||||
/*
|
||||
* C++ Interpreter Register Defines
|
||||
|
||||
@ -264,11 +264,6 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
|
||||
|
||||
__ raw_pop(FP, LR);
|
||||
|
||||
// Restore SP from its saved reg (FP) if the exception PC is a MethodHandle call site.
|
||||
__ ldr(Rtemp, Address(Rthread, JavaThread::is_method_handle_return_offset()));
|
||||
__ cmp(Rtemp, 0);
|
||||
__ mov(SP, Rmh_SP_save, ne);
|
||||
|
||||
// R0 contains handler address
|
||||
// Since this may be the deopt blob we must set R5 to look like we returned
|
||||
// from the original pc that threw the exception
|
||||
|
||||
@ -374,15 +374,6 @@ LIR_Opr FrameMap::stack_pointer() {
|
||||
return SP_opr;
|
||||
}
|
||||
|
||||
|
||||
// JSR 292
|
||||
// On PPC64, there is no need to save the SP, because neither
|
||||
// method handle intrinsics, nor compiled lambda forms modify it.
|
||||
LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
|
||||
return LIR_OprFact::illegalOpr;
|
||||
}
|
||||
|
||||
|
||||
bool FrameMap::validate_frame() {
|
||||
int max_offset = in_bytes(framesize_in_bytes());
|
||||
int java_index = 0;
|
||||
|
||||
@ -2473,10 +2473,6 @@ RegMask Matcher::modL_proj_mask() {
|
||||
return RegMask();
|
||||
}
|
||||
|
||||
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||
return RegMask();
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
//----------ENCODING BLOCK-----------------------------------------------------
|
||||
@ -3434,7 +3430,6 @@ encode %{
|
||||
|
||||
// Create the call node.
|
||||
CallDynamicJavaDirectSchedNode *call = new CallDynamicJavaDirectSchedNode();
|
||||
call->_method_handle_invoke = _method_handle_invoke;
|
||||
call->_vtable_index = _vtable_index;
|
||||
call->_method = _method;
|
||||
call->_optimized_virtual = _optimized_virtual;
|
||||
|
||||
@ -377,11 +377,6 @@ LIR_Opr FrameMap::stack_pointer() {
|
||||
return FrameMap::sp_opr;
|
||||
}
|
||||
|
||||
// JSR 292
|
||||
LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
|
||||
return LIR_OprFact::illegalOpr; // Not needed on riscv
|
||||
}
|
||||
|
||||
bool FrameMap::validate_frame() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -217,8 +217,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
||||
|
||||
nmethod* nm = sender_blob->as_nmethod_or_null();
|
||||
if (nm != nullptr) {
|
||||
if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) ||
|
||||
nm->method()->is_method_handle_intrinsic()) {
|
||||
if (nm->is_deopt_entry(sender_pc) || nm->method()->is_method_handle_intrinsic()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -427,49 +426,6 @@ JavaThread** frame::saved_thread_address(const frame& f) {
|
||||
return thread_addr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::verify_deopt_original_pc
|
||||
//
|
||||
// Verifies the calculated original PC of a deoptimization PC for the
|
||||
// given unextended SP.
|
||||
#ifdef ASSERT
|
||||
void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp) {
|
||||
frame fr;
|
||||
|
||||
// This is ugly but it's better than to change {get,set}_original_pc
|
||||
// to take an SP value as argument. And it's only a debugging
|
||||
// method anyway.
|
||||
fr._unextended_sp = unextended_sp;
|
||||
|
||||
assert_cond(nm != nullptr);
|
||||
address original_pc = nm->get_original_pc(&fr);
|
||||
assert(nm->insts_contains_inclusive(original_pc),
|
||||
"original PC must be in the main code section of the compiled method (or must be immediately following it)");
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
#ifdef ASSERT
|
||||
void frame::adjust_unextended_sp() {
|
||||
// On riscv, sites calling method handle intrinsics and lambda forms are treated
|
||||
// as any other call site. Therefore, no special action is needed when we are
|
||||
// returning to any of these call sites.
|
||||
|
||||
if (_cb != nullptr) {
|
||||
nmethod* sender_nm = _cb->as_nmethod_or_null();
|
||||
if (sender_nm != nullptr) {
|
||||
// If the sender PC is a deoptimization point, get the original PC.
|
||||
if (sender_nm->is_deopt_entry(_pc) ||
|
||||
sender_nm->is_deopt_mh_entry(_pc)) {
|
||||
verify_deopt_original_pc(sender_nm, _unextended_sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::sender_for_interpreter_frame
|
||||
frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -179,17 +179,10 @@
|
||||
int _offset_unextended_sp; // for use in stack-chunk frames
|
||||
};
|
||||
|
||||
void adjust_unextended_sp() NOT_DEBUG_RETURN;
|
||||
|
||||
intptr_t* ptr_at_addr(int offset) const {
|
||||
return (intptr_t*) addr_at(offset);
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
// Used in frame::sender_for_{interpreter,compiled}_frame
|
||||
static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp);
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
|
||||
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -114,8 +114,6 @@ inline void frame::init(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc) {
|
||||
}
|
||||
|
||||
inline void frame::setup(address pc) {
|
||||
adjust_unextended_sp();
|
||||
|
||||
address original_pc = get_deopt_original_pc();
|
||||
if (original_pc != nullptr) {
|
||||
_pc = original_pc;
|
||||
@ -215,7 +213,6 @@ inline frame::frame(intptr_t* ptr_sp, intptr_t* ptr_fp) {
|
||||
// value.
|
||||
|
||||
_cb = CodeCache::find_blob(_pc);
|
||||
adjust_unextended_sp();
|
||||
|
||||
address original_pc = get_deopt_original_pc();
|
||||
if (original_pc != nullptr) {
|
||||
|
||||
@ -2152,10 +2152,6 @@ RegMask Matcher::modL_proj_mask() {
|
||||
return RegMask();
|
||||
}
|
||||
|
||||
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||
return FP_REG_mask();
|
||||
}
|
||||
|
||||
bool size_fits_all_mem_uses(AddPNode* addp, int shift) {
|
||||
assert_cond(addp != nullptr);
|
||||
for (DUIterator_Fast imax, i = addp->fast_outs(imax); i < imax; i++) {
|
||||
|
||||
@ -282,13 +282,6 @@ LIR_Opr FrameMap::stack_pointer() {
|
||||
return Z_SP_opr;
|
||||
}
|
||||
|
||||
// JSR 292
|
||||
// On ZARCH_64, there is no need to save the SP, because neither
|
||||
// method handle intrinsics nor compiled lambda forms modify it.
|
||||
LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
|
||||
return LIR_OprFact::illegalOpr;
|
||||
}
|
||||
|
||||
bool FrameMap::validate_frame() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1980,11 +1980,6 @@ RegMask Matcher::modL_proj_mask() {
|
||||
return _Z_RARG3_LONG_REG_mask;
|
||||
}
|
||||
|
||||
// Copied from sparc.
|
||||
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||
return RegMask();
|
||||
}
|
||||
|
||||
// Should the matcher clone input 'm' of node 'n'?
|
||||
bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) {
|
||||
if (is_encode_and_store_pattern(n, m)) {
|
||||
|
||||
@ -326,13 +326,6 @@ LIR_Opr FrameMap::stack_pointer() {
|
||||
return FrameMap::rsp_opr;
|
||||
}
|
||||
|
||||
// JSR 292
|
||||
// On x86, there is no need to save the SP, because neither
|
||||
// method handle intrinsics, nor compiled lambda forms modify it.
|
||||
LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() {
|
||||
return LIR_OprFact::illegalOpr;
|
||||
}
|
||||
|
||||
bool FrameMap::validate_frame() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -219,8 +219,7 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
||||
|
||||
nmethod* nm = sender_blob->as_nmethod_or_null();
|
||||
if (nm != nullptr) {
|
||||
if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) ||
|
||||
nm->method()->is_method_handle_intrinsic()) {
|
||||
if (nm->is_deopt_entry(sender_pc) || nm->method()->is_method_handle_intrinsic()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -443,47 +442,6 @@ JavaThread** frame::saved_thread_address(const frame& f) {
|
||||
return thread_addr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::verify_deopt_original_pc
|
||||
//
|
||||
// Verifies the calculated original PC of a deoptimization PC for the
|
||||
// given unextended SP.
|
||||
#ifdef ASSERT
|
||||
void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp) {
|
||||
frame fr;
|
||||
|
||||
// This is ugly but it's better than to change {get,set}_original_pc
|
||||
// to take an SP value as argument. And it's only a debugging
|
||||
// method anyway.
|
||||
fr._unextended_sp = unextended_sp;
|
||||
|
||||
address original_pc = nm->get_original_pc(&fr);
|
||||
assert(nm->insts_contains_inclusive(original_pc),
|
||||
"original PC must be in the main code section of the compiled method (or must be immediately following it) original_pc: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " name: %s", p2i(original_pc), p2i(unextended_sp), nm->name());
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
#ifdef ASSERT
|
||||
void frame::adjust_unextended_sp() {
|
||||
// On x86, sites calling method handle intrinsics and lambda forms are treated
|
||||
// as any other call site. Therefore, no special action is needed when we are
|
||||
// returning to any of these call sites.
|
||||
|
||||
if (_cb != nullptr) {
|
||||
nmethod* sender_nm = _cb->as_nmethod_or_null();
|
||||
if (sender_nm != nullptr) {
|
||||
// If the sender PC is a deoptimization point, get the original PC.
|
||||
if (sender_nm->is_deopt_entry(_pc) ||
|
||||
sender_nm->is_deopt_mh_entry(_pc)) {
|
||||
verify_deopt_original_pc(sender_nm, _unextended_sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::sender_for_interpreter_frame
|
||||
frame frame::sender_for_interpreter_frame(RegisterMap* map) const {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -138,17 +138,10 @@
|
||||
int _offset_unextended_sp; // for use in stack-chunk frames
|
||||
};
|
||||
|
||||
void adjust_unextended_sp() NOT_DEBUG_RETURN;
|
||||
|
||||
intptr_t* ptr_at_addr(int offset) const {
|
||||
return (intptr_t*) addr_at(offset);
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
// Used in frame::sender_for_{interpreter,compiled}_frame
|
||||
static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp);
|
||||
#endif
|
||||
|
||||
public:
|
||||
// Constructors
|
||||
|
||||
|
||||
@ -111,8 +111,6 @@ inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) {
|
||||
}
|
||||
|
||||
inline void frame::setup(address pc) {
|
||||
adjust_unextended_sp();
|
||||
|
||||
address original_pc = get_deopt_original_pc();
|
||||
if (original_pc != nullptr) {
|
||||
_pc = original_pc;
|
||||
@ -209,7 +207,6 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) {
|
||||
// assert(_pc != nullptr, "no pc?");
|
||||
|
||||
_cb = CodeCache::find_blob(_pc);
|
||||
adjust_unextended_sp();
|
||||
|
||||
address original_pc = get_deopt_original_pc();
|
||||
if (original_pc != nullptr) {
|
||||
|
||||
@ -1697,11 +1697,6 @@ RegMask Matcher::modL_proj_mask() {
|
||||
return LONG_RDX_REG_mask();
|
||||
}
|
||||
|
||||
// Register for saving SP into on method handle invokes. Not used on x86_64.
|
||||
const RegMask Matcher::method_handle_invoke_SP_save_mask() {
|
||||
return NO_REG_mask();
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
//----------ENCODING BLOCK-----------------------------------------------------
|
||||
|
||||
@ -621,9 +621,7 @@ int JVM_HANDLE_XXX_SIGNAL(int sig, siginfo_t* info,
|
||||
if (cb != nullptr && cb->is_nmethod()) {
|
||||
nmethod* nm = cb->as_nmethod();
|
||||
assert(nm->insts_contains_inclusive(pc), "");
|
||||
address deopt = nm->is_method_handle_return(pc) ?
|
||||
nm->deopt_mh_handler_begin() :
|
||||
nm->deopt_handler_begin();
|
||||
address deopt = nm->deopt_handler_begin();
|
||||
assert(deopt != nullptr, "");
|
||||
|
||||
frame fr = os::fetch_frame_from_context(uc);
|
||||
|
||||
@ -2797,9 +2797,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
||||
if (cb != nullptr && cb->is_nmethod()) {
|
||||
nmethod* nm = cb->as_nmethod();
|
||||
frame fr = os::fetch_frame_from_context((void*)exceptionInfo->ContextRecord);
|
||||
address deopt = nm->is_method_handle_return(pc) ?
|
||||
nm->deopt_mh_handler_begin() :
|
||||
nm->deopt_handler_begin();
|
||||
address deopt = nm->deopt_handler_begin();
|
||||
assert(nm->insts_contains_inclusive(pc), "");
|
||||
nm->set_original_pc(&fr, pc);
|
||||
// Set pc to handler
|
||||
|
||||
@ -57,7 +57,6 @@ public:
|
||||
OSR_Entry,
|
||||
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 };
|
||||
|
||||
@ -77,7 +76,6 @@ public:
|
||||
_values[OSR_Entry ] = 0;
|
||||
_values[Exceptions ] = -1;
|
||||
_values[Deopt ] = -1;
|
||||
_values[DeoptMH ] = -1;
|
||||
_values[UnwindHandler ] = -1;
|
||||
}
|
||||
|
||||
|
||||
@ -310,14 +310,6 @@ void Compilation::emit_code_epilog(LIR_Assembler* assembler) {
|
||||
code_offsets->set_value(CodeOffsets::Deopt, assembler->emit_deopt_handler());
|
||||
CHECK_BAILOUT();
|
||||
|
||||
// Emit the MethodHandle deopt handler code (if required).
|
||||
if (has_method_handle_invokes()) {
|
||||
// We can use the same code as for the normal deopt handler, we
|
||||
// just need a different entry point address.
|
||||
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());
|
||||
@ -574,7 +566,6 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho
|
||||
, _has_unsafe_access(false)
|
||||
, _has_irreducible_loops(false)
|
||||
, _would_profile(false)
|
||||
, _has_method_handle_invokes(false)
|
||||
, _has_reserved_stack_access(method->has_reserved_stack_access())
|
||||
, _has_monitors(method->is_synchronized() || method->has_monitor_bytecodes())
|
||||
, _has_scoped_access(method->is_scoped())
|
||||
|
||||
@ -79,7 +79,6 @@ class Compilation: public StackObj {
|
||||
bool _has_unsafe_access;
|
||||
bool _has_irreducible_loops;
|
||||
bool _would_profile;
|
||||
bool _has_method_handle_invokes; // True if this method has MethodHandle invokes.
|
||||
bool _has_reserved_stack_access;
|
||||
bool _has_monitors; // Fastpath monitors detection for Continuations
|
||||
bool _has_scoped_access; // For shared scope closure
|
||||
@ -180,10 +179,6 @@ class Compilation: public StackObj {
|
||||
// Statistics gathering
|
||||
void notice_inlined_method(ciMethod* method);
|
||||
|
||||
// JSR 292
|
||||
bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
|
||||
void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }
|
||||
|
||||
bool has_reserved_stack_access() const { return _has_reserved_stack_access; }
|
||||
void set_has_reserved_stack_access(bool z) { _has_reserved_stack_access = z; }
|
||||
|
||||
|
||||
@ -155,9 +155,6 @@ class FrameMap : public CompilationResourceObj {
|
||||
// Opr representing the stack_pointer on this platform
|
||||
static LIR_Opr stack_pointer();
|
||||
|
||||
// JSR 292
|
||||
static LIR_Opr method_handle_invoke_SP_save_opr();
|
||||
|
||||
static BasicTypeArray* signature_type_array_for(const ciMethod* method);
|
||||
|
||||
// for outgoing calls, these also update the reserved area to
|
||||
|
||||
@ -190,7 +190,6 @@ CodeEmitInfo::CodeEmitInfo(ValueStack* stack, XHandlers* exception_handlers, boo
|
||||
, _exception_handlers(exception_handlers)
|
||||
, _oop_map(nullptr)
|
||||
, _stack(stack)
|
||||
, _is_method_handle_invoke(false)
|
||||
, _deoptimize_on_exception(deoptimize_on_exception)
|
||||
, _force_reexecute(false) {
|
||||
assert(_stack != nullptr, "must be non null");
|
||||
@ -203,7 +202,6 @@ CodeEmitInfo::CodeEmitInfo(CodeEmitInfo* info, ValueStack* stack)
|
||||
, _exception_handlers(nullptr)
|
||||
, _oop_map(nullptr)
|
||||
, _stack(stack == nullptr ? info->_stack : stack)
|
||||
, _is_method_handle_invoke(info->_is_method_handle_invoke)
|
||||
, _deoptimize_on_exception(info->_deoptimize_on_exception)
|
||||
, _force_reexecute(info->_force_reexecute) {
|
||||
|
||||
@ -218,7 +216,7 @@ void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_
|
||||
// record the safepoint before recording the debug info for enclosing scopes
|
||||
recorder->add_safepoint(pc_offset, _oop_map->deep_copy());
|
||||
bool reexecute = _force_reexecute || _scope_debug_info->should_reexecute();
|
||||
_scope_debug_info->record_debug_info(recorder, pc_offset, reexecute, _is_method_handle_invoke);
|
||||
_scope_debug_info->record_debug_info(recorder, pc_offset, reexecute);
|
||||
recorder->end_safepoint(pc_offset);
|
||||
}
|
||||
|
||||
|
||||
@ -234,7 +234,7 @@ class IRScopeDebugInfo: public CompilationResourceObj {
|
||||
//Whether we should reexecute this bytecode for deopt
|
||||
bool should_reexecute();
|
||||
|
||||
void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool reexecute, bool is_method_handle_invoke = false) {
|
||||
void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool reexecute) {
|
||||
if (caller() != nullptr) {
|
||||
// Order is significant: Must record caller first.
|
||||
caller()->record_debug_info(recorder, pc_offset, false/*reexecute*/);
|
||||
@ -248,7 +248,7 @@ class IRScopeDebugInfo: public CompilationResourceObj {
|
||||
bool has_ea_local_in_scope = false;
|
||||
bool arg_escape = false;
|
||||
recorder->describe_scope(pc_offset, methodHandle(), scope()->method(), bci(),
|
||||
reexecute, rethrow_exception, is_method_handle_invoke, return_oop,
|
||||
reexecute, rethrow_exception, return_oop,
|
||||
has_ea_local_in_scope, arg_escape, locvals, expvals, monvals);
|
||||
}
|
||||
};
|
||||
@ -262,7 +262,6 @@ class CodeEmitInfo: public CompilationResourceObj {
|
||||
XHandlers* _exception_handlers;
|
||||
OopMap* _oop_map;
|
||||
ValueStack* _stack; // used by deoptimization (contains also monitors
|
||||
bool _is_method_handle_invoke; // true if the associated call site is a MethodHandle call site.
|
||||
bool _deoptimize_on_exception;
|
||||
bool _force_reexecute; // force the reexecute flag on, used for patching stub
|
||||
|
||||
@ -288,9 +287,6 @@ class CodeEmitInfo: public CompilationResourceObj {
|
||||
void add_register_oop(LIR_Opr opr);
|
||||
void record_debug_info(DebugInformationRecorder* recorder, int pc_offset);
|
||||
|
||||
bool is_method_handle_invoke() const { return _is_method_handle_invoke; }
|
||||
void set_is_method_handle_invoke(bool x) { _is_method_handle_invoke = x; }
|
||||
|
||||
bool force_reexecute() const { return _force_reexecute; }
|
||||
void set_force_reexecute() { _force_reexecute = true; }
|
||||
|
||||
|
||||
@ -709,11 +709,6 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
|
||||
}
|
||||
|
||||
if (opJavaCall->_info) do_info(opJavaCall->_info);
|
||||
if (FrameMap::method_handle_invoke_SP_save_opr() != LIR_OprFact::illegalOpr &&
|
||||
opJavaCall->is_method_handle_invoke()) {
|
||||
opJavaCall->_method_handle_invoke_SP_save_opr = FrameMap::method_handle_invoke_SP_save_opr();
|
||||
do_temp(opJavaCall->_method_handle_invoke_SP_save_opr);
|
||||
}
|
||||
do_call();
|
||||
if (opJavaCall->_result->is_valid()) do_output(opJavaCall->_result);
|
||||
|
||||
|
||||
@ -1176,7 +1176,6 @@ class LIR_OpJavaCall: public LIR_OpCall {
|
||||
private:
|
||||
ciMethod* _method;
|
||||
LIR_Opr _receiver;
|
||||
LIR_Opr _method_handle_invoke_SP_save_opr; // Used in LIR_OpVisitState::visit to store the reference to FrameMap::method_handle_invoke_SP_save_opr.
|
||||
|
||||
public:
|
||||
LIR_OpJavaCall(LIR_Code code, ciMethod* method,
|
||||
@ -1186,7 +1185,6 @@ class LIR_OpJavaCall: public LIR_OpCall {
|
||||
: LIR_OpCall(code, addr, result, arguments, info)
|
||||
, _method(method)
|
||||
, _receiver(receiver)
|
||||
, _method_handle_invoke_SP_save_opr(LIR_OprFact::illegalOpr)
|
||||
{ assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); }
|
||||
|
||||
LIR_OpJavaCall(LIR_Code code, ciMethod* method,
|
||||
@ -1195,7 +1193,6 @@ class LIR_OpJavaCall: public LIR_OpCall {
|
||||
: LIR_OpCall(code, (address)vtable_offset, result, arguments, info)
|
||||
, _method(method)
|
||||
, _receiver(receiver)
|
||||
, _method_handle_invoke_SP_save_opr(LIR_OprFact::illegalOpr)
|
||||
{ assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); }
|
||||
|
||||
LIR_Opr receiver() const { return _receiver; }
|
||||
|
||||
@ -478,12 +478,6 @@ void LIR_Assembler::emit_call(LIR_OpJavaCall* op) {
|
||||
fatal("unexpected op code: %s", op->name());
|
||||
break;
|
||||
}
|
||||
|
||||
// JSR 292
|
||||
// Record if this method has MethodHandle invokes.
|
||||
if (op->is_method_handle_invoke()) {
|
||||
compilation()->set_has_method_handle_invokes(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -2712,19 +2712,7 @@ void LIRGenerator::do_Invoke(Invoke* x) {
|
||||
// emit invoke code
|
||||
assert(receiver->is_illegal() || receiver->is_equal(LIR_Assembler::receiverOpr()), "must match");
|
||||
|
||||
// JSR 292
|
||||
// Preserve the SP over MethodHandle call sites, if needed.
|
||||
ciMethod* target = x->target();
|
||||
bool is_method_handle_invoke = (// %%% FIXME: Are both of these relevant?
|
||||
target->is_method_handle_intrinsic() ||
|
||||
target->is_compiled_lambda_form());
|
||||
if (is_method_handle_invoke) {
|
||||
info->set_is_method_handle_invoke(true);
|
||||
if(FrameMap::method_handle_invoke_SP_save_opr() != LIR_OprFact::illegalOpr) {
|
||||
__ move(FrameMap::stack_pointer(), FrameMap::method_handle_invoke_SP_save_opr());
|
||||
}
|
||||
}
|
||||
|
||||
switch (x->code()) {
|
||||
case Bytecodes::_invokestatic:
|
||||
__ call_static(target, result_register,
|
||||
@ -2757,13 +2745,6 @@ void LIRGenerator::do_Invoke(Invoke* x) {
|
||||
break;
|
||||
}
|
||||
|
||||
// JSR 292
|
||||
// Restore the SP after MethodHandle call sites, if needed.
|
||||
if (is_method_handle_invoke
|
||||
&& FrameMap::method_handle_invoke_SP_save_opr() != LIR_OprFact::illegalOpr) {
|
||||
__ move(FrameMap::method_handle_invoke_SP_save_opr(), FrameMap::stack_pointer());
|
||||
}
|
||||
|
||||
if (result_register->is_valid()) {
|
||||
LIR_Opr result = rlock_result(x);
|
||||
__ move(result_register, result);
|
||||
|
||||
@ -541,9 +541,6 @@ extern void vm_exit(int code);
|
||||
// unpack_with_exception entry instead. This makes life for the exception blob easier
|
||||
// because making that same check and diverting is painful from assembly language.
|
||||
JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* current, oopDesc* ex, address pc, nmethod*& nm))
|
||||
// Reset method handle flag.
|
||||
current->set_is_method_handle_return(false);
|
||||
|
||||
Handle exception(current, ex);
|
||||
|
||||
// This function is called when we are about to throw an exception. Therefore,
|
||||
@ -622,8 +619,6 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* c
|
||||
if (guard_pages_enabled) {
|
||||
address fast_continuation = nm->handler_for_exception_and_pc(exception, pc);
|
||||
if (fast_continuation != nullptr) {
|
||||
// Set flag if return address is a method handle call site.
|
||||
current->set_is_method_handle_return(nm->is_method_handle_return(pc));
|
||||
return fast_continuation;
|
||||
}
|
||||
}
|
||||
@ -660,8 +655,6 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* c
|
||||
}
|
||||
|
||||
current->set_vm_result_oop(exception());
|
||||
// Set flag if return address is a method handle call site.
|
||||
current->set_is_method_handle_return(nm->is_method_handle_return(pc));
|
||||
|
||||
if (log_is_enabled(Info, exceptions)) {
|
||||
ResourceMark rm;
|
||||
|
||||
@ -283,7 +283,6 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
|
||||
int bci,
|
||||
bool reexecute,
|
||||
bool rethrow_exception,
|
||||
bool is_method_handle_invoke,
|
||||
bool return_oop,
|
||||
bool has_ea_local_in_scope,
|
||||
bool arg_escape,
|
||||
@ -301,7 +300,6 @@ void DebugInformationRecorder::describe_scope(int pc_offset,
|
||||
// Record flags into pcDesc.
|
||||
last_pd->set_should_reexecute(reexecute);
|
||||
last_pd->set_rethrow_exception(rethrow_exception);
|
||||
last_pd->set_is_method_handle_invoke(is_method_handle_invoke);
|
||||
last_pd->set_return_oop(return_oop);
|
||||
last_pd->set_has_ea_local_in_scope(has_ea_local_in_scope);
|
||||
last_pd->set_arg_escape(arg_escape);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -105,7 +105,6 @@ class DebugInformationRecorder: public ResourceObj {
|
||||
int bci,
|
||||
bool reexecute,
|
||||
bool rethrow_exception = false,
|
||||
bool is_method_handle_invoke = false,
|
||||
bool return_oop = false,
|
||||
bool has_ea_local_in_scope = false,
|
||||
bool arg_escape = false,
|
||||
|
||||
@ -465,14 +465,6 @@ static int adjust_pcs_size(int pcs_size) {
|
||||
return nsize;
|
||||
}
|
||||
|
||||
bool nmethod::is_method_handle_return(address return_pc) {
|
||||
if (!has_method_handle_invokes()) return false;
|
||||
PcDesc* pd = pc_desc_at(return_pc);
|
||||
if (pd == nullptr)
|
||||
return false;
|
||||
return pd->is_method_handle_invoke();
|
||||
}
|
||||
|
||||
// Returns a string version of the method state.
|
||||
const char* nmethod::state() const {
|
||||
int state = get_state();
|
||||
@ -1231,7 +1223,6 @@ void nmethod::init_defaults(CodeBuffer *code_buffer, CodeOffsets* offsets) {
|
||||
_state = not_installed;
|
||||
|
||||
_has_unsafe_access = 0;
|
||||
_has_method_handle_invokes = 0;
|
||||
_has_wide_vectors = 0;
|
||||
_has_monitors = 0;
|
||||
_has_scoped_access = 0;
|
||||
@ -1310,7 +1301,6 @@ nmethod::nmethod(
|
||||
// Native wrappers do not have deopt handlers. Make the values
|
||||
// something that will never match a pc like the nmethod vtable entry
|
||||
_deopt_handler_offset = 0;
|
||||
_deopt_mh_handler_offset = 0;
|
||||
_unwind_handler_offset = 0;
|
||||
|
||||
CHECKED_CAST(_oops_size, uint16_t, align_up(code_buffer->total_oop_size(), oopSize));
|
||||
@ -1458,11 +1448,6 @@ nmethod::nmethod(
|
||||
} else {
|
||||
_deopt_handler_offset = -1;
|
||||
}
|
||||
if (offsets->value(CodeOffsets::DeoptMH) != -1) {
|
||||
_deopt_mh_handler_offset = code_offset() + offsets->value(CodeOffsets::DeoptMH);
|
||||
} else {
|
||||
_deopt_mh_handler_offset = -1;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
@ -1472,11 +1457,6 @@ nmethod::nmethod(
|
||||
|
||||
_exception_offset = _stub_offset + offsets->value(CodeOffsets::Exceptions);
|
||||
_deopt_handler_offset = _stub_offset + offsets->value(CodeOffsets::Deopt);
|
||||
if (offsets->value(CodeOffsets::DeoptMH) != -1) {
|
||||
_deopt_mh_handler_offset = _stub_offset + offsets->value(CodeOffsets::DeoptMH);
|
||||
} else {
|
||||
_deopt_mh_handler_offset = -1;
|
||||
}
|
||||
}
|
||||
if (offsets->value(CodeOffsets::UnwindHandler) != -1) {
|
||||
// C1 generates UnwindHandler at the end of instructions section.
|
||||
@ -2693,15 +2673,6 @@ void nmethod::copy_scopes_pcs(PcDesc* pcs, int count) {
|
||||
"must end with a sentinel");
|
||||
#endif //ASSERT
|
||||
|
||||
// Search for MethodHandle invokes and tag the nmethod.
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (pcs[i].is_method_handle_invoke()) {
|
||||
set_has_method_handle_invokes(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(has_method_handle_invokes() == (_deopt_mh_handler_offset != -1), "must have deopt mh handler");
|
||||
|
||||
int size = count * sizeof(PcDesc);
|
||||
assert(scopes_pcs_size() >= size, "oob");
|
||||
memcpy(scopes_pcs_begin(), pcs, size);
|
||||
@ -3711,7 +3682,6 @@ const char* nmethod::nmethod_section_label(address pos) const {
|
||||
if (pos == code_begin()) label = "[Instructions begin]";
|
||||
if (pos == entry_point()) label = "[Entry Point]";
|
||||
if (pos == verified_entry_point()) label = "[Verified Entry Point]";
|
||||
if (has_method_handle_invokes() && (pos == deopt_mh_handler_begin())) label = "[Deopt MH Handler Code]";
|
||||
if (pos == consts_begin() && pos != insts_begin()) label = "[Constants]";
|
||||
// Check stub_code before checking exception_handler or deopt_handler.
|
||||
if (pos == this->stub_begin()) label = "[Stub Code]";
|
||||
|
||||
@ -226,9 +226,6 @@ class nmethod : public CodeBlob {
|
||||
// All deoptee's will resume execution at this location described by
|
||||
// this offset.
|
||||
int _deopt_handler_offset;
|
||||
// All deoptee's at a MethodHandle call site will resume execution
|
||||
// at this location described by this offset.
|
||||
int _deopt_mh_handler_offset;
|
||||
// Offset (from insts_end) of the unwind handler if it exists
|
||||
int16_t _unwind_handler_offset;
|
||||
// Number of arguments passed on the stack
|
||||
@ -267,7 +264,6 @@ class nmethod : public CodeBlob {
|
||||
|
||||
// set during construction
|
||||
uint8_t _has_unsafe_access:1, // May fault due to unsafe access.
|
||||
_has_method_handle_invokes:1,// Has this method MethodHandle invokes?
|
||||
_has_wide_vectors:1, // Preserve wide vectors at safepoints
|
||||
_has_monitors:1, // Fastpath monitor detection for continuations
|
||||
_has_scoped_access:1, // used by for shared scope closure (scopedMemoryAccess.cpp)
|
||||
@ -606,7 +602,6 @@ public:
|
||||
address stub_end () const { return code_end() ; }
|
||||
address exception_begin () const { return header_begin() + _exception_offset ; }
|
||||
address deopt_handler_begin () const { return header_begin() + _deopt_handler_offset ; }
|
||||
address deopt_mh_handler_begin() const { return header_begin() + _deopt_mh_handler_offset ; }
|
||||
address unwind_handler_begin () const { return _unwind_handler_offset != -1 ? (insts_end() - _unwind_handler_offset) : nullptr; }
|
||||
oop* oops_begin () const { return (oop*) data_begin(); }
|
||||
oop* oops_end () const { return (oop*) data_end(); }
|
||||
@ -745,9 +740,6 @@ public:
|
||||
bool has_scoped_access() const { return _has_scoped_access; }
|
||||
void set_has_scoped_access(bool z) { _has_scoped_access = z; }
|
||||
|
||||
bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
|
||||
void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }
|
||||
|
||||
bool has_wide_vectors() const { return _has_wide_vectors; }
|
||||
void set_has_wide_vectors(bool z) { _has_wide_vectors = z; }
|
||||
|
||||
@ -818,12 +810,9 @@ public:
|
||||
ExceptionCache* exception_cache_entry_for_exception(Handle exception);
|
||||
|
||||
|
||||
// MethodHandle
|
||||
bool is_method_handle_return(address return_pc);
|
||||
// Deopt
|
||||
// Return true is the PC is one would expect if the frame is being deopted.
|
||||
inline bool is_deopt_pc(address pc);
|
||||
inline bool is_deopt_mh_entry(address pc);
|
||||
inline bool is_deopt_entry(address pc);
|
||||
|
||||
// Accessor/mutator for the original pc of a frame before a frame was deopted.
|
||||
|
||||
@ -31,16 +31,12 @@
|
||||
#include "runtime/atomicAccess.hpp"
|
||||
#include "runtime/frame.hpp"
|
||||
|
||||
inline bool nmethod::is_deopt_pc(address pc) { return is_deopt_entry(pc) || is_deopt_mh_entry(pc); }
|
||||
inline bool nmethod::is_deopt_pc(address pc) { return is_deopt_entry(pc); }
|
||||
|
||||
inline bool nmethod::is_deopt_entry(address pc) {
|
||||
return pc == deopt_handler_begin();
|
||||
}
|
||||
|
||||
inline bool nmethod::is_deopt_mh_entry(address pc) {
|
||||
return pc == deopt_mh_handler_begin();
|
||||
}
|
||||
|
||||
// class ExceptionCache methods
|
||||
|
||||
inline int ExceptionCache::count() { return AtomicAccess::load_acquire(&_count); }
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -40,11 +40,10 @@ class PcDesc {
|
||||
|
||||
enum {
|
||||
PCDESC_reexecute = 1 << 0,
|
||||
PCDESC_is_method_handle_invoke = 1 << 1,
|
||||
PCDESC_return_oop = 1 << 2,
|
||||
PCDESC_rethrow_exception = 1 << 3,
|
||||
PCDESC_has_ea_local_in_scope = 1 << 4,
|
||||
PCDESC_arg_escape = 1 << 5
|
||||
PCDESC_return_oop = 1 << 1,
|
||||
PCDESC_rethrow_exception = 1 << 2,
|
||||
PCDESC_has_ea_local_in_scope = 1 << 3,
|
||||
PCDESC_arg_escape = 1 << 4
|
||||
};
|
||||
|
||||
int _flags;
|
||||
@ -85,9 +84,6 @@ class PcDesc {
|
||||
_flags == pd->_flags;
|
||||
}
|
||||
|
||||
bool is_method_handle_invoke() const { return (_flags & PCDESC_is_method_handle_invoke) != 0; }
|
||||
void set_is_method_handle_invoke(bool z) { set_flag(PCDESC_is_method_handle_invoke, z); }
|
||||
|
||||
bool return_oop() const { return (_flags & PCDESC_return_oop) != 0; }
|
||||
void set_return_oop(bool z) { set_flag(PCDESC_return_oop, z); }
|
||||
|
||||
|
||||
@ -1141,7 +1141,7 @@ int CodeInstaller::map_jvmci_bci(int bci) {
|
||||
return bci;
|
||||
}
|
||||
|
||||
void CodeInstaller::record_scope(jint pc_offset, HotSpotCompiledCodeStream* stream, u1 debug_info_flags, bool full_info, bool is_mh_invoke, bool return_oop, JVMCI_TRAPS) {
|
||||
void CodeInstaller::record_scope(jint pc_offset, HotSpotCompiledCodeStream* stream, u1 debug_info_flags, bool full_info, bool return_oop, JVMCI_TRAPS) {
|
||||
if (full_info) {
|
||||
read_virtual_objects(stream, JVMCI_CHECK);
|
||||
}
|
||||
@ -1184,7 +1184,7 @@ void CodeInstaller::record_scope(jint pc_offset, HotSpotCompiledCodeStream* stre
|
||||
// has_ea_local_in_scope and arg_escape should be added to JVMCI
|
||||
const bool has_ea_local_in_scope = false;
|
||||
const bool arg_escape = false;
|
||||
_debug_recorder->describe_scope(pc_offset, method, nullptr, bci, reexecute, rethrow_exception, is_mh_invoke, return_oop,
|
||||
_debug_recorder->describe_scope(pc_offset, method, nullptr, bci, reexecute, rethrow_exception, return_oop,
|
||||
has_ea_local_in_scope, arg_escape,
|
||||
locals_token, stack_token, monitors_token);
|
||||
}
|
||||
@ -1242,14 +1242,8 @@ void CodeInstaller::site_Call(CodeBuffer& buffer, u1 tag, jint pc_offset, HotSpo
|
||||
_debug_recorder->add_safepoint(next_pc_offset, map);
|
||||
|
||||
if (!method.is_null()) {
|
||||
vmIntrinsics::ID iid = method->intrinsic_id();
|
||||
bool is_mh_invoke = false;
|
||||
if (direct_call) {
|
||||
is_mh_invoke = !method->is_static() && (iid == vmIntrinsics::_compiledLambdaForm ||
|
||||
(MethodHandles::is_signature_polymorphic(iid) && MethodHandles::is_signature_polymorphic_intrinsic(iid)));
|
||||
}
|
||||
bool return_oop = method->is_returning_oop();
|
||||
record_scope(next_pc_offset, stream, flags, true, is_mh_invoke, return_oop, JVMCI_CHECK);
|
||||
record_scope(next_pc_offset, stream, flags, true, return_oop, JVMCI_CHECK);
|
||||
} else {
|
||||
record_scope(next_pc_offset, stream, flags, true, JVMCI_CHECK);
|
||||
}
|
||||
@ -1339,9 +1333,6 @@ void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, HotSpotCompile
|
||||
case DEOPT_HANDLER_ENTRY:
|
||||
_offsets.set_value(CodeOffsets::Deopt, pc_offset);
|
||||
break;
|
||||
case DEOPT_MH_HANDLER_ENTRY:
|
||||
_offsets.set_value(CodeOffsets::DeoptMH, pc_offset);
|
||||
break;
|
||||
case FRAME_COMPLETE:
|
||||
_offsets.set_value(CodeOffsets::Frame_Complete, pc_offset);
|
||||
break;
|
||||
@ -1369,6 +1360,7 @@ void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, HotSpotCompile
|
||||
case VERIFY_OOP_BITS:
|
||||
case VERIFY_OOP_MASK:
|
||||
case VERIFY_OOP_COUNT_ADDRESS:
|
||||
case DEOPT_MH_HANDLER_ENTRY:
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -411,10 +411,10 @@ protected:
|
||||
void record_oop_patch(HotSpotCompiledCodeStream* stream, address dest, u1 read_tag, bool narrow, JVMCI_TRAPS);
|
||||
|
||||
// full_info: if false, only BytecodePosition is in stream otherwise all DebugInfo is in stream
|
||||
void record_scope(jint pc_offset, HotSpotCompiledCodeStream* stream, u1 debug_info_flags, bool full_info, bool is_mh_invoke, bool return_oop, JVMCI_TRAPS);
|
||||
void record_scope(jint pc_offset, HotSpotCompiledCodeStream* stream, u1 debug_info_flags, bool full_info, bool return_oop, JVMCI_TRAPS);
|
||||
|
||||
void record_scope(jint pc_offset, HotSpotCompiledCodeStream* stream, u1 debug_info_flags, bool full_info, JVMCI_TRAPS) {
|
||||
record_scope(pc_offset, stream, debug_info_flags, full_info, false /* is_mh_invoke */, false /* return_oop */, JVMCIENV);
|
||||
record_scope(pc_offset, stream, debug_info_flags, full_info, false /* return_oop */, JVMCIENV);
|
||||
}
|
||||
void record_object_value(ObjectValue* sv, HotSpotCompiledCodeStream* stream, JVMCI_TRAPS);
|
||||
|
||||
|
||||
@ -228,9 +228,6 @@ extern void vm_exit(int code);
|
||||
// unpack_with_exception entry instead. This makes life for the exception blob easier
|
||||
// because making that same check and diverting is painful from assembly language.
|
||||
JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* current, oopDesc* ex, address pc, nmethod*& nm))
|
||||
// Reset method handle flag.
|
||||
current->set_is_method_handle_return(false);
|
||||
|
||||
Handle exception(current, ex);
|
||||
|
||||
// The frame we rethrow the exception to might not have been processed by the GC yet.
|
||||
@ -305,8 +302,6 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* c
|
||||
if (guard_pages_enabled) {
|
||||
address fast_continuation = nm->handler_for_exception_and_pc(exception, pc);
|
||||
if (fast_continuation != nullptr) {
|
||||
// Set flag if return address is a method handle call site.
|
||||
current->set_is_method_handle_return(nm->is_method_handle_return(pc));
|
||||
return fast_continuation;
|
||||
}
|
||||
}
|
||||
@ -343,9 +338,6 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* c
|
||||
}
|
||||
}
|
||||
|
||||
// Set flag if return address is a method handle call site.
|
||||
current->set_is_method_handle_return(nm->is_method_handle_return(pc));
|
||||
|
||||
if (log_is_enabled(Info, exceptions)) {
|
||||
ResourceMark rm;
|
||||
log_info(exceptions)("Thread " PTR_FORMAT " continuing at PC " PTR_FORMAT
|
||||
|
||||
@ -242,7 +242,6 @@
|
||||
nonstatic_field(JavaThread, _stack_overflow_state._stack_overflow_limit, address) \
|
||||
volatile_nonstatic_field(JavaThread, _exception_oop, oop) \
|
||||
volatile_nonstatic_field(JavaThread, _exception_pc, address) \
|
||||
volatile_nonstatic_field(JavaThread, _is_method_handle_return, int) \
|
||||
volatile_nonstatic_field(JavaThread, _doing_unsafe_access, bool) \
|
||||
nonstatic_field(JavaThread, _osthread, OSThread*) \
|
||||
nonstatic_field(JavaThread, _saved_exception_pc, address) \
|
||||
|
||||
@ -169,10 +169,6 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) {
|
||||
}
|
||||
// Mark the call node as virtual, sort of:
|
||||
call->set_optimized_virtual(true);
|
||||
if (method()->is_method_handle_intrinsic() ||
|
||||
method()->is_compiled_lambda_form()) {
|
||||
call->set_method_handle_invoke(true);
|
||||
}
|
||||
}
|
||||
kit.set_arguments_for_java_call(call);
|
||||
kit.set_edges_for_java_call(call, false, _separate_io_proj);
|
||||
|
||||
@ -778,7 +778,6 @@ protected:
|
||||
|
||||
ciMethod* _method; // Method being direct called
|
||||
bool _optimized_virtual;
|
||||
bool _method_handle_invoke;
|
||||
bool _override_symbolic_info; // Override symbolic call site info from bytecode
|
||||
bool _arg_escape; // ArgEscape in parameter list
|
||||
public:
|
||||
@ -786,7 +785,6 @@ public:
|
||||
: CallNode(tf, addr, TypePtr::BOTTOM),
|
||||
_method(method),
|
||||
_optimized_virtual(false),
|
||||
_method_handle_invoke(false),
|
||||
_override_symbolic_info(false),
|
||||
_arg_escape(false)
|
||||
{
|
||||
@ -798,8 +796,6 @@ public:
|
||||
void set_method(ciMethod *m) { _method = m; }
|
||||
void set_optimized_virtual(bool f) { _optimized_virtual = f; }
|
||||
bool is_optimized_virtual() const { return _optimized_virtual; }
|
||||
void set_method_handle_invoke(bool f) { _method_handle_invoke = f; }
|
||||
bool is_method_handle_invoke() const { return _method_handle_invoke; }
|
||||
void set_override_symbolic_info(bool f) { _override_symbolic_info = f; }
|
||||
bool override_symbolic_info() const { return _override_symbolic_info; }
|
||||
void set_arg_escape(bool f) { _arg_escape = f; }
|
||||
|
||||
@ -650,7 +650,6 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci,
|
||||
_igv_idx(0),
|
||||
_trace_opto_output(directive->TraceOptoOutputOption),
|
||||
#endif
|
||||
_has_method_handle_invokes(false),
|
||||
_clinit_barrier_on_entry(false),
|
||||
_stress_seed(0),
|
||||
_comp_arena(mtCompiler, Arena::Tag::tag_comp),
|
||||
@ -925,7 +924,6 @@ Compile::Compile(ciEnv* ci_env,
|
||||
_igv_idx(0),
|
||||
_trace_opto_output(directive->TraceOptoOutputOption),
|
||||
#endif
|
||||
_has_method_handle_invokes(false),
|
||||
_clinit_barrier_on_entry(false),
|
||||
_stress_seed(0),
|
||||
_comp_arena(mtCompiler, Arena::Tag::tag_comp),
|
||||
|
||||
@ -354,8 +354,6 @@ class Compile : public Phase {
|
||||
bool _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing
|
||||
#endif
|
||||
bool _has_irreducible_loop; // Found irreducible loops
|
||||
// JSR 292
|
||||
bool _has_method_handle_invokes; // True if this method has MethodHandle invokes.
|
||||
bool _has_monitors; // Metadata transfered to nmethod to enable Continuations lock-detection fastpath
|
||||
bool _has_scoped_access; // For shared scope closure
|
||||
bool _clinit_barrier_on_entry; // True if clinit barrier is needed on nmethod entry
|
||||
@ -666,10 +664,6 @@ public:
|
||||
bool has_irreducible_loop() const { return _has_irreducible_loop; }
|
||||
void set_has_irreducible_loop(bool z) { _has_irreducible_loop = z; }
|
||||
|
||||
// JSR 292
|
||||
bool has_method_handle_invokes() const { return _has_method_handle_invokes; }
|
||||
void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; }
|
||||
|
||||
Ticks _latest_stage_start_counter;
|
||||
|
||||
void begin_method();
|
||||
|
||||
@ -946,17 +946,6 @@ uint PhaseCFG::sched_call(Block* block, uint node_cnt, Node_List& worklist, Grow
|
||||
// references but there no way to handle oops differently than other
|
||||
// pointers as far as the kill mask goes.
|
||||
bool exclude_soe = op == Op_CallRuntime;
|
||||
|
||||
// If the call is a MethodHandle invoke, we need to exclude the
|
||||
// register which is used to save the SP value over MH invokes from
|
||||
// the mask. Otherwise this register could be used for
|
||||
// deoptimization information.
|
||||
if (op == Op_CallStaticJava) {
|
||||
MachCallStaticJavaNode* mcallstaticjava = (MachCallStaticJavaNode*) mcall;
|
||||
if (mcallstaticjava->_method_handle_invoke)
|
||||
proj->_rout.OR(Matcher::method_handle_invoke_SP_save_mask());
|
||||
}
|
||||
|
||||
add_call_kills(proj, regs, save_policy, exclude_soe);
|
||||
|
||||
return node_cnt;
|
||||
|
||||
@ -772,8 +772,6 @@ bool MachCallJavaNode::cmp( const Node &n ) const {
|
||||
}
|
||||
#ifndef PRODUCT
|
||||
void MachCallJavaNode::dump_spec(outputStream *st) const {
|
||||
if (_method_handle_invoke)
|
||||
st->print("MethodHandle ");
|
||||
if (_method) {
|
||||
_method->print_short_name(st);
|
||||
st->print(" ");
|
||||
@ -794,10 +792,7 @@ const RegMask &MachCallJavaNode::in_RegMask(uint idx) const {
|
||||
}
|
||||
// Values outside the domain represent debug info
|
||||
Matcher* m = Compile::current()->matcher();
|
||||
// If this call is a MethodHandle invoke we have to use a different
|
||||
// debugmask which does not include the register we use to save the
|
||||
// SP over MH invokes.
|
||||
RegMask** debugmask = _method_handle_invoke ? m->idealreg2mhdebugmask : m->idealreg2debugmask;
|
||||
RegMask** debugmask = m->idealreg2debugmask;
|
||||
return *debugmask[in(idx)->ideal_reg()];
|
||||
}
|
||||
|
||||
|
||||
@ -960,7 +960,6 @@ public:
|
||||
ciMethod* _method; // Method being direct called
|
||||
bool _override_symbolic_info; // Override symbolic call site info from bytecode
|
||||
bool _optimized_virtual; // Tells if node is a static call or an optimized virtual
|
||||
bool _method_handle_invoke; // Tells if the call has to preserve SP
|
||||
bool _arg_escape; // ArgEscape in parameter list
|
||||
MachCallJavaNode() : MachCallNode(), _override_symbolic_info(false) {
|
||||
init_class_id(Class_MachCallJava);
|
||||
|
||||
@ -50,8 +50,6 @@ const RegMask *Matcher::idealreg2regmask[_last_machine_leaf];
|
||||
RegMask Matcher::mreg2regmask[_last_Mach_Reg];
|
||||
RegMask Matcher::caller_save_regmask;
|
||||
RegMask Matcher::caller_save_regmask_exclude_soe;
|
||||
RegMask Matcher::mh_caller_save_regmask;
|
||||
RegMask Matcher::mh_caller_save_regmask_exclude_soe;
|
||||
RegMask Matcher::STACK_ONLY_mask;
|
||||
RegMask Matcher::c_frame_ptr_mask;
|
||||
const uint Matcher::_begin_rematerialize = _BEGIN_REMATERIALIZE;
|
||||
@ -114,21 +112,6 @@ Matcher::Matcher()
|
||||
idealreg2debugmask [Op_RegFlags] = nullptr;
|
||||
idealreg2debugmask [Op_RegVectMask] = nullptr;
|
||||
|
||||
idealreg2mhdebugmask[Op_RegI] = nullptr;
|
||||
idealreg2mhdebugmask[Op_RegN] = nullptr;
|
||||
idealreg2mhdebugmask[Op_RegL] = nullptr;
|
||||
idealreg2mhdebugmask[Op_RegF] = nullptr;
|
||||
idealreg2mhdebugmask[Op_RegD] = nullptr;
|
||||
idealreg2mhdebugmask[Op_RegP] = nullptr;
|
||||
idealreg2mhdebugmask[Op_VecA] = nullptr;
|
||||
idealreg2mhdebugmask[Op_VecS] = nullptr;
|
||||
idealreg2mhdebugmask[Op_VecD] = nullptr;
|
||||
idealreg2mhdebugmask[Op_VecX] = nullptr;
|
||||
idealreg2mhdebugmask[Op_VecY] = nullptr;
|
||||
idealreg2mhdebugmask[Op_VecZ] = nullptr;
|
||||
idealreg2mhdebugmask[Op_RegFlags] = nullptr;
|
||||
idealreg2mhdebugmask[Op_RegVectMask] = nullptr;
|
||||
|
||||
DEBUG_ONLY(_mem_node = nullptr;) // Ideal memory node consumed by mach node
|
||||
}
|
||||
|
||||
@ -465,7 +448,7 @@ int Matcher::scalable_predicate_reg_slots() {
|
||||
return round_up_power_of_2(slots);
|
||||
}
|
||||
|
||||
#define NOF_STACK_MASKS (3*13)
|
||||
#define NOF_STACK_MASKS (2*13)
|
||||
|
||||
// Create the initial stack mask used by values spilling to the stack.
|
||||
// Disallow any debug info in outgoing argument areas by setting the
|
||||
@ -480,51 +463,12 @@ void Matcher::init_first_stack_mask() {
|
||||
new (rms + i) RegMask(C->comp_arena());
|
||||
}
|
||||
|
||||
idealreg2spillmask [Op_RegN] = &rms[0];
|
||||
idealreg2spillmask [Op_RegI] = &rms[1];
|
||||
idealreg2spillmask [Op_RegL] = &rms[2];
|
||||
idealreg2spillmask [Op_RegF] = &rms[3];
|
||||
idealreg2spillmask [Op_RegD] = &rms[4];
|
||||
idealreg2spillmask [Op_RegP] = &rms[5];
|
||||
|
||||
idealreg2debugmask [Op_RegN] = &rms[6];
|
||||
idealreg2debugmask [Op_RegI] = &rms[7];
|
||||
idealreg2debugmask [Op_RegL] = &rms[8];
|
||||
idealreg2debugmask [Op_RegF] = &rms[9];
|
||||
idealreg2debugmask [Op_RegD] = &rms[10];
|
||||
idealreg2debugmask [Op_RegP] = &rms[11];
|
||||
|
||||
idealreg2mhdebugmask[Op_RegN] = &rms[12];
|
||||
idealreg2mhdebugmask[Op_RegI] = &rms[13];
|
||||
idealreg2mhdebugmask[Op_RegL] = &rms[14];
|
||||
idealreg2mhdebugmask[Op_RegF] = &rms[15];
|
||||
idealreg2mhdebugmask[Op_RegD] = &rms[16];
|
||||
idealreg2mhdebugmask[Op_RegP] = &rms[17];
|
||||
|
||||
idealreg2spillmask [Op_VecA] = &rms[18];
|
||||
idealreg2spillmask [Op_VecS] = &rms[19];
|
||||
idealreg2spillmask [Op_VecD] = &rms[20];
|
||||
idealreg2spillmask [Op_VecX] = &rms[21];
|
||||
idealreg2spillmask [Op_VecY] = &rms[22];
|
||||
idealreg2spillmask [Op_VecZ] = &rms[23];
|
||||
|
||||
idealreg2debugmask [Op_VecA] = &rms[24];
|
||||
idealreg2debugmask [Op_VecS] = &rms[25];
|
||||
idealreg2debugmask [Op_VecD] = &rms[26];
|
||||
idealreg2debugmask [Op_VecX] = &rms[27];
|
||||
idealreg2debugmask [Op_VecY] = &rms[28];
|
||||
idealreg2debugmask [Op_VecZ] = &rms[29];
|
||||
|
||||
idealreg2mhdebugmask[Op_VecA] = &rms[30];
|
||||
idealreg2mhdebugmask[Op_VecS] = &rms[31];
|
||||
idealreg2mhdebugmask[Op_VecD] = &rms[32];
|
||||
idealreg2mhdebugmask[Op_VecX] = &rms[33];
|
||||
idealreg2mhdebugmask[Op_VecY] = &rms[34];
|
||||
idealreg2mhdebugmask[Op_VecZ] = &rms[35];
|
||||
|
||||
idealreg2spillmask [Op_RegVectMask] = &rms[36];
|
||||
idealreg2debugmask [Op_RegVectMask] = &rms[37];
|
||||
idealreg2mhdebugmask[Op_RegVectMask] = &rms[38];
|
||||
int index = 0;
|
||||
for (int i = Op_RegN; i <= Op_RegVectMask; ++i) {
|
||||
idealreg2spillmask[i] = &rms[index++];
|
||||
idealreg2debugmask[i] = &rms[index++];
|
||||
}
|
||||
assert(index == NOF_STACK_MASKS, "wrong size");
|
||||
|
||||
// At first, start with the empty mask
|
||||
C->FIRST_STACK_mask().Clear();
|
||||
@ -710,26 +654,10 @@ void Matcher::init_first_stack_mask() {
|
||||
*idealreg2debugmask [Op_VecY] = *idealreg2spillmask[Op_VecY];
|
||||
*idealreg2debugmask [Op_VecZ] = *idealreg2spillmask[Op_VecZ];
|
||||
|
||||
*idealreg2mhdebugmask[Op_RegN] = *idealreg2spillmask[Op_RegN];
|
||||
*idealreg2mhdebugmask[Op_RegI] = *idealreg2spillmask[Op_RegI];
|
||||
*idealreg2mhdebugmask[Op_RegL] = *idealreg2spillmask[Op_RegL];
|
||||
*idealreg2mhdebugmask[Op_RegF] = *idealreg2spillmask[Op_RegF];
|
||||
*idealreg2mhdebugmask[Op_RegD] = *idealreg2spillmask[Op_RegD];
|
||||
*idealreg2mhdebugmask[Op_RegP] = *idealreg2spillmask[Op_RegP];
|
||||
*idealreg2mhdebugmask[Op_RegVectMask] = *idealreg2spillmask[Op_RegVectMask];
|
||||
|
||||
*idealreg2mhdebugmask[Op_VecA] = *idealreg2spillmask[Op_VecA];
|
||||
*idealreg2mhdebugmask[Op_VecS] = *idealreg2spillmask[Op_VecS];
|
||||
*idealreg2mhdebugmask[Op_VecD] = *idealreg2spillmask[Op_VecD];
|
||||
*idealreg2mhdebugmask[Op_VecX] = *idealreg2spillmask[Op_VecX];
|
||||
*idealreg2mhdebugmask[Op_VecY] = *idealreg2spillmask[Op_VecY];
|
||||
*idealreg2mhdebugmask[Op_VecZ] = *idealreg2spillmask[Op_VecZ];
|
||||
|
||||
// Prevent stub compilations from attempting to reference
|
||||
// callee-saved (SOE) registers from debug info
|
||||
bool exclude_soe = !Compile::current()->is_method_compilation();
|
||||
RegMask* caller_save_mask = exclude_soe ? &caller_save_regmask_exclude_soe : &caller_save_regmask;
|
||||
RegMask* mh_caller_save_mask = exclude_soe ? &mh_caller_save_regmask_exclude_soe : &mh_caller_save_regmask;
|
||||
|
||||
idealreg2debugmask[Op_RegN]->SUBTRACT(*caller_save_mask);
|
||||
idealreg2debugmask[Op_RegI]->SUBTRACT(*caller_save_mask);
|
||||
@ -745,21 +673,6 @@ void Matcher::init_first_stack_mask() {
|
||||
idealreg2debugmask[Op_VecX]->SUBTRACT(*caller_save_mask);
|
||||
idealreg2debugmask[Op_VecY]->SUBTRACT(*caller_save_mask);
|
||||
idealreg2debugmask[Op_VecZ]->SUBTRACT(*caller_save_mask);
|
||||
|
||||
idealreg2mhdebugmask[Op_RegN]->SUBTRACT(*mh_caller_save_mask);
|
||||
idealreg2mhdebugmask[Op_RegI]->SUBTRACT(*mh_caller_save_mask);
|
||||
idealreg2mhdebugmask[Op_RegL]->SUBTRACT(*mh_caller_save_mask);
|
||||
idealreg2mhdebugmask[Op_RegF]->SUBTRACT(*mh_caller_save_mask);
|
||||
idealreg2mhdebugmask[Op_RegD]->SUBTRACT(*mh_caller_save_mask);
|
||||
idealreg2mhdebugmask[Op_RegP]->SUBTRACT(*mh_caller_save_mask);
|
||||
idealreg2mhdebugmask[Op_RegVectMask]->SUBTRACT(*mh_caller_save_mask);
|
||||
|
||||
idealreg2mhdebugmask[Op_VecA]->SUBTRACT(*mh_caller_save_mask);
|
||||
idealreg2mhdebugmask[Op_VecS]->SUBTRACT(*mh_caller_save_mask);
|
||||
idealreg2mhdebugmask[Op_VecD]->SUBTRACT(*mh_caller_save_mask);
|
||||
idealreg2mhdebugmask[Op_VecX]->SUBTRACT(*mh_caller_save_mask);
|
||||
idealreg2mhdebugmask[Op_VecY]->SUBTRACT(*mh_caller_save_mask);
|
||||
idealreg2mhdebugmask[Op_VecZ]->SUBTRACT(*mh_caller_save_mask);
|
||||
}
|
||||
|
||||
//---------------------------is_save_on_entry----------------------------------
|
||||
@ -984,23 +897,15 @@ void Matcher::init_spill_mask( Node *ret ) {
|
||||
if (_register_save_policy[i] == 'C' ||
|
||||
_register_save_policy[i] == 'A') {
|
||||
caller_save_regmask.Insert(i);
|
||||
mh_caller_save_regmask.Insert(i);
|
||||
}
|
||||
// Exclude save-on-entry registers from debug masks for stub compilations.
|
||||
if (_register_save_policy[i] == 'C' ||
|
||||
_register_save_policy[i] == 'A' ||
|
||||
_register_save_policy[i] == 'E') {
|
||||
caller_save_regmask_exclude_soe.Insert(i);
|
||||
mh_caller_save_regmask_exclude_soe.Insert(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Also exclude the register we use to save the SP for MethodHandle
|
||||
// invokes to from the corresponding MH debug masks
|
||||
const RegMask sp_save_mask = method_handle_invoke_SP_save_mask();
|
||||
mh_caller_save_regmask.OR(sp_save_mask);
|
||||
mh_caller_save_regmask_exclude_soe.OR(sp_save_mask);
|
||||
|
||||
// Grab the Frame Pointer
|
||||
Node *fp = ret->in(TypeFunc::FramePtr);
|
||||
// Share frame pointer while making spill ops
|
||||
@ -1272,7 +1177,6 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) {
|
||||
CallNode *call;
|
||||
const TypeTuple *domain;
|
||||
ciMethod* method = nullptr;
|
||||
bool is_method_handle_invoke = false; // for special kill effects
|
||||
if( sfpt->is_Call() ) {
|
||||
call = sfpt->as_Call();
|
||||
domain = call->tf()->domain();
|
||||
@ -1298,13 +1202,8 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) {
|
||||
method = call_java->method();
|
||||
mcall_java->_method = method;
|
||||
mcall_java->_optimized_virtual = call_java->is_optimized_virtual();
|
||||
is_method_handle_invoke = call_java->is_method_handle_invoke();
|
||||
mcall_java->_method_handle_invoke = is_method_handle_invoke;
|
||||
mcall_java->_override_symbolic_info = call_java->override_symbolic_info();
|
||||
mcall_java->_arg_escape = call_java->arg_escape();
|
||||
if (is_method_handle_invoke) {
|
||||
C->set_has_method_handle_invokes(true);
|
||||
}
|
||||
if( mcall_java->is_MachCallStaticJava() )
|
||||
mcall_java->as_MachCallStaticJava()->_name =
|
||||
call_java->as_CallStaticJava()->_name;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -177,7 +177,6 @@ public:
|
||||
static const RegMask *idealreg2regmask[];
|
||||
RegMask *idealreg2spillmask [_last_machine_leaf];
|
||||
RegMask *idealreg2debugmask [_last_machine_leaf];
|
||||
RegMask *idealreg2mhdebugmask[_last_machine_leaf];
|
||||
void init_spill_mask( Node *ret );
|
||||
// Convert machine register number to register mask
|
||||
static uint mreg2regmask_max;
|
||||
@ -185,8 +184,6 @@ public:
|
||||
static RegMask STACK_ONLY_mask;
|
||||
static RegMask caller_save_regmask;
|
||||
static RegMask caller_save_regmask_exclude_soe;
|
||||
static RegMask mh_caller_save_regmask;
|
||||
static RegMask mh_caller_save_regmask_exclude_soe;
|
||||
|
||||
MachNode* mach_null() const { return _mach_null; }
|
||||
|
||||
@ -424,8 +421,6 @@ public:
|
||||
// a code which use multiply for division by constant.
|
||||
static bool use_asm_for_ldiv_by_con( jlong divisor );
|
||||
|
||||
static const RegMask method_handle_invoke_SP_save_mask();
|
||||
|
||||
// Java-Interpreter calling convention
|
||||
// (what you use when calling between compiled-Java and Interpreted-Java
|
||||
|
||||
|
||||
@ -992,7 +992,6 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) {
|
||||
MachCallNode *mcall;
|
||||
|
||||
int safepoint_pc_offset = current_offset;
|
||||
bool is_method_handle_invoke = false;
|
||||
bool return_oop = false;
|
||||
bool has_ea_local_in_scope = sfn->_has_ea_local_in_scope;
|
||||
bool arg_escape = false;
|
||||
@ -1004,12 +1003,7 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) {
|
||||
} else {
|
||||
mcall = mach->as_MachCall();
|
||||
|
||||
// Is the call a MethodHandle call?
|
||||
if (mcall->is_MachCallJava()) {
|
||||
if (mcall->as_MachCallJava()->_method_handle_invoke) {
|
||||
assert(C->has_method_handle_invokes(), "must have been set during call generation");
|
||||
is_method_handle_invoke = true;
|
||||
}
|
||||
arg_escape = mcall->as_MachCallJava()->_arg_escape;
|
||||
}
|
||||
|
||||
@ -1192,7 +1186,6 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) {
|
||||
jvms->bci(),
|
||||
jvms->should_reexecute(),
|
||||
rethrow_exception,
|
||||
is_method_handle_invoke,
|
||||
return_oop,
|
||||
has_ea_local_in_scope,
|
||||
arg_escape,
|
||||
@ -1370,9 +1363,6 @@ CodeBuffer* PhaseOutput::init_buffer() {
|
||||
exception_handler_req +
|
||||
deopt_handler_req; // deopt handler
|
||||
|
||||
if (C->has_method_handle_invokes())
|
||||
total_req += deopt_handler_req; // deopt MH handler
|
||||
|
||||
CodeBuffer* cb = code_buffer();
|
||||
cb->set_const_section_alignment(constant_table().alignment());
|
||||
cb->initialize(total_req, _buf_sizes._reloc);
|
||||
@ -1806,13 +1796,6 @@ void PhaseOutput::fill_buffer(C2_MacroAssembler* masm, uint* blk_starts) {
|
||||
}
|
||||
// Emit the deopt handler code.
|
||||
_code_offsets.set_value(CodeOffsets::Deopt, HandlerImpl::emit_deopt_handler(masm));
|
||||
|
||||
// Emit the MethodHandle deopt handler code (if required).
|
||||
if (C->has_method_handle_invokes() && !C->failing()) {
|
||||
// We can use the same code as for the normal deopt handler, we
|
||||
// just need a different entry point address.
|
||||
_code_offsets.set_value(CodeOffsets::DeoptMH, HandlerImpl::emit_deopt_handler(masm));
|
||||
}
|
||||
}
|
||||
|
||||
// One last check for failed CodeBuffer::expand:
|
||||
|
||||
@ -1913,9 +1913,6 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* c
|
||||
|
||||
current->set_exception_pc(pc);
|
||||
current->set_exception_handler_pc(handler_address);
|
||||
|
||||
// Check if the exception PC is a MethodHandle call site.
|
||||
current->set_is_method_handle_return(nm->is_method_handle_return(pc));
|
||||
}
|
||||
|
||||
// Restore correct return pc. Was saved above.
|
||||
|
||||
@ -589,12 +589,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
||||
// Verify we have the right vframeArray
|
||||
assert(cb->frame_size() >= 0, "Unexpected frame size");
|
||||
intptr_t* unpack_sp = stub_frame.sp() + cb->frame_size();
|
||||
|
||||
// If the deopt call site is a MethodHandle invoke call site we have
|
||||
// to adjust the unpack_sp.
|
||||
nmethod* deoptee_nm = deoptee.cb()->as_nmethod_or_null();
|
||||
if (deoptee_nm != nullptr && deoptee_nm->is_method_handle_return(deoptee.pc()))
|
||||
unpack_sp = deoptee.unextended_sp();
|
||||
assert(unpack_sp == deoptee.unextended_sp(), "must be");
|
||||
|
||||
#ifdef ASSERT
|
||||
assert(cb->is_deoptimization_stub() ||
|
||||
|
||||
@ -206,10 +206,7 @@ address frame::raw_pc() const {
|
||||
if (is_deoptimized_frame()) {
|
||||
nmethod* nm = cb()->as_nmethod_or_null();
|
||||
assert(nm != nullptr, "only nmethod is expected here");
|
||||
if (nm->is_method_handle_return(pc()))
|
||||
return nm->deopt_mh_handler_begin() - pc_return_offset;
|
||||
else
|
||||
return nm->deopt_handler_begin() - pc_return_offset;
|
||||
return nm->deopt_handler_begin() - pc_return_offset;
|
||||
} else {
|
||||
return (pc() - pc_return_offset);
|
||||
}
|
||||
@ -358,9 +355,7 @@ void frame::deoptimize(JavaThread* thread) {
|
||||
|
||||
// If the call site is a MethodHandle call site use the MH deopt handler.
|
||||
nmethod* nm = _cb->as_nmethod();
|
||||
address deopt = nm->is_method_handle_return(pc()) ?
|
||||
nm->deopt_mh_handler_begin() :
|
||||
nm->deopt_handler_begin();
|
||||
address deopt = nm->deopt_handler_begin();
|
||||
|
||||
NativePostCallNop* inst = nativePostCallNop_at(pc());
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -76,7 +76,10 @@ inline address frame::get_deopt_original_pc() const {
|
||||
|
||||
nmethod* nm = _cb->as_nmethod_or_null();
|
||||
if (nm != nullptr && nm->is_deopt_pc(_pc)) {
|
||||
return nm->get_original_pc(this);
|
||||
address original_pc = nm->get_original_pc(this);
|
||||
assert(nm->insts_contains_inclusive(original_pc),
|
||||
"original PC must be in the main code section of the compiled method (or must be immediately following it)");
|
||||
return original_pc;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -476,7 +476,6 @@ JavaThread::JavaThread(MemTag mem_tag) :
|
||||
_exception_oop(oop()),
|
||||
_exception_pc(nullptr),
|
||||
_exception_handler_pc(nullptr),
|
||||
_is_method_handle_return(0),
|
||||
|
||||
_jni_active_critical(0),
|
||||
_pending_jni_exception_check_fn(nullptr),
|
||||
|
||||
@ -450,7 +450,6 @@ class JavaThread: public Thread {
|
||||
volatile oop _exception_oop; // Exception thrown in compiled code
|
||||
volatile address _exception_pc; // PC where exception happened
|
||||
volatile address _exception_handler_pc; // PC for handler of exception
|
||||
volatile int _is_method_handle_return; // true (== 1) if the current exception PC is a MethodHandle call site.
|
||||
|
||||
private:
|
||||
// support for JNI critical regions
|
||||
@ -817,7 +816,6 @@ public:
|
||||
void set_exception_oop(oop o);
|
||||
void set_exception_pc(address a) { _exception_pc = a; }
|
||||
void set_exception_handler_pc(address a) { _exception_handler_pc = a; }
|
||||
void set_is_method_handle_return(bool value) { _is_method_handle_return = value ? 1 : 0; }
|
||||
|
||||
void clear_exception_oop_and_pc() {
|
||||
set_exception_oop(nullptr);
|
||||
@ -866,7 +864,6 @@ public:
|
||||
static ByteSize exception_oop_offset() { return byte_offset_of(JavaThread, _exception_oop); }
|
||||
static ByteSize exception_pc_offset() { return byte_offset_of(JavaThread, _exception_pc); }
|
||||
static ByteSize exception_handler_pc_offset() { return byte_offset_of(JavaThread, _exception_handler_pc); }
|
||||
static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); }
|
||||
|
||||
static ByteSize active_handles_offset() { return byte_offset_of(JavaThread, _active_handles); }
|
||||
|
||||
|
||||
@ -525,9 +525,6 @@ address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* curr
|
||||
assert(frame::verify_return_pc(return_address), "must be a return address: " INTPTR_FORMAT, p2i(return_address));
|
||||
assert(current->frames_to_pop_failed_realloc() == 0 || Interpreter::contains(return_address), "missed frames to pop?");
|
||||
|
||||
// Reset method handle flag.
|
||||
current->set_is_method_handle_return(false);
|
||||
|
||||
#if INCLUDE_JVMCI
|
||||
// JVMCI's ExceptionHandlerStub expects the thread local exception PC to be clear
|
||||
// and other exception handler continuations do not read it
|
||||
@ -542,8 +539,6 @@ address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* curr
|
||||
CodeBlob* blob = CodeCache::find_blob(return_address);
|
||||
nmethod* nm = (blob != nullptr) ? blob->as_nmethod_or_null() : nullptr;
|
||||
if (nm != nullptr) {
|
||||
// Set flag if return address is a method handle call site.
|
||||
current->set_is_method_handle_return(nm->is_method_handle_return(return_address));
|
||||
// native nmethods don't have exception handlers
|
||||
assert(!nm->is_native_method() || nm->method()->is_continuation_enter_intrinsic(), "no exception handler");
|
||||
assert(nm->header_begin() != nm->exception_begin(), "no exception handler");
|
||||
|
||||
@ -536,7 +536,6 @@
|
||||
nonstatic_field(nmethod, _state, volatile signed char) \
|
||||
nonstatic_field(nmethod, _exception_offset, int) \
|
||||
nonstatic_field(nmethod, _deopt_handler_offset, int) \
|
||||
nonstatic_field(nmethod, _deopt_mh_handler_offset, int) \
|
||||
nonstatic_field(nmethod, _orig_pc_offset, int) \
|
||||
nonstatic_field(nmethod, _stub_offset, int) \
|
||||
nonstatic_field(nmethod, _scopes_pcs_offset, int) \
|
||||
@ -608,7 +607,6 @@
|
||||
volatile_nonstatic_field(JavaThread, _suspend_flags, uint32_t) \
|
||||
volatile_nonstatic_field(JavaThread, _exception_oop, oop) \
|
||||
volatile_nonstatic_field(JavaThread, _exception_pc, address) \
|
||||
volatile_nonstatic_field(JavaThread, _is_method_handle_return, int) \
|
||||
nonstatic_field(JavaThread, _saved_exception_pc, address) \
|
||||
volatile_nonstatic_field(JavaThread, _thread_state, JavaThreadState) \
|
||||
nonstatic_field(JavaThread, _stack_base, address) \
|
||||
@ -1711,7 +1709,6 @@
|
||||
/**********************/ \
|
||||
\
|
||||
declare_constant(PcDesc::PCDESC_reexecute) \
|
||||
declare_constant(PcDesc::PCDESC_is_method_handle_invoke) \
|
||||
declare_constant(PcDesc::PCDESC_return_oop) \
|
||||
\
|
||||
/**********************/ \
|
||||
|
||||
@ -48,7 +48,6 @@ public class NMethod extends CodeBlob {
|
||||
/** Offsets for different nmethod parts */
|
||||
private static CIntegerField exceptionOffsetField;
|
||||
private static CIntegerField deoptHandlerOffsetField;
|
||||
private static CIntegerField deoptMhHandlerOffsetField;
|
||||
private static CIntegerField origPCOffsetField;
|
||||
private static CIntegerField stubOffsetField;
|
||||
private static CIntField handlerTableOffsetField;
|
||||
@ -86,7 +85,6 @@ public class NMethod extends CodeBlob {
|
||||
immutableDataSizeField = type.getCIntegerField("_immutable_data_size");
|
||||
exceptionOffsetField = type.getCIntegerField("_exception_offset");
|
||||
deoptHandlerOffsetField = type.getCIntegerField("_deopt_handler_offset");
|
||||
deoptMhHandlerOffsetField = type.getCIntegerField("_deopt_mh_handler_offset");
|
||||
origPCOffsetField = type.getCIntegerField("_orig_pc_offset");
|
||||
stubOffsetField = type.getCIntegerField("_stub_offset");
|
||||
scopesPCsOffsetField = type.getCIntegerField("_scopes_pcs_offset");
|
||||
@ -125,7 +123,6 @@ public class NMethod extends CodeBlob {
|
||||
public Address instsEnd() { return headerBegin().addOffsetTo(getStubOffset()); }
|
||||
public Address exceptionBegin() { return headerBegin().addOffsetTo(getExceptionOffset()); }
|
||||
public Address deoptHandlerBegin() { return headerBegin().addOffsetTo(getDeoptHandlerOffset()); }
|
||||
public Address deoptMhHandlerBegin() { return headerBegin().addOffsetTo(getDeoptMhHandlerOffset()); }
|
||||
public Address stubBegin() { return headerBegin().addOffsetTo(getStubOffset()); }
|
||||
public Address stubEnd() { return dataBegin(); }
|
||||
public Address oopsBegin() { return dataBegin(); }
|
||||
@ -250,22 +247,10 @@ public class NMethod extends CodeBlob {
|
||||
return VMObjectFactory.newObject(NMethod.class, osrLinkField.getValue(addr));
|
||||
}
|
||||
|
||||
// MethodHandle
|
||||
public boolean isMethodHandleReturn(Address returnPc) {
|
||||
// Hard to read a bit fields from Java and it's only there for performance
|
||||
// so just go directly to the PCDesc
|
||||
// if (!hasMethodHandleInvokes()) return false;
|
||||
PCDesc pd = getPCDescAt(returnPc);
|
||||
if (pd == null)
|
||||
return false;
|
||||
return pd.isMethodHandleInvoke();
|
||||
}
|
||||
|
||||
// Deopt
|
||||
// Return true is the PC is one would expect if the frame is being deopted.
|
||||
public boolean isDeoptPc (Address pc) { return isDeoptEntry(pc) || isDeoptMhEntry(pc); }
|
||||
public boolean isDeoptPc (Address pc) { return isDeoptEntry(pc); }
|
||||
public boolean isDeoptEntry (Address pc) { return pc == deoptHandlerBegin(); }
|
||||
public boolean isDeoptMhEntry (Address pc) { return pc == deoptMhHandlerBegin(); }
|
||||
|
||||
/** Tells whether frames described by this nmethod can be
|
||||
deoptimized. Note: native wrappers cannot be deoptimized. */
|
||||
@ -494,7 +479,6 @@ public class NMethod extends CodeBlob {
|
||||
private int getEntryBCI() { return (int) entryBCIField .getValue(addr); }
|
||||
private int getExceptionOffset() { return (int) exceptionOffsetField .getValue(addr); }
|
||||
private int getDeoptHandlerOffset() { return (int) deoptHandlerOffsetField .getValue(addr); }
|
||||
private int getDeoptMhHandlerOffset() { return (int) deoptMhHandlerOffsetField.getValue(addr); }
|
||||
private int getStubOffset() { return (int) stubOffsetField .getValue(addr); }
|
||||
private int getScopesDataOffset() { return (int) scopesDataOffsetField .getValue(addr); }
|
||||
private int getScopesPCsOffset() { return (int) scopesPCsOffsetField .getValue(addr); }
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -41,7 +41,6 @@ public class PCDesc extends VMObject {
|
||||
private static CIntegerField objDecodeOffsetField;
|
||||
private static CIntegerField pcFlagsField;
|
||||
private static int reexecuteMask;
|
||||
private static int isMethodHandleInvokeMask;
|
||||
private static int returnOopMask;
|
||||
|
||||
static {
|
||||
@ -61,7 +60,6 @@ public class PCDesc extends VMObject {
|
||||
pcFlagsField = type.getCIntegerField("_flags");
|
||||
|
||||
reexecuteMask = db.lookupIntConstant("PcDesc::PCDESC_reexecute");
|
||||
isMethodHandleInvokeMask = db.lookupIntConstant("PcDesc::PCDESC_is_method_handle_invoke");
|
||||
returnOopMask = db.lookupIntConstant("PcDesc::PCDESC_return_oop");
|
||||
}
|
||||
|
||||
@ -93,11 +91,6 @@ public class PCDesc extends VMObject {
|
||||
return (flags & reexecuteMask) != 0;
|
||||
}
|
||||
|
||||
public boolean isMethodHandleInvoke() {
|
||||
int flags = (int)pcFlagsField.getValue(addr);
|
||||
return (flags & isMethodHandleInvokeMask) != 0;
|
||||
}
|
||||
|
||||
public void print(NMethod code) {
|
||||
printOn(System.out, code);
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -81,6 +81,24 @@ public abstract class Frame implements Cloneable {
|
||||
return pcReturnOffset;
|
||||
}
|
||||
|
||||
protected void adjustForDeopt() {
|
||||
if (pc != null) {
|
||||
// Look for a deopt pc and if it is deopted convert to original pc
|
||||
CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
|
||||
if (cb != null && cb.isJavaMethod()) {
|
||||
NMethod nm = (NMethod) cb;
|
||||
if (pc.equals(nm.deoptHandlerBegin())) {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
|
||||
}
|
||||
// adjust pc if frame is deoptimized.
|
||||
pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
|
||||
deoptimized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static synchronized void initialize(TypeDataBase db) {
|
||||
Type ConstMethodType = db.lookupType("ConstMethod");
|
||||
// FIXME: not sure whether alignment here is correct or how to
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, Red Hat Inc.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
@ -106,30 +106,11 @@ public class AARCH64Frame extends Frame {
|
||||
private AARCH64Frame() {
|
||||
}
|
||||
|
||||
private void adjustForDeopt() {
|
||||
if ( pc != null) {
|
||||
// Look for a deopt pc and if it is deopted convert to original pc
|
||||
CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
|
||||
if (cb != null && cb.isJavaMethod()) {
|
||||
NMethod nm = (NMethod) cb;
|
||||
if (pc.equals(nm.deoptHandlerBegin())) {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
|
||||
}
|
||||
// adjust pc if frame is deoptimized.
|
||||
pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
|
||||
deoptimized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AARCH64Frame(Address raw_sp, Address raw_fp, Address pc) {
|
||||
this.raw_sp = raw_sp;
|
||||
this.raw_unextendedSP = raw_sp;
|
||||
this.raw_fp = raw_fp;
|
||||
this.pc = pc;
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
@ -153,8 +134,6 @@ public class AARCH64Frame extends Frame {
|
||||
this.pc = savedPC;
|
||||
}
|
||||
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
|
||||
@ -169,7 +148,6 @@ public class AARCH64Frame extends Frame {
|
||||
this.raw_unextendedSP = raw_unextendedSp;
|
||||
this.raw_fp = raw_fp;
|
||||
this.pc = pc;
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
@ -355,24 +333,6 @@ public class AARCH64Frame extends Frame {
|
||||
return fr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
private void adjustUnextendedSP() {
|
||||
// Sites calling method handle intrinsics and lambda forms are
|
||||
// treated as any other call site. Therefore, no special action is
|
||||
// needed when we are returning to any of these call sites.
|
||||
|
||||
CodeBlob cb = cb();
|
||||
NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull();
|
||||
if (senderNm != null) {
|
||||
// If the sender PC is a deoptimization point, get the original PC.
|
||||
if (senderNm.isDeoptEntry(getPC()) ||
|
||||
senderNm.isDeoptMhEntry(getPC())) {
|
||||
// DEBUG_ONLY(verifyDeoptriginalPc(senderNm, raw_unextendedSp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Frame senderForInterpreterFrame(AARCH64RegisterMap map) {
|
||||
if (DEBUG) {
|
||||
System.out.println("senderForInterpreterFrame");
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -85,24 +85,6 @@ public class PPC64Frame extends Frame {
|
||||
private PPC64Frame() {
|
||||
}
|
||||
|
||||
private void adjustForDeopt() {
|
||||
if ( pc != null) {
|
||||
// Look for a deopt pc and if it is deopted convert to original pc
|
||||
CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
|
||||
if (cb != null && cb.isJavaMethod()) {
|
||||
NMethod nm = (NMethod) cb;
|
||||
if (pc.equals(nm.deoptHandlerBegin())) {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
|
||||
}
|
||||
// adjust pc if frame is deoptimized.
|
||||
pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
|
||||
deoptimized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PPC64Frame(Address raw_sp, Address raw_fp, Address pc) {
|
||||
this.raw_sp = raw_sp;
|
||||
this.raw_unextendedSP = raw_sp;
|
||||
@ -116,7 +98,6 @@ public class PPC64Frame extends Frame {
|
||||
} else {
|
||||
this.pc = pc;
|
||||
}
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
@ -136,7 +117,6 @@ public class PPC64Frame extends Frame {
|
||||
this.raw_fp = raw_fp;
|
||||
}
|
||||
this.pc = raw_sp.getAddressAt(2 * VM.getVM().getAddressSize());
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
@ -160,7 +140,6 @@ public class PPC64Frame extends Frame {
|
||||
} else {
|
||||
this.pc = pc;
|
||||
}
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
@ -342,12 +321,6 @@ public class PPC64Frame extends Frame {
|
||||
return fr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
private void adjustUnextendedSP() {
|
||||
// Nothing to do. senderForInterpreterFrame finds the correct unextendedSP.
|
||||
}
|
||||
|
||||
private Frame senderForInterpreterFrame(PPC64RegisterMap map) {
|
||||
if (DEBUG) {
|
||||
System.out.println("senderForInterpreterFrame");
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2019, Red Hat Inc.
|
||||
* Copyright (c) 2021, 2023, Huawei Technologies Co., Ltd. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
@ -101,30 +101,11 @@ public class RISCV64Frame extends Frame {
|
||||
private RISCV64Frame() {
|
||||
}
|
||||
|
||||
private void adjustForDeopt() {
|
||||
if ( pc != null) {
|
||||
// Look for a deopt pc and if it is deopted convert to original pc
|
||||
CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
|
||||
if (cb != null && cb.isJavaMethod()) {
|
||||
NMethod nm = (NMethod) cb;
|
||||
if (pc.equals(nm.deoptHandlerBegin())) {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
|
||||
}
|
||||
// adjust pc if frame is deoptimized.
|
||||
pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
|
||||
deoptimized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public RISCV64Frame(Address raw_sp, Address raw_fp, Address pc) {
|
||||
this.raw_sp = raw_sp;
|
||||
this.raw_unextendedSP = raw_sp;
|
||||
this.raw_fp = raw_fp;
|
||||
this.pc = pc;
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
@ -148,8 +129,6 @@ public class RISCV64Frame extends Frame {
|
||||
this.pc = savedPC;
|
||||
}
|
||||
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
|
||||
@ -164,7 +143,6 @@ public class RISCV64Frame extends Frame {
|
||||
this.raw_unextendedSP = raw_unextendedSp;
|
||||
this.raw_fp = raw_fp;
|
||||
this.pc = pc;
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
@ -347,24 +325,6 @@ public class RISCV64Frame extends Frame {
|
||||
return fr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
private void adjustUnextendedSP() {
|
||||
// Sites calling method handle intrinsics and lambda forms are
|
||||
// treated as any other call site. Therefore, no special action is
|
||||
// needed when we are returning to any of these call sites.
|
||||
|
||||
CodeBlob cb = cb();
|
||||
NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull();
|
||||
if (senderNm != null) {
|
||||
// If the sender PC is a deoptimization point, get the original PC.
|
||||
if (senderNm.isDeoptEntry(getPC()) ||
|
||||
senderNm.isDeoptMhEntry(getPC())) {
|
||||
// DEBUG_ONLY(verifyDeoptriginalPc(senderNm, raw_unextendedSp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Frame senderForInterpreterFrame(RISCV64RegisterMap map) {
|
||||
if (DEBUG) {
|
||||
System.out.println("senderForInterpreterFrame");
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -102,24 +102,6 @@ public class X86Frame extends Frame {
|
||||
private X86Frame() {
|
||||
}
|
||||
|
||||
private void adjustForDeopt() {
|
||||
if ( pc != null) {
|
||||
// Look for a deopt pc and if it is deopted convert to original pc
|
||||
CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc);
|
||||
if (cb != null && cb.isJavaMethod()) {
|
||||
NMethod nm = (NMethod) cb;
|
||||
if (pc.equals(nm.deoptHandlerBegin())) {
|
||||
if (Assert.ASSERTS_ENABLED) {
|
||||
Assert.that(this.getUnextendedSP() != null, "null SP in Java frame");
|
||||
}
|
||||
// adjust pc if frame is deoptimized.
|
||||
pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset());
|
||||
deoptimized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initFrame(Address raw_sp, Address raw_fp, Address pc, Address raw_unextendedSp, Address live_bcp) {
|
||||
this.raw_sp = raw_sp;
|
||||
this.raw_fp = raw_fp;
|
||||
@ -134,11 +116,10 @@ public class X86Frame extends Frame {
|
||||
this.pc = pc;
|
||||
}
|
||||
this.live_bcp = live_bcp;
|
||||
adjustUnextendedSP();
|
||||
|
||||
// Frame must be fully constructed before this call
|
||||
adjustForDeopt();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public X86Frame(Address raw_sp, Address raw_fp, Address pc) {
|
||||
@ -352,24 +333,6 @@ public class X86Frame extends Frame {
|
||||
return fr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// frame::adjust_unextended_sp
|
||||
private void adjustUnextendedSP() {
|
||||
// On x86, sites calling method handle intrinsics and lambda forms are treated
|
||||
// as any other call site. Therefore, no special action is needed when we are
|
||||
// returning to any of these call sites.
|
||||
|
||||
CodeBlob cb = cb();
|
||||
NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull();
|
||||
if (senderNm != null) {
|
||||
// If the sender PC is a deoptimization point, get the original PC.
|
||||
if (senderNm.isDeoptEntry(getPC()) ||
|
||||
senderNm.isDeoptMhEntry(getPC())) {
|
||||
// DEBUG_ONLY(verifyDeoptriginalPc(senderNm, raw_unextendedSp));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Frame senderForInterpreterFrame(X86RegisterMap map) {
|
||||
if (DEBUG) {
|
||||
System.out.println("senderForInterpreterFrame");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user