Skip to content

Commit 7be9f1d

Browse files
committed
8321137: Reconsider ICStub alignment
Reviewed-by: dlong, eosterlund, mdoerr, fyang, aph
1 parent b8dafa6 commit 7be9f1d

File tree

6 files changed

+58
-35
lines changed

6 files changed

+58
-35
lines changed

src/hotspot/share/code/compiledIC.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ address CompiledIC::stub_address() const {
187187
// Clears the IC stub if the compiled IC is in transition state
188188
void CompiledIC::clear_ic_stub() {
189189
if (is_in_transition_state()) {
190-
ICStub* stub = ICStub_from_destination_address(stub_address());
190+
ICStub* stub = ICStub::from_destination_address(stub_address());
191191
stub->clear();
192192
}
193193
}

src/hotspot/share/code/icBuffer.cpp

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ void ICStub::finalize() {
8888
CompiledIC *ic = CompiledIC_at(CodeCache::find_compiled(ic_site()), ic_site());
8989
assert(CodeCache::find_compiled(ic->instruction_address()) != nullptr, "inline cache in non-compiled?");
9090

91-
assert(this == ICStub_from_destination_address(ic->stub_address()), "wrong owner of ic buffer");
91+
assert(this == ICStub::from_destination_address(ic->stub_address()), "wrong owner of ic buffer");
9292
ic->set_ic_destination_and_value(destination(), cached_value());
9393
}
9494
}
@@ -146,11 +146,6 @@ void InlineCacheBuffer::initialize() {
146146
}
147147

148148

149-
ICStub* InlineCacheBuffer::new_ic_stub() {
150-
return (ICStub*)buffer()->request_committed(ic_stub_code_size());
151-
}
152-
153-
154149
void InlineCacheBuffer::refill_ic_stubs() {
155150
#ifdef ASSERT
156151
ICRefillVerifier* verifier = current_ic_refill_verifier();
@@ -210,7 +205,7 @@ bool InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_valu
210205
}
211206

212207
// allocate and initialize new "out-of-line" inline-cache
213-
ICStub* ic_stub = new_ic_stub();
208+
ICStub* ic_stub = (ICStub*) buffer()->request_committed(ic_stub_code_size());
214209
if (ic_stub == nullptr) {
215210
#ifdef ASSERT
216211
ICRefillVerifier* verifier = current_ic_refill_verifier();
@@ -219,9 +214,18 @@ bool InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_valu
219214
return false;
220215
}
221216

217+
#ifdef ASSERT
218+
{
219+
ICStub* rev_stub = ICStub::from_destination_address(ic_stub->code_begin());
220+
assert(ic_stub == rev_stub,
221+
"ICStub mapping is reversible: stub=" PTR_FORMAT ", code=" PTR_FORMAT ", rev_stub=" PTR_FORMAT,
222+
p2i(ic_stub), p2i(ic_stub->code_begin()), p2i(rev_stub));
223+
}
224+
#endif
225+
222226
// If an transition stub is already associate with the inline cache, then we remove the association.
223227
if (ic->is_in_transition_state()) {
224-
ICStub* old_stub = ICStub_from_destination_address(ic->stub_address());
228+
ICStub* old_stub = ICStub::from_destination_address(ic->stub_address());
225229
old_stub->clear();
226230
}
227231

@@ -234,13 +238,13 @@ bool InlineCacheBuffer::create_transition_stub(CompiledIC *ic, void* cached_valu
234238

235239

236240
address InlineCacheBuffer::ic_destination_for(CompiledIC *ic) {
237-
ICStub* stub = ICStub_from_destination_address(ic->stub_address());
241+
ICStub* stub = ICStub::from_destination_address(ic->stub_address());
238242
return stub->destination();
239243
}
240244

241245

242246
void* InlineCacheBuffer::cached_value_for(CompiledIC *ic) {
243-
ICStub* stub = ICStub_from_destination_address(ic->stub_address());
247+
ICStub* stub = ICStub::from_destination_address(ic->stub_address());
244248
return stub->cached_value();
245249
}
246250

src/hotspot/share/code/icBuffer.hpp

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,27 @@ class ICStub: public Stub {
6262
// General info
6363
int size() const { return _size; }
6464

65-
// ICStub_from_destination_address looks up Stub* address from code entry address,
66-
// which unfortunately means the stub head should be at the same alignment as the code.
67-
static int alignment() { return CodeEntryAlignment; }
65+
// To be cautious, we want to make sure that each ICStub is in a separate instruction
66+
// cache line. This would allow for piggybacking on instruction cache coherency on
67+
// some architectures to order the updates to ICStub and setting the destination to
68+
// the ICStub. Note that cache line size might be larger than CodeEntryAlignment
69+
// that is normal alignment for CodeBlobs.
70+
static int alignment() { return DEFAULT_CACHE_LINE_SIZE; }
71+
72+
// Aligning the code section is normally done for performance reasons, which is not
73+
// required for ICStubs, as these stubs are transitional. Setting code alignment
74+
// to CodeEntryAlignment would waste a lot of memory in ICBuffer. Aligning to
75+
// word size should be enough. This also offsets the costs of aligning the entire
76+
// ICStub to cache line (see above), as smaller code alignment would allow ICStub
77+
// to fit a _single_ cache line.
78+
static int code_alignment() { return HeapWordSize; }
6879

6980
public:
7081
// Creation
7182
void set_stub(CompiledIC *ic, void* cached_value, address dest_addr);
7283

7384
// Code info
74-
address code_begin() const { return align_up((address)this + sizeof(ICStub), CodeEntryAlignment); }
85+
address code_begin() const { return align_up((address)this + sizeof(ICStub), code_alignment()); }
7586
address code_end() const { return (address)this + size(); }
7687

7788
// Call site info
@@ -88,18 +99,15 @@ class ICStub: public Stub {
8899
void print() PRODUCT_RETURN;
89100

90101
// Creation
91-
friend ICStub* ICStub_from_destination_address(address destination_address);
102+
static inline ICStub* from_destination_address(address destination_address) {
103+
ICStub* stub = (ICStub*) align_down(destination_address - sizeof(ICStub), alignment());
104+
#ifdef ASSERT
105+
stub->verify();
106+
#endif
107+
return stub;
108+
}
92109
};
93110

94-
// ICStub Creation
95-
inline ICStub* ICStub_from_destination_address(address destination_address) {
96-
ICStub* stub = (ICStub*) (destination_address - align_up(sizeof(ICStub), CodeEntryAlignment));
97-
#ifdef ASSERT
98-
stub->verify();
99-
#endif
100-
return stub;
101-
}
102-
103111
#ifdef ASSERT
104112
// The ICRefillVerifier class is a stack allocated RAII object used to
105113
// detect if a failed IC transition that required IC stub refilling has
@@ -151,8 +159,6 @@ class InlineCacheBuffer: public AllStatic {
151159

152160
static StubQueue* buffer() { return _buffer; }
153161

154-
static ICStub* new_ic_stub();
155-
156162
// Machine-dependent implementation of ICBuffer
157163
static void assemble_ic_buffer_code(address code_begin, void* cached_value, address entry_point);
158164
static address ic_buffer_entry_point (address code_begin);

src/hotspot/share/code/stubs.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,15 @@ StubQueue::StubQueue(StubInterface* stub_interface, int buffer_size,
7373
vm_exit_out_of_memory(size, OOM_MALLOC_ERROR, "CodeCache: no room for %s", name);
7474
}
7575
_stub_interface = stub_interface;
76-
_buffer_size = blob->content_size();
77-
_buffer_limit = blob->content_size();
78-
_stub_buffer = blob->content_begin();
76+
77+
// The code blob alignment can be smaller than the requested stub alignment.
78+
// Make sure we put the stubs at their requested alignment by aligning the buffer base and limits.
79+
address aligned_start = align_up(blob->content_begin(), stub_alignment());
80+
address aligned_end = align_down(blob->content_end(), stub_alignment());
81+
int aligned_size = aligned_end - aligned_start;
82+
_buffer_size = aligned_size;
83+
_buffer_limit = aligned_size;
84+
_stub_buffer = aligned_start;
7985
_queue_begin = 0;
8086
_queue_end = 0;
8187
_number_of_stubs = 0;
@@ -94,8 +100,11 @@ void StubQueue::deallocate_unused_tail() {
94100
CodeBlob* blob = CodeCache::find_blob((void*)_stub_buffer);
95101
CodeCache::free_unused_tail(blob, used_space());
96102
// Update the limits to the new, trimmed CodeBlob size
97-
_buffer_size = blob->content_size();
98-
_buffer_limit = blob->content_size();
103+
address aligned_start = align_up(blob->content_begin(), stub_alignment());
104+
address aligned_end = align_down(blob->content_end(), stub_alignment());
105+
int aligned_size = aligned_end - aligned_start;
106+
_buffer_size = aligned_size;
107+
_buffer_limit = aligned_size;
99108
}
100109

101110
Stub* StubQueue::stub_containing(address pc) const {

src/hotspot/share/code/stubs.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class Mutex;
4949
// | | |
5050
// | data | |
5151
// | | |
52-
// code_begin -->|--------| | <--- aligned by CodeEntryAlignment
52+
// code_begin -->|--------| | <--- aligned by code_alignment()
5353
// | | |
5454
// | | |
5555
// | code | | size
@@ -99,6 +99,7 @@ class StubInterface: public CHeapObj<mtCode> {
9999
// General info/converters
100100
virtual int size(Stub* self) const = 0; // the total size of the stub in bytes (must be a multiple of HeapWordSize)
101101
virtual int alignment() const = 0; // computes the alignment
102+
virtual int code_alignment() const = 0; // computes the code alignment
102103

103104
// Code info
104105
virtual address code_begin(Stub* self) const = 0; // points to the first code byte
@@ -127,6 +128,7 @@ class StubInterface: public CHeapObj<mtCode> {
127128
/* General info */ \
128129
virtual int size(Stub* self) const { return cast(self)->size(); } \
129130
virtual int alignment() const { return stub::alignment(); } \
131+
virtual int code_alignment() const { return stub::code_alignment(); } \
130132
\
131133
/* Code info */ \
132134
virtual address code_begin(Stub* self) const { return cast(self)->code_begin(); } \
@@ -154,9 +156,10 @@ class StubQueue: public CHeapObj<mtCode> {
154156
Mutex* const _mutex; // the lock used for a (request, commit) transaction
155157

156158
void check_index(int i) const { assert(0 <= i && i < _buffer_limit && i % stub_alignment() == 0, "illegal index"); }
159+
void check_stub_align(Stub* s) const { assert(((intptr_t)s) % stub_alignment() == 0, "incorrect stub alignment"); }
157160
bool is_contiguous() const { return _queue_begin <= _queue_end; }
158161
int index_of(Stub* s) const { int i = (int)((address)s - _stub_buffer); check_index(i); return i; }
159-
Stub* stub_at(int i) const { check_index(i); return (Stub*)(_stub_buffer + i); }
162+
Stub* stub_at(int i) const { check_index(i); Stub* s = (Stub*)(_stub_buffer + i); check_stub_align(s); return s; }
160163
Stub* current_stub() const { return stub_at(_queue_end); }
161164

162165
// Stub functionality accessed via interface

src/hotspot/share/interpreter/interpreter.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,10 @@ class InterpreterCodelet: public Stub {
6060
// General info/converters
6161
int size() const { return _size; }
6262
static int alignment() { return HeapWordSize; }
63+
static int code_alignment() { return CodeEntryAlignment; }
6364

6465
// Code info
65-
address code_begin() const { return align_up((address)this + sizeof(InterpreterCodelet), CodeEntryAlignment); }
66+
address code_begin() const { return align_up((address)this + sizeof(InterpreterCodelet), code_alignment()); }
6667
address code_end() const { return (address)this + size(); }
6768

6869
// Debugging

0 commit comments

Comments
 (0)