]> gitweb.factorcode.org Git - factor.git/blob - vmpp/local_roots.hpp
6dee443f78b2b0c6201eaaaf2083d5dd3c772f23
[factor.git] / vmpp / local_roots.hpp
1 /* If a runtime function needs to call another function which potentially
2 allocates memory, it must store any local variable references to Factor
3 objects on the root stack */
4 extern F_SEGMENT *gc_locals_region;
5 extern CELL gc_locals;
6
7 DEFPUSHPOP(gc_local_,gc_locals)
8
9 template <typename T>
10 struct gc_root : public tagged<T>
11 {
12         void push() { gc_local_push((CELL)this); }
13         
14         explicit gc_root(CELL value_) : tagged<T>(value_) { push(); }
15         explicit gc_root(T *value_) : tagged<T>(value_) { push(); }
16
17         const gc_root<T>& operator=(const T *x) { tagged<T>::operator=(x); return *this; }
18         const gc_root<T>& operator=(const CELL &x) { tagged<T>::operator=(x); return *this; }
19
20         ~gc_root() { CELL old = gc_local_pop(); assert(old == (CELL)this); }
21 };
22
23 /* Extra roots: stores pointers to objects in the heap. Requires extra work
24 (you have to unregister before accessing the object) but more flexible. */
25 extern F_SEGMENT *extra_roots_region;
26 extern CELL extra_roots;
27
28 DEFPUSHPOP(root_,extra_roots)
29
30 /* We ignore strings which point outside the data heap, but we might be given
31 a char* which points inside the data heap, in which case it is a root, for
32 example if we call unbox_char_string() the result is placed in a byte array */
33 INLINE bool root_push_alien(const void *ptr)
34 {
35         if(in_data_heap_p((CELL)ptr))
36         {
37                 F_BYTE_ARRAY *objptr = ((F_BYTE_ARRAY *)ptr) - 1;
38                 if(objptr->header == tag_header(BYTE_ARRAY_TYPE))
39                 {
40                         root_push(tag_object(objptr));
41                         return true;
42                 }
43         }
44
45         return false;
46 }
47
48 #define REGISTER_C_STRING(obj) \
49         bool obj##_root = root_push_alien((const char *)obj)
50 #define UNREGISTER_C_STRING(type,obj)                   \
51         if(obj##_root) obj = (type *)alien_offset(root_pop())
52
53 #define REGISTER_BIGNUM(obj) if(obj) root_push(tag_bignum(obj))
54 #define UNREGISTER_BIGNUM(obj) if(obj) obj = (untag_bignum_fast(root_pop()))