]> gitweb.factorcode.org Git - factor.git/blob - vm/local_roots.hpp
scryfall: make decks better, import from moxfield
[factor.git] / vm / local_roots.hpp
1 namespace factor
2 {
3
4 /* If a runtime function needs to call another function which potentially
5 allocates memory, it must wrap any local variable references to Factor
6 objects in gc_root instances */
7 extern segment *gc_locals_region;
8 extern cell gc_locals;
9
10 DEFPUSHPOP(gc_local_,gc_locals)
11
12 template <typename T>
13 struct gc_root : public tagged<T>
14 {
15         void push() { gc_local_push((cell)this); }
16         
17         explicit gc_root(cell value_) : tagged<T>(value_) { push(); }
18         explicit gc_root(T *value_) : tagged<T>(value_) { push(); }
19
20         const gc_root<T>& operator=(const T *x) { tagged<T>::operator=(x); return *this; }
21         const gc_root<T>& operator=(const cell &x) { tagged<T>::operator=(x); return *this; }
22
23         ~gc_root() {
24 #ifdef FACTOR_DEBUG
25                 cell old = gc_local_pop();
26                 assert(old == (cell)this);
27 #else
28                 gc_local_pop();
29 #endif
30         }
31 };
32
33 /* A similar hack for the bignum implementation */
34 extern segment *gc_bignums_region;
35 extern cell gc_bignums;
36
37 DEFPUSHPOP(gc_bignum_,gc_bignums)
38
39 struct gc_bignum
40 {
41         bignum **addr;
42
43         gc_bignum(bignum **addr_) : addr(addr_) {
44                 if(*addr_)
45                         check_data_pointer(*addr_);
46                 gc_bignum_push((cell)addr);
47         }
48
49         ~gc_bignum() { assert((cell)addr == gc_bignum_pop()); }
50 };
51
52 #define GC_BIGNUM(x) gc_bignum x##__gc_root(&x)
53
54 }