1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use crate::{
block::Block,
globals::LINE_SIZE,
header::HeapObjectHeader,
internal::{block_list::BlockList, space_bitmap::SpaceBitmap},
};
pub mod normal;
pub mod overflow;
pub type BlockTuple = (*mut Block, u16, u16);
pub trait Allocator {
fn line_bitmap(&self) -> &SpaceBitmap<LINE_SIZE>;
fn get_all_blocks(&mut self, list: &mut BlockList);
fn take_current_block(&mut self) -> Option<BlockTuple>;
fn put_current_block(&mut self, block_tuple: BlockTuple);
fn get_new_block(&mut self) -> Option<BlockTuple>;
fn handle_no_hole(&mut self, size: usize) -> Option<BlockTuple>;
fn handle_full_block(&mut self, block: *mut Block);
fn allocate(&mut self, size: usize) -> Option<*mut HeapObjectHeader> {
self.take_current_block()
.and_then(|tp| self.scan_for_hole(size, tp))
.or_else(|| self.handle_no_hole(size))
.or_else(|| self.get_new_block())
.map(|tp| self.allocate_from_block(size, tp))
.map(|(tp, object)| {
self.put_current_block(tp);
object
})
}
#[inline]
fn scan_for_hole(&mut self, size: usize, block_tuple: BlockTuple) -> Option<BlockTuple> {
let (block, low, high) = block_tuple;
match (high - low as u16) as usize >= size {
true => Some(block_tuple),
false => match unsafe { (*block).scan_block(self.line_bitmap(), high) } {
None => {
self.handle_full_block(block);
None
}
Some((low, high)) => self.scan_for_hole(size, (block, low, high)),
},
}
}
fn allocate_from_block(
&self,
size: usize,
block_tuple: BlockTuple,
) -> (BlockTuple, *mut HeapObjectHeader) {
let (block, low, high) = block_tuple;
let object = unsafe { (*block).offset(low as usize) };
((block, low as u16 + size as u16, high), object.cast())
}
}