8366461: Remove obsolete method handle invoke logic

Reviewed-by: vlivanov, mhaessig
This commit is contained in:
Dean Long 2025-10-02 22:21:13 +00:00
parent fa6e884105
commit da7121aff9
76 changed files with 74 additions and 877 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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 {

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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() {

View File

@ -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;

View File

@ -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);
}

View File

@ -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) {

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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 {

View File

@ -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

View File

@ -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) {

View File

@ -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++) {

View File

@ -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;
}

View File

@ -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)) {

View File

@ -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;
}

View File

@ -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 {

View File

@ -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

View File

@ -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) {

View File

@ -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-----------------------------------------------------

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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())

View File

@ -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; }

View File

@ -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

View File

@ -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);
}

View File

@ -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; }

View File

@ -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);

View File

@ -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; }

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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]";

View File

@ -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.

View File

@ -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); }

View File

@ -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); }

View File

@ -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:

View File

@ -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);

View File

@ -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

View File

@ -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) \

View File

@ -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);

View File

@ -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; }

View File

@ -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),

View File

@ -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();

View File

@ -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;

View File

@ -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()];
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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:

View File

@ -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.

View File

@ -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() ||

View File

@ -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());

View File

@ -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;
}

View File

@ -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),

View File

@ -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); }

View File

@ -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");

View File

@ -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) \
\
/**********************/ \

View File

@ -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); }

View File

@ -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);
}

View File

@ -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

View File

@ -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");

View File

@ -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");

View File

@ -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");

View File

@ -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");