factor/native/memory.c

218 lines
3.8 KiB
C

#include "factor.h"
CELL object_size(CELL pointer)
{
CELL size;
switch(TAG(pointer))
{
case FIXNUM_TYPE:
size = 0;
break;
case BIGNUM_TYPE:
size = untagged_object_size(UNTAG(pointer));
break;
case CONS_TYPE:
size = sizeof(F_CONS);
break;
case RATIO_TYPE:
size = sizeof(F_RATIO);
break;
case FLOAT_TYPE:
size = sizeof(F_FLOAT);
break;
case COMPLEX_TYPE:
size = sizeof(F_CONS);
break;
case OBJECT_TYPE:
if(pointer == F)
size = 0;
else
size = untagged_object_size(UNTAG(pointer));
break;
default:
critical_error("Cannot determine object_size",pointer);
size = 0; /* Can't happen */
break;
}
return align8(size);
}
CELL untagged_object_size(CELL pointer)
{
CELL size;
switch(untag_header(get(pointer)))
{
case WORD_TYPE:
size = sizeof(F_WORD);
break;
case ARRAY_TYPE:
case TUPLE_TYPE:
case BIGNUM_TYPE:
case BYTE_ARRAY_TYPE:
size = array_size(array_capacity((F_ARRAY*)(pointer)));
break;
case HASHTABLE_TYPE:
size = sizeof(F_HASHTABLE);
break;
case VECTOR_TYPE:
size = sizeof(F_VECTOR);
break;
case STRING_TYPE:
size = string_size(string_capacity((F_STRING*)(pointer)));
break;
case SBUF_TYPE:
size = sizeof(F_SBUF);
break;
case FLOAT_TYPE:
size = sizeof(F_FLOAT);
break;
case DLL_TYPE:
size = sizeof(DLL);
break;
case ALIEN_TYPE:
size = sizeof(ALIEN);
break;
case WRAPPER_TYPE:
size = sizeof(F_WRAPPER);
break;
default:
critical_error("Cannot determine untagged_object_size",pointer);
size = -1;/* can't happen */
break;
}
return align8(size);
}
void primitive_type(void)
{
drepl(tag_fixnum(type_of(dpeek())));
}
void primitive_tag(void)
{
drepl(tag_fixnum(TAG(dpeek())));
}
void primitive_slot(void)
{
F_FIXNUM slot = untag_fixnum_fast(dpop());
CELL obj = UNTAG(dpop());
dpush(get(SLOT(obj,slot)));
}
void primitive_set_slot(void)
{
F_FIXNUM slot = untag_fixnum_fast(dpop());
CELL obj = UNTAG(dpop());
CELL value = dpop();
put(SLOT(obj,slot),value);
write_barrier(obj);
}
void primitive_integer_slot(void)
{
F_FIXNUM slot = untag_fixnum_fast(dpop());
CELL obj = UNTAG(dpop());
dpush(tag_integer(get(SLOT(obj,slot))));
}
void primitive_set_integer_slot(void)
{
F_FIXNUM slot = untag_fixnum_fast(dpop());
CELL obj = UNTAG(dpop());
F_FIXNUM value = to_fixnum(dpop());
put(SLOT(obj,slot),value);
}
void primitive_address(void)
{
drepl(tag_bignum(s48_cell_to_bignum(dpeek())));
}
void primitive_size(void)
{
drepl(tag_fixnum(object_size(dpeek())));
}
CELL clone(CELL obj)
{
CELL size = object_size(obj);
CELL tag = TAG(obj);
void *new_obj = allot(size);
return RETAG(memcpy(new_obj,(void*)UNTAG(obj),size),tag);
}
void primitive_clone(void)
{
maybe_gc(0);
drepl(clone(dpeek()));
}
void primitive_room(void)
{
CELL list = F;
int gen;
box_unsigned_cell(compiling.limit - compiling.here);
box_unsigned_cell(compiling.limit - compiling.base);
box_unsigned_cell(cards_end - cards);
box_unsigned_cell(prior.limit - prior.base);
for(gen = gen_count - 1; gen >= 0; gen--)
{
ZONE *z = &generations[gen];
list = cons(cons(tag_cell(z->limit - z->here),
tag_cell(z->limit - z->base)),
list);
}
dpush(list);
}
void primitive_begin_scan(void)
{
garbage_collection(TENURED);
heap_scan_ptr = tenured.base;
heap_scan = true;
}
void primitive_next_object(void)
{
CELL value = get(heap_scan_ptr);
CELL obj = heap_scan_ptr;
CELL size, type;
if(!heap_scan)
general_error(ERROR_HEAP_SCAN,F,true);
if(heap_scan_ptr >= tenured.here)
{
dpush(F);
return;
}
if(headerp(value))
{
size = align8(untagged_object_size(heap_scan_ptr));
type = untag_header(value);
}
else
{
size = CELLS * 2;
type = CONS_TYPE;
}
heap_scan_ptr += size;
if(type < HEADER_TYPE)
dpush(RETAG(obj,type));
else
dpush(RETAG(obj,OBJECT_TYPE));
}
void primitive_end_scan(void)
{
heap_scan = false;
}