Compare commits
6 Commits
0780d1566d
...
0950fc5e87
Author | SHA1 | Date | |
---|---|---|---|
|
0950fc5e87 | ||
|
40b922977b | ||
|
88c1d72eda | ||
|
726bddfb43 | ||
|
924e87cac8 | ||
|
5a5dd6dd06 |
@ -212,11 +212,6 @@ void NativeMovRegMem::verify() {
|
|||||||
|
|
||||||
void NativeJump::verify() { ; }
|
void NativeJump::verify() { ; }
|
||||||
|
|
||||||
|
|
||||||
void NativeJump::check_verified_entry_alignment(address entry, address verified_entry) {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
address NativeJump::jump_destination() const {
|
address NativeJump::jump_destination() const {
|
||||||
address dest = MacroAssembler::target_addr_for_insn_or_null(instruction_address());
|
address dest = MacroAssembler::target_addr_for_insn_or_null(instruction_address());
|
||||||
|
|
||||||
@ -359,31 +354,6 @@ bool NativeInstruction::is_stop() {
|
|||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
// MT-safe inserting of a jump over a jump or a nop (used by
|
|
||||||
// nmethod::make_not_entrant)
|
|
||||||
|
|
||||||
void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
|
|
||||||
|
|
||||||
assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch");
|
|
||||||
assert(nativeInstruction_at(verified_entry)->is_jump_or_nop()
|
|
||||||
|| nativeInstruction_at(verified_entry)->is_sigill_not_entrant(),
|
|
||||||
"Aarch64 cannot replace non-jump with jump");
|
|
||||||
|
|
||||||
// Patch this nmethod atomically.
|
|
||||||
if (Assembler::reachable_from_branch_at(verified_entry, dest)) {
|
|
||||||
ptrdiff_t disp = dest - verified_entry;
|
|
||||||
guarantee(disp < 1 << 27 && disp > - (1 << 27), "branch overflow");
|
|
||||||
|
|
||||||
unsigned int insn = (0b000101 << 26) | ((disp >> 2) & 0x3ffffff);
|
|
||||||
*(unsigned int*)verified_entry = insn;
|
|
||||||
} else {
|
|
||||||
// We use an illegal instruction for marking a method as not_entrant.
|
|
||||||
NativeIllegalInstruction::insert(verified_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
ICache::invalidate_range(verified_entry, instruction_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeGeneralJump::verify() { }
|
void NativeGeneralJump::verify() { }
|
||||||
|
|
||||||
void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
|
void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
|
||||||
|
@ -360,9 +360,6 @@ public:
|
|||||||
|
|
||||||
// Insertion of native jump instruction
|
// Insertion of native jump instruction
|
||||||
static void insert(address code_pos, address entry);
|
static void insert(address code_pos, address entry);
|
||||||
// MT-safe insertion of native jump at verified method entry
|
|
||||||
static void check_verified_entry_alignment(address entry, address verified_entry);
|
|
||||||
static void patch_verified_entry(address entry, address verified_entry, address dest);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline NativeJump* nativeJump_at(address address) {
|
inline NativeJump* nativeJump_at(address address) {
|
||||||
|
@ -282,16 +282,6 @@ void NativeMovConstReg::set_pc_relative_offset(address addr, address pc) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RawNativeJump::check_verified_entry_alignment(address entry, address verified_entry) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void RawNativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
|
|
||||||
assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "should be");
|
|
||||||
int *a = (int *)verified_entry;
|
|
||||||
a[0] = not_entrant_illegal_instruction; // always illegal
|
|
||||||
ICache::invalidate_range((address)&a[0], sizeof a[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
|
void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
|
||||||
int offset = (int)(entry - code_pos - 8);
|
int offset = (int)(entry - code_pos - 8);
|
||||||
assert(offset < 0x2000000 && offset > -0x2000000, "encoding constraint");
|
assert(offset < 0x2000000 && offset > -0x2000000, "encoding constraint");
|
||||||
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -61,10 +61,6 @@ class RawNativeInstruction {
|
|||||||
instr_fld_fst = 0xd0
|
instr_fld_fst = 0xd0
|
||||||
};
|
};
|
||||||
|
|
||||||
// illegal instruction used by NativeJump::patch_verified_entry
|
|
||||||
// permanently undefined (UDF): 0xe << 28 | 0b1111111 << 20 | 0b1111 << 4
|
|
||||||
static const int not_entrant_illegal_instruction = 0xe7f000f0;
|
|
||||||
|
|
||||||
static int decode_rotated_imm12(int encoding) {
|
static int decode_rotated_imm12(int encoding) {
|
||||||
int base = encoding & 0xff;
|
int base = encoding & 0xff;
|
||||||
int right_rotation = (encoding & 0xf00) >> 7;
|
int right_rotation = (encoding & 0xf00) >> 7;
|
||||||
@ -274,10 +270,6 @@ class RawNativeJump: public NativeInstruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_verified_entry_alignment(address entry, address verified_entry);
|
|
||||||
|
|
||||||
static void patch_verified_entry(address entry, address verified_entry, address dest);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline RawNativeJump* rawNativeJump_at(address address) {
|
inline RawNativeJump* rawNativeJump_at(address address) {
|
||||||
|
@ -46,7 +46,6 @@ void C1_MacroAssembler::explicit_null_check(Register base) {
|
|||||||
|
|
||||||
|
|
||||||
void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) {
|
void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) {
|
||||||
// Avoid stack bang as first instruction. It may get overwritten by patch_verified_entry.
|
|
||||||
const Register return_pc = R20;
|
const Register return_pc = R20;
|
||||||
mflr(return_pc);
|
mflr(return_pc);
|
||||||
|
|
||||||
|
@ -39,18 +39,6 @@
|
|||||||
#include "c1/c1_Runtime1.hpp"
|
#include "c1/c1_Runtime1.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We use an illtrap for marking a method as not_entrant
|
|
||||||
// Work around a C++ compiler bug which changes 'this'
|
|
||||||
bool NativeInstruction::is_sigill_not_entrant_at(address addr) {
|
|
||||||
if (!Assembler::is_illtrap(addr)) return false;
|
|
||||||
CodeBlob* cb = CodeCache::find_blob(addr);
|
|
||||||
if (cb == nullptr || !cb->is_nmethod()) return false;
|
|
||||||
nmethod *nm = (nmethod *)cb;
|
|
||||||
// This method is not_entrant iff the illtrap instruction is
|
|
||||||
// located at the verified entry point.
|
|
||||||
return nm->verified_entry_point() == addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void NativeInstruction::verify() {
|
void NativeInstruction::verify() {
|
||||||
// Make sure code pattern is actually an instruction address.
|
// Make sure code pattern is actually an instruction address.
|
||||||
@ -331,25 +319,6 @@ void NativeMovConstReg::verify() {
|
|||||||
}
|
}
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
|
||||||
void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
|
|
||||||
ResourceMark rm;
|
|
||||||
int code_size = 1 * BytesPerInstWord;
|
|
||||||
CodeBuffer cb(verified_entry, code_size + 1);
|
|
||||||
MacroAssembler* a = new MacroAssembler(&cb);
|
|
||||||
#ifdef COMPILER2
|
|
||||||
assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch");
|
|
||||||
#endif
|
|
||||||
// Patch this nmethod atomically. Always use illtrap/trap in debug build.
|
|
||||||
if (DEBUG_ONLY(false &&) a->is_within_range_of_b(dest, a->pc())) {
|
|
||||||
a->b(dest);
|
|
||||||
} else {
|
|
||||||
// The signal handler will continue at dest=OptoRuntime::handle_wrong_method_stub().
|
|
||||||
// We use an illtrap for marking a method as not_entrant.
|
|
||||||
a->illtrap();
|
|
||||||
}
|
|
||||||
ICache::ppc64_flush_icache_bytes(verified_entry, code_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
void NativeJump::verify() {
|
void NativeJump::verify() {
|
||||||
address addr = addr_at(0);
|
address addr = addr_at(0);
|
||||||
@ -462,9 +431,7 @@ bool NativeDeoptInstruction::is_deopt_at(address code_pos) {
|
|||||||
if (!Assembler::is_illtrap(code_pos)) return false;
|
if (!Assembler::is_illtrap(code_pos)) return false;
|
||||||
CodeBlob* cb = CodeCache::find_blob(code_pos);
|
CodeBlob* cb = CodeCache::find_blob(code_pos);
|
||||||
if (cb == nullptr || !cb->is_nmethod()) return false;
|
if (cb == nullptr || !cb->is_nmethod()) return false;
|
||||||
nmethod *nm = (nmethod *)cb;
|
return true;
|
||||||
// see NativeInstruction::is_sigill_not_entrant_at()
|
|
||||||
return nm->verified_entry_point() != code_pos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inserts an instruction which is specified to cause a SIGILL at a given pc
|
// Inserts an instruction which is specified to cause a SIGILL at a given pc
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012, 2024 SAP SE. All rights reserved.
|
* Copyright (c) 2012, 2024 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -328,15 +328,7 @@ class NativeJump: public NativeInstruction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MT-safe insertion of native jump at verified method entry
|
|
||||||
static void patch_verified_entry(address entry, address verified_entry, address dest);
|
|
||||||
|
|
||||||
void verify() NOT_DEBUG_RETURN;
|
void verify() NOT_DEBUG_RETURN;
|
||||||
|
|
||||||
static void check_verified_entry_alignment(address entry, address verified_entry) {
|
|
||||||
// We just patch one instruction on ppc64, so the jump doesn't have to
|
|
||||||
// be aligned. Nothing to do here.
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Instantiates a NativeJump object starting at the given instruction
|
// Instantiates a NativeJump object starting at the given instruction
|
||||||
|
@ -356,18 +356,6 @@ void NativeMovRegMem::verify() {
|
|||||||
|
|
||||||
void NativeJump::verify() { }
|
void NativeJump::verify() { }
|
||||||
|
|
||||||
|
|
||||||
void NativeJump::check_verified_entry_alignment(address entry, address verified_entry) {
|
|
||||||
// Patching to not_entrant can happen while activations of the method are
|
|
||||||
// in use. The patching in that instance must happen only when certain
|
|
||||||
// alignment restrictions are true. These guarantees check those
|
|
||||||
// conditions.
|
|
||||||
|
|
||||||
// Must be 4 bytes aligned
|
|
||||||
MacroAssembler::assert_alignment(verified_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
address NativeJump::jump_destination() const {
|
address NativeJump::jump_destination() const {
|
||||||
address dest = MacroAssembler::target_addr_for_insn(instruction_address());
|
address dest = MacroAssembler::target_addr_for_insn(instruction_address());
|
||||||
|
|
||||||
@ -437,45 +425,6 @@ bool NativeInstruction::is_stop() {
|
|||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
// MT-safe inserting of a jump over a jump or a nop (used by
|
|
||||||
// nmethod::make_not_entrant)
|
|
||||||
|
|
||||||
void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
|
|
||||||
|
|
||||||
assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch");
|
|
||||||
|
|
||||||
assert(nativeInstruction_at(verified_entry)->is_jump_or_nop() ||
|
|
||||||
nativeInstruction_at(verified_entry)->is_sigill_not_entrant(),
|
|
||||||
"riscv cannot replace non-jump with jump");
|
|
||||||
|
|
||||||
check_verified_entry_alignment(entry, verified_entry);
|
|
||||||
|
|
||||||
// Patch this nmethod atomically.
|
|
||||||
if (Assembler::reachable_from_branch_at(verified_entry, dest)) {
|
|
||||||
ptrdiff_t offset = dest - verified_entry;
|
|
||||||
guarantee(Assembler::is_simm21(offset) && ((offset % 2) == 0),
|
|
||||||
"offset is too large to be patched in one jal instruction."); // 1M
|
|
||||||
|
|
||||||
uint32_t insn = 0;
|
|
||||||
address pInsn = (address)&insn;
|
|
||||||
Assembler::patch(pInsn, 31, 31, (offset >> 20) & 0x1);
|
|
||||||
Assembler::patch(pInsn, 30, 21, (offset >> 1) & 0x3ff);
|
|
||||||
Assembler::patch(pInsn, 20, 20, (offset >> 11) & 0x1);
|
|
||||||
Assembler::patch(pInsn, 19, 12, (offset >> 12) & 0xff);
|
|
||||||
Assembler::patch(pInsn, 11, 7, 0); // zero, no link jump
|
|
||||||
Assembler::patch(pInsn, 6, 0, 0b1101111); // j, (jal x0 offset)
|
|
||||||
Assembler::sd_instr(verified_entry, insn);
|
|
||||||
} else {
|
|
||||||
// We use an illegal instruction for marking a method as
|
|
||||||
// not_entrant.
|
|
||||||
NativeIllegalInstruction::insert(verified_entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
ICache::invalidate_range(verified_entry, instruction_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
|
||||||
|
|
||||||
void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
|
void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
|
||||||
CodeBuffer cb(code_pos, instruction_size);
|
CodeBuffer cb(code_pos, instruction_size);
|
||||||
MacroAssembler a(&cb);
|
MacroAssembler a(&cb);
|
||||||
|
@ -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, 2018, Red Hat Inc. All rights reserved.
|
* Copyright (c) 2014, 2018, Red Hat Inc. All rights reserved.
|
||||||
* Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. 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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
@ -274,9 +274,6 @@ class NativeJump: public NativeInstruction {
|
|||||||
|
|
||||||
// Insertion of native jump instruction
|
// Insertion of native jump instruction
|
||||||
static void insert(address code_pos, address entry);
|
static void insert(address code_pos, address entry);
|
||||||
// MT-safe insertion of native jump at verified method entry
|
|
||||||
static void check_verified_entry_alignment(address entry, address verified_entry);
|
|
||||||
static void patch_verified_entry(address entry, address verified_entry, address dest);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline NativeJump* nativeJump_at(address addr) {
|
inline NativeJump* nativeJump_at(address addr) {
|
||||||
|
@ -1796,7 +1796,6 @@ void MachUEPNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const
|
|||||||
// This is the unverified entry point.
|
// This is the unverified entry point.
|
||||||
__ ic_check(CodeEntryAlignment);
|
__ ic_check(CodeEntryAlignment);
|
||||||
|
|
||||||
// Verified entry point must be properly 4 bytes aligned for patching by NativeJump::patch_verified_entry().
|
|
||||||
// ic_check() aligns to CodeEntryAlignment >= InteriorEntryAlignment(min 16) > NativeInstruction::instruction_size(4).
|
// ic_check() aligns to CodeEntryAlignment >= InteriorEntryAlignment(min 16) > NativeInstruction::instruction_size(4).
|
||||||
assert(((__ offset()) % CodeEntryAlignment) == 0, "Misaligned verified entry point");
|
assert(((__ offset()) % CodeEntryAlignment) == 0, "Misaligned verified entry point");
|
||||||
}
|
}
|
||||||
@ -8191,7 +8190,7 @@ instruct unnecessary_membar_volatile_rvtso() %{
|
|||||||
ins_cost(0);
|
ins_cost(0);
|
||||||
|
|
||||||
size(0);
|
size(0);
|
||||||
|
|
||||||
format %{ "#@unnecessary_membar_volatile_rvtso (unnecessary so empty encoding)" %}
|
format %{ "#@unnecessary_membar_volatile_rvtso (unnecessary so empty encoding)" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
__ block_comment("unnecessary_membar_volatile_rvtso");
|
__ block_comment("unnecessary_membar_volatile_rvtso");
|
||||||
|
@ -167,27 +167,6 @@ bool NativeInstruction::is_illegal() {
|
|||||||
return halfword_at(-2) == illegal_instruction();
|
return halfword_at(-2) == illegal_instruction();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We use an illtrap for marking a method as not_entrant.
|
|
||||||
bool NativeInstruction::is_sigill_not_entrant() {
|
|
||||||
if (!is_illegal()) return false; // Just a quick path.
|
|
||||||
|
|
||||||
// One-sided error of is_illegal tolerable here
|
|
||||||
// (see implementation of is_illegal() for details).
|
|
||||||
|
|
||||||
CodeBlob* cb = CodeCache::find_blob(addr_at(0));
|
|
||||||
if (cb == nullptr || !cb->is_nmethod()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
nmethod *nm = (nmethod *)cb;
|
|
||||||
// This method is not_entrant if the illtrap instruction
|
|
||||||
// is located at the verified entry point.
|
|
||||||
// BE AWARE: the current pc (this) points to the instruction after the
|
|
||||||
// "illtrap" location.
|
|
||||||
address sig_addr = ((address) this) - 2;
|
|
||||||
return nm->verified_entry_point() == sig_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NativeInstruction::is_jump() {
|
bool NativeInstruction::is_jump() {
|
||||||
unsigned long inst;
|
unsigned long inst;
|
||||||
Assembler::get_instruction((address)this, &inst);
|
Assembler::get_instruction((address)this, &inst);
|
||||||
@ -620,19 +599,6 @@ void NativeJump::verify() {
|
|||||||
fatal("this is not a `NativeJump' site");
|
fatal("this is not a `NativeJump' site");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Patch atomically with an illtrap.
|
|
||||||
void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
|
|
||||||
ResourceMark rm;
|
|
||||||
int code_size = 2;
|
|
||||||
CodeBuffer cb(verified_entry, code_size + 1);
|
|
||||||
MacroAssembler* a = new MacroAssembler(&cb);
|
|
||||||
#ifdef COMPILER2
|
|
||||||
assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch");
|
|
||||||
#endif
|
|
||||||
a->z_illtrap();
|
|
||||||
ICache::invalidate_range(verified_entry, code_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef LUCY_DBG
|
#undef LUCY_DBG
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2016, 2024 SAP SE. All rights reserved.
|
* Copyright (c) 2016, 2024 SAP SE. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -609,11 +609,6 @@ class NativeJump: public NativeInstruction {
|
|||||||
|
|
||||||
// Insertion of native jump instruction.
|
// Insertion of native jump instruction.
|
||||||
static void insert(address code_pos, address entry);
|
static void insert(address code_pos, address entry);
|
||||||
|
|
||||||
// MT-safe insertion of native jump at verified method entry.
|
|
||||||
static void check_verified_entry_alignment(address entry, address verified_entry) { }
|
|
||||||
|
|
||||||
static void patch_verified_entry(address entry, address verified_entry, address dest);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* Copyright 2008 Red Hat, Inc.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "asm/assembler.inline.hpp"
|
|
||||||
#include "entry_zero.hpp"
|
|
||||||
#include "interpreter/zero/zeroInterpreter.hpp"
|
|
||||||
#include "nativeInst_zero.hpp"
|
|
||||||
#include "runtime/sharedRuntime.hpp"
|
|
||||||
|
|
||||||
// This method is called by nmethod::make_not_entrant to
|
|
||||||
// insert a jump to SharedRuntime::get_handle_wrong_method_stub()
|
|
||||||
// (dest) at the start of a compiled method (verified_entry) to avoid
|
|
||||||
// a race where a method is invoked while being made non-entrant.
|
|
||||||
|
|
||||||
void NativeJump::patch_verified_entry(address entry,
|
|
||||||
address verified_entry,
|
|
||||||
address dest) {
|
|
||||||
assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "should be");
|
|
||||||
|
|
||||||
((ZeroEntry*) verified_entry)->set_entry_point(
|
|
||||||
(address) ZeroInterpreter::normal_entry);
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright 2007 Red Hat, Inc.
|
* Copyright 2007 Red Hat, Inc.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
@ -177,14 +177,6 @@ class NativeJump : public NativeInstruction {
|
|||||||
void set_jump_destination(address dest) {
|
void set_jump_destination(address dest) {
|
||||||
ShouldNotCallThis();
|
ShouldNotCallThis();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check_verified_entry_alignment(address entry,
|
|
||||||
address verified_entry) {
|
|
||||||
}
|
|
||||||
|
|
||||||
static void patch_verified_entry(address entry,
|
|
||||||
address verified_entry,
|
|
||||||
address dest);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline NativeJump* nativeJump_at(address address) {
|
inline NativeJump* nativeJump_at(address address) {
|
||||||
|
@ -2752,19 +2752,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _M_ARM64
|
|
||||||
if (in_java &&
|
|
||||||
(exception_code == EXCEPTION_ILLEGAL_INSTRUCTION ||
|
|
||||||
exception_code == EXCEPTION_ILLEGAL_INSTRUCTION_2)) {
|
|
||||||
if (nativeInstruction_at(pc)->is_sigill_not_entrant()) {
|
|
||||||
if (TraceTraps) {
|
|
||||||
tty->print_cr("trap: not_entrant");
|
|
||||||
}
|
|
||||||
return Handle_Exception(exceptionInfo, SharedRuntime::get_handle_wrong_method_stub());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (in_java) {
|
if (in_java) {
|
||||||
switch (exception_code) {
|
switch (exception_code) {
|
||||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||||
|
@ -229,16 +229,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
|
|||||||
|
|
||||||
CodeBlob *cb = nullptr;
|
CodeBlob *cb = nullptr;
|
||||||
int stop_type = -1;
|
int stop_type = -1;
|
||||||
// Handle signal from NativeJump::patch_verified_entry().
|
if ((sig == (USE_POLL_BIT_ONLY ? SIGTRAP : SIGSEGV)) &&
|
||||||
if (sig == SIGILL && nativeInstruction_at(pc)->is_sigill_not_entrant()) {
|
|
||||||
if (TraceTraps) {
|
|
||||||
tty->print_cr("trap: not_entrant");
|
|
||||||
}
|
|
||||||
stub = SharedRuntime::get_handle_wrong_method_stub();
|
|
||||||
goto run_stub;
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ((sig == (USE_POLL_BIT_ONLY ? SIGTRAP : SIGSEGV)) &&
|
|
||||||
((NativeInstruction*)pc)->is_safepoint_poll() &&
|
((NativeInstruction*)pc)->is_safepoint_poll() &&
|
||||||
CodeCache::contains((void*) pc) &&
|
CodeCache::contains((void*) pc) &&
|
||||||
((cb = CodeCache::find_blob(pc)) != nullptr) &&
|
((cb = CodeCache::find_blob(pc)) != nullptr) &&
|
||||||
|
@ -271,14 +271,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
|
|||||||
// Java thread running in Java code => find exception handler if any
|
// Java thread running in Java code => find exception handler if any
|
||||||
// a fault inside compiled code, the interpreter, or a stub
|
// a fault inside compiled code, the interpreter, or a stub
|
||||||
|
|
||||||
// Handle signal from NativeJump::patch_verified_entry().
|
if ((sig == SIGSEGV || sig == SIGBUS) && SafepointMechanism::is_poll_address((address)info->si_addr)) {
|
||||||
if ((sig == SIGILL)
|
|
||||||
&& nativeInstruction_at(pc)->is_sigill_not_entrant()) {
|
|
||||||
if (TraceTraps) {
|
|
||||||
tty->print_cr("trap: not_entrant");
|
|
||||||
}
|
|
||||||
stub = SharedRuntime::get_handle_wrong_method_stub();
|
|
||||||
} else if ((sig == SIGSEGV || sig == SIGBUS) && SafepointMechanism::is_poll_address((address)info->si_addr)) {
|
|
||||||
stub = SharedRuntime::get_poll_stub(pc);
|
stub = SharedRuntime::get_poll_stub(pc);
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
// 32-bit Darwin reports a SIGBUS for nearly all memory access exceptions.
|
// 32-bit Darwin reports a SIGBUS for nearly all memory access exceptions.
|
||||||
|
@ -232,14 +232,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
|
|||||||
// Java thread running in Java code => find exception handler if any
|
// Java thread running in Java code => find exception handler if any
|
||||||
// a fault inside compiled code, the interpreter, or a stub
|
// a fault inside compiled code, the interpreter, or a stub
|
||||||
|
|
||||||
// Handle signal from NativeJump::patch_verified_entry().
|
if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) {
|
||||||
if ((sig == SIGILL || sig == SIGTRAP)
|
|
||||||
&& nativeInstruction_at(pc)->is_sigill_not_entrant()) {
|
|
||||||
if (TraceTraps) {
|
|
||||||
tty->print_cr("trap: not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL");
|
|
||||||
}
|
|
||||||
stub = SharedRuntime::get_handle_wrong_method_stub();
|
|
||||||
} else if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) {
|
|
||||||
stub = SharedRuntime::get_poll_stub(pc);
|
stub = SharedRuntime::get_poll_stub(pc);
|
||||||
} else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) {
|
} else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) {
|
||||||
// BugId 4454115: A read from a MappedByteBuffer can fault
|
// BugId 4454115: A read from a MappedByteBuffer can fault
|
||||||
|
@ -359,11 +359,6 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
|
|||||||
stub = SharedRuntime::continuation_for_implicit_exception(
|
stub = SharedRuntime::continuation_for_implicit_exception(
|
||||||
thread, pc, SharedRuntime::IMPLICIT_NULL);
|
thread, pc, SharedRuntime::IMPLICIT_NULL);
|
||||||
}
|
}
|
||||||
} else if (sig == SIGILL &&
|
|
||||||
*(int*)pc ==
|
|
||||||
NativeInstruction::not_entrant_illegal_instruction) {
|
|
||||||
// Not entrant
|
|
||||||
stub = SharedRuntime::get_handle_wrong_method_stub();
|
|
||||||
}
|
}
|
||||||
} else if ((thread->thread_state() == _thread_in_vm ||
|
} else if ((thread->thread_state() == _thread_in_vm ||
|
||||||
thread->thread_state() == _thread_in_native) &&
|
thread->thread_state() == _thread_in_native) &&
|
||||||
|
@ -258,15 +258,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
|
|||||||
|
|
||||||
CodeBlob *cb = nullptr;
|
CodeBlob *cb = nullptr;
|
||||||
int stop_type = -1;
|
int stop_type = -1;
|
||||||
// Handle signal from NativeJump::patch_verified_entry().
|
if ((sig == (USE_POLL_BIT_ONLY ? SIGTRAP : SIGSEGV)) &&
|
||||||
if (sig == SIGILL && nativeInstruction_at(pc)->is_sigill_not_entrant()) {
|
|
||||||
if (TraceTraps) {
|
|
||||||
tty->print_cr("trap: not_entrant");
|
|
||||||
}
|
|
||||||
stub = SharedRuntime::get_handle_wrong_method_stub();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if ((sig == (USE_POLL_BIT_ONLY ? SIGTRAP : SIGSEGV)) &&
|
|
||||||
// A linux-ppc64 kernel before 2.6.6 doesn't set si_addr on some segfaults
|
// A linux-ppc64 kernel before 2.6.6 doesn't set si_addr on some segfaults
|
||||||
// in 64bit mode (cf. http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.6),
|
// in 64bit mode (cf. http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.6),
|
||||||
// especially when we try to read from the safepoint polling page. So the check
|
// especially when we try to read from the safepoint polling page. So the check
|
||||||
|
@ -223,14 +223,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
|
|||||||
// Java thread running in Java code => find exception handler if any
|
// Java thread running in Java code => find exception handler if any
|
||||||
// a fault inside compiled code, the interpreter, or a stub
|
// a fault inside compiled code, the interpreter, or a stub
|
||||||
|
|
||||||
// Handle signal from NativeJump::patch_verified_entry().
|
if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) {
|
||||||
if ((sig == SIGILL || sig == SIGTRAP)
|
|
||||||
&& nativeInstruction_at(pc)->is_sigill_not_entrant()) {
|
|
||||||
if (TraceTraps) {
|
|
||||||
tty->print_cr("trap: not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL");
|
|
||||||
}
|
|
||||||
stub = SharedRuntime::get_handle_wrong_method_stub();
|
|
||||||
} else if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) {
|
|
||||||
stub = SharedRuntime::get_poll_stub(pc);
|
stub = SharedRuntime::get_poll_stub(pc);
|
||||||
} else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) {
|
} else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) {
|
||||||
// BugId 4454115: A read from a MappedByteBuffer can fault
|
// BugId 4454115: A read from a MappedByteBuffer can fault
|
||||||
|
@ -257,15 +257,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info,
|
|||||||
// Java thread running in Java code => find exception handler if any
|
// Java thread running in Java code => find exception handler if any
|
||||||
// a fault inside compiled code, the interpreter, or a stub
|
// a fault inside compiled code, the interpreter, or a stub
|
||||||
|
|
||||||
// Handle signal from NativeJump::patch_verified_entry().
|
if (sig == SIGSEGV &&
|
||||||
if (sig == SIGILL && nativeInstruction_at(pc)->is_sigill_not_entrant()) {
|
|
||||||
if (TraceTraps) {
|
|
||||||
tty->print_cr("trap: not_entrant (SIGILL)");
|
|
||||||
}
|
|
||||||
stub = SharedRuntime::get_handle_wrong_method_stub();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (sig == SIGSEGV &&
|
|
||||||
SafepointMechanism::is_poll_address((address)info->si_addr)) {
|
SafepointMechanism::is_poll_address((address)info->si_addr)) {
|
||||||
if (TraceTraps) {
|
if (TraceTraps) {
|
||||||
tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", p2i(pc));
|
tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", p2i(pc));
|
||||||
|
@ -83,7 +83,10 @@ void BarrierSetNMethod::arm_with(nmethod* nm, int value) {
|
|||||||
if (is_not_entrant(nm)) {
|
if (is_not_entrant(nm)) {
|
||||||
value |= not_entrant;
|
value |= not_entrant;
|
||||||
}
|
}
|
||||||
set_guard_value(nm, value);
|
if (guard_value(nm) != value) {
|
||||||
|
// Patch the code only if needed.
|
||||||
|
set_guard_value(nm, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
bool BarrierSetNMethod::is_armed(nmethod* nm) {
|
||||||
@ -243,7 +246,10 @@ void BarrierSetNMethod::make_not_entrant(nmethod* nm) {
|
|||||||
// Enter critical section. Does not block for safepoint.
|
// Enter critical section. Does not block for safepoint.
|
||||||
ConditionalMutexLocker ml(NMethodEntryBarrier_lock, !NMethodEntryBarrier_lock->owned_by_self(), Mutex::_no_safepoint_check_flag);
|
ConditionalMutexLocker ml(NMethodEntryBarrier_lock, !NMethodEntryBarrier_lock->owned_by_self(), Mutex::_no_safepoint_check_flag);
|
||||||
int value = guard_value(nm) | not_entrant;
|
int value = guard_value(nm) | not_entrant;
|
||||||
set_guard_value(nm, value);
|
if (guard_value(nm) != value) {
|
||||||
|
// Patch the code only if needed.
|
||||||
|
set_guard_value(nm, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BarrierSetNMethod::is_not_entrant(nmethod* nm) {
|
bool BarrierSetNMethod::is_not_entrant(nmethod* nm) {
|
||||||
|
@ -43,7 +43,6 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void deoptimize(nmethod* nm, address* return_addr_ptr);
|
void deoptimize(nmethod* nm, address* return_addr_ptr);
|
||||||
void arm(nmethod* nm) { arm_with(nm, armed); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual int guard_value(nmethod* nm);
|
virtual int guard_value(nmethod* nm);
|
||||||
@ -62,6 +61,7 @@ public:
|
|||||||
static int nmethod_stub_entry_barrier(address* return_address_ptr);
|
static int nmethod_stub_entry_barrier(address* return_address_ptr);
|
||||||
bool nmethod_osr_entry_barrier(nmethod* nm);
|
bool nmethod_osr_entry_barrier(nmethod* nm);
|
||||||
virtual bool is_armed(nmethod* nm);
|
virtual bool is_armed(nmethod* nm);
|
||||||
|
void arm(nmethod* nm) { arm_with(nm, armed); }
|
||||||
void disarm(nmethod* nm);
|
void disarm(nmethod* nm);
|
||||||
virtual void make_not_entrant(nmethod* nm);
|
virtual void make_not_entrant(nmethod* nm);
|
||||||
virtual bool is_not_entrant(nmethod* nm);
|
virtual bool is_not_entrant(nmethod* nm);
|
||||||
|
@ -113,7 +113,10 @@ void ZBarrierSetNMethod::arm_with(nmethod* nm, int value) {
|
|||||||
if (is_not_entrant(nm)) {
|
if (is_not_entrant(nm)) {
|
||||||
value |= not_entrant;
|
value |= not_entrant;
|
||||||
}
|
}
|
||||||
set_guard_value(nm, value);
|
if (guard_value(nm) != value) {
|
||||||
|
// Patch the code only if needed.
|
||||||
|
set_guard_value(nm, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZBarrierSetNMethod::is_armed(nmethod* nm) {
|
bool ZBarrierSetNMethod::is_armed(nmethod* nm) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user