summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/dex/dex_to_dex_compiler.cc23
-rw-r--r--compiler/dex/mir_analysis.cc2
-rw-r--r--compiler/dex/mir_dataflow.cc2
-rw-r--r--compiler/dex/quick/mir_to_lir.cc2
-rw-r--r--compiler/dex/quick/quick_compiler.cc2
-rw-r--r--runtime/dex_instruction_list.h2
-rw-r--r--runtime/dex_instruction_utils.h2
-rw-r--r--runtime/interpreter/interpreter_goto_table_impl.cc12
-rw-r--r--runtime/interpreter/interpreter_switch_impl.cc10
-rw-r--r--runtime/oat.h2
-rw-r--r--runtime/verifier/method_verifier.cc17
-rw-r--r--tools/dexfuzz/src/dexfuzz/rawdex/Instruction.java2
-rw-r--r--tools/dexfuzz/src/dexfuzz/rawdex/Opcode.java4
13 files changed, 38 insertions, 44 deletions
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::Compile() {
}
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;
- }
- // Do we need a constructor barrier ?
- if (!driver_.RequiresConstructorBarrier(Thread::Current(), unit_.GetDexFile(),
- unit_.GetClassDefIndex())) {
- 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;
+ }
}
- // 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 @@ static const uint16_t kAnalysisAttributes[kMirOpLast] = {
// 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 @@ const uint64_t MIRGraph::oat_data_flow_attributes_[kMirOpLast] = {
// 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 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list
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 @@ static int kAllOpcodes[] = {
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 IsInstructionReturn(Instruction::Code opcode) {
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 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
}
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 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
}
HANDLE_INSTRUCTION_END();
- HANDLE_INSTRUCTION_START(RETURN_VOID_BARRIER) {
+ HANDLE_INSTRUCTION_START(RETURN_VOID) {
QuasiAtomic::ThreadFenceForConstructor();
JValue result;
self->AllowThreadSuspension();
@@ -2440,7 +2434,7 @@ JValue ExecuteGotoImpl(Thread* self, const DexFile::CodeItem* code_item, ShadowF
#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 @@ JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
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 @@ JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
}
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 InstructionSetFeatures;
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 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
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 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) {
// 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 @@ bool MethodVerifier::UpdateRegisters(uint32_t next_insn, RegisterLine* merge_lin
// 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 @@ public class Instruction implements RawDexObject {
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 @@ public enum Opcode {
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 enum Opcode {
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
+}