mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 11:34:38 +02:00
8299162: Refactor shared trampoline emission logic
Reviewed-by: fyang, adinn, luhenry
This commit is contained in:
parent
522fa13274
commit
773050647e
9 changed files with 83 additions and 62 deletions
|
@ -42,6 +42,8 @@ void CodeBuffer::share_trampoline_for(address dest, int caller_offset) {
|
||||||
_finalize_stubs = true;
|
_finalize_stubs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define __ masm.
|
||||||
|
|
||||||
static bool emit_shared_trampolines(CodeBuffer* cb, CodeBuffer::SharedTrampolineRequests* requests) {
|
static bool emit_shared_trampolines(CodeBuffer* cb, CodeBuffer::SharedTrampolineRequests* requests) {
|
||||||
if (requests == nullptr) {
|
if (requests == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -49,39 +51,35 @@ static bool emit_shared_trampolines(CodeBuffer* cb, CodeBuffer::SharedTrampoline
|
||||||
|
|
||||||
MacroAssembler masm(cb);
|
MacroAssembler masm(cb);
|
||||||
|
|
||||||
bool p_succeeded = true;
|
|
||||||
auto emit = [&](address dest, const CodeBuffer::Offsets &offsets) {
|
auto emit = [&](address dest, const CodeBuffer::Offsets &offsets) {
|
||||||
masm.set_code_section(cb->stubs());
|
assert(cb->stubs()->remaining() >= MacroAssembler::max_trampoline_stub_size(), "pre-allocated trampolines");
|
||||||
if (!is_aligned(masm.offset(), wordSize)) {
|
|
||||||
if (cb->stubs()->maybe_expand_to_ensure_remaining(NativeInstruction::instruction_size) && cb->blob() == NULL) {
|
|
||||||
ciEnv::current()->record_failure("CodeCache is full");
|
|
||||||
p_succeeded = false;
|
|
||||||
return p_succeeded;
|
|
||||||
}
|
|
||||||
masm.align(wordSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
LinkedListIterator<int> it(offsets.head());
|
LinkedListIterator<int> it(offsets.head());
|
||||||
int offset = *it.next();
|
int offset = *it.next();
|
||||||
for (; !it.is_empty(); offset = *it.next()) {
|
address stub = __ emit_trampoline_stub(offset, dest);
|
||||||
masm.relocate(trampoline_stub_Relocation::spec(cb->insts()->start() + offset));
|
assert(stub, "pre-allocated trampolines");
|
||||||
}
|
|
||||||
masm.set_code_section(cb->insts());
|
|
||||||
|
|
||||||
address stub = masm.emit_trampoline_stub(offset, dest);
|
address reloc_pc = cb->stubs()->end() - NativeCallTrampolineStub::instruction_size;
|
||||||
if (stub == nullptr) {
|
while (!it.is_empty()) {
|
||||||
ciEnv::current()->record_failure("CodeCache is full");
|
offset = *it.next();
|
||||||
p_succeeded = false;
|
address caller_pc = cb->insts()->start() + offset;
|
||||||
|
cb->stubs()->relocate(reloc_pc, trampoline_stub_Relocation::spec(caller_pc));
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
return p_succeeded;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
requests->iterate(emit);
|
assert(requests->number_of_entries() >= 1, "at least one");
|
||||||
|
const int total_requested_size = MacroAssembler::max_trampoline_stub_size() * requests->number_of_entries();
|
||||||
return p_succeeded;
|
if (cb->stubs()->maybe_expand_to_ensure_remaining(total_requested_size) && cb->blob() == NULL) {
|
||||||
|
ciEnv::current()->record_failure("CodeCache is full");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requests->iterate(emit);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef __
|
||||||
|
|
||||||
bool CodeBuffer::pd_finalize_stubs() {
|
bool CodeBuffer::pd_finalize_stubs() {
|
||||||
return emit_shared_stubs_to_interp<MacroAssembler>(this, _shared_stub_to_interp_requests)
|
return emit_shared_stubs_to_interp<MacroAssembler>(this, _shared_stub_to_interp_requests)
|
||||||
&& emit_shared_trampolines(this, _shared_trampoline_requests);
|
&& emit_shared_trampolines(this, _shared_trampoline_requests);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2023, 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.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
|
@ -71,15 +71,14 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
|
||||||
#undef __
|
#undef __
|
||||||
|
|
||||||
int CompiledStaticCall::to_interp_stub_size() {
|
int CompiledStaticCall::to_interp_stub_size() {
|
||||||
// isb; movk; movz; movz; movk; movz; movz; br
|
return MacroAssembler::static_call_stub_size();
|
||||||
return 8 * NativeInstruction::instruction_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CompiledStaticCall::to_trampoline_stub_size() {
|
int CompiledStaticCall::to_trampoline_stub_size() {
|
||||||
// Somewhat pessimistically, we count 3 instructions here (although
|
// Somewhat pessimistically, we count 3 instructions here (although
|
||||||
// there are only two) because we sometimes emit an alignment nop.
|
// there are only two) because we sometimes emit an alignment nop.
|
||||||
// Trampoline stubs are always word aligned.
|
// Trampoline stubs are always word aligned.
|
||||||
return 3 * NativeInstruction::instruction_size + wordSize;
|
return MacroAssembler::max_trampoline_stub_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relocation entries for call stub, compiled java to interpreter.
|
// Relocation entries for call stub, compiled java to interpreter.
|
||||||
|
|
|
@ -926,8 +926,7 @@ address MacroAssembler::trampoline_call(Address entry) {
|
||||||
address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset,
|
address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset,
|
||||||
address dest) {
|
address dest) {
|
||||||
// Max stub size: alignment nop, TrampolineStub.
|
// Max stub size: alignment nop, TrampolineStub.
|
||||||
address stub = start_a_stub(NativeInstruction::instruction_size
|
address stub = start_a_stub(max_trampoline_stub_size());
|
||||||
+ NativeCallTrampolineStub::instruction_size);
|
|
||||||
if (stub == NULL) {
|
if (stub == NULL) {
|
||||||
return NULL; // CodeBuffer::expand failed
|
return NULL; // CodeBuffer::expand failed
|
||||||
}
|
}
|
||||||
|
@ -959,6 +958,11 @@ address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset,
|
||||||
return stub_start_addr;
|
return stub_start_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MacroAssembler::max_trampoline_stub_size() {
|
||||||
|
// Max stub size: alignment nop, TrampolineStub.
|
||||||
|
return NativeInstruction::instruction_size + NativeCallTrampolineStub::instruction_size;
|
||||||
|
}
|
||||||
|
|
||||||
void MacroAssembler::emit_static_call_stub() {
|
void MacroAssembler::emit_static_call_stub() {
|
||||||
// CompiledDirectStaticCall::set_to_interpreted knows the
|
// CompiledDirectStaticCall::set_to_interpreted knows the
|
||||||
// exact layout of this stub.
|
// exact layout of this stub.
|
||||||
|
@ -971,6 +975,11 @@ void MacroAssembler::emit_static_call_stub() {
|
||||||
br(rscratch1);
|
br(rscratch1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MacroAssembler::static_call_stub_size() {
|
||||||
|
// isb; movk; movz; movz; movk; movz; movz; br
|
||||||
|
return 8 * NativeInstruction::instruction_size;
|
||||||
|
}
|
||||||
|
|
||||||
void MacroAssembler::c2bool(Register x) {
|
void MacroAssembler::c2bool(Register x) {
|
||||||
// implements x == 0 ? 0 : 1
|
// implements x == 0 ? 0 : 1
|
||||||
// note: must only look at least-significant byte of x
|
// note: must only look at least-significant byte of x
|
||||||
|
|
|
@ -638,7 +638,9 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
address emit_trampoline_stub(int insts_call_instruction_offset, address target);
|
address emit_trampoline_stub(int insts_call_instruction_offset, address target);
|
||||||
|
static int max_trampoline_stub_size();
|
||||||
void emit_static_call_stub();
|
void emit_static_call_stub();
|
||||||
|
static int static_call_stub_size();
|
||||||
|
|
||||||
// The following 4 methods return the offset of the appropriate move instruction
|
// The following 4 methods return the offset of the appropriate move instruction
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,8 @@ void CodeBuffer::share_trampoline_for(address dest, int caller_offset) {
|
||||||
_finalize_stubs = true;
|
_finalize_stubs = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define __ masm.
|
||||||
|
|
||||||
static bool emit_shared_trampolines(CodeBuffer* cb, CodeBuffer::SharedTrampolineRequests* requests) {
|
static bool emit_shared_trampolines(CodeBuffer* cb, CodeBuffer::SharedTrampolineRequests* requests) {
|
||||||
if (requests == nullptr) {
|
if (requests == nullptr) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -51,39 +53,35 @@ static bool emit_shared_trampolines(CodeBuffer* cb, CodeBuffer::SharedTrampoline
|
||||||
|
|
||||||
MacroAssembler masm(cb);
|
MacroAssembler masm(cb);
|
||||||
|
|
||||||
bool p_succeeded = true;
|
|
||||||
auto emit = [&](address dest, const CodeBuffer::Offsets &offsets) {
|
auto emit = [&](address dest, const CodeBuffer::Offsets &offsets) {
|
||||||
masm.set_code_section(cb->stubs());
|
assert(cb->stubs()->remaining() >= MacroAssembler::max_trampoline_stub_size(), "pre-allocated trampolines");
|
||||||
if (!is_aligned(masm.offset() + NativeCallTrampolineStub::data_offset, wordSize)) {
|
|
||||||
if (cb->stubs()->maybe_expand_to_ensure_remaining(NativeInstruction::instruction_size) && cb->blob() == NULL) {
|
|
||||||
ciEnv::current()->record_failure("CodeCache is full");
|
|
||||||
p_succeeded = false;
|
|
||||||
return p_succeeded;
|
|
||||||
}
|
|
||||||
masm.align(wordSize, NativeCallTrampolineStub::data_offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
LinkedListIterator<int> it(offsets.head());
|
LinkedListIterator<int> it(offsets.head());
|
||||||
int offset = *it.next();
|
int offset = *it.next();
|
||||||
for (; !it.is_empty(); offset = *it.next()) {
|
address stub = __ emit_trampoline_stub(offset, dest);
|
||||||
masm.relocate(trampoline_stub_Relocation::spec(cb->insts()->start() + offset));
|
assert(stub, "pre-allocated trampolines");
|
||||||
}
|
|
||||||
masm.set_code_section(cb->insts());
|
|
||||||
|
|
||||||
address stub = masm.emit_trampoline_stub(offset, dest);
|
address reloc_pc = cb->stubs()->end() - NativeCallTrampolineStub::instruction_size;
|
||||||
if (stub == nullptr) {
|
while (!it.is_empty()) {
|
||||||
ciEnv::current()->record_failure("CodeCache is full");
|
offset = *it.next();
|
||||||
p_succeeded = false;
|
address caller_pc = cb->insts()->start() + offset;
|
||||||
|
cb->stubs()->relocate(reloc_pc, trampoline_stub_Relocation::spec(caller_pc));
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
return p_succeeded;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
requests->iterate(emit);
|
assert(requests->number_of_entries() >= 1, "at least one");
|
||||||
|
const int total_requested_size = MacroAssembler::max_trampoline_stub_size() * requests->number_of_entries();
|
||||||
return p_succeeded;
|
if (cb->stubs()->maybe_expand_to_ensure_remaining(total_requested_size) && cb->blob() == NULL) {
|
||||||
|
ciEnv::current()->record_failure("CodeCache is full");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
requests->iterate(emit);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef __
|
||||||
|
|
||||||
bool CodeBuffer::pd_finalize_stubs() {
|
bool CodeBuffer::pd_finalize_stubs() {
|
||||||
return emit_shared_stubs_to_interp<MacroAssembler>(this, _shared_stub_to_interp_requests)
|
return emit_shared_stubs_to_interp<MacroAssembler>(this, _shared_stub_to_interp_requests)
|
||||||
&& emit_shared_trampolines(this, _shared_trampoline_requests);
|
&& emit_shared_trampolines(this, _shared_trampoline_requests);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2023, 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, 2021, Huawei Technologies Co., Ltd. All rights reserved.
|
* Copyright (c) 2020, 2021, 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.
|
||||||
|
@ -69,15 +69,14 @@ address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark)
|
||||||
#undef __
|
#undef __
|
||||||
|
|
||||||
int CompiledStaticCall::to_interp_stub_size() {
|
int CompiledStaticCall::to_interp_stub_size() {
|
||||||
// (lui, addi, slli, addi, slli, addi) + (lui, addi, slli, addi, slli) + jalr
|
return MacroAssembler::static_call_stub_size();
|
||||||
return 12 * NativeInstruction::instruction_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CompiledStaticCall::to_trampoline_stub_size() {
|
int CompiledStaticCall::to_trampoline_stub_size() {
|
||||||
// Somewhat pessimistically, we count 4 instructions here (although
|
// Somewhat pessimistically, we count 4 instructions here (although
|
||||||
// there are only 3) because we sometimes emit an alignment nop.
|
// there are only 3) because we sometimes emit an alignment nop.
|
||||||
// Trampoline stubs are always word aligned.
|
// Trampoline stubs are always word aligned.
|
||||||
return NativeInstruction::instruction_size + NativeCallTrampolineStub::instruction_size;
|
return MacroAssembler::max_trampoline_stub_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relocation entries for call stub, compiled java to interpreter.
|
// Relocation entries for call stub, compiled java to interpreter.
|
||||||
|
|
|
@ -3142,8 +3142,8 @@ address MacroAssembler::ic_call(address entry, jint method_index) {
|
||||||
|
|
||||||
address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset,
|
address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset,
|
||||||
address dest) {
|
address dest) {
|
||||||
address stub = start_a_stub(NativeInstruction::instruction_size
|
// Max stub size: alignment nop, TrampolineStub.
|
||||||
+ NativeCallTrampolineStub::instruction_size);
|
address stub = start_a_stub(max_trampoline_stub_size());
|
||||||
if (stub == NULL) {
|
if (stub == NULL) {
|
||||||
return NULL; // CodeBuffer::expand failed
|
return NULL; // CodeBuffer::expand failed
|
||||||
}
|
}
|
||||||
|
@ -3183,6 +3183,16 @@ address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset,
|
||||||
return stub_start_addr;
|
return stub_start_addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MacroAssembler::max_trampoline_stub_size() {
|
||||||
|
// Max stub size: alignment nop, TrampolineStub.
|
||||||
|
return NativeInstruction::instruction_size + NativeCallTrampolineStub::instruction_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MacroAssembler::static_call_stub_size() {
|
||||||
|
// (lui, addi, slli, addi, slli, addi) + (lui, addi, slli, addi, slli) + jalr
|
||||||
|
return 12 * NativeInstruction::instruction_size;
|
||||||
|
}
|
||||||
|
|
||||||
Address MacroAssembler::add_memory_helper(const Address dst, Register tmp) {
|
Address MacroAssembler::add_memory_helper(const Address dst, Register tmp) {
|
||||||
switch (dst.getMode()) {
|
switch (dst.getMode()) {
|
||||||
case Address::base_plus_offset:
|
case Address::base_plus_offset:
|
||||||
|
|
|
@ -412,7 +412,9 @@ class MacroAssembler: public Assembler {
|
||||||
}
|
}
|
||||||
|
|
||||||
address emit_trampoline_stub(int insts_call_instruction_offset, address target);
|
address emit_trampoline_stub(int insts_call_instruction_offset, address target);
|
||||||
|
static int max_trampoline_stub_size();
|
||||||
void emit_static_call_stub();
|
void emit_static_call_stub();
|
||||||
|
static int static_call_stub_size();
|
||||||
|
|
||||||
// The following 4 methods return the offset of the appropriate move instruction
|
// The following 4 methods return the offset of the appropriate move instruction
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
#include "ci/ciEnv.hpp"
|
#include "ci/ciEnv.hpp"
|
||||||
#include "code/compiledIC.hpp"
|
#include "code/compiledIC.hpp"
|
||||||
|
|
||||||
|
#define __ masm.
|
||||||
|
|
||||||
template <typename MacroAssembler, int relocate_format = 0>
|
template <typename MacroAssembler, int relocate_format = 0>
|
||||||
bool emit_shared_stubs_to_interp(CodeBuffer* cb, SharedStubToInterpRequests* shared_stub_to_interp_requests) {
|
bool emit_shared_stubs_to_interp(CodeBuffer* cb, SharedStubToInterpRequests* shared_stub_to_interp_requests) {
|
||||||
if (shared_stub_to_interp_requests == NULL) {
|
if (shared_stub_to_interp_requests == NULL) {
|
||||||
|
@ -46,7 +48,7 @@ bool emit_shared_stubs_to_interp(CodeBuffer* cb, SharedStubToInterpRequests* sha
|
||||||
shared_stub_to_interp_requests->sort(by_shared_method);
|
shared_stub_to_interp_requests->sort(by_shared_method);
|
||||||
MacroAssembler masm(cb);
|
MacroAssembler masm(cb);
|
||||||
for (int i = 0; i < shared_stub_to_interp_requests->length();) {
|
for (int i = 0; i < shared_stub_to_interp_requests->length();) {
|
||||||
address stub = masm.start_a_stub(CompiledStaticCall::to_interp_stub_size());
|
address stub = __ start_a_stub(CompiledStaticCall::to_interp_stub_size());
|
||||||
if (stub == NULL) {
|
if (stub == NULL) {
|
||||||
ciEnv::current()->record_failure("CodeCache is full");
|
ciEnv::current()->record_failure("CodeCache is full");
|
||||||
return false;
|
return false;
|
||||||
|
@ -55,13 +57,15 @@ bool emit_shared_stubs_to_interp(CodeBuffer* cb, SharedStubToInterpRequests* sha
|
||||||
ciMethod* method = shared_stub_to_interp_requests->at(i).shared_method();
|
ciMethod* method = shared_stub_to_interp_requests->at(i).shared_method();
|
||||||
do {
|
do {
|
||||||
address caller_pc = cb->insts_begin() + shared_stub_to_interp_requests->at(i).call_offset();
|
address caller_pc = cb->insts_begin() + shared_stub_to_interp_requests->at(i).call_offset();
|
||||||
masm.relocate(static_stub_Relocation::spec(caller_pc), relocate_format);
|
__ relocate(static_stub_Relocation::spec(caller_pc), relocate_format);
|
||||||
++i;
|
++i;
|
||||||
} while (i < shared_stub_to_interp_requests->length() && shared_stub_to_interp_requests->at(i).shared_method() == method);
|
} while (i < shared_stub_to_interp_requests->length() && shared_stub_to_interp_requests->at(i).shared_method() == method);
|
||||||
masm.emit_static_call_stub();
|
__ emit_static_call_stub();
|
||||||
masm.end_a_stub();
|
__ end_a_stub();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef __
|
||||||
|
|
||||||
#endif // SHARE_ASM_CODEBUFFER_INLINE_HPP
|
#endif // SHARE_ASM_CODEBUFFER_INLINE_HPP
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue