Enable inlining of Unsafe methods for x86.

Fixes the calculation of the size of a Mov32AR when the base reg is BP
and the displacement is 0.

Also changes time check in heap from DCHECK to unlikely branch and warning,
since time isn't kept well in the x86 emulator.

Change-Id: If8074610bd3d8ac2e20fb9d5b8066ef23ab94050
diff --git a/src/compiler/codegen/gen_invoke.cc b/src/compiler/codegen/gen_invoke.cc
index 04229f8..c47b9eb 100644
--- a/src/compiler/codegen/gen_invoke.cc
+++ b/src/compiler/codegen/gen_invoke.cc
@@ -1128,8 +1128,8 @@
 
 bool Codegen::GenInlinedUnsafeGet(CompilationUnit* cu, CallInfo* info,
                                   bool is_long, bool is_volatile) {
-  if (cu->instruction_set == kX86 || cu->instruction_set == kMips) {
-    // TODO - add x86 and Mips implementation
+  if (cu->instruction_set == kMips) {
+    // TODO - add Mips implementation
     return false;
   }
   // Unused - RegLocation rl_src_unsafe = info->args[0];
@@ -1156,8 +1156,8 @@
 
 bool Codegen::GenInlinedUnsafePut(CompilationUnit* cu, CallInfo* info, bool is_long,
                                   bool is_object, bool is_volatile, bool is_ordered) {
-  if (cu->instruction_set == kX86 || cu->instruction_set == kMips) {
-    // TODO - add x86 and Mips implementation
+  if (cu->instruction_set == kMips) {
+    // TODO - add Mips implementation
     return false;
   }
   // Unused - RegLocation rl_src_unsafe = info->args[0];
diff --git a/src/compiler/codegen/x86/assemble_x86.cc b/src/compiler/codegen/x86/assemble_x86.cc
index 1fa2352..f6ce0d1 100644
--- a/src/compiler/codegen/x86/assemble_x86.cc
+++ b/src/compiler/codegen/x86/assemble_x86.cc
@@ -330,7 +330,7 @@
   { kX86PcRelAdr,      kPcRel,  IS_LOAD | IS_BINARY_OP | REG_DEF0,     { 0, 0, 0xB8, 0, 0, 0, 0, 4 }, "PcRelAdr",      "!0r,!1d" },
 };
 
-static size_t ComputeSize(const X86EncodingMap* entry, int displacement, bool has_sib) {
+static size_t ComputeSize(const X86EncodingMap* entry, int base, int displacement, bool has_sib) {
   size_t size = 0;
   if (entry->skeleton.prefix1 > 0) {
     ++size;
@@ -346,10 +346,12 @@
     }
   }
   ++size;  // modrm
-  if (has_sib) {
+  if (has_sib || base == rX86_SP) {
+    // SP requires a SIB byte.
     ++size;
   }
-  if (displacement != 0) {
+  if (displacement != 0 || base == rBP) {
+    // BP requires an explicit displacement, even when it's 0.
     if (entry->opcode != kX86Lea32RA) {
       DCHECK_NE(entry->flags & (IS_LOAD | IS_STORE), 0ULL) << entry->name;
     }
@@ -369,48 +371,29 @@
     case kNullary:
       return 1;  // 1 byte of opcode
     case kReg:  // lir operands - 0: reg
-      return ComputeSize(entry, 0, false);
-    case kMem: { // lir operands - 0: base, 1: disp
-      int base = lir->operands[0];
-      int disp = lir->operands[1];
-      // SP requires a special extra SIB byte. BP requires explicit disp,
-      // so add a byte for disp 0 which would normally be omitted.
-      return ComputeSize(entry, disp, false) + ((base == rX86_SP) || (base == rBP && disp == 0) ? 1 : 0);
-    }
+      return ComputeSize(entry, 0, 0, false);
+    case kMem:  // lir operands - 0: base, 1: disp
+      return ComputeSize(entry, lir->operands[0], lir->operands[1], false);
     case kArray:  // lir operands - 0: base, 1: index, 2: scale, 3: disp
-      return ComputeSize(entry, lir->operands[3], true);
-    case kMemReg: { // lir operands - 0: base, 1: disp, 2: reg
-      int base = lir->operands[0];
-      int disp = lir->operands[1];
-      // SP requires a special extra SIB byte. BP requires explicit disp,
-      // so add a byte for disp 0 which would normally be omitted.
-      return ComputeSize(entry, disp, false) + ((base == rX86_SP) || (base == rBP && disp == 0) ? 1 : 0);
-    }
+      return ComputeSize(entry, lir->operands[0], lir->operands[3], true);
+    case kMemReg:  // lir operands - 0: base, 1: disp, 2: reg
+      return ComputeSize(entry, lir->operands[0], lir->operands[1], false);
     case kArrayReg:  // lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg
-      return ComputeSize(entry, lir->operands[3], true);
+      return ComputeSize(entry, lir->operands[0], lir->operands[3], true);
     case kThreadReg:  // lir operands - 0: disp, 1: reg
-      return ComputeSize(entry, lir->operands[0], false);
+      return ComputeSize(entry, 0, lir->operands[0], false);
     case kRegReg:
-      return ComputeSize(entry, 0, false);
+      return ComputeSize(entry, 0, 0, false);
     case kRegRegStore:
-      return ComputeSize(entry, 0, false);
-    case kRegMem: { // lir operands - 0: reg, 1: base, 2: disp
-      int base = lir->operands[1];
-      int disp = lir->operands[2];
-      // SP requires a special extra SIB byte. BP requires explicit disp,
-      // so add a byte for disp 0 which would normally be omitted.
-      return ComputeSize(entry, disp, false) + ((base == rX86_SP) || (base == rBP && disp == 0) ? 1 : 0);
-    }
-    case kRegArray:  { // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp
-      int base = lir->operands[1];
-      int disp = lir->operands[4];
-      // BP requires explicit disp, so add a byte for disp 0 which would normally be omitted.
-      return ComputeSize(entry, disp, true) + ((base == rBP && disp == 0) ? 1 : 0);
-    }
+      return ComputeSize(entry, 0, 0, false);
+    case kRegMem:  // lir operands - 0: reg, 1: base, 2: disp
+      return ComputeSize(entry, lir->operands[1], lir->operands[2], false);
+    case kRegArray:   // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp
+      return ComputeSize(entry, lir->operands[1], lir->operands[4], true);
     case kRegThread:  // lir operands - 0: reg, 1: disp
-      return ComputeSize(entry, 0x12345678, false);  // displacement size is always 32bit
+      return ComputeSize(entry, 0, 0x12345678, false);  // displacement size is always 32bit
     case kRegImm: {  // lir operands - 0: reg, 1: immediate
-      size_t size = ComputeSize(entry, 0, false);
+      size_t size = ComputeSize(entry, 0, 0, false);
       if (entry->skeleton.ax_opcode == 0) {
         return size;
       } else {
@@ -420,45 +403,42 @@
       }
     }
     case kMemImm:  // lir operands - 0: base, 1: disp, 2: immediate
-      CHECK_NE(lir->operands[0], static_cast<int>(rX86_SP));  // TODO: add extra SIB byte
-      return ComputeSize(entry, lir->operands[1], false);
+      return ComputeSize(entry, lir->operands[0], lir->operands[1], false);
     case kArrayImm:  // lir operands - 0: base, 1: index, 2: scale, 3: disp 4: immediate
-      return ComputeSize(entry, lir->operands[3], true);
+      return ComputeSize(entry, lir->operands[0], lir->operands[3], true);
     case kThreadImm:  // lir operands - 0: disp, 1: imm
-      return ComputeSize(entry, 0x12345678, false);  // displacement size is always 32bit
+      return ComputeSize(entry, 0, 0x12345678, false);  // displacement size is always 32bit
     case kRegRegImm:  // lir operands - 0: reg, 1: reg, 2: imm
-      return ComputeSize(entry, 0, false);
+      return ComputeSize(entry, 0, 0, false);
     case kRegMemImm:  // lir operands - 0: reg, 1: base, 2: disp, 3: imm
-      CHECK_NE(lir->operands[1], static_cast<int>(rX86_SP));  // TODO: add extra SIB byte
-      return ComputeSize(entry, lir->operands[2], false);
+      return ComputeSize(entry, lir->operands[1], lir->operands[2], false);
     case kRegArrayImm:  // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: disp, 5: imm
-      return ComputeSize(entry, lir->operands[4], true);
+      return ComputeSize(entry, lir->operands[1], lir->operands[4], true);
     case kMovRegImm:  // lir operands - 0: reg, 1: immediate
       return 1 + entry->skeleton.immediate_bytes;
     case kShiftRegImm:  // lir operands - 0: reg, 1: immediate
       // Shift by immediate one has a shorter opcode.
-      return ComputeSize(entry, 0, false) - (lir->operands[1] == 1 ? 1 : 0);
+      return ComputeSize(entry, 0, 0, false) - (lir->operands[1] == 1 ? 1 : 0);
     case kShiftMemImm:  // lir operands - 0: base, 1: disp, 2: immediate
-      CHECK_NE(lir->operands[0], static_cast<int>(rX86_SP));  // TODO: add extra SIB byte
       // Shift by immediate one has a shorter opcode.
-      return ComputeSize(entry, lir->operands[1], false) - (lir->operands[2] == 1 ? 1 : 0);
+      return ComputeSize(entry, lir->operands[0], lir->operands[1], false) -
+             (lir->operands[2] == 1 ? 1 : 0);
     case kShiftArrayImm:  // lir operands - 0: base, 1: index, 2: scale, 3: disp 4: immediate
       // Shift by immediate one has a shorter opcode.
-      return ComputeSize(entry, lir->operands[3], true) - (lir->operands[4] == 1 ? 1 : 0);
+      return ComputeSize(entry, lir->operands[0], lir->operands[3], true) -
+             (lir->operands[4] == 1 ? 1 : 0);
     case kShiftRegCl:
-      return ComputeSize(entry, 0, false);
+      return ComputeSize(entry, 0, 0, false);
     case kShiftMemCl:  // lir operands - 0: base, 1: disp, 2: cl
-      CHECK_NE(lir->operands[0], static_cast<int>(rX86_SP));  // TODO: add extra SIB byte
-      return ComputeSize(entry, lir->operands[1], false);
+      return ComputeSize(entry, lir->operands[0], lir->operands[1], false);
     case kShiftArrayCl:  // lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: reg
-      return ComputeSize(entry, lir->operands[3], true);
+      return ComputeSize(entry, lir->operands[0], lir->operands[3], true);
     case kRegCond:  // lir operands - 0: reg, 1: cond
-      return ComputeSize(entry, 0, false);
+      return ComputeSize(entry, 0, 0, false);
     case kMemCond:  // lir operands - 0: base, 1: disp, 2: cond
-      CHECK_NE(lir->operands[0], static_cast<int>(rX86_SP));  // TODO: add extra SIB byte
-      return ComputeSize(entry, lir->operands[1], false);
+      return ComputeSize(entry, lir->operands[0], lir->operands[1], false);
     case kArrayCond:  // lir operands - 0: base, 1: index, 2: scale, 3: disp, 4: cond
-      return ComputeSize(entry, lir->operands[3], true);
+      return ComputeSize(entry, lir->operands[0], lir->operands[3], true);
     case kJcc:
       if (lir->opcode == kX86Jcc8) {
         return 2;  // opcode + rel8
@@ -479,11 +459,11 @@
       switch (lir->opcode) {
         case kX86CallR: return 2;  // opcode modrm
         case kX86CallM:  // lir operands - 0: base, 1: disp
-          return ComputeSize(entry, lir->operands[1], false);
+          return ComputeSize(entry, lir->operands[0], lir->operands[1], false);
         case kX86CallA:  // lir operands - 0: base, 1: index, 2: scale, 3: disp
-          return ComputeSize(entry, lir->operands[3], true);
+          return ComputeSize(entry, lir->operands[0], lir->operands[3], true);
         case kX86CallT:  // lir operands - 0: disp
-          return ComputeSize(entry, 0x12345678, false);  // displacement size is always 32bit
+          return ComputeSize(entry, 0, 0x12345678, false);  // displacement size is always 32bit
         default:
           break;
       }
@@ -491,7 +471,7 @@
     case kPcRel:
       if (entry->opcode == kX86PcRelLoadRA) {
         // lir operands - 0: reg, 1: base, 2: index, 3: scale, 4: table
-        return ComputeSize(entry, 0x12345678, true);
+        return ComputeSize(entry, lir->operands[1], 0x12345678, true);
       } else {
         DCHECK(entry->opcode == kX86PcRelAdr);
         return 5; // opcode with reg + 4 byte immediate
@@ -499,7 +479,7 @@
     case kMacro:
       DCHECK_EQ(lir->opcode, static_cast<int>(kX86StartOfMethod));
       return 5 /* call opcode + 4 byte displacement */ + 1 /* pop reg */ +
-          ComputeSize(&X86Codegen::EncodingMap[kX86Sub32RI], 0, false) -
+          ComputeSize(&X86Codegen::EncodingMap[kX86Sub32RI], 0, 0, false) -
           (lir->operands[0] == rAX  ? 1 : 0);  // shorter ax encoding
     default:
       break;
diff --git a/src/heap.cc b/src/heap.cc
index 5c96dec..e531dc8 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -1107,7 +1107,9 @@
   uint64_t gc_start_time = NanoTime();
   uint64_t gc_start_size = GetBytesAllocated();
   // Approximate allocation rate in bytes / second.
-  DCHECK_NE(gc_start_time, last_gc_time_);
+  if (UNLIKELY(gc_start_time == last_gc_time_)) {
+    LOG(WARNING) << "Timers are broken (gc_start_time == last_gc_time_).";
+  }
   uint64_t ms_delta = NsToMs(gc_start_time - last_gc_time_);
   if (ms_delta != 0) {
     allocation_rate_ = (gc_start_size - last_gc_size_) * 1000 / ms_delta;