Merge optimizations from master branch

db4
Slava Pestov 2009-10-31 03:02:19 -05:00
commit b2ba465bcd
11 changed files with 141 additions and 131 deletions

View File

@ -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

29
vm/allot.hpp Normal file
View File

@ -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);
}
}

View File

@ -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();
} }

View File

@ -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()

View File

@ -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;

View File

@ -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"

View File

@ -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);

View File

@ -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);

View File

@ -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());
} }

View File

@ -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();
} }

View File

@ -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);