summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/dex/mir_dataflow.cc6
-rw-r--r--compiler/dex/mir_graph.cc13
-rw-r--r--compiler/dex/mir_graph.h5
-rw-r--r--compiler/dex/mir_optimization.cc10
-rw-r--r--compiler/dex/mir_optimization_test.cc2
-rw-r--r--compiler/dex/portable/mir_to_gbc.cc2
-rw-r--r--compiler/dex/quick/mir_to_lir.cc2
-rw-r--r--compiler/dex/quick/x86/utility_x86.cc2
-rw-r--r--compiler/dex/vreg_analysis.cc2
-rw-r--r--runtime/arch/stub_test.cc4
-rw-r--r--runtime/arch/x86_64/quick_entrypoints_x86_64.S56
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