Add DexInstructionIterator and use it a few places
Motivation:
Want to start abstracting away dex specific functionality to enable
CompactDex. Adding an iterator will enable CompactDex iteration to
work differently than normal dex iteration.
Will eventually replace CodeItemIterator.
Bug: 63756964
Test: test-art-host
Change-Id: I90e67c1a994b7698aaac0523a82816b0a003fbdc
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index e49f83f..7581962 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -374,8 +374,8 @@
// Dex pc is not serialized, only used for checking the instructions. Since we access the
// array based on the index of the quickened instruction, the indexes must line up perfectly.
// The reader side uses the NeedsIndexForInstruction function too.
- const Instruction* inst = Instruction::At(code_item->insns_ + info.dex_pc);
- CHECK(QuickenInfoTable::NeedsIndexForInstruction(inst)) << inst->Opcode();
+ const Instruction& inst = code_item->InstructionAt(info.dex_pc);
+ CHECK(QuickenInfoTable::NeedsIndexForInstruction(&inst)) << inst.Opcode();
// Add the index.
quicken_data.push_back(static_cast<uint8_t>(info.dex_member_index >> 0));
quicken_data.push_back(static_cast<uint8_t>(info.dex_member_index >> 8));
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc
index c8e3d5e..925863e 100644
--- a/compiler/dex/inline_method_analyser.cc
+++ b/compiler/dex/inline_method_analyser.cc
@@ -64,14 +64,14 @@
private:
explicit Matcher(const DexFile::CodeItem* code_item)
: code_item_(code_item),
- instruction_(Instruction::At(code_item->insns_)),
+ instruction_(code_item->Instructions().begin()),
pos_(0u),
mark_(0u) { }
static bool DoMatch(const DexFile::CodeItem* code_item, MatchFn* const* pattern, size_t size);
const DexFile::CodeItem* const code_item_;
- const Instruction* instruction_;
+ DexInstructionIterator instruction_;
size_t pos_;
size_t mark_;
};
@@ -93,7 +93,7 @@
return false;
}
matcher->pos_ += 1u;
- matcher->instruction_ = matcher->instruction_->Next();
+ ++matcher->instruction_;
return true;
}
@@ -105,7 +105,7 @@
return true;
}
matcher->pos_ = matcher->mark_;
- matcher->instruction_ = matcher->instruction_->Next();
+ ++matcher->instruction_;
return true;
}
@@ -301,26 +301,27 @@
// Verify the invoke, prevent a few odd cases and collect IPUTs.
uint16_t this_vreg = code_item->registers_size_ - code_item->ins_size_;
uint16_t zero_vreg_mask = 0u;
- for (const Instruction* instruction = Instruction::At(code_item->insns_);
- instruction->Opcode() != Instruction::RETURN_VOID;
- instruction = instruction->Next()) {
- if (instruction->Opcode() == Instruction::INVOKE_DIRECT) {
- ArtMethod* target_method = GetTargetConstructor(method, instruction);
+
+ for (const Instruction& instruction : code_item->Instructions()) {
+ if (instruction.Opcode() == Instruction::RETURN_VOID) {
+ break;
+ } else if (instruction.Opcode() == Instruction::INVOKE_DIRECT) {
+ ArtMethod* target_method = GetTargetConstructor(method, &instruction);
if (target_method == nullptr) {
return false;
}
// We allow forwarding constructors only if they pass more arguments
// to prevent infinite recursion.
if (target_method->GetDeclaringClass() == method->GetDeclaringClass() &&
- instruction->VRegA_35c() <= code_item->ins_size_) {
+ instruction.VRegA_35c() <= code_item->ins_size_) {
return false;
}
- size_t forwarded = CountForwardedConstructorArguments(code_item, instruction, zero_vreg_mask);
+ size_t forwarded = CountForwardedConstructorArguments(code_item, &instruction, zero_vreg_mask);
if (forwarded == static_cast<size_t>(-1)) {
return false;
}
if (target_method->GetDeclaringClass()->IsObjectClass()) {
- DCHECK_EQ(Instruction::At(target_method->GetCodeItem()->insns_)->Opcode(),
+ DCHECK_EQ(target_method->GetCodeItem()->Instructions().begin()->Opcode(),
Instruction::RETURN_VOID);
} else {
const DexFile::CodeItem* target_code_item = target_method->GetCodeItem();
@@ -345,15 +346,15 @@
return false;
}
}
- } else if (IsInstructionDirectConst(instruction->Opcode())) {
- zero_vreg_mask |= GetZeroVRegMask(instruction);
+ } else if (IsInstructionDirectConst(instruction.Opcode())) {
+ zero_vreg_mask |= GetZeroVRegMask(&instruction);
if ((zero_vreg_mask & (1u << this_vreg)) != 0u) {
return false; // Overwriting `this` is unsupported.
}
} else {
- DCHECK(IsInstructionIPut(instruction->Opcode()));
- DCHECK_EQ(instruction->VRegB_22c(), this_vreg);
- if (!RecordConstructorIPut(method, instruction, this_vreg, zero_vreg_mask, iputs)) {
+ DCHECK(IsInstructionIPut(instruction.Opcode()));
+ DCHECK_EQ(instruction.VRegB_22c(), this_vreg);
+ if (!RecordConstructorIPut(method, &instruction, this_vreg, zero_vreg_mask, iputs)) {
return false;
}
}
@@ -447,8 +448,7 @@
// We currently support only plain return or 2-instruction methods.
DCHECK_NE(code_item->insns_size_in_code_units_, 0u);
- const Instruction* instruction = Instruction::At(code_item->insns_);
- Instruction::Code opcode = instruction->Opcode();
+ Instruction::Code opcode = code_item->Instructions().begin()->Opcode();
switch (opcode) {
case Instruction::RETURN_VOID:
@@ -519,7 +519,7 @@
bool InlineMethodAnalyser::AnalyseReturnMethod(const DexFile::CodeItem* code_item,
InlineMethod* result) {
- const Instruction* return_instruction = Instruction::At(code_item->insns_);
+ DexInstructionIterator return_instruction = code_item->Instructions().begin();
Instruction::Code return_opcode = return_instruction->Opcode();
uint32_t reg = return_instruction->VRegA_11x();
uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_;
@@ -541,7 +541,7 @@
bool InlineMethodAnalyser::AnalyseConstMethod(const DexFile::CodeItem* code_item,
InlineMethod* result) {
- const Instruction* instruction = Instruction::At(code_item->insns_);
+ DexInstructionIterator instruction = code_item->Instructions().begin();
const Instruction* return_instruction = instruction->Next();
Instruction::Code return_opcode = return_instruction->Opcode();
if (return_opcode != Instruction::RETURN &&
@@ -575,7 +575,7 @@
bool is_static,
ArtMethod* method,
InlineMethod* result) {
- const Instruction* instruction = Instruction::At(code_item->insns_);
+ DexInstructionIterator instruction = code_item->Instructions().begin();
Instruction::Code opcode = instruction->Opcode();
DCHECK(IsInstructionIGet(opcode));
@@ -639,7 +639,7 @@
bool is_static,
ArtMethod* method,
InlineMethod* result) {
- const Instruction* instruction = Instruction::At(code_item->insns_);
+ DexInstructionIterator instruction = code_item->Instructions().begin();
Instruction::Code opcode = instruction->Opcode();
DCHECK(IsInstructionIPut(opcode));
diff --git a/compiler/dex/verified_method.cc b/compiler/dex/verified_method.cc
index e46dc59..9c5b632 100644
--- a/compiler/dex/verified_method.cc
+++ b/compiler/dex/verified_method.cc
@@ -64,24 +64,21 @@
if (method_verifier->HasFailures()) {
return;
}
- const DexFile::CodeItem* code_item = method_verifier->CodeItem();
- const Instruction* inst = Instruction::At(code_item->insns_);
- const Instruction* end = Instruction::At(code_item->insns_ +
- code_item->insns_size_in_code_units_);
-
- for (; inst < end; inst = inst->Next()) {
- Instruction::Code code = inst->Opcode();
+ IterationRange<DexInstructionIterator> instructions = method_verifier->CodeItem()->Instructions();
+ for (auto it = instructions.begin(); it != instructions.end(); ++it) {
+ const Instruction& inst = *it;
+ const Instruction::Code code = inst.Opcode();
if (code == Instruction::CHECK_CAST) {
- uint32_t dex_pc = inst->GetDexPc(code_item->insns_);
+ const uint32_t dex_pc = it.GetDexPC(instructions.begin());
if (!method_verifier->GetInstructionFlags(dex_pc).IsVisited()) {
// Do not attempt to quicken this instruction, it's unreachable anyway.
continue;
}
const verifier::RegisterLine* line = method_verifier->GetRegLine(dex_pc);
const verifier::RegType& reg_type(line->GetRegisterType(method_verifier,
- inst->VRegA_21c()));
+ inst.VRegA_21c()));
const verifier::RegType& cast_type =
- method_verifier->ResolveCheckedClass(dex::TypeIndex(inst->VRegB_21c()));
+ method_verifier->ResolveCheckedClass(dex::TypeIndex(inst.VRegB_21c()));
// Pass null for the method verifier to not record the VerifierDeps dependency
// if the types are not assignable.
if (cast_type.IsStrictlyAssignableFrom(reg_type, /* method_verifier */ nullptr)) {