summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/dex/inline_method_analyser.cc52
-rw-r--r--compiler/dex/inline_method_analyser.h2
-rw-r--r--compiler/optimizing/inliner.cc17
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;
}
}