ART: Balanced locking

Change the verifier to check for balanced locking. When balanced
locking can't be guaranteed, use a new failure kind to punt to
the interpreter.

Add smali tests, with JNI code to check the balanced-locking result.

Bug: 23502994
Change-Id: Icd7db0be20ef2f69f0ac784de43dcba990035cd8
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 223268d..4f921bd 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -589,7 +589,7 @@
 
 std::ostream& MethodVerifier::Fail(VerifyError error) {
   // Mark the error type as encountered.
-  encountered_failure_types_ |= (1U << static_cast<uint32_t>(error));
+  encountered_failure_types_ |= static_cast<uint32_t>(error);
 
   switch (error) {
     case VERIFY_ERROR_NO_CLASS:
@@ -601,6 +601,7 @@
     case VERIFY_ERROR_INSTANTIATION:
     case VERIFY_ERROR_CLASS_CHANGE:
     case VERIFY_ERROR_FORCE_INTERPRETER:
+    case VERIFY_ERROR_LOCKING:
       if (Runtime::Current()->IsAotCompiler() || !can_load_classes_) {
         // If we're optimistically running verification at compile time, turn NO_xxx, ACCESS_xxx,
         // class change and instantiation errors into soft verification errors so that we re-verify
@@ -631,12 +632,14 @@
         }
       }
       break;
+
       // Indication that verification should be retried at runtime.
     case VERIFY_ERROR_BAD_CLASS_SOFT:
       if (!allow_soft_failures_) {
         have_pending_hard_failure_ = true;
       }
       break;
+
       // Hard verification failures at compile time will still fail at runtime, so the class is
       // marked as rejected to prevent it from being compiled.
     case VERIFY_ERROR_BAD_CLASS_HARD: {
@@ -1657,6 +1660,33 @@
   return DexFile::kDexNoIndex;
 }
 
+// Setup a register line for the given return instruction.
+static void AdjustReturnLine(MethodVerifier* verifier,
+                             const Instruction* ret_inst,
+                             RegisterLine* line) {
+  Instruction::Code opcode = ret_inst->Opcode();
+
+  switch (opcode) {
+    case Instruction::RETURN_VOID:
+    case Instruction::RETURN_VOID_NO_BARRIER:
+      SafelyMarkAllRegistersAsConflicts(verifier, line);
+      break;
+
+    case Instruction::RETURN:
+    case Instruction::RETURN_OBJECT:
+      line->MarkAllRegistersAsConflictsExcept(verifier, ret_inst->VRegA_11x());
+      break;
+
+    case Instruction::RETURN_WIDE:
+      line->MarkAllRegistersAsConflictsExceptWide(verifier, ret_inst->VRegA_11x());
+      break;
+
+    default:
+      LOG(FATAL) << "Unknown return opcode " << opcode;
+      UNREACHABLE();
+  }
+}
+
 bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
   // If we're doing FindLocksAtDexPc, check whether we're at the dex pc we care about.
   // We want the state _before_ the instruction, for the case where the dex pc we're
@@ -3078,10 +3108,9 @@
   } else if (have_pending_runtime_throw_failure_) {
     /* checking interpreter will throw, mark following code as unreachable */
     opcode_flags = Instruction::kThrow;
-    have_any_pending_runtime_throw_failure_ = true;
-    // Reset the pending_runtime_throw flag. The flag is a global to decouple Fail and is per
-    // instruction.
-    have_pending_runtime_throw_failure_ = false;
+    // Note: the flag must be reset as it is only global to decouple Fail and is semantically per
+    //       instruction. However, RETURN checking may throw LOCKING errors, so we clear at the
+    //       very end.
   }
   /*
    * If we didn't just set the result register, clear it out. This ensures that you can only use
@@ -3250,16 +3279,7 @@
     if (insn_flags_[next_insn_idx].IsReturn()) {
       // For returns we only care about the operand to the return, all other registers are dead.
       const Instruction* ret_inst = Instruction::At(code_item_->insns_ + next_insn_idx);
-      Instruction::Code opcode = ret_inst->Opcode();
-      if (opcode == Instruction::RETURN_VOID || opcode == Instruction::RETURN_VOID_NO_BARRIER) {
-        SafelyMarkAllRegistersAsConflicts(this, work_line_.get());
-      } else {
-        if (opcode == Instruction::RETURN_WIDE) {
-          work_line_->MarkAllRegistersAsConflictsExceptWide(this, ret_inst->VRegA_11x());
-        } else {
-          work_line_->MarkAllRegistersAsConflictsExcept(this, ret_inst->VRegA_11x());
-        }
-      }
+      AdjustReturnLine(this, ret_inst, work_line_.get());
     }
     RegisterLine* next_line = reg_table_.GetLine(next_insn_idx);
     if (next_line != nullptr) {
@@ -3280,9 +3300,7 @@
 
   /* If we're returning from the method, make sure monitor stack is empty. */
   if ((opcode_flags & Instruction::kReturn) != 0) {
-    if (!work_line_->VerifyMonitorStackEmpty(this)) {
-      return false;
-    }
+    work_line_->VerifyMonitorStackEmpty(this);
   }
 
   /*
@@ -3302,6 +3320,12 @@
   DCHECK_LT(*start_guess, code_item_->insns_size_in_code_units_);
   DCHECK(insn_flags_[*start_guess].IsOpcode());
 
+  if (have_pending_runtime_throw_failure_) {
+    have_any_pending_runtime_throw_failure_ = true;
+    // Reset the pending_runtime_throw flag now.
+    have_pending_runtime_throw_failure_ = false;
+  }
+
   return true;
 }  // NOLINT(readability/fn_size)
 
@@ -4425,31 +4449,15 @@
      * there's nothing to "merge". Copy the registers over and mark it as changed. (This is the
      * only way a register can transition out of "unknown", so this is not just an optimization.)
      */
-    if (!insn_flags_[next_insn].IsReturn()) {
-      target_line->CopyFromLine(merge_line);
-    } else {
+    target_line->CopyFromLine(merge_line);
+    if (insn_flags_[next_insn].IsReturn()) {
       // Verify that the monitor stack is empty on return.
-      if (!merge_line->VerifyMonitorStackEmpty(this)) {
-        return false;
-      }
+      merge_line->VerifyMonitorStackEmpty(this);
+
       // For returns we only care about the operand to the return, all other registers are dead.
       // Initialize them as conflicts so they don't add to GC and deoptimization information.
       const Instruction* ret_inst = Instruction::At(code_item_->insns_ + next_insn);
-      Instruction::Code opcode = ret_inst->Opcode();
-      if (opcode == Instruction::RETURN_VOID || opcode == Instruction::RETURN_VOID_NO_BARRIER) {
-        // Explicitly copy the this-initialized flag from the merge-line, as we didn't copy its
-        // state. Must be done before SafelyMarkAllRegistersAsConflicts as that will do the
-        // super-constructor-call checking.
-        target_line->CopyThisInitialized(*merge_line);
-        SafelyMarkAllRegistersAsConflicts(this, target_line);
-      } else {
-        target_line->CopyFromLine(merge_line);
-        if (opcode == Instruction::RETURN_WIDE) {
-          target_line->MarkAllRegistersAsConflictsExceptWide(this, ret_inst->VRegA_11x());
-        } else {
-          target_line->MarkAllRegistersAsConflictsExcept(this, ret_inst->VRegA_11x());
-        }
-      }
+      AdjustReturnLine(this, ret_inst, target_line);
     }
   } else {
     std::unique_ptr<RegisterLine> copy(gDebugVerify ?