Change RETURN_VOID_BARRIER to RETURN_VOID_NO_BARRIER

We want to default to having a barrier for the case where we don't
dex to dex.

Bug: 19762303
Change-Id: I60348d89eaf0b9e1e480298afcecbb5f52e8661b
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index fcefb6f..548b6f8 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -180,22 +180,21 @@
 }
 
 void DexCompiler::CompileReturnVoid(Instruction* inst, uint32_t dex_pc) {
-  DCHECK(inst->Opcode() == Instruction::RETURN_VOID);
-  // Are we compiling a non-clinit constructor?
-  if (!unit_.IsConstructor() || unit_.IsStatic()) {
-    return;
+  DCHECK_EQ(inst->Opcode(), Instruction::RETURN_VOID);
+  if (unit_.IsConstructor()) {
+    // Are we compiling a non clinit constructor which needs a barrier ?
+    if (!unit_.IsStatic() &&
+        driver_.RequiresConstructorBarrier(Thread::Current(), unit_.GetDexFile(),
+                                           unit_.GetClassDefIndex())) {
+      return;
+    }
   }
-  // Do we need a constructor barrier ?
-  if (!driver_.RequiresConstructorBarrier(Thread::Current(), unit_.GetDexFile(),
-                                         unit_.GetClassDefIndex())) {
-    return;
-  }
-  // Replace RETURN_VOID by RETURN_VOID_BARRIER.
+  // Replace RETURN_VOID by RETURN_VOID_NO_BARRIER.
   VLOG(compiler) << "Replacing " << Instruction::Name(inst->Opcode())
-                 << " by " << Instruction::Name(Instruction::RETURN_VOID_BARRIER)
+                 << " by " << Instruction::Name(Instruction::RETURN_VOID_NO_BARRIER)
                  << " at dex pc " << StringPrintf("0x%x", dex_pc) << " in method "
                  << PrettyMethod(unit_.GetDexMethodIndex(), GetDexFile(), true);
-  inst->SetOpcode(Instruction::RETURN_VOID_BARRIER);
+  inst->SetOpcode(Instruction::RETURN_VOID_NO_BARRIER);
 }
 
 Instruction* DexCompiler::CompileCheckCast(Instruction* inst, uint32_t dex_pc) {
diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc
index a89b250..3d7a640 100644
--- a/compiler/dex/mir_analysis.cc
+++ b/compiler/dex/mir_analysis.cc
@@ -416,7 +416,7 @@
   // 72 INVOKE_INTERFACE {vD, vE, vF, vG, vA}
   kAnInvoke | kAnHeavyWeight,
 
-  // 73 RETURN_VOID_BARRIER
+  // 73 RETURN_VOID_NO_BARRIER
   kAnBranch,
 
   // 74 INVOKE_VIRTUAL_RANGE {vCCCC .. vNNNN}
diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc
index dfaff6c..f638b0b 100644
--- a/compiler/dex/mir_dataflow.cc
+++ b/compiler/dex/mir_dataflow.cc
@@ -374,7 +374,7 @@
   // 72 INVOKE_INTERFACE {vD, vE, vF, vG, vA}
   DF_FORMAT_35C | DF_NULL_CHK_OUT0 | DF_UMS,
 
-  // 73 RETURN_VOID_BARRIER
+  // 73 RETURN_VOID_NO_BARRIER
   DF_NOP,
 
   // 74 INVOKE_VIRTUAL_RANGE {vCCCC .. vNNNN}
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 8edc5fc..8fc45dc 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -540,7 +540,7 @@
       GenMoveException(rl_dest);
       break;
 
-    case Instruction::RETURN_VOID_BARRIER:
+    case Instruction::RETURN_VOID_NO_BARRIER:
     case Instruction::RETURN_VOID:
       if (((cu_->access_flags & kAccConstructor) != 0) &&
           cu_->compiler_driver->RequiresConstructorBarrier(Thread::Current(), cu_->dex_file,
diff --git a/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc
index 922f2f7..1673312 100644
--- a/compiler/dex/quick/quick_compiler.cc
+++ b/compiler/dex/quick/quick_compiler.cc
@@ -250,7 +250,7 @@
     Instruction::INVOKE_DIRECT,
     Instruction::INVOKE_STATIC,
     Instruction::INVOKE_INTERFACE,
-    Instruction::RETURN_VOID_BARRIER,
+    Instruction::RETURN_VOID_NO_BARRIER,
     Instruction::INVOKE_VIRTUAL_RANGE,
     Instruction::INVOKE_SUPER_RANGE,
     Instruction::INVOKE_DIRECT_RANGE,
diff --git a/runtime/dex_instruction_list.h b/runtime/dex_instruction_list.h
index a90f424..f8f85f9 100644
--- a/runtime/dex_instruction_list.h
+++ b/runtime/dex_instruction_list.h
@@ -133,7 +133,7 @@
   V(0x70, INVOKE_DIRECT, "invoke-direct", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgNonZero) \
   V(0x71, INVOKE_STATIC, "invoke-static", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArg) \
   V(0x72, INVOKE_INTERFACE, "invoke-interface", k35c, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgNonZero) \
-  V(0x73, RETURN_VOID_BARRIER, "return-void-barrier", k10x, false, kNone, kReturn, kVerifyNone) \
+  V(0x73, RETURN_VOID_NO_BARRIER, "return-void-no-barrier", k10x, false, kNone, kReturn, kVerifyNone) \
   V(0x74, INVOKE_VIRTUAL_RANGE, "invoke-virtual/range", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRangeNonZero) \
   V(0x75, INVOKE_SUPER_RANGE, "invoke-super/range", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRangeNonZero) \
   V(0x76, INVOKE_DIRECT_RANGE, "invoke-direct/range", k3rc, false, kMethodRef, kContinue | kThrow | kInvoke, kVerifyRegBMethod | kVerifyVarArgRangeNonZero) \
diff --git a/runtime/dex_instruction_utils.h b/runtime/dex_instruction_utils.h
index 1a671c5..f892f98 100644
--- a/runtime/dex_instruction_utils.h
+++ b/runtime/dex_instruction_utils.h
@@ -55,7 +55,7 @@
 
 constexpr bool IsInstructionInvoke(Instruction::Code opcode) {
   return Instruction::INVOKE_VIRTUAL <= opcode && opcode <= Instruction::INVOKE_INTERFACE_RANGE &&
-      opcode != Instruction::RETURN_VOID_BARRIER;
+      opcode != Instruction::RETURN_VOID_NO_BARRIER;
 }
 
 constexpr bool IsInstructionQuickInvoke(Instruction::Code opcode) {
diff --git a/runtime/interpreter/interpreter_goto_table_impl.cc b/runtime/interpreter/interpreter_goto_table_impl.cc
index af0a530..9c48df6 100644
--- a/runtime/interpreter/interpreter_goto_table_impl.cc
+++ b/runtime/interpreter/interpreter_goto_table_impl.cc
@@ -255,14 +255,8 @@
   }
   HANDLE_INSTRUCTION_END();
 
-  HANDLE_INSTRUCTION_START(RETURN_VOID) {
+  HANDLE_INSTRUCTION_START(RETURN_VOID_NO_BARRIER) {
     JValue result;
-    if (do_access_check) {
-      // If access checks are required then the dex-to-dex compiler and analysis of
-      // whether the class has final fields hasn't been performed. Conservatively
-      // perform the memory barrier now.
-      QuasiAtomic::ThreadFenceForConstructor();
-    }
     self->AllowThreadSuspension();
     instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
     if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
@@ -277,7 +271,7 @@
   }
   HANDLE_INSTRUCTION_END();
 
-  HANDLE_INSTRUCTION_START(RETURN_VOID_BARRIER) {
+  HANDLE_INSTRUCTION_START(RETURN_VOID) {
     QuasiAtomic::ThreadFenceForConstructor();
     JValue result;
     self->AllowThreadSuspension();
@@ -2440,7 +2434,7 @@
 #define INSTRUMENTATION_INSTRUCTION_HANDLER(o, code, n, f, r, i, a, v)                            \
   alt_op_##code: {                                                                                \
     if (Instruction::code != Instruction::RETURN_VOID &&                                          \
-        Instruction::code != Instruction::RETURN_VOID_BARRIER &&                                  \
+        Instruction::code != Instruction::RETURN_VOID_NO_BARRIER &&                               \
         Instruction::code != Instruction::RETURN &&                                               \
         Instruction::code != Instruction::RETURN_WIDE &&                                          \
         Instruction::code != Instruction::RETURN_OBJECT) {                                        \
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 9313c75..609faf5 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -170,14 +170,8 @@
         inst = inst->Next_1xx();
         break;
       }
-      case Instruction::RETURN_VOID: {
+      case Instruction::RETURN_VOID_NO_BARRIER: {
         JValue result;
-        if (do_access_check) {
-          // If access checks are required then the dex-to-dex compiler and analysis of
-          // whether the class has final fields hasn't been performed. Conservatively
-          // perform the memory barrier now.
-          QuasiAtomic::ThreadFenceForConstructor();
-        }
         self->AllowThreadSuspension();
         if (UNLIKELY(instrumentation->HasMethodExitListeners())) {
           instrumentation->MethodExitEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
@@ -189,7 +183,7 @@
         }
         return result;
       }
-      case Instruction::RETURN_VOID_BARRIER: {
+      case Instruction::RETURN_VOID: {
         QuasiAtomic::ThreadFenceForConstructor();
         JValue result;
         self->AllowThreadSuspension();
diff --git a/runtime/oat.h b/runtime/oat.h
index 79cb024..c4716ce 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,7 +32,7 @@
 class PACKED(4) OatHeader {
  public:
   static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
-  static constexpr uint8_t kOatVersion[] = { '0', '5', '8', '\0' };
+  static constexpr uint8_t kOatVersion[] = { '0', '6', '0', '\0' };
 
   static constexpr const char* kImageLocationKey = "image-location";
   static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 9ceb6f4..c67a58a 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -2742,9 +2742,16 @@
       break;
 
     // Special instructions.
-    case Instruction::RETURN_VOID_BARRIER:
-      if (!IsConstructor() || IsStatic()) {
-          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void-barrier not expected";
+    case Instruction::RETURN_VOID_NO_BARRIER:
+      if (IsConstructor() && !IsStatic()) {
+        auto& declaring_class = GetDeclaringClass();
+        auto* klass = declaring_class.GetClass();
+        for (uint32_t i = 0, num_fields = klass->NumInstanceFields(); i < num_fields; ++i) {
+          if (klass->GetInstanceField(i)->IsFinal()) {
+            Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "return-void-no-barrier not expected";
+            break;
+          }
+        }
       }
       break;
     // Note: the following instructions encode offsets derived from class linking.
@@ -3017,7 +3024,7 @@
       // 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_BARRIER)) {
+      if (opcode == Instruction::RETURN_VOID || opcode == Instruction::RETURN_VOID_NO_BARRIER) {
         SafelyMarkAllRegistersAsConflicts(this, work_line_.get());
       } else {
         if (opcode == Instruction::RETURN_WIDE) {
@@ -4163,7 +4170,7 @@
       // 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_BARRIER)) {
+      if (opcode == Instruction::RETURN_VOID || opcode == Instruction::RETURN_VOID_NO_BARRIER) {
         SafelyMarkAllRegistersAsConflicts(this, target_line);
       } else {
         target_line->CopyFromLine(merge_line);
diff --git a/tools/dexfuzz/src/dexfuzz/rawdex/Instruction.java b/tools/dexfuzz/src/dexfuzz/rawdex/Instruction.java
index 2dda78f..adafa62 100644
--- a/tools/dexfuzz/src/dexfuzz/rawdex/Instruction.java
+++ b/tools/dexfuzz/src/dexfuzz/rawdex/Instruction.java
@@ -434,7 +434,7 @@
     addOpcodeInfo(Opcode.INVOKE_DIRECT, "invoke-direct", 0x70, new Format35c());
     addOpcodeInfo(Opcode.INVOKE_STATIC, "invoke-static", 0x71, new Format35c());
     addOpcodeInfo(Opcode.INVOKE_INTERFACE, "invoke-interface", 0x72, new Format35c());
-    addOpcodeInfo(Opcode.RETURN_VOID_BARRIER, "return-void-barrier", 0x73, new Format10x());
+    addOpcodeInfo(Opcode.RETURN_VOID_NO_BARRIER, "return-void-no-barrier", 0x73, new Format10x());
     addOpcodeInfo(Opcode.INVOKE_VIRTUAL_RANGE, "invoke-virtual/range", 0x74, new Format3rc());
     addOpcodeInfo(Opcode.INVOKE_SUPER_RANGE, "invoke-super/range", 0x75, new Format3rc());
     addOpcodeInfo(Opcode.INVOKE_DIRECT_RANGE, "invoke-direct/range", 0x76, new Format3rc());
diff --git a/tools/dexfuzz/src/dexfuzz/rawdex/Opcode.java b/tools/dexfuzz/src/dexfuzz/rawdex/Opcode.java
index 312e855..f7c7788 100644
--- a/tools/dexfuzz/src/dexfuzz/rawdex/Opcode.java
+++ b/tools/dexfuzz/src/dexfuzz/rawdex/Opcode.java
@@ -132,7 +132,7 @@
   INVOKE_DIRECT,
   INVOKE_STATIC,
   INVOKE_INTERFACE,
-  RETURN_VOID_BARRIER,
+  RETURN_VOID_NO_BARRIER,
   INVOKE_VIRTUAL_RANGE,
   INVOKE_SUPER_RANGE,
   INVOKE_DIRECT_RANGE,
@@ -277,4 +277,4 @@
   public static boolean isBetween(Opcode opcode, Opcode opcode1, Opcode opcode2) {
     return (opcode.ordinal() >= opcode1.ordinal() && opcode.ordinal() <= opcode2.ordinal());
   }
-}
\ No newline at end of file
+}