64 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			64 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
/* If a runtime function needs to call another function which potentially
 | 
						|
allocates memory, it must store any local variable references to Factor
 | 
						|
objects on the root stack */
 | 
						|
 | 
						|
/* GC locals: stores addresses of pointers to objects. The GC updates these
 | 
						|
pointers, so you can do
 | 
						|
 | 
						|
REGISTER_ROOT(some_local);
 | 
						|
 | 
						|
... allocate memory ...
 | 
						|
 | 
						|
foo(some_local);
 | 
						|
 | 
						|
...
 | 
						|
 | 
						|
UNREGISTER_ROOT(some_local); */
 | 
						|
F_SEGMENT *gc_locals_region;
 | 
						|
CELL gc_locals;
 | 
						|
 | 
						|
DEFPUSHPOP(gc_local_,gc_locals)
 | 
						|
 | 
						|
#define REGISTER_ROOT(obj) gc_local_push((CELL)&obj)
 | 
						|
#define UNREGISTER_ROOT(obj) \
 | 
						|
	{ \
 | 
						|
		if(gc_local_pop() != (CELL)&obj) \
 | 
						|
			critical_error("Mismatched REGISTER_ROOT/UNREGISTER_ROOT",0); \
 | 
						|
	}
 | 
						|
 | 
						|
/* Extra roots: stores pointers to objects in the heap. Requires extra work
 | 
						|
(you have to unregister before accessing the object) but more flexible. */
 | 
						|
F_SEGMENT *extra_roots_region;
 | 
						|
CELL extra_roots;
 | 
						|
 | 
						|
DEFPUSHPOP(root_,extra_roots)
 | 
						|
 | 
						|
#define REGISTER_UNTAGGED(obj) root_push(obj ? tag_object(obj) : 0)
 | 
						|
#define UNREGISTER_UNTAGGED(obj) obj = untag_object(root_pop())
 | 
						|
 | 
						|
/* We ignore strings which point outside the data heap, but we might be given
 | 
						|
a char* which points inside the data heap, in which case it is a root, for
 | 
						|
example if we call unbox_char_string() the result is placed in a byte array */
 | 
						|
INLINE bool root_push_alien(const void *ptr)
 | 
						|
{
 | 
						|
	if(in_data_heap_p((CELL)ptr))
 | 
						|
	{
 | 
						|
		F_BYTE_ARRAY *objptr = ((F_BYTE_ARRAY *)ptr) - 1;
 | 
						|
		if(objptr->header == tag_header(BYTE_ARRAY_TYPE))
 | 
						|
		{
 | 
						|
			root_push(tag_object(objptr));
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return false;
 | 
						|
}
 | 
						|
 | 
						|
#define REGISTER_C_STRING(obj) \
 | 
						|
	bool obj##_root = root_push_alien(obj)
 | 
						|
#define UNREGISTER_C_STRING(obj) \
 | 
						|
	if(obj##_root) obj = alien_offset(root_pop())
 | 
						|
 | 
						|
#define REGISTER_BIGNUM(obj) if(obj) root_push(tag_bignum(obj))
 | 
						|
#define UNREGISTER_BIGNUM(obj) if(obj) obj = (untag_object(root_pop()))
 |