Fix object identity hash.

The object identity hash is now stored in the monitor word after
being computed. Hashes are computed by a pseudo random number
generator.

When we write the image, we eagerly compute object hashes to
prevent pages getting dirtied.

Bug: 8981901

Change-Id: Ic8edacbacb0afc7055fd740a52444929f88ed564
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 736ce2f..c11349802 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -325,24 +325,25 @@
 ENTRY art_quick_lock_object
     cbz    r0, slow_lock
 retry_lock:
-    ldrex  r1, [r0, #LOCK_WORD_OFFSET]
     ldrt   r2, [r9, #THREAD_ID_OFFSET]
-    cmp    r1, #0
-    bmi    slow_lock                  @ lock word contains a monitor
-    bne    already_thin
+    ldrex  r1, [r0, #LOCK_WORD_OFFSET]
+    cbnz   r1, not_unlocked           @ already thin locked
     @ unlocked case - r2 holds thread id with count of 0
     strex  r3, r2, [r0, #LOCK_WORD_OFFSET]
     cbnz   r3, strex_fail             @ store failed, retry
     bx lr
 strex_fail:
     b retry_lock                      @ unlikely forward branch, need to reload and recheck r1/r2
-already_thin:
+not_unlocked:
+    lsr    r3, r1, 30
+    cbnz   r3, slow_lock              @ if either of the top two bits are set, go slow path
     eor    r2, r1, r2                 @ lock_word.ThreadId() ^ self->ThreadId()
     uxth   r2, r2                     @ zero top 16 bits
     cbnz   r2, slow_lock              @ lock word and self thread id's match -> recursive lock
                                       @ else contention, go to slow path
-    adds   r2, r1, #65536             @ increment count in lock word placing in r2 for storing
-    bmi    slow_lock                  @ if we overflow the count go slow
+    add    r2, r1, #65536             @ increment count in lock word placing in r2 for storing
+    lsr    r1, r2, 30                 @ if either of the top two bits are set, we overflowed.
+    cbnz   r1, slow_lock              @ if we overflow the count go slow path
     str    r2, [r0, #LOCK_WORD_OFFSET] @ no need for strex as we hold the lock
     bx lr
 slow_lock:
@@ -363,9 +364,9 @@
 ENTRY art_quick_unlock_object
     cbz    r0, slow_unlock
     ldr    r1, [r0, #LOCK_WORD_OFFSET]
+    lsr    r2, r1, 30
+    cbnz   r2, slow_unlock            @ if either of the top two bits are set, go slow path
     ldr    r2, [r9, #THREAD_ID_OFFSET]
-    cmp    r1, #0
-    bmi    slow_unlock                @ lock word contains a monitor
     eor    r3, r1, r2                 @ lock_word.ThreadId() ^ self->ThreadId()
     uxth   r3, r3                     @ zero top 16 bits
     cbnz   r3, slow_unlock            @ do lock word and self thread id's match?
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index 805f6f4..4e79770 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -411,9 +411,10 @@
     jz   slow_lock
 retry_lock:
     movl LOCK_WORD_OFFSET(%eax), %ecx     // ecx := lock word
+    test LITERAL(0xC0000000), %ecx        // test the 2 high bits.
+    jne  slow_lock                        // slow path if either of the two high bits are set.
     movl %fs:THREAD_ID_OFFSET, %edx       // edx := thread id
     test %ecx, %ecx
-    jb   slow_lock                        // lock word contains a monitor
     jnz  already_thin                     // lock word contains a thin lock
     // unlocked case - %edx holds thread id with count of 0
     movl %eax, %ecx                       // remember object in case of retry
@@ -428,7 +429,8 @@
     cmpw %ax, %dx                         // do we hold the lock already?
     jne  slow_lock
     addl LITERAL(65536), %eax             // increment recursion count
-    jb   slow_lock                        // count overflowed so go slow
+    test LITERAL(0xC0000000), %eax        // overflowed if either of top two bits are set
+    jne  slow_lock                        // count overflowed so go slow
     movl %eax, LOCK_WORD_OFFSET(%ecx)     // update lockword, cmpxchg not necessary as we hold lock
     ret
 slow_lock: