Faster identity-hashcode primitive; fast path now opencoded by the compiler

db4
Slava Pestov 2009-11-11 00:50:57 -06:00
parent b551721dd9
commit 2afd7ce244
10 changed files with 56 additions and 19 deletions

View File

@ -33,6 +33,7 @@ IN: compiler.cfg.intrinsics
{ {
{ kernel.private:tag [ drop emit-tag ] } { kernel.private:tag [ drop emit-tag ] }
{ kernel.private:getenv [ emit-getenv ] } { kernel.private:getenv [ emit-getenv ] }
{ kernel.private:(identity-hashcode) [ drop emit-identity-hashcode ] }
{ math.private:both-fixnums? [ drop emit-both-fixnums? ] } { math.private:both-fixnums? [ drop emit-both-fixnums? ] }
{ math.private:fixnum+ [ drop emit-fixnum+ ] } { math.private:fixnum+ [ drop emit-fixnum+ ] }
{ math.private:fixnum- [ drop emit-fixnum- ] } { math.private:fixnum- [ drop emit-fixnum- ] }

View File

@ -1,9 +1,9 @@
! Copyright (C) 2008 Slava Pestov. ! Copyright (C) 2008 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: namespaces layouts sequences kernel USING: namespaces layouts sequences kernel math accessors
accessors compiler.tree.propagation.info compiler.tree.propagation.info compiler.cfg.stacks
compiler.cfg.stacks compiler.cfg.hats compiler.cfg.hats compiler.cfg.instructions
compiler.cfg.instructions compiler.cfg.utilities ; compiler.cfg.utilities ;
IN: compiler.cfg.intrinsics.misc IN: compiler.cfg.intrinsics.misc
: emit-tag ( -- ) : emit-tag ( -- )
@ -14,3 +14,9 @@ IN: compiler.cfg.intrinsics.misc
swap node-input-infos first literal>> swap node-input-infos first literal>>
[ ds-drop 0 ^^slot-imm ] [ ds-pop ^^offset>slot ^^slot ] if* [ ds-drop 0 ^^slot-imm ] [ ds-pop ^^offset>slot ^^slot ] if*
ds-push ; ds-push ;
: emit-identity-hashcode ( -- )
ds-pop tag-mask get bitnot ^^load-immediate ^^and 0 0 ^^slot-imm
hashcode-shift ^^shr-imm
^^tag-fixnum
ds-push ;

View File

@ -713,4 +713,6 @@ M: bad-executable summary
\ profiling { object } { } define-primitive \ profiling { object } { } define-primitive
\ identity-hashcode { object } { fixnum } define-primitive \ (identity-hashcode) { object } { fixnum } define-primitive
\ compute-identity-hashcode { object } { } define-primitive

View File

@ -30,3 +30,5 @@ H{
{ word 12 } { word 12 }
{ dll 13 } { dll 13 }
} type-numbers set } type-numbers set
2 header-bits set

View File

@ -518,7 +518,8 @@ 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 )) } { "(identity-hashcode)" "kernel.private" (( obj -- code )) }
{ "compute-identity-hashcode" "kernel.private" (( obj -- )) }
} [ [ first3 ] dip swap make-primitive ] each-index } [ [ first3 ] dip swap make-primitive ] each-index
! Bump build number ! Bump build number

View File

@ -192,6 +192,16 @@ M: f hashcode* 2drop 31337 ; inline
: hashcode ( obj -- code ) 3 swap hashcode* ; inline : hashcode ( obj -- code ) 3 swap hashcode* ; inline
: identity-hashcode ( obj -- code )
dup tag 0 eq? [
dup tag 1 eq? [ drop 0 ] [
dup (identity-hashcode) dup 0 eq? [
drop dup compute-identity-hashcode
(identity-hashcode)
] [ nip ] if
] if
] unless ; inline
GENERIC: equal? ( obj1 obj2 -- ? ) GENERIC: equal? ( obj1 obj2 -- ? )
M: object equal? 2drop f ; inline M: object equal? 2drop f ; inline

View File

@ -16,6 +16,8 @@ SYMBOL: type-numbers
SYMBOL: mega-cache-size SYMBOL: mega-cache-size
SYMBOL: header-bits
: type-number ( class -- n ) : type-number ( class -- n )
type-numbers get at ; type-numbers get at ;
@ -23,11 +25,14 @@ SYMBOL: mega-cache-size
tag-bits get shift ; tag-bits get shift ;
: tag-header ( n -- tagged ) : tag-header ( n -- tagged )
2 shift ; header-bits get shift ;
: untag-fixnum ( n -- tagged ) : untag-fixnum ( n -- tagged )
tag-bits get neg shift ; tag-bits get neg shift ;
: hashcode-shift ( -- n )
tag-bits get header-bits get + ;
! We do this in its own compilation unit so that they can be ! We do this in its own compilation unit so that they can be
! folded below ! folded below
<< <<

View File

@ -19,18 +19,21 @@ void factor_vm::primitive_set_special_object()
void factor_vm::primitive_identity_hashcode() void factor_vm::primitive_identity_hashcode()
{ {
cell tagged = dpeek(); cell tagged = dpeek();
if(immediate_p(tagged)) object *obj = untag<object>(tagged);
drepl(tagged & ~TAG_MASK); drepl(tag_fixnum(obj->hashcode()));
else }
{
object *obj = untag<object>(tagged); void factor_vm::compute_identity_hashcode(object *obj)
if(obj->hashcode() == 0) {
{ object_counter++;
/* Use megamorphic_cache_misses as a random source of randomness */ if(object_counter == 0) object_counter++;
obj->set_hashcode(((cell)obj / block_granularity) ^ dispatch_stats.megamorphic_cache_hits); obj->set_hashcode((cell)obj ^ object_counter);
} }
drepl(tag_fixnum(obj->hashcode()));
} void factor_vm::primitive_compute_identity_hashcode()
{
object *obj = untag<object>(dpop());
compute_identity_hashcode(obj);
} }
void factor_vm::primitive_set_slot() void factor_vm::primitive_set_slot()

View File

@ -127,6 +127,7 @@ 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) PRIMITIVE_FORWARD(identity_hashcode)
PRIMITIVE_FORWARD(compute_identity_hashcode)
const primitive_type primitives[] = { const primitive_type primitives[] = {
primitive_bignum_to_fixnum, primitive_bignum_to_fixnum,
@ -290,6 +291,7 @@ const primitive_type primitives[] = {
primitive_enable_gc_events, primitive_enable_gc_events,
primitive_disable_gc_events, primitive_disable_gc_events,
primitive_identity_hashcode, primitive_identity_hashcode,
primitive_compute_identity_hashcode,
}; };
} }

View File

@ -81,6 +81,9 @@ struct factor_vm
/* Number of entries in a polymorphic inline cache */ /* Number of entries in a polymorphic inline cache */
cell max_pic_size; cell max_pic_size;
/* Incrementing object counter for identity hashing */
cell object_counter;
// contexts // contexts
void reset_datastack(); void reset_datastack();
void reset_retainstack(); void reset_retainstack();
@ -122,6 +125,8 @@ struct factor_vm
void primitive_special_object(); void primitive_special_object();
void primitive_set_special_object(); void primitive_set_special_object();
void primitive_identity_hashcode(); void primitive_identity_hashcode();
void compute_identity_hashcode(object *obj);
void primitive_compute_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();