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
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//! Pointers

use space::*;
use trace::*;
use runtime::*;
use space_ptr::*;

use std::cell::RefCell;

thread_local!(static RUNTIME: RefCell<Runtime> = RefCell::new(Runtime::new()));

pub trait RootedTrait {
    fn rooted(&self) -> bool;
    fn space_ptr(&mut self) -> &mut SpacePtrTrait;
    fn realloc_to(&mut self, &mut Space);
}

pub fn gc_now() {
    RUNTIME.with(|_rt| {
        _rt.borrow_mut().gc()
    })
}

/// On-stack pointers
pub struct Root<T: Trace + Clone + 'static>(*mut Rooted<T>);

impl<T: Traceable> Root<T> {
    pub fn new(t: T) -> Root<T> {
        RUNTIME.with(|_rt| {
            let mut rt = _rt.borrow_mut();

            rt.cons(t)
        })
    }

    pub fn borrow(&self) -> &T {
        unsafe { (*self.0).borrow() }
    }

    pub fn to_heap(&self) -> Heap<T> {
        unsafe { Heap((*self.0).space_ptr.clone()) }
    }
}

impl<T: Trace + Clone + 'static> Drop for Root<T> {
    fn drop(&mut self) {
        println!("Dropping Root");
        unsafe { (&mut *self.0).rooted = false; }
    }
}

pub struct Rooted<T: Trace + Clone + 'static> {
    rooted: bool,
    space_ptr: SpacePtr<T>,
}

impl<T: Trace + Clone + 'static> Rooted<T> {
    pub fn new(ptr: SpacePtr<T>) -> Rooted<T> {
        Rooted {
            rooted: true,
            space_ptr: ptr,
        }
    }

    pub fn borrow(&self) -> &T {
        self.space_ptr.borrow()
    }

    pub fn into_root(ptr: *mut Self) -> Root<T> {
        Root(ptr)
    }
}

impl<T: Trace + Clone + 'static> RootedTrait for Rooted<T> {
    fn rooted(&self) -> bool { self.rooted }

    fn space_ptr(&mut self) -> &mut SpacePtrTrait {
        &mut self.space_ptr
    }

    fn realloc_to(&mut self, space: &mut Space) {
        unsafe {
            let space_ptr = space.allocate((*self.space_ptr.inner()).clone()).unwrap();
            space.set_forward(&self.space_ptr);
            *(self.space_ptr.inner() as *mut (*mut T)) = space_ptr.inner();
            self.space_ptr =  space_ptr;
        }
    }
}

impl<T: Trace + Clone + 'static> Trace for Rooted<T> {
    fn mark(&mut self) { self.space_ptr.mark(); }
    fn root(&mut self) { self.space_ptr.root(); }
    fn unroot(&mut self) { self.space_ptr.unroot(); }
    fn subfields(&mut self)  -> Vec<&mut HeapTrait> {
        self.space_ptr.subfields()
    }
}

/// On-heap pointers
#[derive(Clone)]
pub struct Heap<T: Traceable>(SpacePtr<T>);

impl<T: Traceable> Heap<T> {
    pub fn borrow(&self) -> &T {
        self.0.borrow()
    }
}

impl<T: Traceable> SpacePtrTrait for Heap<T> {
    fn inner(&self) -> *mut (Trace + 'static) { self.0.inner() }
    fn bit_idx(&self) -> usize { self.0.bit_idx() }
    fn raw_inner(&self) -> *mut u8 { self.0.raw_inner() }
    fn set_raw_inner(&mut self, p: *mut u8) { self.0.set_raw_inner(p) }
}

impl<T: Traceable> Trace for Heap<T> {
    fn mark(&mut self) { self.0.mark(); }
    fn root(&mut self) { self.0.root(); }
    fn unroot(&mut self) { self.0.unroot(); }
    fn subfields(&mut self)  -> Vec<&mut HeapTrait> {
        self.0.subfields()
    }
}

impl<T: Traceable> HeapTrait for Heap<T> { }