From 743b98cd3d7db1cfd6b3d7f7795e8abd9d07a42d Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Mon, 24 Nov 2014 19:45:41 +0000 Subject: [PATCH] Skip null check in MarkGCCard() for known non-null values. Use GVN's knowledge of non-null values to set a new MIR flag for IPUT/SPUT/APUT to skip the value null check. Change-Id: I97a8d1447acb530c9bbbf7b362add366d1486ee1 --- compiler/dex/compiler_enums.h | 3 +-- compiler/dex/local_value_numbering.cc | 6 ++++++ compiler/dex/local_value_numbering_test.cc | 7 +++++-- compiler/dex/mir_graph.h | 3 +-- compiler/dex/quick/arm/int_arm.cc | 4 ++-- compiler/dex/quick/arm64/int_arm64.cc | 4 ++-- compiler/dex/quick/codegen_util.cc | 14 +++++++++----- compiler/dex/quick/gen_common.cc | 4 ++-- compiler/dex/quick/gen_invoke.cc | 2 +- compiler/dex/quick/mips/int_mips.cc | 2 +- compiler/dex/quick/mir_to_lir.cc | 2 +- compiler/dex/quick/mir_to_lir.h | 3 ++- compiler/dex/quick/x86/int_x86.cc | 4 ++-- 13 files changed, 35 insertions(+), 23 deletions(-) diff --git a/compiler/dex/compiler_enums.h b/compiler/dex/compiler_enums.h index b56fd6f5c..4d377df09 100644 --- a/compiler/dex/compiler_enums.h +++ b/compiler/dex/compiler_enums.h @@ -316,9 +316,8 @@ enum ExtendedMIROpcode { enum MIROptimizationFlagPositions { kMIRIgnoreNullCheck = 0, - kMIRNullCheckOnly, kMIRIgnoreRangeCheck, - kMIRRangeCheckOnly, + kMIRStoreNonNullValue, // Storing non-null value, always mark GC card. kMIRClassIsInitialized, kMIRClassIsInDexCache, kMirIgnoreDivZeroCheck, diff --git a/compiler/dex/local_value_numbering.cc b/compiler/dex/local_value_numbering.cc index e0c4e27b1..114346dd5 100644 --- a/compiler/dex/local_value_numbering.cc +++ b/compiler/dex/local_value_numbering.cc @@ -1110,6 +1110,12 @@ void LocalValueNumbering::HandlePutObject(MIR* mir) { // If we're storing a non-aliasing reference, stop tracking it as non-aliasing now. uint16_t base = GetOperandValue(mir->ssa_rep->uses[0]); HandleEscapingRef(base); + if (gvn_->CanModify() && null_checked_.count(base) != 0u) { + if (gvn_->GetCompilationUnit()->verbose) { + LOG(INFO) << "Removing GC card mark value null check for 0x" << std::hex << mir->offset; + } + mir->optimization_flags |= MIR_STORE_NON_NULL_VALUE; + } } void LocalValueNumbering::HandleEscapingRef(uint16_t base) { diff --git a/compiler/dex/local_value_numbering_test.cc b/compiler/dex/local_value_numbering_test.cc index f4f13f2c7..0fcb5843c 100644 --- a/compiler/dex/local_value_numbering_test.cc +++ b/compiler/dex/local_value_numbering_test.cc @@ -607,7 +607,9 @@ TEST_F(LocalValueNumberingTest, EscapingRefs) { EXPECT_NE(value_names_[13], value_names_[16]); // New value. EXPECT_NE(value_names_[14], value_names_[17]); // New value. for (size_t i = 0u; i != mir_count_; ++i) { - int expected = (i != 0u && i != 3u && i != 6u) ? MIR_IGNORE_NULL_CHECK : 0; + int expected = + ((i != 0u && i != 3u && i != 6u) ? MIR_IGNORE_NULL_CHECK : 0) | + ((i == 3u) ? MIR_STORE_NON_NULL_VALUE: 0); EXPECT_EQ(expected, mirs_[i].optimization_flags) << i; } } @@ -640,7 +642,8 @@ TEST_F(LocalValueNumberingTest, EscapingArrayRefs) { for (size_t i = 0u; i != mir_count_; ++i) { int expected = ((i != 0u && i != 3u && i != 6u && i != 9u) ? MIR_IGNORE_NULL_CHECK : 0u) | - ((i >= 4 && i != 6u && i != 9u) ? MIR_IGNORE_RANGE_CHECK : 0u); + ((i >= 4 && i != 6u && i != 9u) ? MIR_IGNORE_RANGE_CHECK : 0u) | + ((i == 3u) ? MIR_STORE_NON_NULL_VALUE: 0); EXPECT_EQ(expected, mirs_[i].optimization_flags) << i; } } diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index c8ea972d9..1a1884131 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -145,9 +145,8 @@ enum OatMethodAttributes { #define INVALID_OFFSET (0xDEADF00FU) #define MIR_IGNORE_NULL_CHECK (1 << kMIRIgnoreNullCheck) -#define MIR_NULL_CHECK_ONLY (1 << kMIRNullCheckOnly) #define MIR_IGNORE_RANGE_CHECK (1 << kMIRIgnoreRangeCheck) -#define MIR_RANGE_CHECK_ONLY (1 << kMIRRangeCheckOnly) +#define MIR_STORE_NON_NULL_VALUE (1 << kMIRStoreNonNullValue) #define MIR_CLASS_IS_INITIALIZED (1 << kMIRClassIsInitialized) #define MIR_CLASS_IS_IN_DEX_CACHE (1 << kMIRClassIsInDexCache) #define MIR_IGNORE_DIV_ZERO_CHECK (1 << kMirIgnoreDivZeroCheck) diff --git a/compiler/dex/quick/arm/int_arm.cc b/compiler/dex/quick/arm/int_arm.cc index cab039bfd..e38dbf5a8 100644 --- a/compiler/dex/quick/arm/int_arm.cc +++ b/compiler/dex/quick/arm/int_arm.cc @@ -872,7 +872,7 @@ bool ArmMir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) { if (is_object && !mir_graph_->IsConstantNullRef(rl_new_value)) { // Mark card for object assuming new value is stored. - MarkGCCard(rl_new_value.reg, rl_object.reg); + MarkGCCard(0, rl_new_value.reg, rl_object.reg); } RegLocation rl_offset = LoadValue(rl_src_offset, kCoreReg); @@ -1471,7 +1471,7 @@ void ArmMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, FreeTemp(reg_ptr); } if (card_mark) { - MarkGCCard(rl_src.reg, rl_array.reg); + MarkGCCard(opt_flags, rl_src.reg, rl_array.reg); } } diff --git a/compiler/dex/quick/arm64/int_arm64.cc b/compiler/dex/quick/arm64/int_arm64.cc index 0e0069838..b12fc0a31 100644 --- a/compiler/dex/quick/arm64/int_arm64.cc +++ b/compiler/dex/quick/arm64/int_arm64.cc @@ -758,7 +758,7 @@ bool Arm64Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) { if (is_object && !mir_graph_->IsConstantNullRef(rl_new_value)) { // Mark card for object assuming new value is stored. - MarkGCCard(rl_new_value.reg, rl_object.reg); + MarkGCCard(0, rl_new_value.reg, rl_object.reg); } RegStorage r_ptr = AllocTempRef(); @@ -1281,7 +1281,7 @@ void Arm64Mir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, FreeTemp(reg_ptr); } if (card_mark) { - MarkGCCard(rl_src.reg, rl_array.reg); + MarkGCCard(opt_flags, rl_src.reg, rl_array.reg); } } diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc index 80cb53530..1cde01e24 100644 --- a/compiler/dex/quick/codegen_util.cc +++ b/compiler/dex/quick/codegen_util.cc @@ -314,13 +314,17 @@ void Mir2Lir::UpdateLIROffsets() { } } -void Mir2Lir::MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg) { +void Mir2Lir::MarkGCCard(int opt_flags, RegStorage val_reg, RegStorage tgt_addr_reg) { DCHECK(val_reg.Valid()); DCHECK_EQ(val_reg.Is64Bit(), cu_->target64); - LIR* branch_over = OpCmpImmBranch(kCondEq, val_reg, 0, nullptr); - UnconditionallyMarkGCCard(tgt_addr_reg); - LIR* target = NewLIR0(kPseudoTargetLabel); - branch_over->target = target; + if ((opt_flags & MIR_STORE_NON_NULL_VALUE) != 0) { + UnconditionallyMarkGCCard(tgt_addr_reg); + } else { + LIR* branch_over = OpCmpImmBranch(kCondEq, val_reg, 0, nullptr); + UnconditionallyMarkGCCard(tgt_addr_reg); + LIR* target = NewLIR0(kPseudoTargetLabel); + branch_over->target = target; + } } /* Dump instructions and constant pool contents */ diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index 4dd24cb9f..d1b8b034d 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -665,7 +665,7 @@ void Mir2Lir::GenSput(MIR* mir, RegLocation rl_src, OpSize size) { field_info.IsVolatile() ? kVolatile : kNotVolatile); } if (IsRef(size) && !mir_graph_->IsConstantNullRef(rl_src)) { - MarkGCCard(rl_src.reg, r_base); + MarkGCCard(mir->optimization_flags, rl_src.reg, r_base); } FreeTemp(r_base); } else { @@ -940,7 +940,7 @@ void Mir2Lir::GenIPut(MIR* mir, int opt_flags, OpSize size, } MarkPossibleNullPointerExceptionAfter(opt_flags, store); if (IsRef(size) && !mir_graph_->IsConstantNullRef(rl_src)) { - MarkGCCard(rl_src.reg, rl_obj.reg); + MarkGCCard(opt_flags, rl_src.reg, rl_obj.reg); } } else { QuickEntrypointEnum target; diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc index a7900ae7d..31b81bfb9 100755 --- a/compiler/dex/quick/gen_invoke.cc +++ b/compiler/dex/quick/gen_invoke.cc @@ -1668,7 +1668,7 @@ bool Mir2Lir::GenInlinedUnsafePut(CallInfo* info, bool is_long, GenMemBarrier(kAnyAny); } if (is_object) { - MarkGCCard(rl_value.reg, rl_object.reg); + MarkGCCard(0, rl_value.reg, rl_object.reg); } return true; } diff --git a/compiler/dex/quick/mips/int_mips.cc b/compiler/dex/quick/mips/int_mips.cc index fb4723800..0778c3bad 100644 --- a/compiler/dex/quick/mips/int_mips.cc +++ b/compiler/dex/quick/mips/int_mips.cc @@ -641,7 +641,7 @@ void MipsMir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, FreeTemp(reg_ptr); } if (card_mark) { - MarkGCCard(rl_src.reg, rl_array.reg); + MarkGCCard(opt_flags, rl_src.reg, rl_array.reg); } } diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc index 70ef991de..0d3092767 100644 --- a/compiler/dex/quick/mir_to_lir.cc +++ b/compiler/dex/quick/mir_to_lir.cc @@ -332,7 +332,7 @@ bool Mir2Lir::GenSpecialIPut(MIR* mir, const InlineMethod& special) { kNotVolatile); } if (IsRef(size)) { - MarkGCCard(reg_src, reg_obj); + MarkGCCard(0, reg_src, reg_obj); } return true; } diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index 886b238ee..49b8452cb 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -1075,8 +1075,9 @@ class Mir2Lir : public Backend { * @brief Mark a garbage collection card. Skip if the stored value is null. * @param val_reg the register holding the stored value to check against null. * @param tgt_addr_reg the address of the object or array where the value was stored. + * @param opt_flags the optimization flags which may indicate that the value is non-null. */ - void MarkGCCard(RegStorage val_reg, RegStorage tgt_addr_reg); + void MarkGCCard(int opt_flags, RegStorage val_reg, RegStorage tgt_addr_reg); /* * @brief Load the address of the dex method into the register. diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc index 3f501b4cd..74ae8a6a5 100755 --- a/compiler/dex/quick/x86/int_x86.cc +++ b/compiler/dex/quick/x86/int_x86.cc @@ -1170,7 +1170,7 @@ bool X86Mir2Lir::GenInlinedCas(CallInfo* info, bool is_long, bool is_object) { if (is_object && !mir_graph_->IsConstantNullRef(rl_new_value)) { // Mark card for object assuming new value is stored. FreeTemp(rs_r0); // Temporarily release EAX for MarkGCCard(). - MarkGCCard(rl_new_value.reg, rl_object.reg); + MarkGCCard(0, rl_new_value.reg, rl_object.reg); LockTemp(rs_r0); } @@ -2398,7 +2398,7 @@ void X86Mir2Lir::GenArrayPut(int opt_flags, OpSize size, RegLocation rl_array, if (!constant_index) { FreeTemp(rl_index.reg); } - MarkGCCard(rl_src.reg, rl_array.reg); + MarkGCCard(opt_flags, rl_src.reg, rl_array.reg); } } -- 2.11.0