New identity-hashcode primitive
parent
4162ee2127
commit
064c00f78d
|
@ -71,6 +71,9 @@ C: <eq-wrapper> eq-wrapper
|
||||||
M: eq-wrapper equal?
|
M: eq-wrapper equal?
|
||||||
over eq-wrapper? [ [ obj>> ] bi@ eq? ] [ 2drop f ] if ;
|
over eq-wrapper? [ [ obj>> ] bi@ eq? ] [ 2drop f ] if ;
|
||||||
|
|
||||||
|
M: eq-wrapper hashcode*
|
||||||
|
nip obj>> identity-hashcode ;
|
||||||
|
|
||||||
SYMBOL: objects
|
SYMBOL: objects
|
||||||
|
|
||||||
: cache-eql-object ( obj quot -- value )
|
: cache-eql-object ( obj quot -- value )
|
||||||
|
@ -224,9 +227,11 @@ USERENV: undefined-quot 60
|
||||||
|
|
||||||
: emit-fixnum ( n -- ) tag-fixnum emit ;
|
: emit-fixnum ( n -- ) tag-fixnum emit ;
|
||||||
|
|
||||||
|
: emit-header ( n -- ) tag-header emit ;
|
||||||
|
|
||||||
: emit-object ( class quot -- addr )
|
: emit-object ( class quot -- addr )
|
||||||
[ type-number ] dip over here-as
|
[ type-number ] dip over here-as
|
||||||
[ swap tag-fixnum emit call align-here ] dip ;
|
[ swap emit-header call align-here ] dip ;
|
||||||
inline
|
inline
|
||||||
|
|
||||||
! Write an object to the image.
|
! Write an object to the image.
|
||||||
|
@ -234,7 +239,7 @@ GENERIC: ' ( obj -- ptr )
|
||||||
|
|
||||||
! Image header
|
! Image header
|
||||||
|
|
||||||
: emit-header ( -- )
|
: emit-image-header ( -- )
|
||||||
image-magic emit
|
image-magic emit
|
||||||
image-version emit
|
image-version emit
|
||||||
data-base emit ! relocation base at end of header
|
data-base emit ! relocation base at end of header
|
||||||
|
@ -518,7 +523,7 @@ M: quotation '
|
||||||
: build-image ( -- image )
|
: build-image ( -- image )
|
||||||
800000 <vector> image set
|
800000 <vector> image set
|
||||||
20000 <hashtable> objects set
|
20000 <hashtable> objects set
|
||||||
emit-header t, 0, 1, -1,
|
emit-image-header t, 0, 1, -1,
|
||||||
"Building generic words..." print flush
|
"Building generic words..." print flush
|
||||||
remake-generics
|
remake-generics
|
||||||
"Serializing words..." print flush
|
"Serializing words..." print flush
|
||||||
|
|
|
@ -4,20 +4,16 @@ USING: kernel math vectors arrays accessors namespaces ;
|
||||||
IN: compiler.cfg
|
IN: compiler.cfg
|
||||||
|
|
||||||
TUPLE: basic-block < identity-tuple
|
TUPLE: basic-block < identity-tuple
|
||||||
{ id integer }
|
|
||||||
number
|
number
|
||||||
{ instructions vector }
|
{ instructions vector }
|
||||||
{ successors vector }
|
{ successors vector }
|
||||||
{ predecessors vector } ;
|
{ predecessors vector } ;
|
||||||
|
|
||||||
M: basic-block hashcode* nip id>> ;
|
|
||||||
|
|
||||||
: <basic-block> ( -- bb )
|
: <basic-block> ( -- bb )
|
||||||
basic-block new
|
basic-block new
|
||||||
V{ } clone >>instructions
|
V{ } clone >>instructions
|
||||||
V{ } clone >>successors
|
V{ } clone >>successors
|
||||||
V{ } clone >>predecessors
|
V{ } clone >>predecessors ;
|
||||||
\ basic-block counter >>id ;
|
|
||||||
|
|
||||||
TUPLE: cfg { entry basic-block } word label
|
TUPLE: cfg { entry basic-block } word label
|
||||||
spill-area-size reps
|
spill-area-size reps
|
||||||
|
|
|
@ -27,6 +27,9 @@ C: <reference> reference-expr
|
||||||
M: reference-expr equal?
|
M: reference-expr equal?
|
||||||
over reference-expr? [ [ value>> ] bi@ eq? ] [ 2drop f ] if ;
|
over reference-expr? [ [ value>> ] bi@ eq? ] [ 2drop f ] if ;
|
||||||
|
|
||||||
|
M: reference-expr hashcode*
|
||||||
|
nip value>> identity-hashcode ;
|
||||||
|
|
||||||
: constant>vn ( constant -- vn ) <constant> expr>vn ; inline
|
: constant>vn ( constant -- vn ) <constant> expr>vn ; inline
|
||||||
|
|
||||||
GENERIC: >expr ( insn -- expr )
|
GENERIC: >expr ( insn -- expr )
|
||||||
|
|
|
@ -10,8 +10,6 @@ IN: compiler.tree
|
||||||
|
|
||||||
TUPLE: node < identity-tuple ;
|
TUPLE: node < identity-tuple ;
|
||||||
|
|
||||||
M: node hashcode* drop node hashcode* ;
|
|
||||||
|
|
||||||
TUPLE: #introduce < node out-d ;
|
TUPLE: #introduce < node out-d ;
|
||||||
|
|
||||||
: #introduce ( out-d -- node )
|
: #introduce ( out-d -- node )
|
||||||
|
|
|
@ -373,7 +373,7 @@ M: ppc %set-alien-double -rot STFD ;
|
||||||
scratch-reg nursery-ptr 0 STW ;
|
scratch-reg nursery-ptr 0 STW ;
|
||||||
|
|
||||||
:: store-header ( dst class -- )
|
:: store-header ( dst class -- )
|
||||||
class type-number tag-fixnum scratch-reg LI
|
class type-number tag-header scratch-reg LI
|
||||||
scratch-reg dst 0 STW ;
|
scratch-reg dst 0 STW ;
|
||||||
|
|
||||||
: store-tagged ( dst tag -- )
|
: store-tagged ( dst tag -- )
|
||||||
|
|
|
@ -430,7 +430,7 @@ M: x86 %vm-field-ptr ( dst field -- )
|
||||||
[ [] ] dip data-alignment get align ADD ;
|
[ [] ] dip data-alignment get align ADD ;
|
||||||
|
|
||||||
: store-header ( temp class -- )
|
: store-header ( temp class -- )
|
||||||
[ [] ] [ type-number tag-fixnum ] bi* MOV ;
|
[ [] ] [ type-number tag-header ] bi* MOV ;
|
||||||
|
|
||||||
: store-tagged ( dst tag -- )
|
: store-tagged ( dst tag -- )
|
||||||
type-number OR ;
|
type-number OR ;
|
||||||
|
|
|
@ -82,8 +82,6 @@ SYMBOL: wait-flag
|
||||||
V{ } clone swap processes get set-at
|
V{ } clone swap processes get set-at
|
||||||
wait-flag get-global raise-flag ;
|
wait-flag get-global raise-flag ;
|
||||||
|
|
||||||
M: process hashcode* handle>> hashcode* ;
|
|
||||||
|
|
||||||
: pass-environment? ( process -- ? )
|
: pass-environment? ( process -- ? )
|
||||||
dup environment>> assoc-empty? not
|
dup environment>> assoc-empty? not
|
||||||
swap environment-mode>> +replace-environment+ eq? or ;
|
swap environment-mode>> +replace-environment+ eq? or ;
|
||||||
|
|
|
@ -17,8 +17,6 @@ value connections dependencies ref locked? ;
|
||||||
: <model> ( value -- model )
|
: <model> ( value -- model )
|
||||||
model new-model ;
|
model new-model ;
|
||||||
|
|
||||||
M: model hashcode* drop model hashcode* ;
|
|
||||||
|
|
||||||
: add-dependency ( dep model -- )
|
: add-dependency ( dep model -- )
|
||||||
dependencies>> push ;
|
dependencies>> push ;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ TUPLE: id obj ;
|
||||||
|
|
||||||
C: <id> id
|
C: <id> id
|
||||||
|
|
||||||
M: id hashcode* obj>> hashcode* ;
|
M: id hashcode* nip obj>> identity-hashcode ;
|
||||||
|
|
||||||
M: id equal? over id? [ [ obj>> ] bi@ eq? ] [ 2drop f ] if ;
|
M: id equal? over id? [ [ obj>> ] bi@ eq? ] [ 2drop f ] if ;
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,6 @@ fixed-point
|
||||||
introductions
|
introductions
|
||||||
loop? ;
|
loop? ;
|
||||||
|
|
||||||
M: inline-recursive hashcode* id>> hashcode* ;
|
|
||||||
|
|
||||||
: inlined-block? ( word -- ? ) "inlined-block" word-prop ;
|
: inlined-block? ( word -- ? ) "inlined-block" word-prop ;
|
||||||
|
|
||||||
: <inline-recursive> ( word -- label )
|
: <inline-recursive> ( word -- label )
|
||||||
|
|
|
@ -712,3 +712,5 @@ M: bad-executable summary
|
||||||
\ disable-gc-events { } { object } define-primitive
|
\ disable-gc-events { } { object } define-primitive
|
||||||
|
|
||||||
\ profiling { object } { } define-primitive
|
\ profiling { object } { } define-primitive
|
||||||
|
|
||||||
|
\ identity-hashcode { object } { fixnum } define-primitive
|
||||||
|
|
|
@ -37,14 +37,14 @@ GENERIC: (input-value?) ( value -- ? )
|
||||||
GENERIC: (literal) ( known -- literal )
|
GENERIC: (literal) ( known -- literal )
|
||||||
|
|
||||||
! Literal value
|
! Literal value
|
||||||
TUPLE: literal < identity-tuple value recursion hashcode ;
|
TUPLE: literal < identity-tuple value recursion ;
|
||||||
|
|
||||||
: literal ( value -- literal ) known (literal) ;
|
: literal ( value -- literal ) known (literal) ;
|
||||||
|
|
||||||
M: literal hashcode* nip hashcode>> ;
|
M: literal hashcode* nip value>> identity-hashcode ;
|
||||||
|
|
||||||
: <literal> ( obj -- value )
|
: <literal> ( obj -- value )
|
||||||
recursive-state get over hashcode \ literal boa ;
|
recursive-state get \ literal boa ;
|
||||||
|
|
||||||
M: literal (input-value?) drop f ;
|
M: literal (input-value?) drop f ;
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ M: literal (literal) ;
|
||||||
: curried/composed-literal ( input1 input2 quot -- literal )
|
: curried/composed-literal ( input1 input2 quot -- literal )
|
||||||
[ [ literal ] bi@ ] dip
|
[ [ literal ] bi@ ] dip
|
||||||
[ [ [ value>> ] bi@ ] dip call ] [ drop nip recursion>> ] 3bi
|
[ [ [ value>> ] bi@ ] dip call ] [ drop nip recursion>> ] 3bi
|
||||||
over hashcode \ literal boa ; inline
|
\ literal boa ; inline
|
||||||
|
|
||||||
! Result of curry
|
! Result of curry
|
||||||
TUPLE: curried obj quot ;
|
TUPLE: curried obj quot ;
|
||||||
|
|
|
@ -518,6 +518,7 @@ tuple
|
||||||
{ "<callback>" "alien" (( word -- alien )) }
|
{ "<callback>" "alien" (( word -- alien )) }
|
||||||
{ "enable-gc-events" "memory" (( -- )) }
|
{ "enable-gc-events" "memory" (( -- )) }
|
||||||
{ "disable-gc-events" "memory" (( -- events )) }
|
{ "disable-gc-events" "memory" (( -- events )) }
|
||||||
|
{ "identity-hashcode" "kernel" (( obj -- code )) }
|
||||||
} [ [ first3 ] dip swap make-primitive ] each-index
|
} [ [ first3 ] dip swap make-primitive ] each-index
|
||||||
|
|
||||||
! Bump build number
|
! Bump build number
|
||||||
|
|
|
@ -26,15 +26,11 @@ SLOT: continuation
|
||||||
PRIVATE>
|
PRIVATE>
|
||||||
|
|
||||||
TUPLE: disposable < identity-tuple
|
TUPLE: disposable < identity-tuple
|
||||||
{ id integer }
|
|
||||||
{ disposed boolean }
|
{ disposed boolean }
|
||||||
continuation ;
|
continuation ;
|
||||||
|
|
||||||
M: disposable hashcode* nip id>> ;
|
|
||||||
|
|
||||||
: new-disposable ( class -- disposable )
|
: new-disposable ( class -- disposable )
|
||||||
new \ disposable counter >>id
|
new dup register-disposable ; inline
|
||||||
dup register-disposable ; inline
|
|
||||||
|
|
||||||
GENERIC: dispose* ( disposable -- )
|
GENERIC: dispose* ( disposable -- )
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,8 @@ $nl
|
||||||
$nl
|
$nl
|
||||||
"In certain advanced applications, this cannot be avoided and the best design involves mutating hashtable keys. In this case, a custom " { $link hashcode* } " method must be defined which only depends on immutable slots."
|
"In certain advanced applications, this cannot be avoided and the best design involves mutating hashtable keys. In this case, a custom " { $link hashcode* } " method must be defined which only depends on immutable slots."
|
||||||
$nl
|
$nl
|
||||||
"In addition, the " { $link equal? } " and " { $link hashcode* } " methods must be congruent, and if one is defined the other should be defined also. This is documented in detail in the documentation for these respective words." ;
|
"In addition, the " { $link equal? } " and " { $link hashcode* } " methods must be congruent, and if one is defined the other should be defined also. This is documented in detail in the documentation for these respective words."
|
||||||
|
{ $subsections hashcode hashcode* identity-hashcode } ;
|
||||||
|
|
||||||
ARTICLE: "hashtables.utilities" "Hashtable utilities"
|
ARTICLE: "hashtables.utilities" "Hashtable utilities"
|
||||||
"Utility words to create a new hashtable from a single key/value pair:"
|
"Utility words to create a new hashtable from a single key/value pair:"
|
||||||
|
|
|
@ -72,7 +72,11 @@ HELP: hashcode
|
||||||
{ $values { "obj" object } { "code" fixnum } }
|
{ $values { "obj" object } { "code" fixnum } }
|
||||||
{ $description "Computes the hashcode of an object with a default hashing depth. See " { $link hashcode* } " for the hashcode contract." } ;
|
{ $description "Computes the hashcode of an object with a default hashing depth. See " { $link hashcode* } " for the hashcode contract." } ;
|
||||||
|
|
||||||
{ hashcode hashcode* } related-words
|
HELP: identity-hashcode
|
||||||
|
{ $values { "obj" object } { "code" fixnum } }
|
||||||
|
{ $description "Outputs the identity hashcode of an object. The identity hashcode is not guaranteed to be unique, however it will not change during the object's lifetime." } ;
|
||||||
|
|
||||||
|
{ hashcode hashcode* identity-hashcode } related-words
|
||||||
|
|
||||||
HELP: =
|
HELP: =
|
||||||
{ $values { "obj1" object } { "obj2" object } { "?" "a boolean" } }
|
{ $values { "obj1" object } { "obj2" object } { "?" "a boolean" } }
|
||||||
|
|
|
@ -169,3 +169,7 @@ IN: kernel.tests
|
||||||
[ 3 -1 5/6 ] [ 1 2 3 4 5 6 [ + ] [ - ] [ / ] 2tri* ] unit-test
|
[ 3 -1 5/6 ] [ 1 2 3 4 5 6 [ + ] [ - ] [ / ] 2tri* ] unit-test
|
||||||
|
|
||||||
[ { 1 2 } { 3 4 } { 5 6 } ] [ 1 2 3 4 5 6 [ 2array ] 2tri@ ] unit-test
|
[ { 1 2 } { 3 4 } { 5 6 } ] [ 1 2 3 4 5 6 [ 2array ] 2tri@ ] unit-test
|
||||||
|
|
||||||
|
[ t ] [ { } identity-hashcode fixnum? ] unit-test
|
||||||
|
[ 123 ] [ 123 identity-hashcode ] unit-test
|
||||||
|
[ t ] [ f identity-hashcode fixnum? ] unit-test
|
||||||
|
|
|
@ -200,6 +200,8 @@ TUPLE: identity-tuple ;
|
||||||
|
|
||||||
M: identity-tuple equal? 2drop f ; inline
|
M: identity-tuple equal? 2drop f ; inline
|
||||||
|
|
||||||
|
M: identity-tuple hashcode* nip identity-hashcode ; inline
|
||||||
|
|
||||||
: = ( obj1 obj2 -- ? )
|
: = ( obj1 obj2 -- ? )
|
||||||
2dup eq? [ 2drop t ] [
|
2dup eq? [ 2drop t ] [
|
||||||
2dup both-fixnums? [ 2drop f ] [ equal? ] if
|
2dup both-fixnums? [ 2drop f ] [ equal? ] if
|
||||||
|
|
|
@ -22,6 +22,9 @@ SYMBOL: mega-cache-size
|
||||||
: tag-fixnum ( n -- tagged )
|
: tag-fixnum ( n -- tagged )
|
||||||
tag-bits get shift ;
|
tag-bits get shift ;
|
||||||
|
|
||||||
|
: tag-header ( n -- tagged )
|
||||||
|
2 shift ;
|
||||||
|
|
||||||
: untag-fixnum ( n -- tagged )
|
: untag-fixnum ( n -- tagged )
|
||||||
tag-bits get neg shift ;
|
tag-bits get neg shift ;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace factor
|
||||||
* 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!
|
||||||
*/
|
*/
|
||||||
inline object *factor_vm::allot_object(header header, cell size)
|
inline object *factor_vm::allot_object(cell type, cell size)
|
||||||
{
|
{
|
||||||
/* If the object is smaller than the nursery, allocate it in the nursery,
|
/* If the object is smaller than the nursery, allocate it in the nursery,
|
||||||
after a GC if needed */
|
after a GC if needed */
|
||||||
|
@ -17,13 +17,13 @@ inline object *factor_vm::allot_object(header header, cell size)
|
||||||
|
|
||||||
object *obj = nursery.allot(size);
|
object *obj = nursery.allot(size);
|
||||||
|
|
||||||
obj->h = header;
|
obj->initialize(type);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
/* If the object is bigger than the nursery, allocate it in
|
/* If the object is bigger than the nursery, allocate it in
|
||||||
tenured space */
|
tenured space */
|
||||||
else
|
else
|
||||||
return allot_large_object(header,size);
|
return allot_large_object(type,size);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ template<typename Visitor> struct code_block_visitor {
|
||||||
|
|
||||||
void visit_object_code_block(object *obj)
|
void visit_object_code_block(object *obj)
|
||||||
{
|
{
|
||||||
switch(obj->h.hi_tag())
|
switch(obj->type())
|
||||||
{
|
{
|
||||||
case WORD_TYPE:
|
case WORD_TYPE:
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,11 +16,10 @@ template<typename TargetGeneration, typename Policy> struct collector_workhorse
|
||||||
parent->check_data_pointer(untagged);
|
parent->check_data_pointer(untagged);
|
||||||
|
|
||||||
/* is there another forwarding pointer? */
|
/* is there another forwarding pointer? */
|
||||||
while(untagged->h.forwarding_pointer_p())
|
while(untagged->forwarding_pointer_p())
|
||||||
untagged = untagged->h.forwarding_pointer();
|
untagged = untagged->forwarding_pointer();
|
||||||
|
|
||||||
/* we've found the destination */
|
/* we've found the destination */
|
||||||
untagged->h.check_header();
|
|
||||||
return untagged;
|
return untagged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +31,7 @@ template<typename TargetGeneration, typename Policy> struct collector_workhorse
|
||||||
if(!newpointer) longjmp(parent->current_gc->gc_unwind,1);
|
if(!newpointer) longjmp(parent->current_gc->gc_unwind,1);
|
||||||
|
|
||||||
memcpy(newpointer,untagged,size);
|
memcpy(newpointer,untagged,size);
|
||||||
untagged->h.forward_to(newpointer);
|
untagged->forward_to(newpointer);
|
||||||
|
|
||||||
policy.promoted_object(newpointer);
|
policy.promoted_object(newpointer);
|
||||||
|
|
||||||
|
@ -114,7 +113,7 @@ template<typename TargetGeneration, typename Policy> struct collector {
|
||||||
void trace_object(object *ptr)
|
void trace_object(object *ptr)
|
||||||
{
|
{
|
||||||
workhorse.visit_slots(ptr);
|
workhorse.visit_slots(ptr);
|
||||||
if(ptr->h.hi_tag() == ALIEN_TYPE)
|
if(ptr->type() == ALIEN_TYPE)
|
||||||
((alien *)ptr)->update_address();
|
((alien *)ptr)->update_address();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ struct compaction_sizer {
|
||||||
{
|
{
|
||||||
if(!forwarding_map->marked_p(obj))
|
if(!forwarding_map->marked_p(obj))
|
||||||
return forwarding_map->unmarked_block_size(obj);
|
return forwarding_map->unmarked_block_size(obj);
|
||||||
else if(obj->h.hi_tag() == TUPLE_TYPE)
|
else if(obj->type() == TUPLE_TYPE)
|
||||||
return align(tuple_size_with_forwarding(forwarding_map,obj),data_alignment);
|
return align(tuple_size_with_forwarding(forwarding_map,obj),data_alignment);
|
||||||
else
|
else
|
||||||
return obj->size();
|
return obj->size();
|
||||||
|
@ -72,7 +72,7 @@ struct object_compaction_updater {
|
||||||
void operator()(object *old_address, object *new_address, cell size)
|
void operator()(object *old_address, object *new_address, cell size)
|
||||||
{
|
{
|
||||||
cell payload_start;
|
cell payload_start;
|
||||||
if(old_address->h.hi_tag() == TUPLE_TYPE)
|
if(old_address->type() == TUPLE_TYPE)
|
||||||
payload_start = tuple_size_with_forwarding(data_forwarding_map,old_address);
|
payload_start = tuple_size_with_forwarding(data_forwarding_map,old_address);
|
||||||
else
|
else
|
||||||
payload_start = old_address->binary_payload_start();
|
payload_start = old_address->binary_payload_start();
|
||||||
|
|
|
@ -126,7 +126,7 @@ cell object::size() const
|
||||||
{
|
{
|
||||||
if(free_p()) return ((free_heap_block *)this)->size();
|
if(free_p()) return ((free_heap_block *)this)->size();
|
||||||
|
|
||||||
switch(h.hi_tag())
|
switch(type())
|
||||||
{
|
{
|
||||||
case ARRAY_TYPE:
|
case ARRAY_TYPE:
|
||||||
return align(array_size((array*)this),data_alignment);
|
return align(array_size((array*)this),data_alignment);
|
||||||
|
@ -166,7 +166,7 @@ the GC. Some types have a binary payload at the end (string, word, DLL) which
|
||||||
we ignore. */
|
we ignore. */
|
||||||
cell object::binary_payload_start() const
|
cell object::binary_payload_start() const
|
||||||
{
|
{
|
||||||
switch(h.hi_tag())
|
switch(type())
|
||||||
{
|
{
|
||||||
/* these objects do not refer to other objects at all */
|
/* these objects do not refer to other objects at all */
|
||||||
case FLOAT_TYPE:
|
case FLOAT_TYPE:
|
||||||
|
@ -234,7 +234,7 @@ struct object_accumulator {
|
||||||
|
|
||||||
void operator()(object *obj)
|
void operator()(object *obj)
|
||||||
{
|
{
|
||||||
if(type == TYPE_COUNT || obj->h.hi_tag() == type)
|
if(type == TYPE_COUNT || obj->type() == type)
|
||||||
objects.push_back(tag_dynamic(obj));
|
objects.push_back(tag_dynamic(obj));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -243,7 +243,7 @@ struct object_dumper {
|
||||||
|
|
||||||
void operator()(object *obj)
|
void operator()(object *obj)
|
||||||
{
|
{
|
||||||
if(type == TYPE_COUNT || obj->h.hi_tag() == type)
|
if(type == TYPE_COUNT || obj->type() == type)
|
||||||
{
|
{
|
||||||
std::cout << padded_address((cell)obj) << " ";
|
std::cout << padded_address((cell)obj) << " ";
|
||||||
parent->print_nested_obj(tag_dynamic(obj),2);
|
parent->print_nested_obj(tag_dynamic(obj),2);
|
||||||
|
|
|
@ -234,7 +234,7 @@ VM_C_API void inline_gc(cell *data_roots_base, cell data_roots_size, factor_vm *
|
||||||
* 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_large_object(header header, cell size)
|
object *factor_vm::allot_large_object(cell type, cell size)
|
||||||
{
|
{
|
||||||
/* 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))
|
||||||
|
@ -257,7 +257,7 @@ object *factor_vm::allot_large_object(header header, cell size)
|
||||||
a nursery allocation */
|
a nursery allocation */
|
||||||
write_barrier(obj,size);
|
write_barrier(obj,size);
|
||||||
|
|
||||||
obj->h = header;
|
obj->initialize(type);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,12 +135,12 @@ void factor_vm::relocate_object(object *object,
|
||||||
cell data_relocation_base,
|
cell data_relocation_base,
|
||||||
cell code_relocation_base)
|
cell code_relocation_base)
|
||||||
{
|
{
|
||||||
cell hi_tag = object->h.hi_tag();
|
cell type = object->type();
|
||||||
|
|
||||||
/* Tuple relocation is a bit trickier; we have to fix up the
|
/* Tuple relocation is a bit trickier; we have to fix up the
|
||||||
layout object before we can get the tuple size, so do_slots is
|
layout object before we can get the tuple size, so do_slots is
|
||||||
out of the question */
|
out of the question */
|
||||||
if(hi_tag == TUPLE_TYPE)
|
if(type == TUPLE_TYPE)
|
||||||
{
|
{
|
||||||
tuple *t = (tuple *)object;
|
tuple *t = (tuple *)object;
|
||||||
data_fixup(&t->layout,data_relocation_base);
|
data_fixup(&t->layout,data_relocation_base);
|
||||||
|
@ -156,7 +156,7 @@ void factor_vm::relocate_object(object *object,
|
||||||
object_fixupper fixupper(this,data_relocation_base);
|
object_fixupper fixupper(this,data_relocation_base);
|
||||||
do_slots(object,fixupper);
|
do_slots(object,fixupper);
|
||||||
|
|
||||||
switch(hi_tag)
|
switch(type)
|
||||||
{
|
{
|
||||||
case WORD_TYPE:
|
case WORD_TYPE:
|
||||||
fixup_word((word *)object,code_relocation_base);
|
fixup_word((word *)object,code_relocation_base);
|
||||||
|
|
|
@ -51,8 +51,6 @@ static const cell data_alignment = 16;
|
||||||
|
|
||||||
#define TYPE_COUNT 14
|
#define TYPE_COUNT 14
|
||||||
|
|
||||||
#define FORWARDING_POINTER 5 /* can be anything other than FIXNUM_TYPE */
|
|
||||||
|
|
||||||
enum code_block_type
|
enum code_block_type
|
||||||
{
|
{
|
||||||
code_block_unoptimized,
|
code_block_unoptimized,
|
||||||
|
@ -95,59 +93,57 @@ inline static cell tag_fixnum(fixnum untagged)
|
||||||
|
|
||||||
struct object;
|
struct object;
|
||||||
|
|
||||||
struct header {
|
|
||||||
cell value;
|
|
||||||
|
|
||||||
/* Default ctor to make gcc 3.x happy */
|
|
||||||
explicit header() { abort(); }
|
|
||||||
|
|
||||||
explicit header(cell value_) : value(value_ << TAG_BITS) {}
|
|
||||||
|
|
||||||
void check_header() const
|
|
||||||
{
|
|
||||||
#ifdef FACTOR_DEBUG
|
|
||||||
assert(TAG(value) == FIXNUM_TYPE && untag_fixnum(value) < TYPE_COUNT);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
cell hi_tag() const
|
|
||||||
{
|
|
||||||
check_header();
|
|
||||||
return value >> TAG_BITS;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool forwarding_pointer_p() const
|
|
||||||
{
|
|
||||||
return TAG(value) == FORWARDING_POINTER;
|
|
||||||
}
|
|
||||||
|
|
||||||
object *forwarding_pointer() const
|
|
||||||
{
|
|
||||||
return (object *)UNTAG(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void forward_to(object *pointer)
|
|
||||||
{
|
|
||||||
value = RETAG(pointer,FORWARDING_POINTER);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#define NO_TYPE_CHECK static const cell type_number = TYPE_COUNT
|
#define NO_TYPE_CHECK static const cell type_number = TYPE_COUNT
|
||||||
|
|
||||||
struct object {
|
struct object {
|
||||||
NO_TYPE_CHECK;
|
NO_TYPE_CHECK;
|
||||||
header h;
|
cell header;
|
||||||
|
|
||||||
cell size() const;
|
cell size() const;
|
||||||
cell binary_payload_start() const;
|
cell binary_payload_start() const;
|
||||||
|
|
||||||
cell *slots() const { return (cell *)this; }
|
cell *slots() const { return (cell *)this; }
|
||||||
|
|
||||||
/* Only valid for objects in tenured space; must fast to free_heap_block
|
/* Only valid for objects in tenured space; must cast to free_heap_block
|
||||||
to do anything with it if its free */
|
to do anything with it if its free */
|
||||||
bool free_p() const
|
bool free_p() const
|
||||||
{
|
{
|
||||||
return (h.value & 1) == 1;
|
return (header & 1) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell type() const
|
||||||
|
{
|
||||||
|
return (header >> 2) & TAG_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initialize(cell type)
|
||||||
|
{
|
||||||
|
header = type << 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
cell hashcode() const
|
||||||
|
{
|
||||||
|
return (header >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_hashcode(cell hashcode)
|
||||||
|
{
|
||||||
|
header = (header & 0x3f) | (hashcode << 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool forwarding_pointer_p() const
|
||||||
|
{
|
||||||
|
return (header & 2) == 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
object *forwarding_pointer() const
|
||||||
|
{
|
||||||
|
return (object *)UNTAG(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
void forward_to(object *pointer)
|
||||||
|
{
|
||||||
|
header = ((cell)pointer | 2);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,23 @@ void factor_vm::primitive_set_special_object()
|
||||||
special_objects[e] = value;
|
special_objects[e] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void factor_vm::primitive_identity_hashcode()
|
||||||
|
{
|
||||||
|
cell tagged = dpeek();
|
||||||
|
if(immediate_p(tagged))
|
||||||
|
drepl(tagged & ~TAG_MASK);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
object *obj = untag<object>(tagged);
|
||||||
|
if(obj->hashcode() == 0)
|
||||||
|
{
|
||||||
|
/* Use megamorphic_cache_misses as a random source of randomness */
|
||||||
|
obj->set_hashcode(((cell)obj / block_granularity) ^ dispatch_stats.megamorphic_cache_hits);
|
||||||
|
}
|
||||||
|
drepl(tag_fixnum(obj->hashcode()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void factor_vm::primitive_set_slot()
|
void factor_vm::primitive_set_slot()
|
||||||
{
|
{
|
||||||
fixnum slot = untag_fixnum(dpop());
|
fixnum slot = untag_fixnum(dpop());
|
||||||
|
@ -36,8 +53,9 @@ cell factor_vm::clone_object(cell obj_)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cell size = object_size(obj.value());
|
cell size = object_size(obj.value());
|
||||||
object *new_obj = allot_object(header(obj.type()),size);
|
object *new_obj = allot_object(obj.type(),size);
|
||||||
memcpy(new_obj,obj.untagged(),size);
|
memcpy(new_obj,obj.untagged(),size);
|
||||||
|
new_obj->set_hashcode(0);
|
||||||
return tag_dynamic(new_obj);
|
return tag_dynamic(new_obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,6 +126,7 @@ PRIMITIVE_FORWARD(strip_stack_traces)
|
||||||
PRIMITIVE_FORWARD(callback)
|
PRIMITIVE_FORWARD(callback)
|
||||||
PRIMITIVE_FORWARD(enable_gc_events)
|
PRIMITIVE_FORWARD(enable_gc_events)
|
||||||
PRIMITIVE_FORWARD(disable_gc_events)
|
PRIMITIVE_FORWARD(disable_gc_events)
|
||||||
|
PRIMITIVE_FORWARD(identity_hashcode)
|
||||||
|
|
||||||
const primitive_type primitives[] = {
|
const primitive_type primitives[] = {
|
||||||
primitive_bignum_to_fixnum,
|
primitive_bignum_to_fixnum,
|
||||||
|
@ -288,6 +289,7 @@ const primitive_type primitives[] = {
|
||||||
primitive_callback,
|
primitive_callback,
|
||||||
primitive_enable_gc_events,
|
primitive_enable_gc_events,
|
||||||
primitive_disable_gc_events,
|
primitive_disable_gc_events,
|
||||||
|
primitive_identity_hashcode,
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ template<typename Type> cell tag(Type *value)
|
||||||
|
|
||||||
inline static cell tag_dynamic(object *value)
|
inline static cell tag_dynamic(object *value)
|
||||||
{
|
{
|
||||||
return RETAG(value,value->h.hi_tag());
|
return RETAG(value,value->type());
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
|
|
|
@ -121,6 +121,7 @@ struct factor_vm
|
||||||
// objects
|
// objects
|
||||||
void primitive_special_object();
|
void primitive_special_object();
|
||||||
void primitive_set_special_object();
|
void primitive_set_special_object();
|
||||||
|
void primitive_identity_hashcode();
|
||||||
cell object_size(cell tagged);
|
cell object_size(cell tagged);
|
||||||
cell clone_object(cell obj_);
|
cell clone_object(cell obj_);
|
||||||
void primitive_clone();
|
void primitive_clone();
|
||||||
|
@ -284,12 +285,12 @@ struct factor_vm
|
||||||
void inline_gc(cell *data_roots_base, cell data_roots_size);
|
void inline_gc(cell *data_roots_base, cell data_roots_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_object(cell type, cell size);
|
||||||
object *allot_large_object(header header, cell size);
|
object *allot_large_object(cell type, cell size);
|
||||||
|
|
||||||
template<typename Type> Type *allot(cell size)
|
template<typename Type> Type *allot(cell size)
|
||||||
{
|
{
|
||||||
return (Type *)allot_object(header(Type::type_number),size);
|
return (Type *)allot_object(Type::type_number,size);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void check_data_pointer(object *pointer)
|
inline void check_data_pointer(object *pointer)
|
||||||
|
|
Loading…
Reference in New Issue