Created
March 26, 2023 08:36
-
-
Save mrnugget/7bcf4ce2accb8fc4d6d3006320dd3b23 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::{ | |
alloc::{self, Layout}, | |
mem::size_of, | |
}; | |
use crate::{ | |
heap::{AllocError, AllocResult}, | |
object::ObjectHeader, | |
raw::RawPtr, | |
}; | |
pub struct LargeObject { | |
addr: RawPtr<u8>, | |
pub size: usize, | |
} | |
impl LargeObject { | |
fn free(&mut self) { | |
unsafe { | |
let layout = Layout::from_size_align_unchecked(self.size, self.size); | |
alloc::dealloc(self.addr.as_mut_ref(), layout); | |
} | |
} | |
pub fn as_object_header(&self) -> RawPtr<ObjectHeader> { | |
let untyped_ptr = self.addr.as_untyped(); | |
let object_header_ptr = untyped_ptr.cast::<ObjectHeader>().as_ptr(); | |
RawPtr::new(object_header_ptr) | |
} | |
} | |
pub struct LargeObjectSpace { | |
pub nodes: Vec<LargeObject>, | |
live_bytes: usize, | |
} | |
impl LargeObjectSpace { | |
pub fn new() -> LargeObjectSpace { | |
LargeObjectSpace { | |
nodes: vec![], | |
live_bytes: 0, | |
} | |
} | |
pub fn find_space(&mut self, size: usize) -> AllocResult { | |
let ptr = self.alloc(size)?; | |
let object = LargeObject { addr: ptr, size }; | |
self.nodes.push(object); | |
Ok(ptr.as_ptr()) | |
} | |
fn alloc(&mut self, size: usize) -> Result<RawPtr<u8>, AllocError> { | |
unsafe { | |
let layout = match Layout::from_size_align(size, size_of::<usize>()) { | |
Ok(layout) => layout, | |
Err(_) => return Err(AllocError::BadRequest), | |
}; | |
let ptr = alloc::alloc(layout); | |
if ptr.is_null() { | |
Err(AllocError::Oom) | |
} else { | |
Ok(RawPtr::new(ptr)) | |
} | |
} | |
} | |
pub fn contains_ptr(&self, header_ptr: &RawPtr<ObjectHeader>) -> bool { | |
let addr = header_ptr.as_ptr() as usize; | |
self.nodes.iter().any(|n| n.addr.as_word() == addr) | |
} | |
pub fn sweep(&mut self, mark: u8) { | |
let mut i = 0; | |
while i < self.nodes.len() { | |
let header = self.nodes[i].as_object_header(); | |
let header_ref = unsafe { header.as_ref() }; | |
let is_marked = header_ref.is_marked_with(mark); | |
if is_marked { | |
i += 1; | |
continue; | |
} | |
// Remove this object from the vector and free its memory | |
let mut object = self.nodes.remove(i); | |
object.free(); | |
} | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use crate::space::BLOCK_SIZE; | |
use super::LargeObjectSpace; | |
#[test] | |
fn alloc_array() { | |
let mut space = LargeObjectSpace::new(); | |
let _ = space | |
.find_space(BLOCK_SIZE + 64) | |
.expect("allocation failed"); | |
} | |
#[test] | |
fn sweeping() { | |
let mut space = LargeObjectSpace::new(); | |
// Size doesn't matter since we're already in LO space, but | |
let n1 = space.find_space(32).expect("allocation failed"); | |
let n2 = space.find_space(32).expect("allocation failed"); | |
let n3 = space.find_space(32).expect("allocation failed"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment