ART: Fix forbidden thread state change in interpreter

While loading a type for assignability, it might happen that it's
not available yet locally and must be resolved. Formerly, we
disallowed a state change to ensure no GC taking place while a new
shadow frame has not been pushed on the stack yet.

As a fix, allow a "shadow frame under construction" in the thread,
which is visited during GC.

Change-Id: I973487a46b0e9e21fd6d49099d713b58f06d3b45
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 63ae6fd..19b85e4 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -74,7 +74,13 @@
   // Initialize new shadow frame.
   const size_t first_dest_reg = num_regs - num_ins;
   if (do_assignability_check) {
-    // Slow path: we need to do runtime check on reference assignment. We need to load the shorty
+    // Slow path.
+    // We might need to do class loading, which incurs a thread state change to kNative. So
+    // register the shadow frame as under construction and allow suspension again.
+    self->SetShadowFrameUnderConstruction(new_shadow_frame);
+    self->EndAssertNoThreadSuspension(old_cause);
+
+    // We need to do runtime check on reference assignment. We need to load the shorty
     // to get the exact type of each reference argument.
     const DexFile::TypeList* params = mh.GetParameterTypeList();
     const char* shorty = mh.GetShorty();
@@ -107,11 +113,9 @@
             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;",
@@ -138,6 +142,8 @@
           break;
       }
     }
+    // We're done with the construction.
+    self->ClearShadowFrameUnderConstruction();
   } else {
     // Fast path: no extra checks.
     if (is_range) {
@@ -158,8 +164,8 @@
         AssignRegister(new_shadow_frame, shadow_frame, first_dest_reg + arg_index, regList & 0x0f);
       }
     }
+    self->EndAssertNoThreadSuspension(old_cause);
   }
-  self->EndAssertNoThreadSuspension(old_cause);
 
   // Do the call now.
   if (LIKELY(Runtime::Current()->IsStarted())) {