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 9 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
2 changes: 1 addition & 1 deletion src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6654,7 +6654,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
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
46 changes: 38 additions & 8 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 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
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
46 changes: 38 additions & 8 deletions src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#endif
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "code/aotCodeCache.hpp"
#include "code/compiledIC.hpp"
#include "code/debugInfoRec.hpp"
#include "code/nativeInst.hpp"
Expand Down Expand Up @@ -2600,6 +2601,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);
if (blob != nullptr) {
_deopt_blob = blob->as_deoptimization_blob();
return;
}

CodeBuffer buffer(name, 2560+pad, 1024);
MacroAssembler* masm = new MacroAssembler(&buffer);
int frame_size_in_words;
Expand Down Expand Up @@ -2951,6 +2958,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);
}

//------------------------------generate_handler_blob------
Expand All @@ -2963,12 +2972,16 @@ SafepointBlob* SharedRuntime::generate_handler_blob(SharedStubId id, address cal
"must be generated before");
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, 2548, 1024);
MacroAssembler* masm = new MacroAssembler(&buffer);

Expand Down Expand Up @@ -3128,7 +3141,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 @@ -3143,10 +3159,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, 1552, 512);
MacroAssembler* masm = new MacroAssembler(&buffer);

Expand Down Expand Up @@ -3215,7 +3235,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 @@ -3253,10 +3276,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 Down Expand Up @@ -3314,6 +3342,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
9 changes: 7 additions & 2 deletions src/hotspot/cpu/x86/x86_64.ad
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ reg_class int_rdi_reg(RDI);
source_hpp %{

#include "peephole_x86_64.hpp"
#include "code/aotCodeCache.hpp"

bool castLL_is_imm32(const Node* n);

Expand Down Expand Up @@ -1859,8 +1860,12 @@ encode %{
%}

enc_class Java_To_Runtime(method meth) %{
// No relocation needed
__ mov64(r10, (int64_t) $meth$$method);
if (AOTCodeCache::is_on_for_dump()) {
// Created runtime_call_type relocation when caching code
__ lea(r10, RuntimeAddress((address)$meth$$method));
} else {
__ mov64(r10, (int64_t) $meth$$method);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should do it always, not conditionally. On AArch64 it is unconditional - relocation processing know how to do that.

Copy link
Contributor

Choose a reason for hiding this comment

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

I will update premain code too later.

__ call(r10);
__ post_call_nop();
%}
Expand Down
Loading