aboutsummaryrefslogtreecommitdiffstats
path: root/bytecode/src/heap.rs
blob: d76456a638949d8a055779f5d4d9f42c9e8d21da (plain) (blame)
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
fn transmute(p: &u8) -> Result<&u64, String> {
    let u8_p = p as *const u8;
    let u64_p = u8_p as *const u64;
    if u64_p as usize % 8 != 0 {
        return Err(String::from("not aligned"));
    }
    unsafe {
        return Ok(&*u64_p);
    }
}

fn transmute_mut(p: &mut u8) -> Result<&mut u64, String> {
    let u8_p = p as *mut u8;
    let u64_p = u8_p as *mut u64;
    if u64_p as usize % 8 != 0 {
        return Err(String::from("not aligned"));
    }
    unsafe {
        return Ok(&mut *u64_p);
    }
}

pub struct Heap {
    heap: Vec<u8>,
}

pub struct Pointer(usize);

impl Heap {
    pub fn new() -> Self {
        Heap {
            heap: vec![0; 128], // 1 kB
        }
    }

    pub fn alloc(&mut self, n: usize) -> Pointer {
        let p = Pointer(self.heap.len());
        self.heap.append(&mut vec![0; n]);
        p
    }

    pub fn peek(&self, p: Pointer) -> Result<u64, String> {
        let Pointer(x) = p;
        let u8_p = &self.heap[x];
        let u64_p = transmute(u8_p)?;
        Ok(*u64_p)
    }

    pub fn poke(&mut self, u: u64, p: Pointer) -> Result<(), String> {
        let Pointer(x) = p;
        let u8_p = &mut self.heap[x];
        let u64_p = transmute_mut(u8_p)?;
        *u64_p = u;
        Ok(())
    }

    pub fn peek_byte(&self, p: Pointer) -> u8 {
        let Pointer(x) = p;
        self.heap[x]
    }

    pub fn poke_byte(&mut self, u: u8, p: Pointer) {
        let Pointer(x) = p;
        self.heap[x] = u;
    }
}

impl Pointer {
    pub fn from_bytes(p: u64) -> Self {
        Pointer(usize::try_from(p).unwrap() >> 1)
    }

    pub fn bytes(&self) -> u64 {
        let Pointer(x) = self;
        u64::try_from(*x).unwrap() << 1
    }

    pub fn offset(&self, off: u8) -> Pointer {
        let Pointer(x) = self;
        Pointer(*x + usize::from(off))
    }
}