Skip to content

Commit 7195f85

Browse files
committed
Remove recursion in deallocate by transforming it into a loop
1 parent 9f6c2ca commit 7195f85

File tree

1 file changed

+21
-5
lines changed

1 file changed

+21
-5
lines changed

src/hole.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,8 @@ fn allocate_first_fit(previous: &mut Hole, size: usize, align: usize) -> Option<
203203

204204
/// Frees the allocation given by `(addr, size)`. It starts at the given hole and walks the list to
205205
/// find the correct place (the list is sorted by address).
206-
fn deallocate(hole: &mut Hole, addr: usize, size: usize) {
206+
fn deallocate(mut hole: &mut Hole, addr: usize, mut size: usize) {
207+
loop {
207208
assert!(size >= HoleList::min_size());
208209

209210
let hole_addr = if hole.size == 0 {
@@ -216,8 +217,8 @@ fn deallocate(hole: &mut Hole, addr: usize, size: usize) {
216217
hole as *mut _ as usize
217218
};
218219

219-
// Each freed block must be handled by the previous hole in memory. Thus the freed address must
220-
// be always behind the current hole.
220+
// Each freed block must be handled by the previous hole in memory. Thus the freed
221+
// address must be always behind the current hole.
221222
assert!(hole_addr + hole.size <= addr);
222223

223224
// get information about the next block
@@ -245,14 +246,16 @@ fn deallocate(hole: &mut Hole, addr: usize, size: usize) {
245246
// after: ___XXX__FFFFYYYYY____ where F is the freed block
246247

247248
hole.next = hole.next_unwrap().next.take(); // remove the Y block
248-
deallocate(hole, addr, size + next.size); // free the merged F/Y block
249+
size += next.size; // free the merged F/Y block in next iteration
250+
continue;
249251
}
250252
Some(next) if next.addr <= addr => {
251253
// block is behind the next hole, so we delegate it to the next hole
252254
// before: ___XXX__YYYYY________ where X is this hole and Y the next hole
253255
// after: ___XXX__YYYYY__FFFF__ where F is the freed block
254256

255-
deallocate(hole.next_unwrap(), addr, size);
257+
hole = move_helper(hole).next_unwrap(); // start next iteration at next hole
258+
continue;
256259
}
257260
_ => {
258261
// block is between this and the next hole
@@ -274,4 +277,17 @@ fn deallocate(hole: &mut Hole, addr: usize, size: usize) {
274277
hole.next = Some(unsafe { Unique::new(ptr) });
275278
}
276279
}
280+
break;
281+
}
282+
}
283+
284+
/// Identity function to ease moving of references.
285+
///
286+
/// By default, references are reborrowed instead of moved (equivalent to `&mut *reference`). This
287+
/// function forces a move.
288+
///
289+
/// for more information, see:
290+
/// https://bluss.github.io/rust/fun/2015/10/11/stuff-the-identity-function-does/#id-forces-references-to-move
291+
fn move_helper<T>(x: T) -> T {
292+
x
277293
}

0 commit comments

Comments
 (0)