Jit: Update monitor lock/unlock to reflect thinlock changes (I34b20f49)
diff --git a/vm/compiler/codegen/arm/ArmLIR.h b/vm/compiler/codegen/arm/ArmLIR.h
index 1500055..8772b79 100644
--- a/vm/compiler/codegen/arm/ArmLIR.h
+++ b/vm/compiler/codegen/arm/ArmLIR.h
@@ -598,7 +598,11 @@
                                   imm8[7-0] */
     kThumb2Strex,        /* strex [111010000100] rn[19-16] rt[11-8] rd[11-8]
                                   imm8[7-0] */
-    kThumb2Clrex,       /* clrex [111100111011111110000111100101111\ */
+    kThumb2Clrex,        /* clrex [111100111011111110000111100101111] */
+    kThumb2Bfi,          /* bfi [111100110110] rn[19-16] [0] imm3[14-12]
+                                  rd[11-8] imm2[7-6] [0] msb[4-0] */
+    kThumb2Bfc,          /* bfc [11110011011011110] [0] imm3[14-12]
+                                  rd[11-8] imm2[7-6] [0] msb[4-0] */
 
     kArmLast,
 } ArmOpCode;
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index 8e977c1..26e227f 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -859,6 +859,14 @@
     ENCODING_MAP(kThumb2Clrex,       0xf3bf8f2f,
                  kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, NO_OPERAND, "clrex", "", 2),
+    ENCODING_MAP(kThumb2Bfi,         0xf3600000,
+                 kFmtBitBlt, 11, 8, kFmtBitBlt, 19, 16, kFmtShift5, -1, -1,
+                 kFmtBitBlt, 4, 0, IS_QUAD_OP | REG_DEF0_USE1,
+                 "bfi", "r!0d,r!1d,#!2d,#!3d", 2),
+    ENCODING_MAP(kThumb2Bfc,         0xf36f0000,
+                 kFmtBitBlt, 11, 8, kFmtShift5, -1, -1, kFmtBitBlt, 4, 0,
+                 kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0,
+                 "bfc", "r!0d,#!1d,#!2d", 2),
 };
 
 /*
diff --git a/vm/compiler/codegen/arm/CodegenDriver.c b/vm/compiler/codegen/arm/CodegenDriver.c
index 249970c..f3648b9 100644
--- a/vm/compiler/codegen/arm/CodegenDriver.c
+++ b/vm/compiler/codegen/arm/CodegenDriver.c
@@ -2098,7 +2098,7 @@
         }
         case OP_MONITOR_EXIT:
         case OP_MONITOR_ENTER:
-#if 1 || defined(WITH_DEADLOCK_PREDICTION) || defined(WITH_MONITOR_TRACKING)
+#if defined(WITH_DEADLOCK_PREDICTION) || defined(WITH_MONITOR_TRACKING)
             genMonitorPortable(cUnit, mir);
 #else
             genMonitor(cUnit, mir);
diff --git a/vm/compiler/codegen/arm/Thumb2/Gen.c b/vm/compiler/codegen/arm/Thumb2/Gen.c
index 9251364..d108f92 100644
--- a/vm/compiler/codegen/arm/Thumb2/Gen.c
+++ b/vm/compiler/codegen/arm/Thumb2/Gen.c
@@ -177,6 +177,18 @@
  * r4 -> allow to be used by utilities as general temp
  *
  * The result of the strex is 0 if we acquire the lock.
+ *
+ * See comments in Sync.c for the layout of the lock word.
+ * Of particular interest to this code is the test for the
+ * simple case - which we handle inline.  For monitor enter, the
+ * simple case is thin lock, held by no-one.  For monitor exit,
+ * the simple case is thin lock, held by the unlocking thread with
+ * a recurse count of 0.
+ *
+ * A minor complication is that there is a field in the lock word
+ * unrelated to locking: the hash state.  This field must be ignored, but
+ * preserved.
+ *
  */
 static void genMonitor(CompilationUnit *cUnit, MIR *mir)
 {
@@ -185,6 +197,7 @@
     ArmLIR *target;
     ArmLIR *branch;
 
+    assert(LW_SHAPE_THIN == 0);
     loadValueDirectFixed(cUnit, rlSrc, r1);  // Get obj
     lockAllTemps(cUnit);  // Prepare for explicit register usage
     freeTemp(cUnit, r4PC);  // Free up r4 for general use
@@ -193,11 +206,18 @@
     loadWordDisp(cUnit, r0, offsetof(Thread, threadId), r3); // Get threadId
     newLIR3(cUnit, kThumb2Ldrex, r2, r1,
             offsetof(Object, lock.thin) >> 2); // Get object->lock.thin
+    opRegImm(cUnit, kOpLsl, r3, LW_LOCK_OWNER_SHIFT); // Align owner
     // Is lock.thin unheld on lock or held by us (==threadId) on unlock?
     if (enter) {
-        opRegImm(cUnit, kOpSub, r2, DVM_LOCK_INITIAL_THIN_VALUE);
+        newLIR4(cUnit, kThumb2Bfi, r3, r2, 0, LW_LOCK_OWNER_SHIFT - 1);
+        newLIR3(cUnit, kThumb2Bfc, r2, LW_HASH_STATE_SHIFT,
+                 LW_LOCK_OWNER_SHIFT - 1);
+        opRegImm(cUnit, kOpCmp, r2, 0);
     } else {
-        loadConstant(cUnit, r7, DVM_LOCK_INITIAL_THIN_VALUE);
+        opRegRegImm(cUnit, kOpAnd, r7, r2,
+                (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
+        newLIR3(cUnit, kThumb2Bfc, r2, LW_HASH_STATE_SHIFT,
+                 LW_LOCK_OWNER_SHIFT - 1);
         opRegReg(cUnit, kOpSub, r2, r3);
     }
     // Note: start of IT block.  If last sub result != clear, else strex