Skip to content

8354887: Preserve runtime blobs in AOT code cache #25019

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 62 additions & 1 deletion src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5340,7 +5340,41 @@ bool MacroAssembler::set_klass_decode_mode(address base, int shift, const size_t
return _klass_decode_mode != KlassDecodeNone;
}

static Register pick_different_tmp(Register dst, Register src) {
auto tmps = RegSet::of(r0, r1, r2) - RegSet::of(src, dst);
return *tmps.begin();
}

void MacroAssembler::encode_klass_not_null_for_aot(Register dst, Register src) {
// we have to load the klass base from the AOT constants area but
// not the shift because it is not allowed to change
int shift = CompressedKlassPointers::shift();
assert(shift >= 0 && shift < 4, "unexpected compressd klass shift!");
if (dst != src) {
// we can load the base into dst, subtract it formthe src and shift down
lea(dst, ExternalAddress(CompressedKlassPointers::base_addr()));
ldr(dst, dst);
sub(dst, src, dst);
lsr(dst, dst, shift);
} else {
// we need an extra register in order to load the coop base
Register tmp = pick_different_tmp(dst, src);
RegSet regs = RegSet::of(tmp);
push(regs, sp);
lea(tmp, ExternalAddress(CompressedKlassPointers::base_addr()));
ldr(tmp, tmp);
sub(dst, src, tmp);
lsr(dst, dst, shift);
pop(regs, sp);
}
}

void MacroAssembler::encode_klass_not_null(Register dst, Register src) {
if (AOTCodeCache::is_on_for_dump()) {
encode_klass_not_null_for_aot(dst, src);
return;
}

switch (klass_decode_mode()) {
case KlassDecodeZero:
if (CompressedKlassPointers::shift() != 0) {
Expand Down Expand Up @@ -5377,9 +5411,36 @@ void MacroAssembler::encode_klass_not_null(Register r) {
encode_klass_not_null(r, r);
}

void MacroAssembler::decode_klass_not_null_for_aot(Register dst, Register src) {
// we have to load the klass base from the AOT constants area but
// not the shift because it is not allowed to change
int shift = CompressedKlassPointers::shift();
assert(shift >= 0 && shift < 4, "unexpected compressd klass shift!");
if (dst != src) {
// we can load the base into dst then add the offset with a suitable shift
lea(dst, ExternalAddress(CompressedKlassPointers::base_addr()));
ldr(dst, dst);
add(dst, dst, src, LSL, shift);
} else {
// we need an extra register in order to load the coop base
Register tmp = pick_different_tmp(dst, src);
RegSet regs = RegSet::of(tmp);
push(regs, sp);
lea(tmp, ExternalAddress(CompressedKlassPointers::base_addr()));
ldr(tmp, tmp);
add(dst, tmp, src, LSL, shift);
pop(regs, sp);
}
}

void MacroAssembler::decode_klass_not_null(Register dst, Register src) {
assert (UseCompressedClassPointers, "should only be used for compressed headers");

if (AOTCodeCache::is_on_for_dump()) {
decode_klass_not_null_for_aot(dst, src);
return;
}

switch (klass_decode_mode()) {
case KlassDecodeZero:
if (CompressedKlassPointers::shift() != 0) {
Expand Down Expand Up @@ -6654,7 +6715,7 @@ void MacroAssembler::get_thread(Register dst) {
protect_return_address();
push(saved_regs, sp);

mov(lr, CAST_FROM_FN_PTR(address, JavaThread::aarch64_get_thread_helper));
mov(lr, ExternalAddress(CAST_FROM_FN_PTR(address, JavaThread::aarch64_get_thread_helper)));
blr(lr);
if (dst != c_rarg0) {
mov(dst, c_rarg0);
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,8 @@ class MacroAssembler: public Assembler {

void set_narrow_oop(Register dst, jobject obj);

void decode_klass_not_null_for_aot(Register dst, Register src);
void encode_klass_not_null_for_aot(Register dst, Register src);
void encode_klass_not_null(Register r);
void decode_klass_not_null(Register r);
void encode_klass_not_null(Register dst, Register src);
Expand Down
25 changes: 20 additions & 5 deletions src/hotspot/cpu/aarch64/runtime_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#ifdef COMPILER2
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/aotCodeCache.hpp"
#include "code/vmreg.hpp"
#include "interpreter/interpreter.hpp"
#include "opto/runtime.hpp"
Expand Down Expand Up @@ -60,10 +61,15 @@ class SimpleRuntimeFrame {

//------------------------------generate_uncommon_trap_blob--------------------
UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, (uint)OptoStubId::uncommon_trap_id, name);
if (blob != nullptr) {
return blob->as_uncommon_trap_blob();
}

// Allocate space for the code
ResourceMark rm;
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
Expand Down Expand Up @@ -246,8 +252,10 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Make sure all code is generated
masm->flush();

return UncommonTrapBlob::create(&buffer, oop_maps,
SimpleRuntimeFrame::framesize >> 1);
UncommonTrapBlob *ut_blob = UncommonTrapBlob::create(&buffer, oop_maps,
SimpleRuntimeFrame::framesize >> 1);
AOTCodeCache::store_code_blob(*ut_blob, AOTCodeEntry::C2Blob, (uint)OptoStubId::uncommon_trap_id, name);
return ut_blob;
}

//------------------------------generate_exception_blob---------------------------
Expand Down Expand Up @@ -283,10 +291,15 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {

assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned");

const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, (uint)OptoStubId::exception_id, name);
if (blob != nullptr) {
return blob->as_exception_blob();
}

// Allocate space for the code
ResourceMark rm;
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
Expand Down Expand Up @@ -384,7 +397,9 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
masm->flush();

// Set exception blob
return ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1);
ExceptionBlob* ex_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1);
AOTCodeCache::store_code_blob(*ex_blob, AOTCodeEntry::C2Blob, (uint)OptoStubId::exception_id, name);
return ex_blob;
}
#endif // COMPILER2

Expand Down
48 changes: 39 additions & 9 deletions src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/aotCodeCache.hpp"
#include "code/codeCache.hpp"
#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
Expand Down Expand Up @@ -2184,6 +2185,12 @@ void SharedRuntime::generate_deopt_blob() {
}
#endif
const char* name = SharedRuntime::stub_name(SharedStubId::deopt_id);
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)SharedStubId::deopt_id, name);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For most shared blobs we have a single entry at offset 0. However, for the deopt blob we have 3 (or 5) extra entry points which are embedded in the deopt blob as field values. Saving and restoring the blob internal state removes the need to pass a count and array of entry offsets into load_code_blob and store_code_blob at this point.
That makes we wonder if we need to do the same with AdapterBlob. If we embedded the offsets that are currently stored in AdapterHandlerEntry into AdapterBlob then we could also avoid having to explicitly pass the count and array of offsets at AOT load/store for adapters. The getters in AdapterHandlerEntry could fetch them indirectly or else the entry could cache them locally when it is initialized depending on whether we care about a memory indirection. Maybe this would make things more uniform?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, I agree and I have the similar idea of storing entry points in AdapterBlob just like DeoptimizationBlob. Currently the pointer to AdapterBlob is not maintained anywhere. So the AdapterHandlerEntry would also have to maintain pointer to AdapterBlob.
I was actually wondering if we can eliminate AdapterHandlerEntry by also storing AdapterFingerprint in the AdapterBlob. The Method can then have a pointer to AdapterBlob.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will open an RFE to move entry points to AdapterBlob.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, let's do that in follow up RFE.

@adinn can you approve current changes so we can proceed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

if (blob != nullptr) {
_deopt_blob = blob->as_deoptimization_blob();
return;
}

CodeBuffer buffer(name, 2048+pad, 1024);
MacroAssembler* masm = new MacroAssembler(&buffer);
int frame_size_in_words;
Expand Down Expand Up @@ -2547,6 +2554,8 @@ void SharedRuntime::generate_deopt_blob() {
_deopt_blob->set_implicit_exception_uncommon_trap_offset(implicit_exception_uncommon_trap_offset);
}
#endif

AOTCodeCache::store_code_blob(*_deopt_blob, AOTCodeEntry::SharedBlob, (uint)SharedStubId::deopt_id, name);
}

// Number of stack slots between incoming argument block and the start of
Expand Down Expand Up @@ -2575,12 +2584,16 @@ VMReg SharedRuntime::thread_register() {
SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address call_ptr) {
assert(is_polling_page_id(id), "expected a polling page stub id");

// Allocate space for the code. Setup code generation tools.
const char* name = SharedRuntime::stub_name(id);
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)id, name);
if (blob != nullptr) {
return blob->as_safepoint_blob();
}

ResourceMark rm;
OopMapSet *oop_maps = new OopMapSet();
OopMap* map;

// Allocate space for the code. Setup code generation tools.
const char* name = SharedRuntime::stub_name(id);
CodeBuffer buffer(name, 2048, 1024);
MacroAssembler* masm = new MacroAssembler(&buffer);

Expand Down Expand Up @@ -2689,7 +2702,10 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal
masm->flush();

// Fill-out other meta info
return SafepointBlob::create(&buffer, oop_maps, frame_size_in_words);
SafepointBlob* sp_blob = SafepointBlob::create(&buffer, oop_maps, frame_size_in_words);

AOTCodeCache::store_code_blob(*sp_blob, AOTCodeEntry::SharedBlob, (uint)id, name);
return sp_blob;
}

//
Expand All @@ -2704,10 +2720,14 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti
assert (StubRoutines::forward_exception_entry() != nullptr, "must be generated before");
assert(is_resolve_id(id), "expected a resolve stub id");

const char* name = SharedRuntime::stub_name(id);
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)id, name);
if (blob != nullptr) {
return blob->as_runtime_stub();
}

// allocate space for the code
ResourceMark rm;

const char* name = SharedRuntime::stub_name(id);
CodeBuffer buffer(name, 1000, 512);
MacroAssembler* masm = new MacroAssembler(&buffer);

Expand Down Expand Up @@ -2780,7 +2800,10 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(SharedStubId id, address desti

// return the blob
// frame_size_words or bytes??
return RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true);
RuntimeStub* rs_blob = RuntimeStub::new_runtime_stub(name, &buffer, frame_complete, frame_size_in_words, oop_maps, true);

AOTCodeCache::store_code_blob(*rs_blob, AOTCodeEntry::SharedBlob, (uint)id, name);
return rs_blob;
}

// Continuation point for throwing of implicit exceptions that are
Expand Down Expand Up @@ -2820,10 +2843,15 @@ RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address ru
int insts_size = 512;
int locs_size = 64;

ResourceMark rm;
const char* timer_msg = "SharedRuntime generate_throw_exception";
TraceTime timer(timer_msg, TRACETIME_LOG(Info, startuptime));

CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::SharedBlob, (uint)id, name);
if (blob != nullptr) {
return blob->as_runtime_stub();
}

ResourceMark rm;
CodeBuffer code(name, insts_size, locs_size);
OopMapSet* oop_maps = new OopMapSet();
MacroAssembler* masm = new MacroAssembler(&code);
Expand All @@ -2850,7 +2878,7 @@ RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address ru

__ mov(c_rarg0, rthread);
BLOCK_COMMENT("call runtime_entry");
__ mov(rscratch1, runtime_entry);
__ lea(rscratch1, RuntimeAddress(runtime_entry));
__ blr(rscratch1);

// Generate oop map
Expand Down Expand Up @@ -2883,6 +2911,8 @@ RuntimeStub* SharedRuntime::generate_throw_exception(SharedStubId id, address ru
frame_complete,
(framesize >> (LogBytesPerWord - LogBytesPerInt)),
oop_maps, false);
AOTCodeCache::store_code_blob(*stub, AOTCodeEntry::SharedBlob, (uint)id, name);

return stub;
}

Expand Down
12 changes: 10 additions & 2 deletions src/hotspot/cpu/x86/macroAssembler_x86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5404,7 +5404,11 @@ void MacroAssembler::decode_heap_oop_not_null(Register dst, Register src) {
void MacroAssembler::encode_klass_not_null(Register r, Register tmp) {
assert_different_registers(r, tmp);
if (CompressedKlassPointers::base() != nullptr) {
mov64(tmp, (int64_t)CompressedKlassPointers::base());
if (AOTCodeCache::is_on_for_dump()) {
movptr(tmp, ExternalAddress(CompressedKlassPointers::base_addr()));
} else {
mov64(tmp, (int64_t)CompressedKlassPointers::base());
}
subq(r, tmp);
}
if (CompressedKlassPointers::shift() != 0) {
Expand Down Expand Up @@ -5436,7 +5440,11 @@ void MacroAssembler::decode_klass_not_null(Register r, Register tmp) {
shlq(r, CompressedKlassPointers::shift());
}
if (CompressedKlassPointers::base() != nullptr) {
mov64(tmp, (int64_t)CompressedKlassPointers::base());
if (AOTCodeCache::is_on_for_dump()) {
movptr(tmp, ExternalAddress(CompressedKlassPointers::base_addr()));
} else {
mov64(tmp, (int64_t)CompressedKlassPointers::base());
}
addq(r, tmp);
}
}
Expand Down
25 changes: 20 additions & 5 deletions src/hotspot/cpu/x86/runtime_x86_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#ifdef COMPILER2
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/aotCodeCache.hpp"
#include "code/vmreg.hpp"
#include "interpreter/interpreter.hpp"
#include "opto/runtime.hpp"
Expand Down Expand Up @@ -56,10 +57,15 @@ class SimpleRuntimeFrame {

//------------------------------generate_uncommon_trap_blob--------------------
UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, (uint)OptoStubId::uncommon_trap_id, name);
if (blob != nullptr) {
return blob->as_uncommon_trap_blob();
}

// Allocate space for the code
ResourceMark rm;
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::uncommon_trap_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
Expand Down Expand Up @@ -228,8 +234,10 @@ UncommonTrapBlob* OptoRuntime::generate_uncommon_trap_blob() {
// Make sure all code is generated
masm->flush();

return UncommonTrapBlob::create(&buffer, oop_maps,
SimpleRuntimeFrame::framesize >> 1);
UncommonTrapBlob *ut_blob = UncommonTrapBlob::create(&buffer, oop_maps,
SimpleRuntimeFrame::framesize >> 1);
AOTCodeCache::store_code_blob(*ut_blob, AOTCodeEntry::C2Blob, (uint)OptoStubId::uncommon_trap_id, name);
return ut_blob;
}

//------------------------------generate_exception_blob---------------------------
Expand Down Expand Up @@ -265,10 +273,15 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {

assert(SimpleRuntimeFrame::framesize % 4 == 0, "sp not 16-byte aligned");

const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::C2Blob, (uint)OptoStubId::exception_id, name);
if (blob != nullptr) {
return blob->as_exception_blob();
}

// Allocate space for the code
ResourceMark rm;
// Setup code generation tools
const char* name = OptoRuntime::stub_name(OptoStubId::exception_id);
CodeBuffer buffer(name, 2048, 1024);
if (buffer.blob() == nullptr) {
return nullptr;
Expand Down Expand Up @@ -363,6 +376,8 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() {
masm->flush();

// Set exception blob
return ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1);
ExceptionBlob* ex_blob = ExceptionBlob::create(&buffer, oop_maps, SimpleRuntimeFrame::framesize >> 1);
AOTCodeCache::store_code_blob(*ex_blob, AOTCodeEntry::C2Blob, (uint)OptoStubId::exception_id, name);
return ex_blob;
}
#endif // COMPILER2
Loading