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 // General info
int size() const { return _size; } 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: public:
// Creation // Creation
void set_stub(CompiledIC *ic, void* cached_value, address dest_addr); void set_stub(CompiledIC *ic, void* cached_value, address dest_addr);
// Code info // 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(); } address code_end() const { return (address)this + size(); }
// Call site info // Call site info

View File

@ -113,12 +113,18 @@ Stub* StubQueue::request_committed(int code_size) {
return s; 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) { Stub* StubQueue::request(int requested_code_size) {
assert(requested_code_size > 0, "requested_code_size must be > 0"); assert(requested_code_size > 0, "requested_code_size must be > 0");
if (_mutex != NULL) _mutex->lock_without_safepoint_check(); if (_mutex != NULL) _mutex->lock_without_safepoint_check();
Stub* s = current_stub(); 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 (requested_size <= available_space()) {
if (is_contiguous()) { if (is_contiguous()) {
// Queue: |...|XXXXXXX|.............| // Queue: |...|XXXXXXX|.............|
@ -154,8 +160,8 @@ Stub* StubQueue::request(int requested_code_size) {
void StubQueue::commit(int committed_code_size) { void StubQueue::commit(int committed_code_size) {
assert(committed_code_size > 0, "committed_code_size must be > 0"); 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(); 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"); assert(committed_size <= stub_size(s), "committed size must not exceed requested size");
stub_initialize(s, committed_size); stub_initialize(s, committed_size);
_queue_end += 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_begin && _queue_begin < _buffer_limit, "_queue_begin out of bounds");
guarantee(0 <= _queue_end && _queue_end <= _buffer_limit, "_queue_end out of bounds"); guarantee(0 <= _queue_end && _queue_end <= _buffer_limit, "_queue_end out of bounds");
// verify alignment // verify alignment
guarantee(_buffer_size % CodeEntryAlignment == 0, "_buffer_size not aligned"); guarantee(_buffer_size % stub_alignment() == 0, "_buffer_size not aligned");
guarantee(_buffer_limit % CodeEntryAlignment == 0, "_buffer_limit not aligned"); guarantee(_buffer_limit % stub_alignment() == 0, "_buffer_limit not aligned");
guarantee(_queue_begin % CodeEntryAlignment == 0, "_queue_begin not aligned"); guarantee(_queue_begin % stub_alignment() == 0, "_queue_begin not aligned");
guarantee(_queue_end % CodeEntryAlignment == 0, "_queue_end not aligned"); guarantee(_queue_end % stub_alignment() == 0, "_queue_end not aligned");
// verify buffer limit/size relationship // verify buffer limit/size relationship
if (is_contiguous()) { if (is_contiguous()) {
guarantee(_buffer_limit == _buffer_size, "_buffer_limit must equal _buffer_size"); 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 // A concrete stub layout may look like this (both data
// and code sections could be empty as well): // and code sections could be empty as well):
// //
// ________ //
// stub -->| | <--+ // stub -->|--------| <--+ <--- aligned by alignment()
// | | |
// | data | | // | data | |
// |________| | // | | |
// code_begin -->| | | // code_begin -->|--------| | <--- aligned by CodeEntryAlignment
// | | |
// | | | // | | |
// | code | | size // | code | | size
// | | | // | | |
// |________| | // | | |
// code_end -->| | | // code_end -->|--------| <--+
// | data | | //
// |________| |
// <--+
class Stub { class Stub {
public: public:
@ -65,7 +64,6 @@ class Stub {
// General info/converters // General info/converters
int size() const { ShouldNotCallThis(); return 0; } // must return the size provided by initialize 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 // Code info
address code_begin() const { ShouldNotCallThis(); return NULL; } // points to the first byte of the code 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 virtual void finalize(Stub* self) = 0; // called before deallocation
// General info/converters // 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 size(Stub* self) const = 0; // the total size of the stub in bytes (must be a multiple of HeapWordSize)
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 alignment() const = 0; // computes the alignment
// Code info // Code info
virtual address code_begin(Stub* self) const = 0; // points to the first code byte 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 */ \ /* General info */ \
virtual int size(Stub* self) const { return cast(self)->size(); } \ 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 */ \ /* Code info */ \
virtual address code_begin(Stub* self) const { return cast(self)->code_begin(); } \ 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 int _number_of_stubs; // the number of buffered stubs
Mutex* const _mutex; // the lock used for a (request, commit) transaction 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; } 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; } 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* stub_at(int i) const { check_index(i); return (Stub*)(_stub_buffer + i); }
Stub* current_stub() const { return stub_at(_queue_end); } Stub* current_stub() const { return stub_at(_queue_end); }
// Stub functionality accessed via interface // 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); } void stub_finalize(Stub* s) { _stub_interface->finalize(s); }
int stub_size(Stub* s) const { return _stub_interface->size(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); } 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_verify(Stub* s) { _stub_interface->verify(s); }
void stub_print(Stub* s) { _stub_interface->print(s); } void stub_print(Stub* s) { _stub_interface->print(s); }
// Helpers
int compute_stub_size(Stub* stub, int code_size);
public: public:
StubQueue(StubInterface* stub_interface, int buffer_size, Mutex* lock, StubQueue(StubInterface* stub_interface, int buffer_size, Mutex* lock,
const char* name); const char* name);

View File

@ -59,10 +59,10 @@ class InterpreterCodelet: public Stub {
// General info/converters // General info/converters
int size() const { return _size; } 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 // 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(); } address code_end() const { return (address)this + size(); }
// Debugging // Debugging

View File

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