Merge "Fix oat_file_assistant_test32 flaky failures with GSS collector."
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 689f535..0a069a7 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -2312,9 +2312,12 @@
       break;
     }
     case Primitive::kPrimLong: {
-      locations->SetInAt(0, Location::RequiresRegister());
-      locations->SetInAt(1, Location::RequiresRegister());
-      locations->SetOut(Location::RequiresRegister());
+      InvokeRuntimeCallingConvention calling_convention;
+      locations->SetInAt(0, Location::RegisterPairLocation(
+          calling_convention.GetRegisterAt(0), calling_convention.GetRegisterAt(1)));
+      locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(2)));
+      // The runtime helper puts the output in R0,R1.
+      locations->SetOut(Location::RegisterPairLocation(R0, R1));
       break;
     }
     default:
@@ -2362,54 +2365,24 @@
       break;
     }
     case Primitive::kPrimLong: {
-      Register o_h = out.AsRegisterPairHigh<Register>();
-      Register o_l = out.AsRegisterPairLow<Register>();
+      // TODO: Inline the assembly instead of calling the runtime.
+      InvokeRuntimeCallingConvention calling_convention;
+      DCHECK_EQ(calling_convention.GetRegisterAt(0), first.AsRegisterPairLow<Register>());
+      DCHECK_EQ(calling_convention.GetRegisterAt(1), first.AsRegisterPairHigh<Register>());
+      DCHECK_EQ(calling_convention.GetRegisterAt(2), second.AsRegister<Register>());
+      DCHECK_EQ(R0, out.AsRegisterPairLow<Register>());
+      DCHECK_EQ(R1, out.AsRegisterPairHigh<Register>());
 
-      Register high = first.AsRegisterPairHigh<Register>();
-      Register low = first.AsRegisterPairLow<Register>();
-
-      Register second_reg = second.AsRegister<Register>();
-
+      int32_t entry_point_offset;
       if (op->IsShl()) {
-        // Shift the high part
-        __ and_(second_reg, second_reg, ShifterOperand(63));
-        __ Lsl(high, high, second_reg);
-        // Shift the low part and `or` what overflowed on the high part
-        __ rsb(IP, second_reg, ShifterOperand(32));
-        __ Lsr(IP, low, IP);
-        __ orr(o_h, high, ShifterOperand(IP));
-        // If the shift is > 32 bits, override the high part
-        __ subs(IP, second_reg, ShifterOperand(32));
-        __ it(PL);
-        __ Lsl(o_h, low, IP, false, PL);
-        // Shift the low part
-        __ Lsl(o_l, low, second_reg);
+        entry_point_offset = QUICK_ENTRY_POINT(pShlLong);
       } else if (op->IsShr()) {
-        // Shift the low part
-        __ and_(second_reg, second_reg, ShifterOperand(63));
-        __ Lsr(low, low, second_reg);
-        // Shift the high part and `or` what underflowed on the low part
-        __ rsb(IP, second_reg, ShifterOperand(32));
-        __ Lsl(IP, high, IP);
-        __ orr(o_l, low, ShifterOperand(IP));
-        // If the shift is > 32 bits, override the low part
-        __ subs(IP, second_reg, ShifterOperand(32));
-        __ it(PL);
-        __ Asr(o_l, high, IP, false, PL);
-        // Shift the high part
-        __ Asr(o_h, high, second_reg);
+        entry_point_offset = QUICK_ENTRY_POINT(pShrLong);
       } else {
-        // same as Shr except we use `Lsr`s and not `Asr`s
-        __ and_(second_reg, second_reg, ShifterOperand(63));
-        __ Lsr(low, low, second_reg);
-        __ rsb(IP, second_reg, ShifterOperand(32));
-        __ Lsl(IP, high, IP);
-        __ orr(o_l, low, ShifterOperand(IP));
-        __ subs(IP, second_reg, ShifterOperand(32));
-        __ it(PL);
-        __ Lsr(o_l, high, IP, false, PL);
-        __ Lsr(o_h, high, second_reg);
+        entry_point_offset = QUICK_ENTRY_POINT(pUshrLong);
       }
+      __ LoadFromOffset(kLoadWord, LR, TR, entry_point_offset);
+      __ blx(LR);
       break;
     }
     default:
diff --git a/compiler/utils/arm/assembler_arm.h b/compiler/utils/arm/assembler_arm.h
index dd0dba2..8730f52 100644
--- a/compiler/utils/arm/assembler_arm.h
+++ b/compiler/utils/arm/assembler_arm.h
@@ -100,10 +100,6 @@
     return rm_;
   }
 
-  Register GetSecondRegister() const {
-    return rs_;
-  }
-
   enum Type {
     kUnknown = -1,
     kRegister,
diff --git a/compiler/utils/arm/assembler_thumb2.cc b/compiler/utils/arm/assembler_thumb2.cc
index e8eb019..6d0571e 100644
--- a/compiler/utils/arm/assembler_thumb2.cc
+++ b/compiler/utils/arm/assembler_thumb2.cc
@@ -826,9 +826,7 @@
     // Check special cases.
     if ((opcode == SUB || opcode == ADD) && (so.GetImmediate() < (1u << 12))) {
       if (opcode == SUB) {
-        if (!set_cc) {
-          thumb_opcode = 5U /* 0b0101 */;
-        }
+        thumb_opcode = 5U /* 0b0101 */;
       } else {
         thumb_opcode = 0;
       }
@@ -838,14 +836,13 @@
       uint32_t imm3 = (imm >> 8) & 7U /* 0b111 */;
       uint32_t imm8 = imm & 0xff;
 
-      encoding = B31 | B30 | B29 | B28 |
-          (set_cc ? B20 : B25) |
-          thumb_opcode << 21 |
-          rn << 16 |
-          rd << 8 |
-          i << 26 |
-          imm3 << 12 |
-          imm8;
+      encoding = B31 | B30 | B29 | B28 | B25 |
+           thumb_opcode << 21 |
+           rn << 16 |
+           rd << 8 |
+           i << 26 |
+           imm3 << 12 |
+           imm8;
     } else {
       // Modified immediate.
       uint32_t imm = ModifiedImmediate(so.encodingThumb());
@@ -861,13 +858,13 @@
           imm;
     }
   } else if (so.IsRegister()) {
-    // Register (possibly shifted)
-    encoding = B31 | B30 | B29 | B27 | B25 |
-        thumb_opcode << 21 |
-        (set_cc ? 1 : 0) << 20 |
-        rn << 16 |
-        rd << 8 |
-        so.encodingThumb();
+     // Register (possibly shifted)
+     encoding = B31 | B30 | B29 | B27 | B25 |
+         thumb_opcode << 21 |
+         (set_cc ? 1 : 0) << 20 |
+         rn << 16 |
+         rd << 8 |
+         so.encodingThumb();
   }
   Emit32(encoding);
 }
@@ -924,8 +921,6 @@
       use_immediate = true;
       immediate = so.GetImmediate();
     } else {
-      CHECK(!(so.IsRegister() && so.IsShift() && so.GetSecondRegister() != kNoRegister))
-          << "No register-shifted register instruction available in thumb";
       // Adjust rn and rd: only two registers will be emitted.
       switch (opcode) {
         case AND:
diff --git a/compiler/utils/arm/assembler_thumb2_test.cc b/compiler/utils/arm/assembler_thumb2_test.cc
index d802852..ebea9d4 100644
--- a/compiler/utils/arm/assembler_thumb2_test.cc
+++ b/compiler/utils/arm/assembler_thumb2_test.cc
@@ -227,14 +227,4 @@
   DriverStr(expected, "abs");
 }
 
-TEST_F(AssemblerThumb2Test, sub) {
-  __ subs(arm::R1, arm::R0, arm::ShifterOperand(42));
-  __ sub(arm::R1, arm::R0, arm::ShifterOperand(42));
-
-  const char* expected =
-      "subs r1, r0, #42\n"
-      "subw r1, r0, #42\n";
-  DriverStr(expected, "sub");
-}
-
 }  // namespace art
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index c056adc..8395150 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -59,10 +59,11 @@
     DEBUG_ENABLE_ASSERT             = 1 << 2,
     DEBUG_ENABLE_SAFEMODE           = 1 << 3,
     DEBUG_ENABLE_JNI_LOGGING        = 1 << 4,
+    DEBUG_ENABLE_JIT                = 1 << 5,
   };
 
+  Runtime* const runtime = Runtime::Current();
   if ((debug_flags & DEBUG_ENABLE_CHECKJNI) != 0) {
-    Runtime* runtime = Runtime::Current();
     JavaVMExt* vm = runtime->GetJavaVM();
     if (!vm->IsCheckJniEnabled()) {
       LOG(INFO) << "Late-enabling -Xcheck:jni";
@@ -86,13 +87,26 @@
   }
   debug_flags &= ~DEBUG_ENABLE_DEBUGGER;
 
-  if ((debug_flags & DEBUG_ENABLE_SAFEMODE) != 0) {
+  const bool safe_mode = (debug_flags & DEBUG_ENABLE_SAFEMODE) != 0;
+  if (safe_mode) {
     // Ensure that any (secondary) oat files will be interpreted.
-    Runtime* runtime = Runtime::Current();
     runtime->AddCompilerOption("--compiler-filter=interpret-only");
     debug_flags &= ~DEBUG_ENABLE_SAFEMODE;
   }
 
+  if ((debug_flags & DEBUG_ENABLE_JIT) != 0) {
+    if (safe_mode) {
+      LOG(INFO) << "Not enabling JIT due to VM safe mode";
+    } else {
+      if (runtime->GetJit() == nullptr) {
+        runtime->CreateJit();
+      } else {
+        LOG(INFO) << "Not late-enabling JIT (already on)";
+      }
+    }
+    debug_flags &= ~DEBUG_ENABLE_JIT;
+  }
+
   // This is for backwards compatibility with Dalvik.
   debug_flags &= ~DEBUG_ENABLE_ASSERT;