Merge optimizations from master branch
commit
b2ba465bcd
|
@ -271,10 +271,10 @@ ERROR: integer-length-expected obj ;
|
||||||
dup integer? [ integer-length-expected ] unless ; inline
|
dup integer? [ integer-length-expected ] unless ; inline
|
||||||
|
|
||||||
TUPLE: copy-state
|
TUPLE: copy-state
|
||||||
{ src-i integer read-only }
|
{ src-i read-only }
|
||||||
{ src sequence read-only }
|
{ src read-only }
|
||||||
{ dst-i integer read-only }
|
{ dst-i read-only }
|
||||||
{ dst sequence read-only } ;
|
{ dst read-only } ;
|
||||||
|
|
||||||
C: <copy> copy-state
|
C: <copy> copy-state
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
namespace factor
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It is up to the caller to fill in the object's fields in a meaningful
|
||||||
|
* fashion!
|
||||||
|
*/
|
||||||
|
inline object *factor_vm::allot_object(header header, cell size)
|
||||||
|
{
|
||||||
|
/* If the object is smaller than the nursery, allocate it in the nursery,
|
||||||
|
after a GC if needed */
|
||||||
|
if(nursery.size > size)
|
||||||
|
{
|
||||||
|
/* If there is insufficient room, collect the nursery */
|
||||||
|
if(nursery.here + size > nursery.end)
|
||||||
|
primitive_minor_gc();
|
||||||
|
|
||||||
|
object *obj = nursery.allot(size);
|
||||||
|
|
||||||
|
obj->h = header;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
/* If the object is bigger than the nursery, allocate it in
|
||||||
|
tenured space */
|
||||||
|
else
|
||||||
|
return allot_large_object(header,size);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,17 +8,7 @@ array *factor_vm::allot_array(cell capacity, cell fill_)
|
||||||
{
|
{
|
||||||
gc_root<object> fill(fill_,this);
|
gc_root<object> fill(fill_,this);
|
||||||
gc_root<array> new_array(allot_uninitialized_array<array>(capacity),this);
|
gc_root<array> new_array(allot_uninitialized_array<array>(capacity),this);
|
||||||
|
memset_cell(new_array->data(),fill.value(),capacity * sizeof(cell));
|
||||||
if(fill.value() == tag_fixnum(0))
|
|
||||||
memset(new_array->data(),'\0',capacity * sizeof(cell));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* No need for write barrier here. Either the object is in
|
|
||||||
the nursery, or it was allocated directly in tenured space
|
|
||||||
and the write barrier is already hit for us in that case. */
|
|
||||||
for(cell i = 0; i < capacity; i++)
|
|
||||||
new_array->data()[i] = fill.value();
|
|
||||||
}
|
|
||||||
return new_array.untagged();
|
return new_array.untagged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,10 @@ cell factor_vm::search_lookup_hash(cell table, cell klass, cell hashcode)
|
||||||
{
|
{
|
||||||
array *buckets = untag<array>(table);
|
array *buckets = untag<array>(table);
|
||||||
cell bucket = array_nth(buckets,hashcode & (array_capacity(buckets) - 1));
|
cell bucket = array_nth(buckets,hashcode & (array_capacity(buckets) - 1));
|
||||||
if(tagged<object>(bucket).type_p(WORD_TYPE) || !to_boolean(bucket))
|
if(TAG(bucket) == ARRAY_TYPE)
|
||||||
return bucket;
|
|
||||||
else
|
|
||||||
return search_lookup_alist(bucket,klass);
|
return search_lookup_alist(bucket,klass);
|
||||||
|
else
|
||||||
|
return bucket;
|
||||||
}
|
}
|
||||||
|
|
||||||
cell factor_vm::nth_superclass(tuple_layout *layout, fixnum echelon)
|
cell factor_vm::nth_superclass(tuple_layout *layout, fixnum echelon)
|
||||||
|
@ -46,9 +46,7 @@ cell factor_vm::lookup_tuple_method(cell obj, cell methods)
|
||||||
|
|
||||||
array *echelons = untag<array>(methods);
|
array *echelons = untag<array>(methods);
|
||||||
|
|
||||||
fixnum echelon = untag_fixnum(layout->echelon);
|
fixnum echelon = std::min(untag_fixnum(layout->echelon),(fixnum)array_capacity(echelons) - 1);
|
||||||
fixnum max_echelon = array_capacity(echelons) - 1;
|
|
||||||
if(echelon > max_echelon) echelon = max_echelon;
|
|
||||||
|
|
||||||
while(echelon >= 0)
|
while(echelon >= 0)
|
||||||
{
|
{
|
||||||
|
@ -82,35 +80,27 @@ cell factor_vm::lookup_hi_tag_method(cell obj, cell methods)
|
||||||
return array_nth(hi_tag_methods,tag);
|
return array_nth(hi_tag_methods,tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
cell factor_vm::lookup_hairy_method(cell obj, cell methods)
|
|
||||||
{
|
|
||||||
cell method = array_nth(untag<array>(methods),TAG(obj));
|
|
||||||
if(tagged<object>(method).type_p(WORD_TYPE))
|
|
||||||
return method;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch(TAG(obj))
|
|
||||||
{
|
|
||||||
case TUPLE_TYPE:
|
|
||||||
return lookup_tuple_method(obj,method);
|
|
||||||
break;
|
|
||||||
case OBJECT_TYPE:
|
|
||||||
return lookup_hi_tag_method(obj,method);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
critical_error("Bad methods array",methods);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cell factor_vm::lookup_method(cell obj, cell methods)
|
cell factor_vm::lookup_method(cell obj, cell methods)
|
||||||
{
|
{
|
||||||
cell tag = TAG(obj);
|
cell tag = TAG(obj);
|
||||||
if(tag == TUPLE_TYPE || tag == OBJECT_TYPE)
|
cell method = array_nth(untag<array>(methods),tag);
|
||||||
return lookup_hairy_method(obj,methods);
|
|
||||||
|
if(tag == TUPLE_TYPE)
|
||||||
|
{
|
||||||
|
if(TAG(method) == ARRAY_TYPE)
|
||||||
|
return lookup_tuple_method(obj,method);
|
||||||
else
|
else
|
||||||
return array_nth(untag<array>(methods),TAG(obj));
|
return method;
|
||||||
|
}
|
||||||
|
else if(tag == OBJECT_TYPE)
|
||||||
|
{
|
||||||
|
if(TAG(method) == ARRAY_TYPE)
|
||||||
|
return lookup_hi_tag_method(obj,method);
|
||||||
|
else
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
void factor_vm::primitive_lookup_method()
|
void factor_vm::primitive_lookup_method()
|
||||||
|
|
24
vm/gc.cpp
24
vm/gc.cpp
|
@ -271,26 +271,7 @@ VM_C_API void inline_gc(cell *gc_roots_base, cell gc_roots_size, factor_vm *pare
|
||||||
* It is up to the caller to fill in the object's fields in a meaningful
|
* It is up to the caller to fill in the object's fields in a meaningful
|
||||||
* fashion!
|
* fashion!
|
||||||
*/
|
*/
|
||||||
object *factor_vm::allot_object(header header, cell size)
|
object *factor_vm::allot_large_object(header header, cell size)
|
||||||
{
|
|
||||||
#ifdef GC_DEBUG
|
|
||||||
if(!gc_off)
|
|
||||||
primitive_full_gc();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
object *obj;
|
|
||||||
|
|
||||||
/* If the object is smaller than the nursery, allocate it in the nursery,
|
|
||||||
after a GC if needed */
|
|
||||||
if(size < nursery.size)
|
|
||||||
{
|
|
||||||
/* If there is insufficient room, collect the nursery */
|
|
||||||
if(nursery.here + size > nursery.end)
|
|
||||||
primitive_minor_gc();
|
|
||||||
|
|
||||||
obj = nursery.allot(size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
/* If tenured space does not have enough room, collect and compact */
|
/* If tenured space does not have enough room, collect and compact */
|
||||||
if(!data->tenured->can_allot_p(size))
|
if(!data->tenured->can_allot_p(size))
|
||||||
|
@ -306,7 +287,7 @@ object *factor_vm::allot_object(header header, cell size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = data->tenured->allot(size);
|
object *obj = data->tenured->allot(size);
|
||||||
|
|
||||||
/* Allows initialization code to store old->new pointers
|
/* Allows initialization code to store old->new pointers
|
||||||
without hitting the write barrier in the common case of
|
without hitting the write barrier in the common case of
|
||||||
|
@ -314,7 +295,6 @@ object *factor_vm::allot_object(header header, cell size)
|
||||||
char *start = (char *)obj;
|
char *start = (char *)obj;
|
||||||
for(cell offset = 0; offset < size; offset += card_size)
|
for(cell offset = 0; offset < size; offset += card_size)
|
||||||
write_barrier((cell *)(start + offset));
|
write_barrier((cell *)(start + offset));
|
||||||
}
|
|
||||||
|
|
||||||
obj->h = header;
|
obj->h = header;
|
||||||
return obj;
|
return obj;
|
||||||
|
|
|
@ -71,6 +71,7 @@ namespace factor
|
||||||
#include "alien.hpp"
|
#include "alien.hpp"
|
||||||
#include "callbacks.hpp"
|
#include "callbacks.hpp"
|
||||||
#include "vm.hpp"
|
#include "vm.hpp"
|
||||||
|
#include "allot.hpp"
|
||||||
#include "tagged.hpp"
|
#include "tagged.hpp"
|
||||||
#include "local_roots.hpp"
|
#include "local_roots.hpp"
|
||||||
#include "slot_visitor.hpp"
|
#include "slot_visitor.hpp"
|
||||||
|
|
18
vm/math.cpp
18
vm/math.cpp
|
@ -231,21 +231,9 @@ void factor_vm::primitive_byte_array_to_bignum()
|
||||||
drepl(tag<bignum>(result));
|
drepl(tag<bignum>(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
cell factor_vm::unbox_array_size()
|
cell factor_vm::unbox_array_size_slow()
|
||||||
{
|
{
|
||||||
switch(tagged<object>(dpeek()).type())
|
if(tagged<object>(dpeek()).type() == BIGNUM_TYPE)
|
||||||
{
|
|
||||||
case FIXNUM_TYPE:
|
|
||||||
{
|
|
||||||
fixnum n = untag_fixnum(dpeek());
|
|
||||||
if(n >= 0 && n < (fixnum)array_size_max)
|
|
||||||
{
|
|
||||||
dpop();
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BIGNUM_TYPE:
|
|
||||||
{
|
{
|
||||||
bignum *zero = untag<bignum>(bignum_zero);
|
bignum *zero = untag<bignum>(bignum_zero);
|
||||||
bignum *max = cell_to_bignum(array_size_max);
|
bignum *max = cell_to_bignum(array_size_max);
|
||||||
|
@ -256,8 +244,6 @@ cell factor_vm::unbox_array_size()
|
||||||
dpop();
|
dpop();
|
||||||
return bignum_to_cell(n);
|
return bignum_to_cell(n);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
general_error(ERROR_ARRAY_SIZE,dpop(),tag_fixnum(array_size_max),NULL);
|
general_error(ERROR_ARRAY_SIZE,dpop(),tag_fixnum(array_size_max),NULL);
|
||||||
|
|
16
vm/math.hpp
16
vm/math.hpp
|
@ -58,7 +58,21 @@ inline double factor_vm::fixnum_to_float(cell tagged)
|
||||||
return (double)untag_fixnum(tagged);
|
return (double)untag_fixnum(tagged);
|
||||||
}
|
}
|
||||||
|
|
||||||
// defined in assembler
|
inline cell factor_vm::unbox_array_size()
|
||||||
|
{
|
||||||
|
cell obj = dpeek();
|
||||||
|
if(TAG(obj) == FIXNUM_TYPE)
|
||||||
|
{
|
||||||
|
fixnum n = untag_fixnum(obj);
|
||||||
|
if(n >= 0 && n < (fixnum)array_size_max)
|
||||||
|
{
|
||||||
|
dpop();
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return unbox_array_size_slow();
|
||||||
|
}
|
||||||
|
|
||||||
VM_C_API void box_float(float flo, factor_vm *vm);
|
VM_C_API void box_float(float flo, factor_vm *vm);
|
||||||
VM_C_API float to_float(cell value, factor_vm *vm);
|
VM_C_API float to_float(cell value, factor_vm *vm);
|
||||||
|
|
|
@ -3,34 +3,29 @@
|
||||||
namespace factor
|
namespace factor
|
||||||
{
|
{
|
||||||
|
|
||||||
/* push a new tuple on the stack */
|
/* push a new tuple on the stack, filling its slots with f */
|
||||||
tuple *factor_vm::allot_tuple(cell layout_)
|
|
||||||
{
|
|
||||||
gc_root<tuple_layout> layout(layout_,this);
|
|
||||||
gc_root<tuple> t(allot<tuple>(tuple_size(layout.untagged())),this);
|
|
||||||
t->layout = layout.value();
|
|
||||||
return t.untagged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void factor_vm::primitive_tuple()
|
void factor_vm::primitive_tuple()
|
||||||
{
|
{
|
||||||
gc_root<tuple_layout> layout(dpop(),this);
|
gc_root<tuple_layout> layout(dpop(),this);
|
||||||
tuple *t = allot_tuple(layout.value());
|
tagged<tuple> t(allot<tuple>(tuple_size(layout.untagged())));
|
||||||
fixnum i;
|
t->layout = layout.value();
|
||||||
for(i = tuple_size(layout.untagged()) - 1; i >= 0; i--)
|
|
||||||
t->data()[i] = false_object;
|
|
||||||
|
|
||||||
dpush(tag<tuple>(t));
|
memset_cell(t->data(),false_object,tuple_size(layout.untagged()) - sizeof(cell));
|
||||||
|
|
||||||
|
dpush(t.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push a new tuple on the stack, filling its slots from the stack */
|
/* push a new tuple on the stack, filling its slots from the stack */
|
||||||
void factor_vm::primitive_tuple_boa()
|
void factor_vm::primitive_tuple_boa()
|
||||||
{
|
{
|
||||||
gc_root<tuple_layout> layout(dpop(),this);
|
gc_root<tuple_layout> layout(dpop(),this);
|
||||||
gc_root<tuple> t(allot_tuple(layout.value()),this);
|
tagged<tuple> t(allot<tuple>(tuple_size(layout.untagged())));
|
||||||
|
t->layout = layout.value();
|
||||||
|
|
||||||
cell size = untag_fixnum(layout.untagged()->size) * sizeof(cell);
|
cell size = untag_fixnum(layout.untagged()->size) * sizeof(cell);
|
||||||
memcpy(t->data(),(cell *)(ds - (size - sizeof(cell))),size);
|
memcpy(t->data(),(cell *)(ds - size + sizeof(cell)),size);
|
||||||
ds -= size;
|
ds -= size;
|
||||||
|
|
||||||
dpush(t.value());
|
dpush(t.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,31 @@
|
||||||
namespace factor
|
namespace factor
|
||||||
{
|
{
|
||||||
vm_char *safe_strdup(const vm_char *str);
|
|
||||||
void print_cell_hex_pad(cell x);
|
inline static void memset_cell(void *dst, cell pattern, size_t size)
|
||||||
cell read_cell_hex();
|
{
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#ifdef FACTOR_64
|
||||||
|
memset_pattern8(dst,&pattern,size);
|
||||||
|
#else
|
||||||
|
memset_pattern4(dst,&pattern,size);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
if(pattern == 0)
|
||||||
|
memset(dst,0,size);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cell *start = (cell *)dst;
|
||||||
|
cell *end = (cell *)((cell)dst + size);
|
||||||
|
while(start < end)
|
||||||
|
{
|
||||||
|
*start = pattern;
|
||||||
|
start++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_char *safe_strdup(const vm_char *str);
|
||||||
|
cell read_cell_hex();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -257,9 +257,10 @@ struct factor_vm
|
||||||
void primitive_compact_gc();
|
void primitive_compact_gc();
|
||||||
void primitive_become();
|
void primitive_become();
|
||||||
void inline_gc(cell *gc_roots_base, cell gc_roots_size);
|
void inline_gc(cell *gc_roots_base, cell gc_roots_size);
|
||||||
object *allot_object(header header, cell size);
|
|
||||||
void primitive_enable_gc_events();
|
void primitive_enable_gc_events();
|
||||||
void primitive_disable_gc_events();
|
void primitive_disable_gc_events();
|
||||||
|
object *allot_object(header header, cell size);
|
||||||
|
object *allot_large_object(header header, cell size);
|
||||||
|
|
||||||
template<typename Type> Type *allot(cell size)
|
template<typename Type> Type *allot(cell size)
|
||||||
{
|
{
|
||||||
|
@ -345,7 +346,6 @@ struct factor_vm
|
||||||
template<typename T> byte_array *byte_array_from_values(T *values, cell len);
|
template<typename T> byte_array *byte_array_from_values(T *values, cell len);
|
||||||
|
|
||||||
//tuples
|
//tuples
|
||||||
tuple *allot_tuple(cell layout_);
|
|
||||||
void primitive_tuple();
|
void primitive_tuple();
|
||||||
void primitive_tuple_boa();
|
void primitive_tuple_boa();
|
||||||
|
|
||||||
|
@ -392,7 +392,8 @@ struct factor_vm
|
||||||
void primitive_bignum_log2();
|
void primitive_bignum_log2();
|
||||||
unsigned int bignum_producer(unsigned int digit);
|
unsigned int bignum_producer(unsigned int digit);
|
||||||
void primitive_byte_array_to_bignum();
|
void primitive_byte_array_to_bignum();
|
||||||
cell unbox_array_size();
|
inline cell unbox_array_size();
|
||||||
|
cell unbox_array_size_slow();
|
||||||
void primitive_fixnum_to_float();
|
void primitive_fixnum_to_float();
|
||||||
void primitive_bignum_to_float();
|
void primitive_bignum_to_float();
|
||||||
void primitive_str_to_float();
|
void primitive_str_to_float();
|
||||||
|
@ -610,7 +611,6 @@ struct factor_vm
|
||||||
cell nth_hashcode(tuple_layout *layout, fixnum echelon);
|
cell nth_hashcode(tuple_layout *layout, fixnum echelon);
|
||||||
cell lookup_tuple_method(cell obj, cell methods);
|
cell lookup_tuple_method(cell obj, cell methods);
|
||||||
cell lookup_hi_tag_method(cell obj, cell methods);
|
cell lookup_hi_tag_method(cell obj, cell methods);
|
||||||
cell lookup_hairy_method(cell obj, cell methods);
|
|
||||||
cell lookup_method(cell obj, cell methods);
|
cell lookup_method(cell obj, cell methods);
|
||||||
void primitive_lookup_method();
|
void primitive_lookup_method();
|
||||||
cell object_class(cell obj);
|
cell object_class(cell obj);
|
||||||
|
|
Loading…
Reference in New Issue