Fix interpreter bugs.

These showed up in compaction work.

Change-Id: Iac8eb0a1395c25aabba9f2e0ff6b01fc6180bdca
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 8aa6fa2..48c0014 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -309,6 +309,7 @@
     return;
   }
 
+  const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke");
   MethodHelper mh(method);
   const DexFile::CodeItem* code_item = mh.GetCodeItem();
   uint16_t num_regs;
@@ -317,6 +318,7 @@
     num_regs =  code_item->registers_size_;
     num_ins = code_item->ins_size_;
   } else if (method->IsAbstract()) {
+    self->EndAssertNoThreadSuspension(old_cause);
     ThrowAbstractMethodError(method);
     return;
   } else {
@@ -332,6 +334,8 @@
   void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
   ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, last_shadow_frame, method, 0, memory));
   self->PushShadowFrame(shadow_frame);
+  self->EndAssertNoThreadSuspension(old_cause);
+
   size_t cur_reg = num_regs - num_ins;
   if (!method->IsStatic()) {
     CHECK(receiver != NULL);
@@ -339,8 +343,7 @@
     ++cur_reg;
   } else if (UNLIKELY(!method->GetDeclaringClass()->IsInitializing())) {
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-    if (UNLIKELY(!class_linker->EnsureInitialized(method->GetDeclaringClass(),
-                                                  true, true))) {
+    if (UNLIKELY(!class_linker->EnsureInitialized(method->GetDeclaringClass(), true, true))) {
       CHECK(self->IsExceptionPending());
       self->PopShadowFrame();
       return;
@@ -421,6 +424,7 @@
     return;
   }
 
+  self->PushShadowFrame(shadow_frame);
   ArtMethod* method = shadow_frame->GetMethod();
   // Ensure static methods are initialized.
   if (method->IsStatic()) {
@@ -429,12 +433,12 @@
       if (UNLIKELY(!Runtime::Current()->GetClassLinker()->EnsureInitialized(declaringClass,
                                                                             true, true))) {
         DCHECK(Thread::Current()->IsExceptionPending());
+        self->PopShadowFrame();
         return;
       }
       CHECK(declaringClass->IsInitializing());
     }
   }
-  self->PushShadowFrame(shadow_frame);
 
   if (LIKELY(!method->IsNative())) {
     result->SetJ(Execute(self, mh, code_item, *shadow_frame, JValue()).GetJ());
@@ -442,7 +446,7 @@
     // We don't expect to be asked to interpret native code (which is entered via a JNI compiler
     // generated stub) except during testing and image writing.
     CHECK(!Runtime::Current()->IsStarted());
-    Object* receiver = method->IsStatic() ? NULL : shadow_frame->GetVRegReference(0);
+    Object* receiver = method->IsStatic() ? nullptr : shadow_frame->GetVRegReference(0);
     uint32_t* args = shadow_frame->GetVRegArgs(method->IsStatic() ? 0 : 1);
     UnstartedRuntimeJni(self, method, receiver, args, result);
   }
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index f0f10bb..19f55d2 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -54,6 +54,7 @@
   }
 
   // Allocate shadow frame on the stack.
+  const char* old_cause = self->StartAssertNoThreadSuspension("DoCall");
   void* memory = alloca(ShadowFrame::ComputeSize(num_regs));
   ShadowFrame* new_shadow_frame(ShadowFrame::Create(num_regs, &shadow_frame, method, 0, memory));
 
@@ -94,9 +95,11 @@
             Class* arg_type = mh.GetClassFromTypeIdx(params->GetTypeItem(shorty_pos).type_idx_);
             if (arg_type == NULL) {
               CHECK(self->IsExceptionPending());
+              self->EndAssertNoThreadSuspension(old_cause);
               return false;
             }
             if (!o->VerifierInstanceOf(arg_type)) {
+              self->EndAssertNoThreadSuspension(old_cause);
               // This should never happen.
               self->ThrowNewExceptionF(self->GetCurrentLocationForThrow(),
                                        "Ljava/lang/VirtualMachineError;",
@@ -144,6 +147,7 @@
       }
     }
   }
+  self->EndAssertNoThreadSuspension(old_cause);
 
   // Do the call now.
   if (LIKELY(Runtime::Current()->IsStarted())) {
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h
index 481d6cc..29b00d2 100644
--- a/runtime/interpreter/interpreter_common.h
+++ b/runtime/interpreter/interpreter_common.h
@@ -98,9 +98,14 @@
                             uint16_t inst_data, JValue* result) {
   const uint32_t method_idx = (is_range) ? inst->VRegB_3rc() : inst->VRegB_35c();
   const uint32_t vregC = (is_range) ? inst->VRegC_3rc() : inst->VRegC_35c();
-  Object* const receiver = (type == kStatic) ? NULL : shadow_frame.GetVRegReference(vregC);
+  Object* receiver = (type == kStatic) ? nullptr : shadow_frame.GetVRegReference(vregC);
   ArtMethod* const method = FindMethodFromCode(method_idx, receiver, shadow_frame.GetMethod(), self,
                                                do_access_check, type);
+  if (type != kStatic) {
+    // Reload the vreg since the GC may have moved the object.
+    receiver = shadow_frame.GetVRegReference(vregC);
+  }
+
   if (UNLIKELY(method == NULL)) {
     CHECK(self->IsExceptionPending());
     result->SetJ(0);
@@ -524,26 +529,27 @@
 static inline void TraceExecution(const ShadowFrame& shadow_frame, const Instruction* inst,
                                   const uint32_t dex_pc, MethodHelper& mh)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  const bool kTracing = false;
+  constexpr bool kTracing = false;
   if (kTracing) {
 #define TRACE_LOG std::cerr
-    TRACE_LOG << PrettyMethod(shadow_frame.GetMethod())
-              << StringPrintf("\n0x%x: ", dex_pc)
-              << inst->DumpString(&mh.GetDexFile()) << "\n";
+    std::ostringstream oss;
+    oss << PrettyMethod(shadow_frame.GetMethod())
+        << StringPrintf("\n0x%x: ", dex_pc)
+        << inst->DumpString(&mh.GetDexFile()) << "\n";
     for (size_t i = 0; i < shadow_frame.NumberOfVRegs(); ++i) {
       uint32_t raw_value = shadow_frame.GetVReg(i);
       Object* ref_value = shadow_frame.GetVRegReference(i);
-      TRACE_LOG << StringPrintf(" vreg%d=0x%08X", i, raw_value);
+      oss << StringPrintf(" vreg%d=0x%08X", i, raw_value);
       if (ref_value != NULL) {
         if (ref_value->GetClass()->IsStringClass() &&
             ref_value->AsString()->GetCharArray() != NULL) {
-          TRACE_LOG << "/java.lang.String \"" << ref_value->AsString()->ToModifiedUtf8() << "\"";
+          oss << "/java.lang.String \"" << ref_value->AsString()->ToModifiedUtf8() << "\"";
         } else {
-          TRACE_LOG << "/" << PrettyTypeOf(ref_value);
+          oss << "/" << PrettyTypeOf(ref_value);
         }
       }
     }
-    TRACE_LOG << "\n";
+    TRACE_LOG << oss.str() << "\n";
 #undef TRACE_LOG
   }
 }
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index daf6f93..3a91b8c 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -264,12 +264,12 @@
 
   HANDLE_INSTRUCTION_START(RETURN_OBJECT) {
     JValue result;
-    Object* obj_result = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
-    result.SetJ(0);
-    result.SetL(obj_result);
     if (UNLIKELY(self->TestAllFlags())) {
       CheckSuspend(self);
     }
+    Object* obj_result = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
+    result.SetJ(0);
+    result.SetL(obj_result);
     if (do_assignability_check && obj_result != NULL) {
       Class* return_type = MethodHelper(shadow_frame.GetMethod()).GetReturnType();
       if (return_type == NULL) {
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index c3977c6..bd0d87e 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -227,12 +227,12 @@
       case Instruction::RETURN_OBJECT: {
         PREAMBLE();
         JValue result;
-        Object* obj_result = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
-        result.SetJ(0);
-        result.SetL(obj_result);
         if (UNLIKELY(self->TestAllFlags())) {
           CheckSuspend(self);
         }
+        Object* obj_result = shadow_frame.GetVRegReference(inst->VRegA_11x(inst_data));
+        result.SetJ(0);
+        result.SetL(obj_result);
         if (do_assignability_check && obj_result != NULL) {
           Class* return_type = MethodHelper(shadow_frame.GetMethod()).GetReturnType();
           if (return_type == NULL) {