Skip to content

Commit

Permalink
Complete initial layout and refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
nekevss committed Oct 31, 2022
1 parent 991b8f0 commit e5b649e
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 14 deletions.
19 changes: 15 additions & 4 deletions boa_gc/src/internals/ephemeron.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,26 @@ pub struct Ephemeron<K: Trace + ?Sized + 'static, V: Trace + ?Sized + 'static> {
}

impl<K: Trace + ?Sized> Ephemeron<K, ()> {
pub unsafe fn new(value: *mut GcBox<K>) -> Self {
let ptr = NonNull::new_unchecked(value);
pub unsafe fn new(value: NonNull<GcBox<K>>) -> Self {
let ptr = NonNull::new_unchecked(value.as_ptr());
Ephemeron {
key: Cell::new(Some(ptr)),
value: (),
}
}
}

impl<K: Trace + ?Sized, V: Trace> Ephemeron<K, V> {
pub unsafe fn new_pair(key: NonNull<GcBox<K>>, value: V) -> Self {
let ptr = NonNull::new_unchecked(key.as_ptr());

Ephemeron {
key: Cell::new(Some(ptr)),
value,
}
}
}

impl<K: Trace + ?Sized, V: Trace + ?Sized> Ephemeron<K, V> {
#[inline]
pub(crate) fn is_marked(&self) -> bool {
Expand Down Expand Up @@ -53,7 +64,7 @@ impl<K: Trace + ?Sized, V: Trace + ?Sized> Ephemeron<K, V> {
}

#[inline]
pub fn key_value(&self) -> Option<&K> {
pub fn key(&self) -> Option<&K> {
if let Some(key_box) = self.inner_key() {
Some(key_box.value())
} else {
Expand All @@ -62,7 +73,7 @@ impl<K: Trace + ?Sized, V: Trace + ?Sized> Ephemeron<K, V> {
}

#[inline]
pub fn inner_value(&self) -> &V {
pub fn value(&self) -> &V {
&self.value
}

Expand Down
31 changes: 26 additions & 5 deletions boa_gc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub mod trace;
pub use crate::trace::{Finalize, Trace};
pub(crate) use gc_box::GcBox;
pub use internals::{Ephemeron, GcCell as Cell, GcCellRef as CellRef};
pub use pointers::{Gc, WeakGc};
pub use pointers::{Gc, WeakGc, WeakPair};

pub type GcPointer = NonNull<GcBox<dyn Trace>>;

Expand Down Expand Up @@ -172,7 +172,28 @@ impl BoaAlloc {
}

pub fn new_weak_pair<V: Trace>(key: GcPointer, value: V) {
todo!()
BOA_GC.with(|internals| {
let mut gc = internals.borrow_mut();

unsafe {
Self::manage_state(&mut *gc);
let ephem = Ephemeron::new_pair(key, value);
let gc_box = GcBox::new_weak(ephem);

let element_size = mem::size_of_val::<GcBox<_>>(&gc_box);
let element_pointer = Box::into_raw(Box::from(gc_box));

let old_start = gc.youth_start.take();
(*element_pointer).set_header_pointer(old_start);
gc.youth_start
.set(Some(NonNull::new_unchecked(element_pointer)));

gc.runtime.object_allocations += 1;
gc.runtime.total_bytes_allocated += element_size;

WeakPair::new(NonNull::new_unchecked(element_pointer))
}
})
}

pub fn new_weak_ref<T: Trace>(value: NonNull<GcBox<T>>) -> WeakGc<Ephemeron<T, ()>> {
Expand All @@ -182,7 +203,7 @@ impl BoaAlloc {
unsafe {
Self::manage_state(&mut *gc);

let ephemeron = Ephemeron::new(value.as_ptr());
let ephemeron = Ephemeron::new(value);
let gc_box = GcBox::new_weak(ephemeron);

let element_size = mem::size_of_val::<GcBox<_>>(&gc_box);
Expand All @@ -209,7 +230,7 @@ impl BoaAlloc {
) {
for node in promotions {
(*node.as_ptr()).set_header_pointer(gc.adult_start.take());
let allocation_bytes= mem::size_of_val::<GcBox<_>>(&(*node.as_ptr()));
let allocation_bytes = mem::size_of_val::<GcBox<_>>(&(*node.as_ptr()));
gc.runtime.youth_bytes -= allocation_bytes;
gc.runtime.adult_bytes += allocation_bytes;
gc.adult_start.set(Some(node));
Expand Down Expand Up @@ -238,7 +259,7 @@ impl BoaAlloc {
(gc.runtime.youth_bytes as f64 / gc.config.growth_ratio) as usize
}

// The young object threshold should only be raised in cases of high laod. It
// The young object threshold should only be raised in cases of high laod. It
// should retract back to base when the load lessens
if gc.runtime.youth_bytes < gc.config.youth_threshold_base
&& gc.config.youth_threshold != gc.config.youth_threshold_base
Expand Down
6 changes: 4 additions & 2 deletions boa_gc/src/pointers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
//! Pointers represents the External types returned by the Boa Garbage Collector

pub mod gc_ptr;
pub mod weak_ptr;
mod gc_ptr;
mod weak_pair;
mod weak_ptr;

pub use gc_ptr::Gc;
pub use weak_pair::WeakPair;
pub use weak_ptr::WeakGc;
77 changes: 77 additions & 0 deletions boa_gc/src/pointers/weak_pair.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use crate::{
finalizer_safe,
internals::Ephemeron,
trace::{Finalize, Trace},
GcBox, EPHEMERON_QUEUE,
};
use std::cell::Cell;
use std::ptr::NonNull;

pub struct WeakPair<K: Trace + ?Sized + 'static, V: Trace + ?Sized, 'static> {
inner_ptr: Cell<NonNull<GcBox<Ephemeron<K, V>>>>,
}

impl<K: Trace, V: Trace> WeakPair<K, V> {
pub fn new(value: NonNull<GcBox<Ephemeron<K, V>>>) -> Self {
unsafe {
Self {
inner_ptr: Cell::new(NonNull::new_unchecked(value.as_ptr())),
}
}
}
}

impl<K: Trace + ?Sized, V: Trace> WeakPair<K, V> {
#[inline]
fn inner_ptr(&self) -> *mut GcBox<Ephemeron<K, V>> {
assert!(finalizer_safe());

unsafe { self.inner_ptr.get().as_ptr() }
}

#[inline]
pub fn inner(&self) -> &GcBox<Ephemeron<K, V>> {
unsafe { &*self.inner_ptr() }
}

#[inline]
pub fn key(&self) -> Option<&K> {
self.inner().key()
}

#[inline]
pub fn value(&self) -> &V {
self.inner().value()
}
}

impl<K: Trace, V:Trace> Finalize for WeakPair<K, V> {}

unsafe impl<K: Trace, V: Trace> Trace for WeakPair<K, V> {
#[inline]
unsafe fn trace(&self) {}

#[inline]
unsafe fn is_marked_ephemeron(&self) -> bool {
false
}

#[inline]
unsafe fn weak_trace(&self) {
EPHEMERON_QUEUE.with(|q| {
let mut queue = q.take().expect("queue is initialized by weak_trace");
queue.push(NonNull::new_unchecked(self.inner_ptr()))
})
}

#[inline]
unsafe fn root(&self) {}

#[inline]
unsafe fn unroot(&self) {}

#[inline]
fn run_finalizer(&self) {
Finalize::finalize(self)
}
}
22 changes: 19 additions & 3 deletions boa_gc/src/pointers/weak_ptr.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use crate::{
finalizer_safe,
internals::Ephemeron,
trace::{Finalize, Trace},
GcBox, EPHEMERON_QUEUE,
};
use std::cell::Cell;
use std::ptr::NonNull;

pub struct WeakGc<T: Trace + ?Sized + 'static> {
inner_ptr: Cell<NonNull<GcBox<T>>>,
inner_ptr: Cell<NonNull<GcBox<Ephemeron<T, ()>>>>,
}

impl<T: Trace> WeakGc<T> {
pub fn new(value: NonNull<GcBox<T>>) -> Self {
pub fn new(value: NonNull<GcBox<Ephemeron<T, ()>>>) -> Self {
unsafe {
Self {
inner_ptr: Cell::new(NonNull::new_unchecked(value.as_ptr())),
Expand All @@ -22,11 +23,26 @@ impl<T: Trace> WeakGc<T> {

impl<T: Trace + ?Sized> WeakGc<T> {
#[inline]
fn inner_ptr(&self) -> *mut GcBox<T> {
fn inner_ptr(&self) -> *mut GcBox<Ephemeron<T, ()>> {
assert!(finalizer_safe());

unsafe { self.inner_ptr.get().as_ptr() }
}

#[inline]
fn value(&self) -> T {
self.inner_ptr()
}

#[inline]
fn inner(&self) -> &GcBox<Ephemeron<T, ()>> {
unsafe { &*self.inner_ptr() }
}

#[inline]
pub fn value(&self) -> Option<&T> {
self.inner().key()
}
}

impl<T: Trace> Finalize for WeakGc<T> {}
Expand Down

0 comments on commit e5b649e

Please sign in to comment.