8366905: Store AdapterBlob pointer in AdapterHandlerEntry

Reviewed-by: kvn, adinn
This commit is contained in:
Ashutosh Mehra 2025-09-24 13:37:58 +00:00
parent ed31023fc5
commit 156eb767f1
12 changed files with 184 additions and 231 deletions

View File

@ -683,12 +683,12 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
int comp_args_on_stack,
const BasicType *sig_bt,
const VMRegPair *regs,
AdapterHandlerEntry* handler) {
address i2c_entry = __ pc();
address entry_address[AdapterBlob::ENTRY_COUNT]) {
entry_address[AdapterBlob::I2C] = __ pc();
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
address c2i_unverified_entry = __ pc();
entry_address[AdapterBlob::C2I_Unverified] = __ pc();
Label skip_fixup;
Register data = rscratch2;
@ -718,10 +718,10 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ block_comment("} c2i_unverified_entry");
}
address c2i_entry = __ pc();
entry_address[AdapterBlob::C2I] = __ pc();
// Class initialization barrier for static methods
address c2i_no_clinit_check_entry = nullptr;
entry_address[AdapterBlob::C2I_No_Clinit_Check] = nullptr;
if (VM_Version::supports_fast_class_init_checks()) {
Label L_skip_barrier;
@ -736,15 +736,13 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
__ bind(L_skip_barrier);
c2i_no_clinit_check_entry = __ pc();
entry_address[AdapterBlob::C2I_No_Clinit_Check] = __ pc();
}
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->c2i_entry_barrier(masm);
gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
handler->set_entry_points(i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
return;
}

View File

@ -617,11 +617,11 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
int comp_args_on_stack,
const BasicType *sig_bt,
const VMRegPair *regs,
AdapterHandlerEntry* handler) {
address i2c_entry = __ pc();
address entry_address[AdapterBlob::ENTRY_COUNT]) {
entry_address[AdapterBlob::I2C] = __ pc();
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
address c2i_unverified_entry = __ pc();
entry_address[AdapterBlob::C2I_Unverified] = __ pc();
Label skip_fixup;
const Register receiver = R0;
const Register holder_klass = Rtemp; // XXX should be OK for C2 but not 100% sure
@ -634,10 +634,9 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ b(skip_fixup, eq);
__ jump(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type, noreg, ne);
address c2i_entry = __ pc();
entry_address[AdapterBlob::C2I] = __ pc();
entry_address[AdapterBlob::C2I_No_Clinit_Check] = nullptr;
gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
handler->set_entry_points(i2c_entry, c2i_entry, c2i_unverified_entry, nullptr);
return;
}

View File

@ -1199,16 +1199,11 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
int comp_args_on_stack,
const BasicType *sig_bt,
const VMRegPair *regs,
AdapterHandlerEntry* handler) {
address i2c_entry;
address c2i_unverified_entry;
address c2i_entry;
address entry_address[AdapterBlob::ENTRY_COUNT]) {
// entry: i2c
__ align(CodeEntryAlignment);
i2c_entry = __ pc();
entry_address[AdapterBlob::I2C] = __ pc();
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
@ -1216,7 +1211,7 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ align(CodeEntryAlignment);
BLOCK_COMMENT("c2i unverified entry");
c2i_unverified_entry = __ pc();
entry_address[AdapterBlob::C2I_Unverified] = __ pc();
// inline_cache contains a CompiledICData
const Register ic = R19_inline_cache_reg;
@ -1244,10 +1239,10 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
// entry: c2i
c2i_entry = __ pc();
entry_address[AdapterBlob::C2I] = __ pc();
// Class initialization barrier for static methods
address c2i_no_clinit_check_entry = nullptr;
entry_address[AdapterBlob::C2I_No_Clinit_Check] = nullptr;
if (VM_Version::supports_fast_class_init_checks()) {
Label L_skip_barrier;
@ -1266,15 +1261,13 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ bctr();
__ bind(L_skip_barrier);
c2i_no_clinit_check_entry = __ pc();
entry_address[AdapterBlob::C2I_No_Clinit_Check] = __ pc();
}
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->c2i_entry_barrier(masm, /* tmp register*/ ic_klass, /* tmp register*/ receiver_klass, /* tmp register*/ code);
gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, call_interpreter, ientry);
handler->set_entry_points(i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
return;
}

View File

@ -602,11 +602,11 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
int comp_args_on_stack,
const BasicType *sig_bt,
const VMRegPair *regs,
AdapterHandlerEntry* handler) {
address i2c_entry = __ pc();
address entry_address[AdapterBlob::ENTRY_COUNT]) {
entry_address[AdapterBlob::I2C] = __ pc();
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
address c2i_unverified_entry = __ pc();
entry_address[AdapterBlob::C2I_Unverified] = __ pc();
Label skip_fixup;
const Register receiver = j_rarg0;
@ -633,10 +633,10 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ block_comment("} c2i_unverified_entry");
}
address c2i_entry = __ pc();
entry_address[AdapterBlob::C2I] = __ pc();
// Class initialization barrier for static methods
address c2i_no_clinit_check_entry = nullptr;
entry_address[AdapterBlob::C2I_No_Clinit_Check] = nullptr;
if (VM_Version::supports_fast_class_init_checks()) {
Label L_skip_barrier;
@ -651,15 +651,13 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
__ bind(L_skip_barrier);
c2i_no_clinit_check_entry = __ pc();
entry_address[AdapterBlob::C2I_No_Clinit_Check] = __ pc();
}
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->c2i_entry_barrier(masm);
gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
handler->set_entry_points(i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
return;
}

View File

@ -2347,13 +2347,11 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
int comp_args_on_stack,
const BasicType *sig_bt,
const VMRegPair *regs,
AdapterHandlerEntry* handler) {
address entry_address[AdapterBlob::ENTRY_COUNT]) {
__ align(CodeEntryAlignment);
address i2c_entry = __ pc();
entry_address[AdapterBlob::I2C] = __ pc();
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
address c2i_unverified_entry;
Label skip_fixup;
{
Label ic_miss;
@ -2363,7 +2361,7 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
// Unverified Entry Point UEP
__ align(CodeEntryAlignment);
c2i_unverified_entry = __ pc();
entry_address[AdapterBlob::C2I_Unverified] = __ pc();
__ ic_check(2);
__ z_lg(Z_method, Address(Z_inline_cache, CompiledICData::speculated_method_offset()));
@ -2376,10 +2374,10 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
// Fallthru to VEP. Duplicate LTG, but saved taken branch.
}
address c2i_entry = __ pc();
entry_address[AdapterBlob::C2I] = __ pc();
// Class initialization barrier for static methods
address c2i_no_clinit_check_entry = nullptr;
entry_address[AdapterBlob::C2I_No_Clinit_Check] = nullptr;
if (VM_Version::supports_fast_class_init_checks()) {
Label L_skip_barrier;
@ -2396,12 +2394,10 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ z_br(klass);
__ bind(L_skip_barrier);
c2i_no_clinit_check_entry = __ pc();
entry_address[AdapterBlob::C2I_No_Clinit_Check] = __ pc();
}
gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
handler->set_entry_points(i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
return;
}

View File

@ -1007,8 +1007,8 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
int comp_args_on_stack,
const BasicType *sig_bt,
const VMRegPair *regs,
AdapterHandlerEntry* handler) {
address i2c_entry = __ pc();
address entry_address[AdapterBlob::ENTRY_COUNT]) {
entry_address[AdapterBlob::I2C] = __ pc();
gen_i2c_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs);
@ -1021,7 +1021,7 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
// On exit from the interpreter, the interpreter will restore our SP (lest the
// compiled code, which relies solely on SP and not RBP, get sick).
address c2i_unverified_entry = __ pc();
entry_address[AdapterBlob::C2I_Unverified] = __ pc();
Label skip_fixup;
Register data = rax;
@ -1039,10 +1039,10 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
}
address c2i_entry = __ pc();
entry_address[AdapterBlob::C2I] = __ pc();
// Class initialization barrier for static methods
address c2i_no_clinit_check_entry = nullptr;
entry_address[AdapterBlob::C2I_No_Clinit_Check] = nullptr;
if (VM_Version::supports_fast_class_init_checks()) {
Label L_skip_barrier;
Register method = rbx;
@ -1061,15 +1061,13 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
__ jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub())); // slow path
__ bind(L_skip_barrier);
c2i_no_clinit_check_entry = __ pc();
entry_address[AdapterBlob::C2I_No_Clinit_Check] = __ pc();
}
BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
bs->c2i_entry_barrier(masm);
gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
handler->set_entry_points(i2c_entry, c2i_entry, c2i_unverified_entry, c2i_no_clinit_check_entry);
return;
}

View File

@ -38,12 +38,6 @@
#include "opto/runtime.hpp"
#endif
static address zero_null_code_stub() {
address start = ShouldNotCallThisStub();
return start;
}
int SharedRuntime::java_calling_convention(const BasicType *sig_bt,
VMRegPair *regs,
int total_args_passed) {
@ -55,12 +49,9 @@ void SharedRuntime::generate_i2c2i_adapters(MacroAssembler *masm,
int comp_args_on_stack,
const BasicType *sig_bt,
const VMRegPair *regs,
AdapterHandlerEntry* handler) {
// foil any attempt to call the i2c, c2i or unverified c2i entries
handler->set_entry_points(CAST_FROM_FN_PTR(address,zero_null_code_stub),
CAST_FROM_FN_PTR(address,zero_null_code_stub),
CAST_FROM_FN_PTR(address,zero_null_code_stub),
nullptr);
address entry_address[AdapterBlob::ENTRY_COUNT]) {
ShouldNotCallThis();
return;
}
nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,

View File

@ -448,16 +448,19 @@ void BufferBlob::free(BufferBlob *blob) {
AdapterBlob::AdapterBlob(int size, CodeBuffer* cb, int entry_offset[AdapterBlob::ENTRY_COUNT]) :
BufferBlob("I2C/C2I adapters", CodeBlobKind::Adapter, cb, size, sizeof(AdapterBlob)) {
assert(entry_offset[0] == 0, "sanity check");
assert(entry_offset[I2C] == 0, "sanity check");
#ifdef ASSERT
for (int i = 1; i < AdapterBlob::ENTRY_COUNT; i++) {
// The entry is within the adapter blob or unset.
assert((entry_offset[i] > 0 && entry_offset[i] < cb->insts()->size()) ||
(entry_offset[i] == -1),
"invalid entry offset[%d] = 0x%x", i, entry_offset[i]);
int offset = entry_offset[i];
assert((offset > 0 && offset < cb->insts()->size()) ||
(i >= C2I_No_Clinit_Check && offset == -1),
"invalid entry offset[%d] = 0x%x", i, offset);
}
_c2i_offset = entry_offset[1];
_c2i_unverified_offset = entry_offset[2];
_c2i_no_clinit_check_offset = entry_offset[3];
#endif // ASSERT
_c2i_offset = entry_offset[C2I];
_c2i_unverified_offset = entry_offset[C2I_Unverified];
_c2i_no_clinit_check_offset = entry_offset[C2I_No_Clinit_Check];
CodeCache::commit(this);
}
@ -478,13 +481,6 @@ AdapterBlob* AdapterBlob::create(CodeBuffer* cb, int entry_offset[AdapterBlob::E
return blob;
}
void AdapterBlob::get_offsets(int entry_offset[ENTRY_COUNT]) {
entry_offset[0] = 0;
entry_offset[1] = _c2i_offset;
entry_offset[2] = _c2i_unverified_offset;
entry_offset[3] = _c2i_no_clinit_check_offset;
}
//----------------------------------------------------------------------------------------------------
// Implementation of VtableBlob

View File

@ -405,7 +405,13 @@ class BufferBlob: public RuntimeBlob {
class AdapterBlob: public BufferBlob {
public:
static const int ENTRY_COUNT = 4;
enum Entry {
I2C,
C2I,
C2I_Unverified,
C2I_No_Clinit_Check,
ENTRY_COUNT
};
private:
AdapterBlob(int size, CodeBuffer* cb, int entry_offset[ENTRY_COUNT]);
// _i2c_offset is always 0 so no need to store it
@ -415,7 +421,10 @@ private:
public:
// Creation
static AdapterBlob* create(CodeBuffer* cb, int entry_offset[ENTRY_COUNT]);
void get_offsets(int entry_offset[ENTRY_COUNT]);
address i2c_entry() { return code_begin(); }
address c2i_entry() { return i2c_entry() + _c2i_offset; }
address c2i_unverified_entry() { return i2c_entry() + _c2i_unverified_offset; }
address c2i_no_clinit_check_entry() { return _c2i_no_clinit_check_offset == -1 ? nullptr : i2c_entry() + _c2i_no_clinit_check_offset; }
};
//---------------------------------------------------------------------------------------------------

View File

@ -1287,7 +1287,9 @@ void Method::link_method(const methodHandle& h_method, TRAPS) {
h_method->_from_compiled_entry = SharedRuntime::get_handle_wrong_method_abstract_stub();
} else if (_adapter == nullptr) {
(void) make_adapters(h_method, CHECK);
#ifndef ZERO
assert(adapter()->is_linked(), "Adapter must have been linked");
#endif
h_method->_from_compiled_entry = adapter()->get_c2i_entry();
}

View File

@ -2526,21 +2526,21 @@ BufferBlob* AdapterHandlerLibrary::buffer_blob() {
return _buffer;
}
static void post_adapter_creation(const AdapterBlob* new_adapter,
const AdapterHandlerEntry* entry) {
static void post_adapter_creation(const AdapterHandlerEntry* entry) {
if (Forte::is_enabled() || JvmtiExport::should_post_dynamic_code_generated()) {
AdapterBlob* adapter_blob = entry->adapter_blob();
char blob_id[256];
jio_snprintf(blob_id,
sizeof(blob_id),
"%s(%s)",
new_adapter->name(),
adapter_blob->name(),
entry->fingerprint()->as_string());
if (Forte::is_enabled()) {
Forte::register_stub(blob_id, new_adapter->content_begin(), new_adapter->content_end());
Forte::register_stub(blob_id, adapter_blob->content_begin(), adapter_blob->content_end());
}
if (JvmtiExport::should_post_dynamic_code_generated()) {
JvmtiExport::post_dynamic_code_generated(blob_id, new_adapter->content_begin(), new_adapter->content_end());
JvmtiExport::post_dynamic_code_generated(blob_id, adapter_blob->content_begin(), adapter_blob->content_end());
}
}
}
@ -2562,27 +2562,22 @@ void AdapterHandlerLibrary::initialize() {
#endif // INCLUDE_CDS
ResourceMark rm;
AdapterBlob* no_arg_blob = nullptr;
AdapterBlob* int_arg_blob = nullptr;
AdapterBlob* obj_arg_blob = nullptr;
AdapterBlob* obj_int_arg_blob = nullptr;
AdapterBlob* obj_obj_arg_blob = nullptr;
{
MutexLocker mu(AdapterHandlerLibrary_lock);
_no_arg_handler = create_adapter(no_arg_blob, 0, nullptr);
_no_arg_handler = create_adapter(0, nullptr);
BasicType obj_args[] = { T_OBJECT };
_obj_arg_handler = create_adapter(obj_arg_blob, 1, obj_args);
_obj_arg_handler = create_adapter(1, obj_args);
BasicType int_args[] = { T_INT };
_int_arg_handler = create_adapter(int_arg_blob, 1, int_args);
_int_arg_handler = create_adapter(1, int_args);
BasicType obj_int_args[] = { T_OBJECT, T_INT };
_obj_int_arg_handler = create_adapter(obj_int_arg_blob, 2, obj_int_args);
_obj_int_arg_handler = create_adapter(2, obj_int_args);
BasicType obj_obj_args[] = { T_OBJECT, T_OBJECT };
_obj_obj_arg_handler = create_adapter(obj_obj_arg_blob, 2, obj_obj_args);
_obj_obj_arg_handler = create_adapter(2, obj_obj_args);
// we should always get an entry back but we don't have any
// associated blob on Zero
@ -2596,11 +2591,11 @@ void AdapterHandlerLibrary::initialize() {
// Outside of the lock
#ifndef ZERO
// no blobs to register when we are on Zero
post_adapter_creation(no_arg_blob, _no_arg_handler);
post_adapter_creation(obj_arg_blob, _obj_arg_handler);
post_adapter_creation(int_arg_blob, _int_arg_handler);
post_adapter_creation(obj_int_arg_blob, _obj_int_arg_handler);
post_adapter_creation(obj_obj_arg_blob, _obj_obj_arg_handler);
post_adapter_creation(_no_arg_handler);
post_adapter_creation(_obj_arg_handler);
post_adapter_creation(_int_arg_handler);
post_adapter_creation(_obj_int_arg_handler);
post_adapter_creation(_obj_obj_arg_handler);
#endif // ZERO
}
@ -2695,9 +2690,8 @@ const char* AdapterHandlerEntry::_entry_names[] = {
void AdapterHandlerLibrary::verify_adapter_sharing(int total_args_passed, BasicType* sig_bt, AdapterHandlerEntry* cached_entry) {
// we can only check for the same code if there is any
#ifndef ZERO
AdapterBlob* comparison_blob = nullptr;
AdapterHandlerEntry* comparison_entry = create_adapter(comparison_blob, total_args_passed, sig_bt, true);
assert(comparison_blob == nullptr, "no blob should be created when creating an adapter for comparison");
AdapterHandlerEntry* comparison_entry = create_adapter(total_args_passed, sig_bt, true);
assert(comparison_entry->adapter_blob() == nullptr, "no blob should be created when creating an adapter for comparison");
assert(comparison_entry->compare_code(cached_entry), "code must match");
// Release the one just created
AdapterHandlerEntry::deallocate(comparison_entry);
@ -2719,7 +2713,7 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& meth
}
ResourceMark rm;
AdapterBlob* adapter_blob = nullptr;
bool new_entry = false;
// Fill in the signature array, for the calling-convention call.
int total_args_passed = method->size_of_parameters(); // All args on stack
@ -2735,54 +2729,48 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& meth
entry = lookup(total_args_passed, sig_bt);
if (entry != nullptr) {
#ifndef ZERO
assert(entry->is_linked(), "AdapterHandlerEntry must have been linked");
#endif
#ifdef ASSERT
if (!entry->in_aot_cache() && VerifyAdapterSharing) {
verify_adapter_sharing(total_args_passed, sig_bt, entry);
}
#endif
} else {
entry = create_adapter(adapter_blob, total_args_passed, sig_bt);
entry = create_adapter(total_args_passed, sig_bt);
if (entry != nullptr) {
new_entry = true;
}
}
}
// Outside of the lock
if (adapter_blob != nullptr) {
post_adapter_creation(adapter_blob, entry);
if (new_entry) {
post_adapter_creation(entry);
}
return entry;
}
AdapterBlob* AdapterHandlerLibrary::lookup_aot_cache(AdapterHandlerEntry* handler) {
void AdapterHandlerLibrary::lookup_aot_cache(AdapterHandlerEntry* handler) {
ResourceMark rm;
const char* name = AdapterHandlerLibrary::name(handler->fingerprint());
const uint32_t id = AdapterHandlerLibrary::id(handler->fingerprint());
int offsets[AdapterBlob::ENTRY_COUNT];
AdapterBlob* adapter_blob = nullptr;
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::Adapter, id, name);
if (blob != nullptr) {
adapter_blob = blob->as_adapter_blob();
adapter_blob->get_offsets(offsets);
address i2c_entry = adapter_blob->content_begin();
assert(offsets[0] == 0, "sanity check");
handler->set_entry_points(
i2c_entry,
(offsets[1] != -1) ? (i2c_entry + offsets[1]) : nullptr,
(offsets[2] != -1) ? (i2c_entry + offsets[2]) : nullptr,
(offsets[3] != -1) ? (i2c_entry + offsets[3]) : nullptr
);
handler->set_adapter_blob(blob->as_adapter_blob());
}
return adapter_blob;
}
#ifndef PRODUCT
void AdapterHandlerLibrary::print_adapter_handler_info(outputStream* st, AdapterHandlerEntry* handler, AdapterBlob* adapter_blob) {
void AdapterHandlerLibrary::print_adapter_handler_info(outputStream* st, AdapterHandlerEntry* handler) {
ttyLocker ttyl;
ResourceMark rm;
int insts_size;
// on Zero the blob may be null
handler->print_adapter_on(tty);
AdapterBlob* adapter_blob = handler->adapter_blob();
if (adapter_blob == nullptr) {
return;
}
@ -2792,7 +2780,7 @@ void AdapterHandlerLibrary::print_adapter_handler_info(outputStream* st, Adapter
handler->fingerprint()->as_string(), insts_size);
st->print_cr("c2i argument handler starts at " INTPTR_FORMAT, p2i(handler->get_c2i_entry()));
if (Verbose || PrintStubCode) {
address first_pc = handler->base_address();
address first_pc = adapter_blob->content_begin();
if (first_pc != nullptr) {
Disassembler::decode(first_pc, first_pc + insts_size, st, &adapter_blob->asm_remarks());
st->cr();
@ -2801,8 +2789,19 @@ void AdapterHandlerLibrary::print_adapter_handler_info(outputStream* st, Adapter
}
#endif // PRODUCT
bool AdapterHandlerLibrary::generate_adapter_code(AdapterBlob*& adapter_blob,
AdapterHandlerEntry* handler,
void AdapterHandlerLibrary::address_to_offset(address entry_address[AdapterBlob::ENTRY_COUNT],
int entry_offset[AdapterBlob::ENTRY_COUNT]) {
entry_offset[AdapterBlob::I2C] = 0;
entry_offset[AdapterBlob::C2I] = entry_address[AdapterBlob::C2I] - entry_address[AdapterBlob::I2C];
entry_offset[AdapterBlob::C2I_Unverified] = entry_address[AdapterBlob::C2I_Unverified] - entry_address[AdapterBlob::I2C];
if (entry_address[AdapterBlob::C2I_No_Clinit_Check] == nullptr) {
entry_offset[AdapterBlob::C2I_No_Clinit_Check] = -1;
} else {
entry_offset[AdapterBlob::C2I_No_Clinit_Check] = entry_address[AdapterBlob::C2I_No_Clinit_Check] - entry_address[AdapterBlob::I2C];
}
}
bool AdapterHandlerLibrary::generate_adapter_code(AdapterHandlerEntry* handler,
int total_args_passed,
BasicType* sig_bt,
bool is_transient) {
@ -2810,6 +2809,7 @@ bool AdapterHandlerLibrary::generate_adapter_code(AdapterBlob*& adapter_blob,
ClassLoader::perf_method_adapters_count()->inc();
}
#ifndef ZERO
BufferBlob* buf = buffer_blob(); // the temporary code buffer in CodeCache
CodeBuffer buffer(buf);
short buffer_locs[20];
@ -2821,17 +2821,17 @@ bool AdapterHandlerLibrary::generate_adapter_code(AdapterBlob*& adapter_blob,
// Get a description of the compiled java calling convention and the largest used (VMReg) stack slot usage
int comp_args_on_stack = SharedRuntime::java_calling_convention(sig_bt, regs, total_args_passed);
address entry_address[AdapterBlob::ENTRY_COUNT];
SharedRuntime::generate_i2c2i_adapters(&masm,
total_args_passed,
comp_args_on_stack,
sig_bt,
regs,
handler);
#ifdef ZERO
entry_address);
// On zero there is no code to save and no need to create a blob and
// or relocate the handler.
adapter_blob = nullptr;
#else
int entry_offset[AdapterBlob::ENTRY_COUNT];
address_to_offset(entry_address, entry_offset);
#ifdef ASSERT
if (VerifyAdapterSharing) {
handler->save_code(buf->code_begin(), buffer.insts_size());
@ -2840,25 +2840,14 @@ bool AdapterHandlerLibrary::generate_adapter_code(AdapterBlob*& adapter_blob,
}
}
#endif
int entry_offset[AdapterBlob::ENTRY_COUNT];
assert(AdapterBlob::ENTRY_COUNT == 4, "sanity");
address i2c_entry = handler->get_i2c_entry();
entry_offset[0] = 0; // i2c_entry offset
entry_offset[1] = (handler->get_c2i_entry() != nullptr) ?
(handler->get_c2i_entry() - i2c_entry) : -1;
entry_offset[2] = (handler->get_c2i_unverified_entry() != nullptr) ?
(handler->get_c2i_unverified_entry() - i2c_entry) : -1;
entry_offset[3] = (handler->get_c2i_no_clinit_check_entry() != nullptr) ?
(handler->get_c2i_no_clinit_check_entry() - i2c_entry) : -1;
adapter_blob = AdapterBlob::create(&buffer, entry_offset);
AdapterBlob* adapter_blob = AdapterBlob::create(&buffer, entry_offset);
if (adapter_blob == nullptr) {
// CodeCache is full, disable compilation
// Ought to log this but compile log is only per compile thread
// and we're some non descript Java thread.
return false;
}
handler->set_adapter_blob(adapter_blob);
if (!is_transient && AOTCodeCache::is_dumping_adapter()) {
// try to save generated code
const char* name = AdapterHandlerLibrary::name(handler->fingerprint());
@ -2866,26 +2855,24 @@ bool AdapterHandlerLibrary::generate_adapter_code(AdapterBlob*& adapter_blob,
bool success = AOTCodeCache::store_code_blob(*adapter_blob, AOTCodeEntry::Adapter, id, name);
assert(success || !AOTCodeCache::is_dumping_adapter(), "caching of adapter must be disabled");
}
handler->relocate(adapter_blob->content_begin());
#endif // ZERO
#ifndef PRODUCT
// debugging support
if (PrintAdapterHandlers || PrintStubCode) {
print_adapter_handler_info(tty, handler, adapter_blob);
print_adapter_handler_info(tty, handler);
}
#endif
return true;
}
AdapterHandlerEntry* AdapterHandlerLibrary::create_adapter(AdapterBlob*& adapter_blob,
int total_args_passed,
AdapterHandlerEntry* AdapterHandlerLibrary::create_adapter(int total_args_passed,
BasicType* sig_bt,
bool is_transient) {
AdapterFingerPrint* fp = AdapterFingerPrint::allocate(total_args_passed, sig_bt);
AdapterHandlerEntry* handler = AdapterHandlerLibrary::new_entry(fp);
if (!generate_adapter_code(adapter_blob, handler, total_args_passed, sig_bt, is_transient)) {
if (!generate_adapter_code(handler, total_args_passed, sig_bt, is_transient)) {
AdapterHandlerEntry::deallocate(handler);
return nullptr;
}
@ -2902,7 +2889,8 @@ void AdapterHandlerEntry::remove_unshareable_info() {
_saved_code = nullptr;
_saved_code_length = 0;
#endif // ASSERT
set_entry_points(nullptr, nullptr, nullptr, nullptr, false);
_adapter_blob = nullptr;
_linked = false;
}
class CopyAdapterTableToArchive : StackObj {
@ -2952,26 +2940,24 @@ void AdapterHandlerLibrary::serialize_shared_table_header(SerializeClosure* soc)
_aot_adapter_handler_table.serialize_header(soc);
}
AdapterBlob* AdapterHandlerLibrary::link_aot_adapter_handler(AdapterHandlerEntry* handler) {
void AdapterHandlerLibrary::link_aot_adapter_handler(AdapterHandlerEntry* handler) {
#ifdef ASSERT
if (TestAOTAdapterLinkFailure) {
return nullptr;
return;
}
#endif
AdapterBlob* blob = lookup_aot_cache(handler);
lookup_aot_cache(handler);
#ifndef PRODUCT
// debugging support
if ((blob != nullptr) && (PrintAdapterHandlers || PrintStubCode)) {
print_adapter_handler_info(tty, handler, blob);
if (PrintAdapterHandlers || PrintStubCode) {
print_adapter_handler_info(tty, handler);
}
#endif
return blob;
}
// This method is used during production run to link archived adapters (stored in AOT Cache)
// to their code in AOT Code Cache
void AdapterHandlerEntry::link() {
AdapterBlob* adapter_blob = nullptr;
ResourceMark rm;
assert(_fingerprint != nullptr, "_fingerprint must not be null");
bool generate_code = false;
@ -2979,8 +2965,9 @@ void AdapterHandlerEntry::link() {
// caching adapters is disabled, or we fail to link
// the AdapterHandlerEntry to its code in the AOTCodeCache
if (AOTCodeCache::is_using_adapter()) {
adapter_blob = AdapterHandlerLibrary::link_aot_adapter_handler(this);
if (adapter_blob == nullptr) {
AdapterHandlerLibrary::link_aot_adapter_handler(this);
// If link_aot_adapter_handler() succeeds, _adapter_blob will be non-null
if (_adapter_blob == nullptr) {
log_warning(aot)("Failed to link AdapterHandlerEntry (fp=%s) to its code in the AOT code cache", _fingerprint->as_basic_args_string());
generate_code = true;
}
@ -2990,16 +2977,15 @@ void AdapterHandlerEntry::link() {
if (generate_code) {
int nargs;
BasicType* bt = _fingerprint->as_basic_type(nargs);
if (!AdapterHandlerLibrary::generate_adapter_code(adapter_blob, this, nargs, bt, /* is_transient */ false)) {
if (!AdapterHandlerLibrary::generate_adapter_code(this, nargs, bt, /* is_transient */ false)) {
// Don't throw exceptions during VM initialization because java.lang.* classes
// might not have been initialized, causing problems when constructing the
// Java exception object.
vm_exit_during_initialization("Out of space in CodeCache for adapters");
}
}
// Outside of the lock
if (adapter_blob != nullptr) {
post_adapter_creation(adapter_blob, this);
if (_adapter_blob != nullptr) {
post_adapter_creation(this);
}
assert(_linked, "AdapterHandlerEntry must now be linked");
}
@ -3045,30 +3031,6 @@ void AdapterHandlerLibrary::lookup_simple_adapters() {
}
#endif // INCLUDE_CDS
address AdapterHandlerEntry::base_address() {
address base = _i2c_entry;
if (base == nullptr) base = _c2i_entry;
assert(base <= _c2i_entry || _c2i_entry == nullptr, "");
assert(base <= _c2i_unverified_entry || _c2i_unverified_entry == nullptr, "");
assert(base <= _c2i_no_clinit_check_entry || _c2i_no_clinit_check_entry == nullptr, "");
return base;
}
void AdapterHandlerEntry::relocate(address new_base) {
address old_base = base_address();
assert(old_base != nullptr, "");
ptrdiff_t delta = new_base - old_base;
if (_i2c_entry != nullptr)
_i2c_entry += delta;
if (_c2i_entry != nullptr)
_c2i_entry += delta;
if (_c2i_unverified_entry != nullptr)
_c2i_unverified_entry += delta;
if (_c2i_no_clinit_check_entry != nullptr)
_c2i_no_clinit_check_entry += delta;
assert(base_address() == new_base, "");
}
void AdapterHandlerEntry::metaspace_pointers_do(MetaspaceClosure* it) {
LogStreamHandle(Trace, aot) lsh;
if (lsh.is_enabled()) {
@ -3443,17 +3405,13 @@ void AdapterHandlerLibrary::print_handler_on(outputStream* st, const CodeBlob* b
void AdapterHandlerEntry::print_adapter_on(outputStream* st) const {
st->print("AHE@" INTPTR_FORMAT ": %s", p2i(this), fingerprint()->as_string());
if (get_i2c_entry() != nullptr) {
if (adapter_blob() != nullptr) {
st->print(" i2c: " INTPTR_FORMAT, p2i(get_i2c_entry()));
}
if (get_c2i_entry() != nullptr) {
st->print(" c2i: " INTPTR_FORMAT, p2i(get_c2i_entry()));
}
if (get_c2i_unverified_entry() != nullptr) {
st->print(" c2iUV: " INTPTR_FORMAT, p2i(get_c2i_unverified_entry()));
}
if (get_c2i_no_clinit_check_entry() != nullptr) {
st->print(" c2iNCI: " INTPTR_FORMAT, p2i(get_c2i_no_clinit_check_entry()));
if (get_c2i_no_clinit_check_entry() != nullptr) {
st->print(" c2iNCI: " INTPTR_FORMAT, p2i(get_c2i_no_clinit_check_entry()));
}
}
st->cr();
}

View File

@ -476,11 +476,11 @@ class SharedRuntime: AllStatic {
// handshaking path with compiled code to keep the stack walking correct.
static void generate_i2c2i_adapters(MacroAssembler *_masm,
int total_args_passed,
int max_arg,
const BasicType *sig_bt,
const VMRegPair *regs,
AdapterHandlerEntry* handler);
int total_args_passed,
int max_arg,
const BasicType *sig_bt,
const VMRegPair *regs,
address entry_address[AdapterBlob::ENTRY_COUNT]);
static void gen_i2c_adapter(MacroAssembler *_masm,
int total_args_passed,
@ -685,11 +685,8 @@ class AdapterHandlerEntry : public MetaspaceObj {
private:
AdapterFingerPrint* _fingerprint;
address _i2c_entry;
address _c2i_entry;
address _c2i_unverified_entry;
address _c2i_no_clinit_check_entry;
bool _linked;
AdapterBlob* _adapter_blob;
bool _linked;
static const char *_entry_names[];
@ -702,10 +699,7 @@ class AdapterHandlerEntry : public MetaspaceObj {
AdapterHandlerEntry(AdapterFingerPrint* fingerprint) :
_fingerprint(fingerprint),
_i2c_entry(nullptr),
_c2i_entry(nullptr),
_c2i_unverified_entry(nullptr),
_c2i_no_clinit_check_entry(nullptr),
_adapter_blob(nullptr),
_linked(false)
#ifdef ASSERT
, _saved_code(nullptr),
@ -734,27 +728,49 @@ class AdapterHandlerEntry : public MetaspaceObj {
handler->~AdapterHandlerEntry();
}
void set_entry_points(address i2c_entry, address c2i_entry, address c2i_unverified_entry, address c2i_no_clinit_check_entry, bool linked = true) {
_i2c_entry = i2c_entry;
_c2i_entry = c2i_entry;
_c2i_unverified_entry = c2i_unverified_entry;
_c2i_no_clinit_check_entry = c2i_no_clinit_check_entry;
_linked = linked;
void set_adapter_blob(AdapterBlob* blob) {
_adapter_blob = blob;
_linked = true;
}
address get_i2c_entry() const { return _i2c_entry; }
address get_c2i_entry() const { return _c2i_entry; }
address get_c2i_unverified_entry() const { return _c2i_unverified_entry; }
address get_c2i_no_clinit_check_entry() const { return _c2i_no_clinit_check_entry; }
static const char* entry_name(int i) {
assert(i >=0 && i < ENTRIES_COUNT, "entry id out of range");
return _entry_names[i];
address get_i2c_entry() const {
#ifndef ZERO
assert(_adapter_blob != nullptr, "must be");
return _adapter_blob->i2c_entry();
#else
return nullptr;
#endif // ZERO
}
address get_c2i_entry() const {
#ifndef ZERO
assert(_adapter_blob != nullptr, "must be");
return _adapter_blob->c2i_entry();
#else
return nullptr;
#endif // ZERO
}
address get_c2i_unverified_entry() const {
#ifndef ZERO
assert(_adapter_blob != nullptr, "must be");
return _adapter_blob->c2i_unverified_entry();
#else
return nullptr;
#endif // ZERO
}
address get_c2i_no_clinit_check_entry() const {
#ifndef ZERO
assert(_adapter_blob != nullptr, "must be");
return _adapter_blob->c2i_no_clinit_check_entry();
#else
return nullptr;
#endif // ZERO
}
AdapterBlob* adapter_blob() const { return _adapter_blob; }
bool is_linked() const { return _linked; }
address base_address();
void relocate(address new_base);
AdapterFingerPrint* fingerprint() const { return _fingerprint; }
@ -795,14 +811,13 @@ class AdapterHandlerLibrary: public AllStatic {
static BufferBlob* buffer_blob();
static void initialize();
static AdapterHandlerEntry* get_simple_adapter(const methodHandle& method);
static AdapterBlob* lookup_aot_cache(AdapterHandlerEntry* handler);
static AdapterHandlerEntry* create_adapter(AdapterBlob*& new_adapter,
int total_args_passed,
static void lookup_aot_cache(AdapterHandlerEntry* handler);
static AdapterHandlerEntry* create_adapter(int total_args_passed,
BasicType* sig_bt,
bool is_transient = false);
static void lookup_simple_adapters() NOT_CDS_RETURN;
#ifndef PRODUCT
static void print_adapter_handler_info(outputStream* st, AdapterHandlerEntry* handler, AdapterBlob* adapter_blob);
static void print_adapter_handler_info(outputStream* st, AdapterHandlerEntry* handler);
#endif // PRODUCT
public:
@ -810,8 +825,7 @@ class AdapterHandlerLibrary: public AllStatic {
static void create_native_wrapper(const methodHandle& method);
static AdapterHandlerEntry* get_adapter(const methodHandle& method);
static AdapterHandlerEntry* lookup(int total_args_passed, BasicType* sig_bt);
static bool generate_adapter_code(AdapterBlob*& adapter_blob,
AdapterHandlerEntry* handler,
static bool generate_adapter_code(AdapterHandlerEntry* handler,
int total_args_passed,
BasicType* sig_bt,
bool is_transient);
@ -829,10 +843,11 @@ class AdapterHandlerLibrary: public AllStatic {
static void print_statistics();
#endif // PRODUCT
static AdapterBlob* link_aot_adapter_handler(AdapterHandlerEntry* handler) NOT_CDS_RETURN_(nullptr);
static void link_aot_adapter_handler(AdapterHandlerEntry* handler) NOT_CDS_RETURN;
static void dump_aot_adapter_table() NOT_CDS_RETURN;
static void serialize_shared_table_header(SerializeClosure* soc) NOT_CDS_RETURN;
static void link_aot_adapters() NOT_CDS_RETURN;
static void address_to_offset(address entry_address[AdapterBlob::ENTRY_COUNT], int entry_offset[AdapterBlob::ENTRY_COUNT]);
};
#endif // SHARE_RUNTIME_SHAREDRUNTIME_HPP