]> gitweb.factorcode.org Git - factor.git/blob - vm/data_roots.hpp
VM: the copy assignment operator is overloaded so you need a custom swap
[factor.git] / vm / data_roots.hpp
1 namespace factor {
2
3 template <typename Type> struct data_root : public tagged<Type> {
4   factor_vm* parent;
5
6   void push() {
7     parent->data_roots.push_back(&this->value_);
8   }
9
10   data_root(cell value, factor_vm* parent)
11       : tagged<Type>(value), parent(parent) {
12     push();
13   }
14
15   data_root(Type* value, factor_vm* parent)
16       : tagged<Type>(value), parent(parent) {
17     push();
18   }
19
20   const data_root<Type>& operator=(const Type* x) {
21     tagged<Type>::operator=(x);
22     return *this;
23   }
24   const data_root<Type>& operator=(const cell& x) {
25     tagged<Type>::operator=(x);
26     return *this;
27   }
28
29   ~data_root() {
30     parent->data_roots.pop_back();
31   }
32
33   friend void swap(data_root<Type>& a, data_root<Type>& b) {
34     cell tmp = a.value_;
35     a.value_ = b.value_;
36     b.value_ = tmp;
37   }
38 };
39
40 /* A similar hack for the bignum implementation */
41 struct gc_bignum {
42   bignum** addr;
43   factor_vm* parent;
44
45   gc_bignum(bignum** addr, factor_vm* parent) : addr(addr), parent(parent) {
46     /* Don't bother with variables holding NULL pointers. */
47     if (*addr) {
48       parent->check_data_pointer(*addr);
49       parent->bignum_roots.push_back(addr);
50     }
51   }
52
53   ~gc_bignum() {
54     if (*addr) {
55       FACTOR_ASSERT(parent->bignum_roots.back() == addr);
56       parent->bignum_roots.pop_back();
57     }
58   }
59 };
60
61 #define GC_BIGNUM(x) gc_bignum x##__data_root(&x, this)
62
63 }