@@ -111,20 +111,43 @@ static uint64_t _roundup_to_power_of_two(uint64_t value) {
111
111
static struct block_allocator ::blockpair *
112
112
_first_fit (struct block_allocator ::blockpair *blocks_array,
113
113
uint64_t n_blocks, uint64_t size, uint64_t alignment,
114
- bool forward, uint64_t max_padding) {
114
+ uint64_t max_padding) {
115
115
if (n_blocks == 1 ) {
116
116
// won't enter loop, can't underflow the direction < 0 case
117
117
return nullptr ;
118
118
}
119
119
120
- struct block_allocator ::blockpair *bp = forward ? &blocks_array[0 ] : &blocks_array[- 1 ];
120
+ struct block_allocator ::blockpair *bp = &blocks_array[0 ];
121
121
for (uint64_t n_spaces_to_check = n_blocks - 1 ; n_spaces_to_check > 0 ;
122
- n_spaces_to_check--, forward ? bp++ : bp-- ) {
122
+ n_spaces_to_check--, bp++) {
123
123
// Consider the space after bp
124
124
uint64_t padded_alignment = max_padding != 0 ? _align (max_padding, alignment) : alignment;
125
125
uint64_t possible_offset = _align (bp->offset + bp->size , padded_alignment);
126
- if (possible_offset + size <= bp[1 ].offset ) {
127
- invariant ((forward ? bp - blocks_array : blocks_array - bp) < (int64_t ) n_blocks);
126
+ if (possible_offset + size <= bp[1 ].offset ) { // bp[1] is always valid since bp < &blocks_array[n_blocks-1]
127
+ invariant (bp - blocks_array < (int64_t ) n_blocks);
128
+ return bp;
129
+ }
130
+ }
131
+ return nullptr ;
132
+ }
133
+
134
+ static struct block_allocator ::blockpair *
135
+ _first_fit_bw (struct block_allocator ::blockpair *blocks_array,
136
+ uint64_t n_blocks, uint64_t size, uint64_t alignment,
137
+ uint64_t max_padding, struct block_allocator ::blockpair *blocks_array_limit) {
138
+ if (n_blocks == 1 ) {
139
+ // won't enter loop, can't underflow the direction < 0 case
140
+ return nullptr ;
141
+ }
142
+
143
+ struct block_allocator ::blockpair *bp = &blocks_array[-1 ];
144
+ for (uint64_t n_spaces_to_check = n_blocks - 1 ; n_spaces_to_check > 0 ;
145
+ n_spaces_to_check--, bp--) {
146
+ // Consider the space after bp
147
+ uint64_t padded_alignment = max_padding != 0 ? _align (max_padding, alignment) : alignment;
148
+ uint64_t possible_offset = _align (bp->offset + bp->size , padded_alignment);
149
+ if (&bp[1 ] < blocks_array_limit && possible_offset + size <= bp[1 ].offset ) {
150
+ invariant (blocks_array - bp < (int64_t ) n_blocks);
128
151
return bp;
129
152
}
130
153
}
@@ -134,7 +157,7 @@ _first_fit(struct block_allocator::blockpair *blocks_array,
134
157
struct block_allocator ::blockpair *
135
158
block_allocator_strategy::first_fit (struct block_allocator ::blockpair *blocks_array,
136
159
uint64_t n_blocks, uint64_t size, uint64_t alignment) {
137
- return _first_fit (blocks_array, n_blocks, size, alignment, true , 0 );
160
+ return _first_fit (blocks_array, n_blocks, size, alignment, 0 );
138
161
}
139
162
140
163
// Best fit block allocation
@@ -188,7 +211,7 @@ static void determine_padded_fit_alignment_from_env(void) {
188
211
struct block_allocator ::blockpair *
189
212
block_allocator_strategy::padded_fit (struct block_allocator ::blockpair *blocks_array,
190
213
uint64_t n_blocks, uint64_t size, uint64_t alignment) {
191
- return _first_fit (blocks_array, n_blocks, size, alignment, true , padded_fit_alignment);
214
+ return _first_fit (blocks_array, n_blocks, size, alignment, padded_fit_alignment);
192
215
}
193
216
194
217
static double hot_zone_threshold = 0.85 ;
@@ -231,21 +254,21 @@ block_allocator_strategy::heat_zone(struct block_allocator::blockpair *blocks_ar
231
254
232
255
if (blocks_in_zone > 0 ) {
233
256
// Find the first fit in the hot zone, going forward.
234
- bp = _first_fit (boundary_bp, blocks_in_zone, size, alignment, true , 0 );
257
+ bp = _first_fit (boundary_bp, blocks_in_zone, size, alignment, 0 );
235
258
if (bp != nullptr ) {
236
259
return bp;
237
260
}
238
261
}
239
262
if (blocks_outside_zone > 0 ) {
240
263
// Find the first fit in the cold zone, going backwards.
241
- bp = _first_fit (boundary_bp, blocks_outside_zone, size, alignment, false , 0 );
264
+ bp = _first_fit_bw (boundary_bp, blocks_outside_zone, size, alignment, 0 , &blocks_array[n_blocks] );
242
265
if (bp != nullptr ) {
243
266
return bp;
244
267
}
245
268
}
246
269
} else {
247
270
// Cold allocations are simply first-fit from the beginning.
248
- return _first_fit (blocks_array, n_blocks, size, alignment, true , 0 );
271
+ return _first_fit (blocks_array, n_blocks, size, alignment, 0 );
249
272
}
250
273
return nullptr ;
251
274
}
0 commit comments