8284578: Relax InterpreterCodelet stub alignment
Reviewed-by: kvn, dlong
This commit is contained in:
parent
bf85b0095f
commit
2241a05705
@ -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
|
||||||
|
@ -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");
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user