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
+}