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: