Skip to content

Instantly share code, notes, and snippets.

@mrnugget
Created March 26, 2023 08:36
Show Gist options
  • Save mrnugget/7bcf4ce2accb8fc4d6d3006320dd3b23 to your computer and use it in GitHub Desktop.
Save mrnugget/7bcf4ce2accb8fc4d6d3006320dd3b23 to your computer and use it in GitHub Desktop.
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