<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -33,6 +33,7 @@ IN: compiler.cfg.intrinsics
 {
     { kernel.private:tag [ drop emit-tag ] }
     { kernel.private:getenv [ emit-getenv ] }
+    { kernel.private:(identity-hashcode) [ drop emit-identity-hashcode ] }
     { math.private:both-fixnums? [ drop emit-both-fixnums? ] }
     { math.private:fixnum+ [ drop emit-fixnum+ ] }
     { math.private:fixnum- [ drop emit-fixnum- ] }</diff>
      <filename>basis/compiler/cfg/intrinsics/intrinsics.factor</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,9 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: namespaces layouts sequences kernel
-accessors compiler.tree.propagation.info
-compiler.cfg.stacks compiler.cfg.hats
-compiler.cfg.instructions compiler.cfg.utilities ;
+USING: namespaces layouts sequences kernel math accessors
+compiler.tree.propagation.info compiler.cfg.stacks
+compiler.cfg.hats compiler.cfg.instructions
+compiler.cfg.utilities ;
 IN: compiler.cfg.intrinsics.misc
 
 : emit-tag ( -- )
@@ -14,3 +14,9 @@ IN: compiler.cfg.intrinsics.misc
     swap node-input-infos first literal&gt;&gt;
     [ ds-drop 0 ^^slot-imm ] [ ds-pop ^^offset&gt;slot ^^slot ] if*
     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 ;</diff>
      <filename>basis/compiler/cfg/intrinsics/misc/misc.factor</filename>
    </modified>
    <modified>
      <diff>@@ -713,4 +713,6 @@ M: bad-executable summary
 
 \ profiling { object } { } define-primitive
 
-\ identity-hashcode { object } { fixnum } define-primitive
+\ (identity-hashcode) { object } { fixnum } define-primitive
+
+\ compute-identity-hashcode { object } { } define-primitive</diff>
      <filename>basis/stack-checker/known-words/known-words.factor</filename>
    </modified>
    <modified>
      <diff>@@ -30,3 +30,5 @@ H{
     { word 12 }
     { dll 13 }
 } type-numbers set
+
+2 header-bits set</diff>
      <filename>core/bootstrap/layouts/layouts.factor</filename>
    </modified>
    <modified>
      <diff>@@ -518,7 +518,8 @@ tuple
     { &quot;&lt;callback&gt;&quot; &quot;alien&quot; (( word -- alien )) }
     { &quot;enable-gc-events&quot; &quot;memory&quot; (( -- )) }
     { &quot;disable-gc-events&quot; &quot;memory&quot; (( -- events )) }
-    { &quot;identity-hashcode&quot; &quot;kernel&quot; (( obj -- code )) }
+    { &quot;(identity-hashcode)&quot; &quot;kernel.private&quot; (( obj -- code )) }
+    { &quot;compute-identity-hashcode&quot; &quot;kernel.private&quot; (( obj -- )) }
 } [ [ first3 ] dip swap make-primitive ] each-index
 
 ! Bump build number</diff>
      <filename>core/bootstrap/primitives.factor</filename>
    </modified>
    <modified>
      <diff>@@ -192,6 +192,16 @@ M: f hashcode* 2drop 31337 ; 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 -- ? )
 
 M: object equal? 2drop f ; inline</diff>
      <filename>core/kernel/kernel.factor</filename>
    </modified>
    <modified>
      <diff>@@ -16,6 +16,8 @@ SYMBOL: type-numbers
 
 SYMBOL: mega-cache-size
 
+SYMBOL: header-bits
+
 : type-number ( class -- n )
     type-numbers get at ;
 
@@ -23,11 +25,14 @@ SYMBOL: mega-cache-size
     tag-bits get shift ;
 
 : tag-header ( n -- tagged )
-    2 shift ;
+    header-bits get shift ;
 
 : untag-fixnum ( n -- tagged )
     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
 ! folded below
 &lt;&lt;</diff>
      <filename>core/layouts/layouts.factor</filename>
    </modified>
    <modified>
      <diff>@@ -19,18 +19,21 @@ void factor_vm::primitive_set_special_object()
 void factor_vm::primitive_identity_hashcode()
 {
 	cell tagged = dpeek();
-	if(immediate_p(tagged))
-		drepl(tagged &amp; ~TAG_MASK);
-	else
-	{
-		object *obj = untag&lt;object&gt;(tagged);
-		if(obj-&gt;hashcode() == 0)
-		{
-			/* Use megamorphic_cache_misses as a random source of randomness */
-			obj-&gt;set_hashcode(((cell)obj / block_granularity) ^ dispatch_stats.megamorphic_cache_hits);
-		}
-		drepl(tag_fixnum(obj-&gt;hashcode()));
-	}
+	object *obj = untag&lt;object&gt;(tagged);
+	drepl(tag_fixnum(obj-&gt;hashcode()));
+}
+
+void factor_vm::compute_identity_hashcode(object *obj)
+{
+	object_counter++;
+	if(object_counter == 0) object_counter++;
+	obj-&gt;set_hashcode((cell)obj ^ object_counter);
+}
+
+void factor_vm::primitive_compute_identity_hashcode()
+{
+	object *obj = untag&lt;object&gt;(dpop());
+	compute_identity_hashcode(obj);
 }
 
 void factor_vm::primitive_set_slot()</diff>
      <filename>vm/objects.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -127,6 +127,7 @@ PRIMITIVE_FORWARD(callback)
 PRIMITIVE_FORWARD(enable_gc_events)
 PRIMITIVE_FORWARD(disable_gc_events)
 PRIMITIVE_FORWARD(identity_hashcode)
+PRIMITIVE_FORWARD(compute_identity_hashcode)
 
 const primitive_type primitives[] = {
 	primitive_bignum_to_fixnum,
@@ -290,6 +291,7 @@ const primitive_type primitives[] = {
 	primitive_enable_gc_events,
 	primitive_disable_gc_events,
 	primitive_identity_hashcode,
+	primitive_compute_identity_hashcode,
 };
 
 }</diff>
      <filename>vm/primitives.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -81,6 +81,9 @@ struct factor_vm
 	/* Number of entries in a polymorphic inline cache */
 	cell max_pic_size;
 
+	/* Incrementing object counter for identity hashing */
+	cell object_counter;
+
 	// contexts
 	void reset_datastack();
 	void reset_retainstack();
@@ -122,6 +125,8 @@ struct factor_vm
 	void primitive_special_object();
 	void primitive_set_special_object();
 	void primitive_identity_hashcode();
+	void compute_identity_hashcode(object *obj);
+	void primitive_compute_identity_hashcode();
 	cell object_size(cell tagged);
 	cell clone_object(cell obj_);
 	void primitive_clone();</diff>
      <filename>vm/vm.hpp</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>4fe132df8d4d82c1c5b7fc8f01d47fed4ce9bdb3</id>
    </parent>
  </parents>
  <author>
    <name>Slava Pestov</name>
    <email>slava@slava-pestovs-macbook-pro.local</email>
  </author>
  <url>http://github.com/slavapestov/factor/commit/68f3087c1c6f606ebc6959e114146c7c612c9280</url>
  <id>68f3087c1c6f606ebc6959e114146c7c612c9280</id>
  <committed-date>2009-11-11T00:27:19-08:00</committed-date>
  <authored-date>2009-11-10T22:50:57-08:00</authored-date>
  <message>Faster identity-hashcode primitive; fast path now opencoded by the compiler</message>
  <tree>6c1ffc5380f443597df55cffed6b8f12a71e4c76</tree>
  <committer>
    <name>Slava Pestov</name>
    <email>slava@slava-pestovs-macbook-pro.local</email>
  </committer>
</commit>
