diff options
-rw-r--r-- | compiler/dex/inline_method_analyser.cc | 52 | ||||
-rw-r--r-- | compiler/dex/inline_method_analyser.h | 2 | ||||
-rw-r--r-- | compiler/optimizing/inliner.cc | 17 |
3 files changed, 32 insertions, 39 deletions
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc index 85cf83c099..11b20aa190 100644 --- a/compiler/dex/inline_method_analyser.cc +++ b/compiler/dex/inline_method_analyser.cc @@ -210,7 +210,8 @@ bool RecordConstructorIPut(ArtMethod* method, const Instruction* new_iput, uint16_t this_vreg, uint16_t zero_vreg_mask, - /*inout*/ ConstructorIPutData (&iputs)[kMaxConstructorIPuts]) + /*inout*/ ConstructorIPutData (&iputs)[kMaxConstructorIPuts], + /*inout*/ size_t& iput_count) REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK(IsInstructionIPut(new_iput->Opcode())); uint32_t field_index = new_iput->VRegC_22c(); @@ -221,46 +222,38 @@ bool RecordConstructorIPut(ArtMethod* method, } // Remove previous IPUT to the same field, if any. Different field indexes may refer // to the same field, so we need to compare resolved fields from the dex cache. - for (size_t old_pos = 0; old_pos != arraysize(iputs); ++old_pos) { - if (iputs[old_pos].field_index == DexFile::kDexNoIndex16) { - break; - } + for (size_t old_pos = 0, end = iput_count; old_pos < end; ++old_pos) { ArtField* f = class_linker->LookupResolvedField(iputs[old_pos].field_index, method, /* is_static= */ false); DCHECK(f != nullptr); if (f == field) { - auto back_it = std::copy(iputs + old_pos + 1, iputs + arraysize(iputs), iputs + old_pos); + auto back_it = std::copy(iputs + old_pos + 1, iputs + iput_count, iputs + old_pos); *back_it = ConstructorIPutData(); + --iput_count; break; } } // If the stored value isn't zero, record the IPUT. if ((zero_vreg_mask & (1u << new_iput->VRegA_22c())) == 0u) { - size_t new_pos = 0; - while (new_pos != arraysize(iputs) && iputs[new_pos].field_index != DexFile::kDexNoIndex16) { - ++new_pos; - } + size_t new_pos = iput_count; if (new_pos == arraysize(iputs)) { return false; // Exceeded capacity of the output array. } iputs[new_pos].field_index = field_index; iputs[new_pos].arg = new_iput->VRegA_22c() - this_vreg; + ++iput_count; } return true; } bool DoAnalyseConstructor(const CodeItemDataAccessor* code_item, ArtMethod* method, - /*inout*/ ConstructorIPutData (&iputs)[kMaxConstructorIPuts]) + /*inout*/ ConstructorIPutData (&iputs)[kMaxConstructorIPuts], + /*inout*/ size_t &iput_count) REQUIRES_SHARED(Locks::mutator_lock_) { // On entry we should not have any IPUTs yet. - DCHECK(std::all_of( - iputs, - iputs + arraysize(iputs), - [](const ConstructorIPutData& iput_data) { - return iput_data.field_index == DexFile::kDexNoIndex16; - })); + DCHECK_EQ(iput_count, 0u); // Limit the maximum number of code units we're willing to match. static constexpr size_t kMaxCodeUnits = 16u; @@ -329,21 +322,21 @@ bool DoAnalyseConstructor(const CodeItemDataAccessor* code_item, if (!target_code_item.HasCodeItem()) { return false; // Native constructor? } - if (!DoAnalyseConstructor(&target_code_item, target_method, iputs)) { + if (!DoAnalyseConstructor(&target_code_item, target_method, iputs, iput_count)) { return false; } // Prune IPUTs with zero input. auto kept_end = std::remove_if( iputs, - iputs + arraysize(iputs), + iputs + iput_count, [forwarded](const ConstructorIPutData& iput_data) { return iput_data.arg >= forwarded; }); + iput_count = std::distance(iputs, kept_end); std::fill(kept_end, iputs + arraysize(iputs), ConstructorIPutData()); // If we have any IPUTs from the call, check that the target method is in the same // dex file (compare DexCache references), otherwise field_indexes would be bogus. - if (iputs[0].field_index != DexFile::kDexNoIndex16 && - target_method->GetDexCache() != method->GetDexCache()) { + if (iput_count > 0u && target_method->GetDexCache() != method->GetDexCache()) { return false; } } @@ -355,7 +348,12 @@ bool DoAnalyseConstructor(const CodeItemDataAccessor* code_item, } else { DCHECK(IsInstructionIPut(instruction.Opcode())); DCHECK_EQ(instruction.VRegB_22c(), this_vreg); - if (!RecordConstructorIPut(method, &instruction, this_vreg, zero_vreg_mask, iputs)) { + if (!RecordConstructorIPut(method, + &instruction, + this_vreg, + zero_vreg_mask, + iputs, + iput_count)) { return false; } } @@ -369,15 +367,13 @@ bool AnalyseConstructor(const CodeItemDataAccessor* code_item, ArtMethod* method, InlineMethod* result) REQUIRES_SHARED(Locks::mutator_lock_) { + size_t iput_count(0u); ConstructorIPutData iputs[kMaxConstructorIPuts]; - if (!DoAnalyseConstructor(code_item, method, iputs)) { + if (!DoAnalyseConstructor(code_item, method, iputs, iput_count)) { return false; } static_assert(kMaxConstructorIPuts == 3, "Unexpected limit"); // Code below depends on this. - DCHECK_IMPLIES(iputs[0].field_index == DexFile::kDexNoIndex16, - iputs[1].field_index == DexFile::kDexNoIndex16); - DCHECK_IMPLIES(iputs[1].field_index == DexFile::kDexNoIndex16, - iputs[2].field_index == DexFile::kDexNoIndex16); + DCHECK_LE(iput_count, kMaxConstructorIPuts); #define STORE_IPUT(n) \ do { \ @@ -391,7 +387,7 @@ bool AnalyseConstructor(const CodeItemDataAccessor* code_item, #undef STORE_IPUT result->opcode = kInlineOpConstructor; - result->d.constructor_data.reserved = 0u; + result->d.constructor_data.iput_count = static_cast<uint16_t>(iput_count); return true; } diff --git a/compiler/dex/inline_method_analyser.h b/compiler/dex/inline_method_analyser.h index 4cd5b824f1..68e8912c93 100644 --- a/compiler/dex/inline_method_analyser.h +++ b/compiler/dex/inline_method_analyser.h @@ -76,7 +76,7 @@ struct InlineConstructorData { uint16_t iput0_arg : 4; uint16_t iput1_arg : 4; uint16_t iput2_arg : 4; - uint16_t reserved : 4; + uint16_t iput_count: 4; }; static_assert(sizeof(InlineConstructorData) == sizeof(uint64_t), "Invalid size of InlineConstructorData"); diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 396aa95692..c90308d39c 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -1768,17 +1768,14 @@ bool HInliner::TryPatternSubstitution(HInvoke* invoke_instruction, uint16_t iput_args[] = { data.iput0_arg, data.iput1_arg, data.iput2_arg }; static_assert(arraysize(iput_args) == arraysize(iput_field_indexes), "Size mismatch"); // Count valid field indexes. - size_t number_of_iputs = 0u; - while (number_of_iputs != arraysize(iput_field_indexes) && - iput_field_indexes[number_of_iputs] != DexFile::kDexNoIndex16) { + for (size_t i = 0, end = data.iput_count; i < end; i++) { // Check that there are no duplicate valid field indexes. - DCHECK_EQ(0, std::count(iput_field_indexes + number_of_iputs + 1, - iput_field_indexes + arraysize(iput_field_indexes), - iput_field_indexes[number_of_iputs])); - ++number_of_iputs; + DCHECK_EQ(0, std::count(iput_field_indexes + i + 1, + iput_field_indexes + end, + iput_field_indexes[i])); } // Check that there are no valid field indexes in the rest of the array. - DCHECK_EQ(0, std::count_if(iput_field_indexes + number_of_iputs, + DCHECK_EQ(0, std::count_if(iput_field_indexes + data.iput_count, iput_field_indexes + arraysize(iput_field_indexes), [](uint16_t index) { return index != DexFile::kDexNoIndex16; })); @@ -1786,7 +1783,7 @@ bool HInliner::TryPatternSubstitution(HInvoke* invoke_instruction, HInstruction* obj = GetInvokeInputForArgVRegIndex(invoke_instruction, /* arg_vreg_index= */ 0u); bool needs_constructor_barrier = false; - for (size_t i = 0; i != number_of_iputs; ++i) { + for (size_t i = 0, end = data.iput_count; i != end; ++i) { HInstruction* value = GetInvokeInputForArgVRegIndex(invoke_instruction, iput_args[i]); if (!IsZeroBitPattern(value)) { uint16_t field_index = iput_field_indexes[i]; @@ -1811,7 +1808,7 @@ bool HInliner::TryPatternSubstitution(HInvoke* invoke_instruction, invoke_instruction); } *return_replacement = nullptr; - number_of_instructions = number_of_iputs + (needs_constructor_barrier ? 1u : 0u); + number_of_instructions = data.iput_count + (needs_constructor_barrier ? 1u : 0u); break; } } |