Skip to content

Commit a98db8f

Browse files
authored
i#3699: Change HEAP_ALIGNMENT to 8 on 32-bit ARM. (#7175)
Some C++ library functions require 8-byte alignment. This made the test drcacheoff.simple pass on 32-bit ARM. Issue: #3699
1 parent 4dfb878 commit a98db8f

File tree

3 files changed

+29
-8
lines changed

3 files changed

+29
-8
lines changed

core/heap.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ static const uint BLOCK_SIZES[] = {
105105
8, /* for instr bits */
106106
#ifndef X64
107107
/* for x64 future_fragment_t is 24 bytes (could be 20 if we could put flags last) */
108-
sizeof(future_fragment_t), /* 12 (24 x64) */
108+
ALIGN_FORWARD(sizeof(future_fragment_t), /* 12 (24 x64) */
109+
HEAP_ALIGNMENT),
109110
#endif
110111
/* we have a lot of size 16 requests for IR but they are transient */
111112
24, /* fcache empties and vm_area_t are now 20, vm area extras still 24 */
@@ -119,8 +120,9 @@ static const uint BLOCK_SIZES[] = {
119120
sizeof(instr_t), /* 112 x64 */
120121
# endif
121122
#else
122-
sizeof(fragment_t) + sizeof(direct_linkstub_t) +
123-
sizeof(cbr_fallthrough_linkstub_t), /* 60 dbg / 56 rel */
123+
ALIGN_FORWARD(sizeof(fragment_t) + sizeof(direct_linkstub_t) +
124+
sizeof(cbr_fallthrough_linkstub_t), /* 60 dbg / 56 rel */
125+
HEAP_ALIGNMENT),
124126
# ifndef DEBUG
125127
sizeof(instr_t), /* 72 */
126128
# endif
@@ -156,11 +158,21 @@ DECLARE_NEVERPROT_VAR(static int block_peak_align_pad[BLOCK_TYPES], { 0 });
156158
DECLARE_NEVERPROT_VAR(static bool out_of_vmheap_once, false);
157159
#endif
158160

159-
/* variable-length: we steal one int for the size */
160-
#define HEADER_SIZE (sizeof(size_t))
161+
/* The size of a variable-size allocation is stored as a size_t in the header.
162+
* On 32-bit ARM, HEAP_ALIGNMENT is twice the size of a size_t but the wasted
163+
* space for DR's own use is not expected to be significant as only allocs
164+
* that do not fit in the buckets use headers. Client heap allocations
165+
* probably bear the biggest hit.
166+
*/
167+
#define HEADER_SIZE HEAP_ALIGNMENT
161168
/* VARIABLE_SIZE is assignable */
162169
#define VARIABLE_SIZE(p) (*(size_t *)((p)-HEADER_SIZE))
163-
#define MEMSET_HEADER(p, value) VARIABLE_SIZE(p) = HEAP_TO_PTR_UINT(value)
170+
#define MEMSET_HEADER(p, value) \
171+
do { \
172+
ASSERT(HEADER_SIZE % sizeof(VARIABLE_SIZE(p)) == 0); \
173+
for (size_t k = 0; k < HEADER_SIZE / sizeof(VARIABLE_SIZE(p)); k++) \
174+
(&VARIABLE_SIZE(p))[k] = HEAP_TO_PTR_UINT(value); \
175+
} while (0)
164176
#define GET_VARIABLE_ALLOCATION_SIZE(p) (VARIABLE_SIZE(p) + HEADER_SIZE)
165177

166178
/* The heap is allocated in units.

core/heap.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,11 @@ typedef enum {
9393
} map_flags_t;
9494

9595
typedef byte *heap_pc;
96-
#define HEAP_ALIGNMENT sizeof(heap_pc *)
96+
#ifdef ARM
97+
# define HEAP_ALIGNMENT 8 /* Some C++ functions require 8-byte alignment on ARM. */
98+
#else
99+
# define HEAP_ALIGNMENT sizeof(heap_pc *)
100+
#endif
97101
extern vm_area_vector_t *landing_pad_areas;
98102

99103
#ifdef X64

core/loader_shared.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -940,7 +940,13 @@ redirect_malloc(size_t size)
940940
/* We need extra space to store the size and alignment bit and ensure the returned
941941
* pointer is aligned.
942942
*/
943+
#ifdef ARM
944+
size_t alloc_size = size + STANDARD_HEAP_ALIGNMENT;
945+
ASSERT(HEAP_ALIGNMENT == STANDARD_HEAP_ALIGNMENT);
946+
#else
943947
size_t alloc_size = size + sizeof(size_t) + STANDARD_HEAP_ALIGNMENT - HEAP_ALIGNMENT;
948+
ASSERT(HEAP_ALIGNMENT * 2 == STANDARD_HEAP_ALIGNMENT);
949+
#endif
944950
/* Our header is the size itself, with the top bit stolen to indicate alignment. */
945951
if (TEST(REDIRECT_HEADER_SHIFTED, alloc_size)) {
946952
/* We do not support the top bit being set as that conflicts with the bit in
@@ -958,7 +964,6 @@ redirect_malloc(size_t size)
958964
ptr_uint_t res =
959965
ALIGN_FORWARD((ptr_uint_t)mem + sizeof(size_t), STANDARD_HEAP_ALIGNMENT);
960966
size_t header = alloc_size;
961-
ASSERT(HEAP_ALIGNMENT * 2 == STANDARD_HEAP_ALIGNMENT);
962967
ASSERT(!TEST(REDIRECT_HEADER_SHIFTED, header));
963968
if (res == (ptr_uint_t)mem + sizeof(size_t)) {
964969
/* Already aligned. */

0 commit comments

Comments
 (0)