8284578: Relax InterpreterCodelet stub alignment

Reviewed-by: kvn, dlong
This commit is contained in:
Aleksey Shipilev 2022-04-14 07:30:37 +00:00
parent bf85b0095f
commit 2241a05705
5 changed files with 41 additions and 30 deletions

View File

@ -61,14 +61,17 @@ class ICStub: public Stub {
// General info
int size() const { return _size; }
static int code_size_to_size(int code_size) { return align_up((int)sizeof(ICStub), CodeEntryAlignment) + code_size; }
// ICStub_from_destination_address looks up Stub* address from code entry address,
// which unfortunately means the stub head should be at the same alignment as the code.
static int alignment() { return CodeEntryAlignment; }
public:
// Creation
void set_stub(CompiledIC *ic, void* cached_value, address dest_addr);
// Code info
address code_begin() const { return (address)this + align_up(sizeof(ICStub), CodeEntryAlignment); }
address code_begin() const { return align_up((address)this + sizeof(ICStub), CodeEntryAlignment); }
address code_end() const { return (address)this + size(); }
// Call site info

View File

@ -113,12 +113,18 @@ Stub* StubQueue::request_committed(int code_size) {
return s;
}
int StubQueue::compute_stub_size(Stub* stub, int code_size) {
address stub_begin = (address) stub;
address code_begin = stub_code_begin(stub);
address code_end = align_up(code_begin + code_size, stub_alignment());
return (int)(code_end - stub_begin);
}
Stub* StubQueue::request(int requested_code_size) {
assert(requested_code_size > 0, "requested_code_size must be > 0");
if (_mutex != NULL) _mutex->lock_without_safepoint_check();
Stub* s = current_stub();
int requested_size = align_up(stub_code_size_to_size(requested_code_size), CodeEntryAlignment);
int requested_size = compute_stub_size(s, requested_code_size);
if (requested_size <= available_space()) {
if (is_contiguous()) {
// Queue: |...|XXXXXXX|.............|
@ -154,8 +160,8 @@ Stub* StubQueue::request(int requested_code_size) {
void StubQueue::commit(int committed_code_size) {
assert(committed_code_size > 0, "committed_code_size must be > 0");
int committed_size = align_up(stub_code_size_to_size(committed_code_size), CodeEntryAlignment);
Stub* s = current_stub();
int committed_size = compute_stub_size(s, committed_code_size);
assert(committed_size <= stub_size(s), "committed size must not exceed requested size");
stub_initialize(s, committed_size);
_queue_end += committed_size;
@ -211,10 +217,10 @@ void StubQueue::verify() {
guarantee(0 <= _queue_begin && _queue_begin < _buffer_limit, "_queue_begin out of bounds");
guarantee(0 <= _queue_end && _queue_end <= _buffer_limit, "_queue_end out of bounds");
// verify alignment
guarantee(_buffer_size % CodeEntryAlignment == 0, "_buffer_size not aligned");
guarantee(_buffer_limit % CodeEntryAlignment == 0, "_buffer_limit not aligned");
guarantee(_queue_begin % CodeEntryAlignment == 0, "_queue_begin not aligned");
guarantee(_queue_end % CodeEntryAlignment == 0, "_queue_end not aligned");
guarantee(_buffer_size % stub_alignment() == 0, "_buffer_size not aligned");
guarantee(_buffer_limit % stub_alignment() == 0, "_buffer_limit not aligned");
guarantee(_queue_begin % stub_alignment() == 0, "_queue_begin not aligned");
guarantee(_queue_end % stub_alignment() == 0, "_queue_end not aligned");
// verify buffer limit/size relationship
if (is_contiguous()) {
guarantee(_buffer_limit == _buffer_size, "_buffer_limit must equal _buffer_size");

View File

@ -42,20 +42,19 @@
// A concrete stub layout may look like this (both data
// and code sections could be empty as well):
//
// ________
// stub -->| | <--+
//
// stub -->|--------| <--+ <--- aligned by alignment()
// | | |
// | data | |
// |________| |
// code_begin -->| | |
// | | |
// code_begin -->|--------| | <--- aligned by CodeEntryAlignment
// | | |
// | | |
// | code | | size
// | | |
// |________| |
// code_end -->| | |
// | data | |
// |________| |
// <--+
// | | |
// code_end -->|--------| <--+
//
class Stub {
public:
@ -65,7 +64,6 @@ class Stub {
// General info/converters
int size() const { ShouldNotCallThis(); return 0; } // must return the size provided by initialize
static int code_size_to_size(int code_size) { ShouldNotCallThis(); return 0; } // computes the size given the code size
// Code info
address code_begin() const { ShouldNotCallThis(); return NULL; } // points to the first byte of the code
@ -97,8 +95,8 @@ class StubInterface: public CHeapObj<mtCode> {
virtual void finalize(Stub* self) = 0; // called before deallocation
// General info/converters
virtual int size(Stub* self) const = 0; // the total size of the stub in bytes (must be a multiple of CodeEntryAlignment)
virtual int code_size_to_size(int code_size) const = 0; // computes the total stub size in bytes given the code size in bytes
virtual int size(Stub* self) const = 0; // the total size of the stub in bytes (must be a multiple of HeapWordSize)
virtual int alignment() const = 0; // computes the alignment
// Code info
virtual address code_begin(Stub* self) const = 0; // points to the first code byte
@ -126,7 +124,7 @@ class StubInterface: public CHeapObj<mtCode> {
\
/* General info */ \
virtual int size(Stub* self) const { return cast(self)->size(); } \
virtual int code_size_to_size(int code_size) const { return stub::code_size_to_size(code_size); } \
virtual int alignment() const { return stub::alignment(); } \
\
/* Code info */ \
virtual address code_begin(Stub* self) const { return cast(self)->code_begin(); } \
@ -153,21 +151,25 @@ class StubQueue: public CHeapObj<mtCode> {
int _number_of_stubs; // the number of buffered stubs
Mutex* const _mutex; // the lock used for a (request, commit) transaction
void check_index(int i) const { assert(0 <= i && i < _buffer_limit && i % CodeEntryAlignment == 0, "illegal index"); }
void check_index(int i) const { assert(0 <= i && i < _buffer_limit && i % stub_alignment() == 0, "illegal index"); }
bool is_contiguous() const { return _queue_begin <= _queue_end; }
int index_of(Stub* s) const { int i = (address)s - _stub_buffer; check_index(i); return i; }
Stub* stub_at(int i) const { check_index(i); return (Stub*)(_stub_buffer + i); }
Stub* current_stub() const { return stub_at(_queue_end); }
// Stub functionality accessed via interface
void stub_initialize(Stub* s, int size) { assert(size % CodeEntryAlignment == 0, "size not aligned"); _stub_interface->initialize(s, size); }
void stub_initialize(Stub* s, int size) { assert(size % stub_alignment() == 0, "size not aligned"); _stub_interface->initialize(s, size); }
void stub_finalize(Stub* s) { _stub_interface->finalize(s); }
int stub_size(Stub* s) const { return _stub_interface->size(s); }
bool stub_contains(Stub* s, address pc) const { return _stub_interface->code_begin(s) <= pc && pc < _stub_interface->code_end(s); }
int stub_code_size_to_size(int code_size) const { return _stub_interface->code_size_to_size(code_size); }
int stub_alignment() const { return _stub_interface->alignment(); }
address stub_code_begin(Stub* s) const { return _stub_interface->code_begin(s); }
void stub_verify(Stub* s) { _stub_interface->verify(s); }
void stub_print(Stub* s) { _stub_interface->print(s); }
// Helpers
int compute_stub_size(Stub* stub, int code_size);
public:
StubQueue(StubInterface* stub_interface, int buffer_size, Mutex* lock,
const char* name);

View File

@ -59,10 +59,10 @@ class InterpreterCodelet: public Stub {
// General info/converters
int size() const { return _size; }
static int code_size_to_size(int code_size) { return align_up((int)sizeof(InterpreterCodelet), CodeEntryAlignment) + code_size; }
static int alignment() { return HeapWordSize; }
// Code info
address code_begin() const { return (address)this + align_up(sizeof(InterpreterCodelet), CodeEntryAlignment); }
address code_begin() const { return align_up((address)this + sizeof(InterpreterCodelet), CodeEntryAlignment); }
address code_end() const { return (address)this + size(); }
// Debugging

View File

@ -47,10 +47,10 @@ void TemplateInterpreter::initialize_stub() {
// allocate interpreter
int code_size = InterpreterCodeSize;
NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space
// 270+ interpreter codelets are generated and each of them is required to be aligned to
// CodeEntryAlignment twice. So we need additional size due to alignment.
// 270+ interpreter codelets are generated and each of them is aligned to HeapWordSize,
// plus their code section is aligned to CodeEntryAlignement. So we need additional size due to alignment.
int max_aligned_codelets = 280;
int max_aligned_bytes = max_aligned_codelets * CodeEntryAlignment * 2;
int max_aligned_bytes = max_aligned_codelets * (HeapWordSize + CodeEntryAlignment);
_code = new StubQueue(new InterpreterCodeletInterface, code_size + max_aligned_bytes, NULL,
"Interpreter");
}