Revert^4 "Allow deoptimization when returning from a runtime method."

This reverts commit 07c7028e518b98d3267a77dfe0d149db1adbe858.

Need some special treatment of string init's shorty.

Test: run-test/gtest on both host and target
Test: 597-deopt-busy-loop, 597-deopt-invoke-stub
Bug: 33616143
Change-Id: Id4c64910acfdd088835b6db6fc503e6ade0218e7
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 9cb74f7..ec183b3 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -467,29 +467,6 @@
   self->PopShadowFrame();
 }
 
-static bool IsStringInit(const Instruction* instr, ArtMethod* caller)
-    REQUIRES_SHARED(Locks::mutator_lock_) {
-  if (instr->Opcode() == Instruction::INVOKE_DIRECT ||
-      instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE) {
-    // Instead of calling ResolveMethod() which has suspend point and can trigger
-    // GC, look up the callee method symbolically.
-    uint16_t callee_method_idx = (instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE) ?
-        instr->VRegB_3rc() : instr->VRegB_35c();
-    const DexFile* dex_file = caller->GetDexFile();
-    const DexFile::MethodId& method_id = dex_file->GetMethodId(callee_method_idx);
-    const char* class_name = dex_file->StringByTypeIdx(method_id.class_idx_);
-    const char* method_name = dex_file->GetMethodName(method_id);
-    // Compare method's class name and method name against string init.
-    // It's ok since it's not allowed to create your own java/lang/String.
-    // TODO: verify that assumption.
-    if ((strcmp(class_name, "Ljava/lang/String;") == 0) &&
-        (strcmp(method_name, "<init>") == 0)) {
-      return true;
-    }
-  }
-  return false;
-}
-
 static int16_t GetReceiverRegisterForStringInit(const Instruction* instr) {
   DCHECK(instr->Opcode() == Instruction::INVOKE_DIRECT_RANGE ||
          instr->Opcode() == Instruction::INVOKE_DIRECT);
@@ -499,8 +476,9 @@
 
 void EnterInterpreterFromDeoptimize(Thread* self,
                                     ShadowFrame* shadow_frame,
+                                    JValue* ret_val,
                                     bool from_code,
-                                    JValue* ret_val)
+                                    DeoptimizationMethodType deopt_method_type)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   JValue value;
   // Set value to last known result in case the shadow frame chain is empty.
@@ -527,11 +505,27 @@
       new_dex_pc = found_dex_pc;  // the dex pc of a matching catch handler
                                   // or DexFile::kDexNoIndex if there is none.
     } else if (!from_code) {
-      // For the debugger and full deoptimization stack, we must go past the invoke
-      // instruction, as it already executed.
-      // TODO: should be tested more once b/17586779 is fixed.
+      // Deoptimization is not called from code directly.
       const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]);
-      if (instr->IsInvoke()) {
+      if (deopt_method_type == DeoptimizationMethodType::kKeepDexPc) {
+        DCHECK(first);
+        // Need to re-execute the dex instruction.
+        // (1) An invocation might be split into class initialization and invoke.
+        //     In this case, the invoke should not be skipped.
+        // (2) A suspend check should also execute the dex instruction at the
+        //     corresponding dex pc.
+        DCHECK_EQ(new_dex_pc, dex_pc);
+      } else if (instr->Opcode() == Instruction::MONITOR_ENTER ||
+                 instr->Opcode() == Instruction::MONITOR_EXIT) {
+        DCHECK(deopt_method_type == DeoptimizationMethodType::kDefault);
+        DCHECK(first);
+        // Non-idempotent dex instruction should not be re-executed.
+        // On the other hand, if a MONITOR_ENTER is at the dex_pc of a suspend
+        // check, that MONITOR_ENTER should be executed. That case is handled
+        // above.
+        new_dex_pc = dex_pc + instr->SizeInCodeUnits();
+      } else if (instr->IsInvoke()) {
+        DCHECK(deopt_method_type == DeoptimizationMethodType::kDefault);
         if (IsStringInit(instr, shadow_frame->GetMethod())) {
           uint16_t this_obj_vreg = GetReceiverRegisterForStringInit(instr);
           // Move the StringFactory.newStringFromChars() result into the register representing
@@ -544,30 +538,27 @@
         }
         new_dex_pc = dex_pc + instr->SizeInCodeUnits();
       } else if (instr->Opcode() == Instruction::NEW_INSTANCE) {
-        // It's possible to deoptimize at a NEW_INSTANCE dex instruciton that's for a
-        // java string, which is turned into a call into StringFactory.newEmptyString();
-        // Move the StringFactory.newEmptyString() result into the destination register.
-        DCHECK(value.GetL()->IsString());
-        shadow_frame->SetVRegReference(instr->VRegA_21c(), value.GetL());
-        // new-instance doesn't generate a result value.
-        value.SetJ(0);
-        // Skip the dex instruction since we essentially come back from an invocation.
-        new_dex_pc = dex_pc + instr->SizeInCodeUnits();
-        if (kIsDebugBuild) {
-          ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-          // This is a suspend point. But it's ok since value has been set into shadow_frame.
-          ObjPtr<mirror::Class> klass = class_linker->ResolveType(
-              dex::TypeIndex(instr->VRegB_21c()), shadow_frame->GetMethod());
-          DCHECK(klass->IsStringClass());
-        }
+        // A NEW_INSTANCE is simply re-executed, including
+        // "new-instance String" which is compiled into a call into
+        // StringFactory.newEmptyString().
+        DCHECK_EQ(new_dex_pc, dex_pc);
       } else {
-        CHECK(false) << "Unexpected instruction opcode " << instr->Opcode()
-                     << " at dex_pc " << dex_pc
-                     << " of method: " << ArtMethod::PrettyMethod(shadow_frame->GetMethod(), false);
+        DCHECK(deopt_method_type == DeoptimizationMethodType::kDefault);
+        DCHECK(first);
+        // By default, we re-execute the dex instruction since if they are not
+        // an invoke, so that we don't have to decode the dex instruction to move
+        // result into the right vreg. All slow paths have been audited to be
+        // idempotent except monitor-enter/exit and invocation stubs.
+        // TODO: move result and advance dex pc. That also requires that we
+        // can tell the return type of a runtime method, possibly by decoding
+        // the dex instruction at the caller.
+        DCHECK_EQ(new_dex_pc, dex_pc);
       }
     } else {
       // Nothing to do, the dex_pc is the one at which the code requested
       // the deoptimization.
+      DCHECK(first);
+      DCHECK_EQ(new_dex_pc, dex_pc);
     }
     if (new_dex_pc != DexFile::kDexNoIndex) {
       shadow_frame->SetDexPC(new_dex_pc);
@@ -576,8 +567,10 @@
     ShadowFrame* old_frame = shadow_frame;
     shadow_frame = shadow_frame->GetLink();
     ShadowFrame::DeleteDeoptimizedFrame(old_frame);
-    // Following deoptimizations of shadow frames must pass the invoke instruction.
+    // Following deoptimizations of shadow frames must be at invocation point
+    // and should advance dex pc past the invoke instruction.
     from_code = false;
+    deopt_method_type = DeoptimizationMethodType::kDefault;
     first = false;
   }
   ret_val->SetJ(value.GetJ());