diff options
-rw-r--r-- | compiler/dex/dex_to_dex_compiler.cc | 23 | ||||
-rw-r--r-- | compiler/dex/mir_analysis.cc | 2 | ||||
-rw-r--r-- | compiler/dex/mir_dataflow.cc | 2 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.cc | 2 | ||||
-rw-r--r-- | compiler/dex/quick/quick_compiler.cc | 2 | ||||
-rw-r--r-- | runtime/dex_instruction_list.h | 2 | ||||
-rw-r--r-- | runtime/dex_instruction_utils.h | 2 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_goto_table_impl.cc | 12 | ||||
-rw-r--r-- | runtime/interpreter/interpreter_switch_impl.cc | 10 | ||||
-rw-r--r-- | runtime/oat.h | 2 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 17 | ||||
-rw-r--r-- | tools/dexfuzz/src/dexfuzz/rawdex/Instruction.java | 2 | ||||
-rw-r--r-- | tools/dexfuzz/src/dexfuzz/rawdex/Opcode.java | 4 |
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 +} |