diff options
| -rw-r--r-- | compiler/dex/mir_dataflow.cc | 6 | ||||
| -rw-r--r-- | compiler/dex/mir_graph.cc | 13 | ||||
| -rw-r--r-- | compiler/dex/mir_graph.h | 5 | ||||
| -rw-r--r-- | compiler/dex/mir_optimization.cc | 10 | ||||
| -rw-r--r-- | compiler/dex/mir_optimization_test.cc | 2 | ||||
| -rw-r--r-- | compiler/dex/portable/mir_to_gbc.cc | 2 | ||||
| -rw-r--r-- | compiler/dex/quick/mir_to_lir.cc | 2 | ||||
| -rw-r--r-- | compiler/dex/quick/x86/utility_x86.cc | 2 | ||||
| -rw-r--r-- | compiler/dex/vreg_analysis.cc | 2 | ||||
| -rw-r--r-- | runtime/arch/stub_test.cc | 4 | ||||
| -rw-r--r-- | runtime/arch/x86_64/quick_entrypoints_x86_64.S | 56 |
11 files changed, 83 insertions, 21 deletions
diff --git a/compiler/dex/mir_dataflow.cc b/compiler/dex/mir_dataflow.cc index 36f1be7bdf..651fa66b9d 100644 --- a/compiler/dex/mir_dataflow.cc +++ b/compiler/dex/mir_dataflow.cc @@ -879,7 +879,7 @@ bool MIRGraph::FindLocalLiveIn(BasicBlock* bb) { new (arena_) ArenaBitVector(arena_, cu_->num_dalvik_registers, false, kBitMapLiveIn); for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { - uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; + uint64_t df_attributes = GetDataFlowAttributes(mir); DecodedInstruction *d_insn = &mir->dalvikInsn; if (df_attributes & DF_HAS_USES) { @@ -994,7 +994,7 @@ bool MIRGraph::DoSSAConversion(BasicBlock* bb) { static_cast<struct SSARepresentation *>(arena_->Alloc(sizeof(SSARepresentation), kArenaAllocDFInfo)); - uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; + uint64_t df_attributes = GetDataFlowAttributes(mir); // If not a pseudo-op, note non-leaf or can throw if (static_cast<int>(mir->dalvikInsn.opcode) < @@ -1252,7 +1252,7 @@ void MIRGraph::CountUses(struct BasicBlock* bb) { use_counts_.Put(s_reg, use_counts_.Get(s_reg) + weight); } if (!(cu_->disable_opt & (1 << kPromoteCompilerTemps))) { - uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; + uint64_t df_attributes = GetDataFlowAttributes(mir); // Implicit use of Method* ? */ if (df_attributes & DF_UMS) { /* diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc index 8ce4f1ff9a..6857edbbe7 100644 --- a/compiler/dex/mir_graph.cc +++ b/compiler/dex/mir_graph.cc @@ -621,7 +621,7 @@ void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_ int flags = Instruction::FlagsOf(insn->dalvikInsn.opcode); int verify_flags = Instruction::VerifyFlagsOf(insn->dalvikInsn.opcode); - uint64_t df_flags = oat_data_flow_attributes_[insn->dalvikInsn.opcode]; + uint64_t df_flags = GetDataFlowAttributes(insn); merged_df_flags |= df_flags; if (df_flags & DF_HAS_DEFS) { @@ -743,6 +743,17 @@ void MIRGraph::ShowOpcodeStats() { } } +uint64_t MIRGraph::GetDataFlowAttributes(Instruction::Code opcode) { + DCHECK_LT((size_t) opcode, (sizeof(oat_data_flow_attributes_) / sizeof(oat_data_flow_attributes_[0]))); + return oat_data_flow_attributes_[opcode]; +} + +uint64_t MIRGraph::GetDataFlowAttributes(MIR* mir) { + DCHECK(mir != nullptr); + Instruction::Code opcode = mir->dalvikInsn.opcode; + return GetDataFlowAttributes(opcode); +} + // TODO: use a configurable base prefix, and adjust callers to supply pass name. /* Dump the CFG into a DOT graph */ void MIRGraph::DumpCFG(const char* dir_prefix, bool all_blocks, const char *suffix) { diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index 2c125f6aa0..5997e5b5bd 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -851,6 +851,9 @@ class MIRGraph { */ void CountUses(struct BasicBlock* bb); + static uint64_t GetDataFlowAttributes(Instruction::Code opcode); + static uint64_t GetDataFlowAttributes(MIR* mir); + /** * @brief Combine BasicBlocks * @param the BasicBlock we are considering @@ -868,7 +871,6 @@ class MIRGraph { RegLocation* reg_location_; // Map SSA names to location. SafeMap<unsigned int, unsigned int> block_id_map_; // Block collapse lookup cache. - static const uint64_t oat_data_flow_attributes_[kMirOpLast]; static const char* extended_mir_op_names_[kMirOpLast - kMirOpFirst]; static const uint32_t analysis_attributes_[kMirOpLast]; @@ -985,6 +987,7 @@ class MIRGraph { GrowableArray<MirIFieldLoweringInfo> ifield_lowering_infos_; GrowableArray<MirSFieldLoweringInfo> sfield_lowering_infos_; GrowableArray<MirMethodLoweringInfo> method_lowering_infos_; + static const uint64_t oat_data_flow_attributes_[kMirOpLast]; friend class ClassInitCheckEliminationTest; friend class LocalValueNumberingTest; diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc index 937e2585ef..72c46cc975 100644 --- a/compiler/dex/mir_optimization.cc +++ b/compiler/dex/mir_optimization.cc @@ -43,11 +43,11 @@ void MIRGraph::DoConstantPropagation(BasicBlock* bb) { for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) { // Skip pass if BB has MIR without SSA representation. - if (mir->ssa_rep == NULL) { + if (mir->ssa_rep == nullptr) { return; } - uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; + uint64_t df_attributes = GetDataFlowAttributes(mir); DecodedInstruction *d_insn = &mir->dalvikInsn; @@ -559,7 +559,7 @@ void MIRGraph::CountChecks(struct BasicBlock* bb) { if (mir->ssa_rep == NULL) { continue; } - uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; + uint64_t df_attributes = GetDataFlowAttributes(mir); if (df_attributes & DF_HAS_NULL_CHKS) { checkstats_->null_checks++; if (mir->optimization_flags & MIR_IGNORE_NULL_CHECK) { @@ -644,7 +644,7 @@ void MIRGraph::CombineBlocks(struct BasicBlock* bb) { MIR* mir = bb->last_mir_insn; // Grab the attributes from the paired opcode MIR* throw_insn = mir->meta.throw_insn; - uint64_t df_attributes = oat_data_flow_attributes_[throw_insn->dalvikInsn.opcode]; + uint64_t df_attributes = GetDataFlowAttributes(throw_insn); bool can_combine = true; if (df_attributes & DF_HAS_NULL_CHKS) { can_combine &= ((throw_insn->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0); @@ -796,7 +796,7 @@ bool MIRGraph::EliminateNullChecksAndInferTypes(BasicBlock* bb) { continue; } - uint64_t df_attributes = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; + uint64_t df_attributes = GetDataFlowAttributes(mir); // Might need a null check? if (df_attributes & DF_HAS_NULL_CHKS) { diff --git a/compiler/dex/mir_optimization_test.cc b/compiler/dex/mir_optimization_test.cc index 40ced70948..891d9fb7ea 100644 --- a/compiler/dex/mir_optimization_test.cc +++ b/compiler/dex/mir_optimization_test.cc @@ -172,7 +172,7 @@ class ClassInitCheckEliminationTest : public testing::Test { mir->offset = 2 * i; // All insns need to be at least 2 code units long. mir->width = 2u; mir->optimization_flags = 0u; - merged_df_flags |= MIRGraph::oat_data_flow_attributes_[def->opcode]; + merged_df_flags |= MIRGraph::GetDataFlowAttributes(def->opcode); } cu_.mir_graph->merged_df_flags_ = merged_df_flags; diff --git a/compiler/dex/portable/mir_to_gbc.cc b/compiler/dex/portable/mir_to_gbc.cc index 70438ecd50..576e2424fa 100644 --- a/compiler/dex/portable/mir_to_gbc.cc +++ b/compiler/dex/portable/mir_to_gbc.cc @@ -722,7 +722,7 @@ bool MirConverter::ConvertMIRNode(MIR* mir, BasicBlock* bb, /* Prep Src and Dest locations */ int next_sreg = 0; int next_loc = 0; - uint64_t attrs = mir_graph_->oat_data_flow_attributes_[opcode]; + uint64_t attrs = MirGraph::GetDataFlowAttributes(opcode); rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc(); if (attrs & DF_UA) { if (attrs & DF_A_WIDE) { diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc index 6c5279e184..107987ef0d 100644 --- a/compiler/dex/quick/mir_to_lir.cc +++ b/compiler/dex/quick/mir_to_lir.cc @@ -286,7 +286,7 @@ void Mir2Lir::CompileDalvikInstruction(MIR* mir, BasicBlock* bb, LIR* label_list // Prep Src and Dest locations. int next_sreg = 0; int next_loc = 0; - uint64_t attrs = mir_graph_->oat_data_flow_attributes_[opcode]; + uint64_t attrs = MIRGraph::GetDataFlowAttributes(opcode); rl_src[0] = rl_src[1] = rl_src[2] = mir_graph_->GetBadLoc(); if (attrs & DF_UA) { if (attrs & DF_A_WIDE) { diff --git a/compiler/dex/quick/x86/utility_x86.cc b/compiler/dex/quick/x86/utility_x86.cc index 4d45055927..b972d0885d 100644 --- a/compiler/dex/quick/x86/utility_x86.cc +++ b/compiler/dex/quick/x86/utility_x86.cc @@ -889,7 +889,7 @@ void X86Mir2Lir::AnalyzeMIR(int opcode, BasicBlock * bb, MIR *mir) { void X86Mir2Lir::AnalyzeFPInstruction(int opcode, BasicBlock * bb, MIR *mir) { // Look at all the uses, and see if they are double constants. - uint64_t attrs = mir_graph_->oat_data_flow_attributes_[opcode]; + uint64_t attrs = MIRGraph::GetDataFlowAttributes(static_cast<Instruction::Code>(opcode)); int next_sreg = 0; if (attrs & DF_UA) { if (attrs & DF_A_WIDE) { diff --git a/compiler/dex/vreg_analysis.cc b/compiler/dex/vreg_analysis.cc index 4be0f59071..d5c2598356 100644 --- a/compiler/dex/vreg_analysis.cc +++ b/compiler/dex/vreg_analysis.cc @@ -124,7 +124,7 @@ bool MIRGraph::SetHigh(int index) { bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) { SSARepresentation *ssa_rep = mir->ssa_rep; if (ssa_rep) { - uint64_t attrs = oat_data_flow_attributes_[mir->dalvikInsn.opcode]; + uint64_t attrs = GetDataFlowAttributes(mir); const int* uses = ssa_rep->uses; const int* defs = ssa_rep->defs; diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc index 437beb5b0f..8fbca9408a 100644 --- a/runtime/arch/stub_test.cc +++ b/runtime/arch/stub_test.cc @@ -183,12 +183,12 @@ TEST_F(StubTest, Memcpy) { } -#if defined(__i386__) || defined(__arm__) +#if defined(__i386__) || defined(__arm__) || defined(__x86_64__) extern "C" void art_quick_lock_object(void); #endif TEST_F(StubTest, LockObject) { -#if defined(__i386__) || defined(__arm__) +#if defined(__i386__) || defined(__arm__) || defined(__x86_64__) Thread* self = Thread::Current(); // Create an object ScopedObjectAccess soa(self); diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S index cac6cfdd79..9ccf6c97de 100644 --- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S +++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S @@ -661,13 +661,61 @@ TWO_ARG_DOWNCALL art_quick_initialize_type_and_verify_access, artInitializeTypeA TWO_ARG_DOWNCALL art_quick_handle_fill_data, artHandleFillArrayDataFromCode, RETURN_IF_EAX_ZERO DEFINE_FUNCTION art_quick_lock_object - int3 - int3 + testl %edi, %edi // Null check object/rdi. + jz .Lslow_lock +.Lretry_lock: + movl LOCK_WORD_OFFSET(%edi), %ecx // ecx := lock word. + test LITERAL(0xC0000000), %ecx // Test the 2 high bits. + jne .Lslow_lock // Slow path if either of the two high bits are set. + movl %gs:THREAD_ID_OFFSET, %edx // edx := thread id + test %ecx, %ecx + jnz .Lalready_thin // Lock word contains a thin lock. + // unlocked case - %edx holds thread id with count of 0 + xor %eax, %eax // eax == 0 for comparison with lock word in cmpxchg + lock cmpxchg %edx, LOCK_WORD_OFFSET(%edi) + jnz .Lretry_lock // cmpxchg failed retry + ret +.Lalready_thin: + cmpw %cx, %dx // do we hold the lock already? + jne .Lslow_lock + addl LITERAL(65536), %ecx // increment recursion count + test LITERAL(0xC0000000), %ecx // overflowed if either of top two bits are set + jne .Lslow_lock // count overflowed so go slow + movl %ecx, LOCK_WORD_OFFSET(%edi) // update lockword, cmpxchg not necessary as we hold lock + ret +.Lslow_lock: + SETUP_REF_ONLY_CALLEE_SAVE_FRAME + movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current() + movq %rsp, %rdx // pass SP + call PLT_SYMBOL(artLockObjectFromCode) // artLockObjectFromCode(object, Thread*, SP) + RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address + RETURN_IF_EAX_ZERO END_FUNCTION art_quick_lock_object DEFINE_FUNCTION art_quick_unlock_object - int3 - int3 + testl %edi, %edi // null check object/edi + jz .Lslow_unlock + movl LOCK_WORD_OFFSET(%edi), %ecx // ecx := lock word + movl %gs:THREAD_ID_OFFSET, %edx // edx := thread id + test %ecx, %ecx + jb .Lslow_unlock // lock word contains a monitor + cmpw %cx, %dx // does the thread id match? + jne .Lslow_unlock + cmpl LITERAL(65536), %ecx + jae .Lrecursive_thin_unlock + movl LITERAL(0), LOCK_WORD_OFFSET(%edi) + ret +.Lrecursive_thin_unlock: + subl LITERAL(65536), %ecx + mov %ecx, LOCK_WORD_OFFSET(%edi) + ret +.Lslow_unlock: + SETUP_REF_ONLY_CALLEE_SAVE_FRAME + movq %gs:THREAD_SELF_OFFSET, %rsi // pass Thread::Current() + movq %rsp, %rdx // pass SP + call PLT_SYMBOL(artUnlockObjectFromCode) // artUnlockObjectFromCode(object, Thread*, SP) + RESTORE_REF_ONLY_CALLEE_SAVE_FRAME // restore frame up to return address + RETURN_IF_EAX_ZERO END_FUNCTION art_quick_unlock_object DEFINE_FUNCTION art_quick_is_assignable |