30
30
#include " runtime/task.hpp"
31
31
#include " runtime/threadCritical.hpp"
32
32
#include " services/memTracker.hpp"
33
+ #include " utilities/align.hpp"
34
+ #include " utilities/debug.hpp"
33
35
#include " utilities/ostream.hpp"
34
36
37
+ // Pre-defined default chunk sizes must be arena-aligned, see Chunk::operator new()
38
+ STATIC_ASSERT (is_aligned((int )Chunk::tiny_size, ARENA_AMALLOC_ALIGNMENT));
39
+ STATIC_ASSERT (is_aligned((int )Chunk::init_size, ARENA_AMALLOC_ALIGNMENT));
40
+ STATIC_ASSERT (is_aligned((int )Chunk::medium_size, ARENA_AMALLOC_ALIGNMENT));
41
+ STATIC_ASSERT (is_aligned((int )Chunk::size, ARENA_AMALLOC_ALIGNMENT));
42
+ STATIC_ASSERT (is_aligned((int )Chunk::non_pool_size, ARENA_AMALLOC_ALIGNMENT));
43
+
35
44
// --------------------------------------------------------------------------------------
36
45
// ChunkPool implementation
37
46
@@ -171,13 +180,30 @@ class ChunkPoolCleaner : public PeriodicTask {
171
180
// --------------------------------------------------------------------------------------
172
181
// Chunk implementation
173
182
174
- void * Chunk::operator new (size_t requested_size, AllocFailType alloc_failmode, size_t length) throw () {
175
- // requested_size is equal to sizeof(Chunk) but in order for the arena
176
- // allocations to come out aligned as expected the size must be aligned
177
- // to expected arena alignment.
178
- // expect requested_size but if sizeof(Chunk) doesn't match isn't proper size we must align it.
179
- assert (ARENA_ALIGN (requested_size) == aligned_overhead_size (), " Bad alignment" );
180
- size_t bytes = ARENA_ALIGN (requested_size) + length;
183
+ void * Chunk::operator new (size_t sizeofChunk, AllocFailType alloc_failmode, size_t length) throw () {
184
+
185
+ // - requested_size = sizeof(Chunk)
186
+ // - length = payload size
187
+ // We must ensure that the boundaries of the payload (C and D) are aligned to 64-bit:
188
+ //
189
+ // +-----------+--+--------------------------------------------+
190
+ // | |g | |
191
+ // | Chunk |a | Payload |
192
+ // | |p | |
193
+ // +-----------+--+--------------------------------------------+
194
+ // A B C D
195
+ //
196
+ // - The Chunk is allocated from C-heap, therefore its start address (A) should be
197
+ // 64-bit aligned on all our platforms, including 32-bit.
198
+ // - sizeof(Chunk) (B) may not be aligned to 64-bit, and we have to take that into
199
+ // account when calculating the Payload bottom (C) (see Chunk::bottom())
200
+ // - the payload size (length) must be aligned to 64-bit, which takes care of 64-bit
201
+ // aligning (D)
202
+
203
+ assert (sizeofChunk == sizeof (Chunk), " weird request size" );
204
+ assert (is_aligned (length, ARENA_AMALLOC_ALIGNMENT), " chunk payload length misaligned: "
205
+ SIZE_FORMAT " ." , length);
206
+ size_t bytes = ARENA_ALIGN (sizeofChunk) + length;
181
207
switch (length) {
182
208
case Chunk::size: return ChunkPool::large_pool ()->allocate (bytes, alloc_failmode);
183
209
case Chunk::medium_size: return ChunkPool::medium_pool ()->allocate (bytes, alloc_failmode);
@@ -188,6 +214,8 @@ void* Chunk::operator new (size_t requested_size, AllocFailType alloc_failmode,
188
214
if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) {
189
215
vm_exit_out_of_memory (bytes, OOM_MALLOC_ERROR, " Chunk::new" );
190
216
}
217
+ // We rely on arena alignment <= malloc alignment.
218
+ assert (is_aligned (p, ARENA_AMALLOC_ALIGNMENT), " Chunk start address misaligned." );
191
219
return p;
192
220
}
193
221
}
@@ -239,8 +267,7 @@ void Chunk::start_chunk_pool_cleaner_task() {
239
267
// ------------------------------Arena------------------------------------------
240
268
241
269
Arena::Arena (MEMFLAGS flag, size_t init_size) : _flags(flag), _size_in_bytes(0 ) {
242
- size_t round_size = (sizeof (char *)) - 1 ;
243
- init_size = (init_size+round_size) & ~round_size;
270
+ init_size = ARENA_ALIGN (init_size);
244
271
_first = _chunk = new (AllocFailStrategy::EXIT_OOM, init_size) Chunk (init_size);
245
272
_hwm = _chunk->bottom (); // Save the cached hwm, max
246
273
_max = _chunk->top ();
@@ -340,7 +367,8 @@ size_t Arena::used() const {
340
367
// Grow a new Chunk
341
368
void * Arena::grow (size_t x, AllocFailType alloc_failmode) {
342
369
// Get minimal required size. Either real big, or even bigger for giant objs
343
- size_t len = MAX2 (x, (size_t ) Chunk::size);
370
+ // (Note: all chunk sizes have to be 64-bit aligned)
371
+ size_t len = MAX2 (ARENA_ALIGN (x), (size_t ) Chunk::size);
344
372
345
373
Chunk *k = _chunk; // Get filled-up chunk address
346
374
_chunk = new (alloc_failmode, len) Chunk (len);
0 commit comments