diff options
author | 2017-11-06 20:02:24 -0800 | |
---|---|---|
committer | 2017-11-09 19:06:10 -0800 | |
commit | 69147f165efaa9da152bb37da3a16dd5d8c6cf3c (patch) | |
tree | 25dbec549b8c06cf24729a577c76ef0b6d3d4c7f /compiler/dex/inline_method_analyser.cc | |
parent | 2202d56061941b4fecbdb018d84bcefb05b6c683 (diff) |
Add code item accessor helper classes
Add classes to abstract accesses to code item data. These classes
handle both standard dex and compact dex.
Added:
- CodeItemInstructionsAccessor to handle code item instructions.
- CodeItemDataAccessor to handle code item data excluding debug info.
Moved inline_method_analyzer to use the new classes to test the new
APIs.
Bug: 63756964
Test: test-art-host
Change-Id: I9926acb77b81fa64ed4a3b49b7bed1aab30a0f33
Diffstat (limited to 'compiler/dex/inline_method_analyser.cc')
-rw-r--r-- | compiler/dex/inline_method_analyser.cc | 104 |
1 files changed, 51 insertions, 53 deletions
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc index 518b0ece73..b409eb2dbb 100644 --- a/compiler/dex/inline_method_analyser.cc +++ b/compiler/dex/inline_method_analyser.cc @@ -20,6 +20,7 @@ #include "art_method-inl.h" #include "base/enums.h" #include "class_linker-inl.h" +#include "code_item_accessors-inl.h" #include "dex_file-inl.h" #include "dex_instruction-inl.h" #include "dex_instruction.h" @@ -43,7 +44,7 @@ class Matcher { typedef bool MatchFn(Matcher* matcher); template <size_t size> - static bool Match(const DexFile::CodeItem* code_item, MatchFn* const (&pattern)[size]); + static bool Match(const CodeItemDataAccessor* code_item, MatchFn* const (&pattern)[size]); // Match and advance. @@ -62,22 +63,20 @@ class Matcher { bool IPutOnThis(); private: - explicit Matcher(const DexFile::CodeItem* code_item) + explicit Matcher(const CodeItemDataAccessor* code_item) : code_item_(code_item), - instruction_(code_item->Instructions().begin()), - pos_(0u), - mark_(0u) { } + instruction_(code_item->begin()) {} - static bool DoMatch(const DexFile::CodeItem* code_item, MatchFn* const* pattern, size_t size); + static bool DoMatch(const CodeItemDataAccessor* code_item, MatchFn* const* pattern, size_t size); - const DexFile::CodeItem* const code_item_; + const CodeItemDataAccessor* const code_item_; DexInstructionIterator instruction_; - size_t pos_; - size_t mark_; + size_t pos_ = 0u; + size_t mark_ = 0u; }; template <size_t size> -bool Matcher::Match(const DexFile::CodeItem* code_item, MatchFn* const (&pattern)[size]) { +bool Matcher::Match(const CodeItemDataAccessor* code_item, MatchFn* const (&pattern)[size]) { return DoMatch(code_item, pattern, size); } @@ -122,12 +121,12 @@ bool Matcher::Const0() { } bool Matcher::IPutOnThis() { - DCHECK_NE(code_item_->ins_size_, 0u); + DCHECK_NE(code_item_->InsSize(), 0u); return IsInstructionIPut(instruction_->Opcode()) && - instruction_->VRegB_22c() == code_item_->registers_size_ - code_item_->ins_size_; + instruction_->VRegB_22c() == code_item_->RegistersSize() - code_item_->InsSize(); } -bool Matcher::DoMatch(const DexFile::CodeItem* code_item, MatchFn* const* pattern, size_t size) { +bool Matcher::DoMatch(const CodeItemDataAccessor* code_item, MatchFn* const* pattern, size_t size) { Matcher matcher(code_item); while (matcher.pos_ != size) { if (!pattern[matcher.pos_](&matcher)) { @@ -158,7 +157,7 @@ ArtMethod* GetTargetConstructor(ArtMethod* method, const Instruction* invoke_dir // Return the forwarded arguments and check that all remaining arguments are zero. // If the check fails, return static_cast<size_t>(-1). -size_t CountForwardedConstructorArguments(const DexFile::CodeItem* code_item, +size_t CountForwardedConstructorArguments(const CodeItemDataAccessor* code_item, const Instruction* invoke_direct, uint16_t zero_vreg_mask) { DCHECK_EQ(invoke_direct->Opcode(), Instruction::INVOKE_DIRECT); @@ -167,7 +166,7 @@ size_t CountForwardedConstructorArguments(const DexFile::CodeItem* code_item, uint32_t args[Instruction::kMaxVarArgRegs]; invoke_direct->GetVarArgs(args); uint16_t this_vreg = args[0]; - DCHECK_EQ(this_vreg, code_item->registers_size_ - code_item->ins_size_); // Checked by verifier. + DCHECK_EQ(this_vreg, code_item->RegistersSize() - code_item->InsSize()); // Checked by verifier. size_t forwarded = 1u; while (forwarded < number_of_args && args[forwarded] == this_vreg + forwarded && @@ -249,7 +248,7 @@ bool RecordConstructorIPut(ArtMethod* method, return true; } -bool DoAnalyseConstructor(const DexFile::CodeItem* code_item, +bool DoAnalyseConstructor(const CodeItemDataAccessor* code_item, ArtMethod* method, /*inout*/ ConstructorIPutData (&iputs)[kMaxConstructorIPuts]) REQUIRES_SHARED(Locks::mutator_lock_) { @@ -292,17 +291,17 @@ bool DoAnalyseConstructor(const DexFile::CodeItem* code_item, DCHECK(method->IsConstructor()); DCHECK(code_item != nullptr); if (!method->GetDeclaringClass()->IsVerified() || - code_item->insns_size_in_code_units_ > kMaxCodeUnits || - code_item->registers_size_ > kMaxVRegs || + code_item->InsnsSizeInCodeUnits() > kMaxCodeUnits || + code_item->RegistersSize() > kMaxVRegs || !Matcher::Match(code_item, kConstructorPattern)) { return false; } // 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 this_vreg = code_item->RegistersSize() - code_item->InsSize(); uint16_t zero_vreg_mask = 0u; - for (const DexInstructionPcPair& pair : code_item->Instructions()) { + for (const DexInstructionPcPair& pair : *code_item) { const Instruction& instruction = pair.Inst(); if (instruction.Opcode() == Instruction::RETURN_VOID) { break; @@ -314,7 +313,7 @@ bool DoAnalyseConstructor(const DexFile::CodeItem* code_item, // 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->InsSize()) { return false; } size_t forwarded = CountForwardedConstructorArguments(code_item, &instruction, zero_vreg_mask); @@ -322,14 +321,13 @@ bool DoAnalyseConstructor(const DexFile::CodeItem* code_item, return false; } if (target_method->GetDeclaringClass()->IsObjectClass()) { - DCHECK_EQ(target_method->GetCodeItem()->Instructions().begin()->Opcode(), - Instruction::RETURN_VOID); + DCHECK_EQ(CodeItemDataAccessor(target_method).begin()->Opcode(), Instruction::RETURN_VOID); } else { - const DexFile::CodeItem* target_code_item = target_method->GetCodeItem(); - if (target_code_item == nullptr) { + CodeItemDataAccessor target_code_item = CodeItemDataAccessor::CreateNullable(target_method); + 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)) { return false; } // Prune IPUTs with zero input. @@ -365,7 +363,7 @@ bool DoAnalyseConstructor(const DexFile::CodeItem* code_item, } // anonymous namespace -bool AnalyseConstructor(const DexFile::CodeItem* code_item, +bool AnalyseConstructor(const CodeItemDataAccessor* code_item, ArtMethod* method, InlineMethod* result) REQUIRES_SHARED(Locks::mutator_lock_) { @@ -429,27 +427,27 @@ static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_SHORT) == InlineMethodAnalyser::IPutVariant(Instruction::IPUT_SHORT), "iget/iput_short variant"); bool InlineMethodAnalyser::AnalyseMethodCode(ArtMethod* method, InlineMethod* result) { - const DexFile::CodeItem* code_item = method->GetCodeItem(); - if (code_item == nullptr) { + CodeItemDataAccessor code_item = CodeItemDataAccessor::CreateNullable(method); + if (!code_item.HasCodeItem()) { // Native or abstract. return false; } - return AnalyseMethodCode(code_item, + return AnalyseMethodCode(&code_item, MethodReference(method->GetDexFile(), method->GetDexMethodIndex()), method->IsStatic(), method, result); } -bool InlineMethodAnalyser::AnalyseMethodCode(const DexFile::CodeItem* code_item, +bool InlineMethodAnalyser::AnalyseMethodCode(const CodeItemDataAccessor* code_item, const MethodReference& method_ref, bool is_static, ArtMethod* method, InlineMethod* result) { // We currently support only plain return or 2-instruction methods. - DCHECK_NE(code_item->insns_size_in_code_units_, 0u); - Instruction::Code opcode = code_item->Instructions().begin()->Opcode(); + DCHECK_NE(code_item->InsnsSizeInCodeUnits(), 0u); + Instruction::Code opcode = code_item->begin()->Opcode(); switch (opcode) { case Instruction::RETURN_VOID: @@ -518,15 +516,15 @@ bool InlineMethodAnalyser::IsSyntheticAccessor(MethodReference ref) { strncmp(method_name, "-", strlen("-")) == 0; } -bool InlineMethodAnalyser::AnalyseReturnMethod(const DexFile::CodeItem* code_item, +bool InlineMethodAnalyser::AnalyseReturnMethod(const CodeItemDataAccessor* code_item, InlineMethod* result) { - DexInstructionIterator return_instruction = code_item->Instructions().begin(); + DexInstructionIterator return_instruction = code_item->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_; + uint32_t arg_start = code_item->RegistersSize() - code_item->InsSize(); DCHECK_GE(reg, arg_start); DCHECK_LT((return_opcode == Instruction::RETURN_WIDE) ? reg + 1 : reg, - code_item->registers_size_); + code_item->RegistersSize()); if (result != nullptr) { result->opcode = kInlineOpReturnArg; @@ -540,9 +538,9 @@ bool InlineMethodAnalyser::AnalyseReturnMethod(const DexFile::CodeItem* code_ite return true; } -bool InlineMethodAnalyser::AnalyseConstMethod(const DexFile::CodeItem* code_item, +bool InlineMethodAnalyser::AnalyseConstMethod(const CodeItemDataAccessor* code_item, InlineMethod* result) { - DexInstructionIterator instruction = code_item->Instructions().begin(); + DexInstructionIterator instruction = code_item->begin(); const Instruction* return_instruction = instruction->Next(); Instruction::Code return_opcode = return_instruction->Opcode(); if (return_opcode != Instruction::RETURN && @@ -551,13 +549,13 @@ bool InlineMethodAnalyser::AnalyseConstMethod(const DexFile::CodeItem* code_item } int32_t return_reg = return_instruction->VRegA_11x(); - DCHECK_LT(return_reg, code_item->registers_size_); + DCHECK_LT(return_reg, code_item->RegistersSize()); int32_t const_value = instruction->VRegB(); if (instruction->Opcode() == Instruction::CONST_HIGH16) { const_value <<= 16; } - DCHECK_LT(instruction->VRegA(), code_item->registers_size_); + DCHECK_LT(instruction->VRegA(), code_item->RegistersSize()); if (instruction->VRegA() != return_reg) { return false; // Not returning the value set by const? } @@ -571,12 +569,12 @@ bool InlineMethodAnalyser::AnalyseConstMethod(const DexFile::CodeItem* code_item return true; } -bool InlineMethodAnalyser::AnalyseIGetMethod(const DexFile::CodeItem* code_item, +bool InlineMethodAnalyser::AnalyseIGetMethod(const CodeItemDataAccessor* code_item, const MethodReference& method_ref, bool is_static, ArtMethod* method, InlineMethod* result) { - DexInstructionIterator instruction = code_item->Instructions().begin(); + DexInstructionIterator instruction = code_item->begin(); Instruction::Code opcode = instruction->Opcode(); DCHECK(IsInstructionIGet(opcode)); @@ -591,17 +589,17 @@ bool InlineMethodAnalyser::AnalyseIGetMethod(const DexFile::CodeItem* code_item, uint32_t return_reg = return_instruction->VRegA_11x(); DCHECK_LT(return_opcode == Instruction::RETURN_WIDE ? return_reg + 1 : return_reg, - code_item->registers_size_); + code_item->RegistersSize()); uint32_t dst_reg = instruction->VRegA_22c(); uint32_t object_reg = instruction->VRegB_22c(); uint32_t field_idx = instruction->VRegC_22c(); - uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_; + uint32_t arg_start = code_item->RegistersSize() - code_item->InsSize(); DCHECK_GE(object_reg, arg_start); - DCHECK_LT(object_reg, code_item->registers_size_); + DCHECK_LT(object_reg, code_item->RegistersSize()); uint32_t object_arg = object_reg - arg_start; - DCHECK_LT(opcode == Instruction::IGET_WIDE ? dst_reg + 1 : dst_reg, code_item->registers_size_); + DCHECK_LT(opcode == Instruction::IGET_WIDE ? dst_reg + 1 : dst_reg, code_item->RegistersSize()); if (dst_reg != return_reg) { return false; // Not returning the value retrieved by IGET? } @@ -635,18 +633,18 @@ bool InlineMethodAnalyser::AnalyseIGetMethod(const DexFile::CodeItem* code_item, return true; } -bool InlineMethodAnalyser::AnalyseIPutMethod(const DexFile::CodeItem* code_item, +bool InlineMethodAnalyser::AnalyseIPutMethod(const CodeItemDataAccessor* code_item, const MethodReference& method_ref, bool is_static, ArtMethod* method, InlineMethod* result) { - DexInstructionIterator instruction = code_item->Instructions().begin(); + DexInstructionIterator instruction = code_item->begin(); Instruction::Code opcode = instruction->Opcode(); DCHECK(IsInstructionIPut(opcode)); const Instruction* return_instruction = instruction->Next(); Instruction::Code return_opcode = return_instruction->Opcode(); - uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_; + uint32_t arg_start = code_item->RegistersSize() - code_item->InsSize(); uint16_t return_arg_plus1 = 0u; if (return_opcode != Instruction::RETURN_VOID) { if (return_opcode != Instruction::RETURN && @@ -658,7 +656,7 @@ bool InlineMethodAnalyser::AnalyseIPutMethod(const DexFile::CodeItem* code_item, uint32_t return_reg = return_instruction->VRegA_11x(); DCHECK_GE(return_reg, arg_start); DCHECK_LT(return_opcode == Instruction::RETURN_WIDE ? return_reg + 1u : return_reg, - code_item->registers_size_); + code_item->RegistersSize()); return_arg_plus1 = return_reg - arg_start + 1u; } @@ -666,9 +664,9 @@ bool InlineMethodAnalyser::AnalyseIPutMethod(const DexFile::CodeItem* code_item, uint32_t object_reg = instruction->VRegB_22c(); uint32_t field_idx = instruction->VRegC_22c(); DCHECK_GE(object_reg, arg_start); - DCHECK_LT(object_reg, code_item->registers_size_); + DCHECK_LT(object_reg, code_item->RegistersSize()); DCHECK_GE(src_reg, arg_start); - DCHECK_LT(opcode == Instruction::IPUT_WIDE ? src_reg + 1 : src_reg, code_item->registers_size_); + DCHECK_LT(opcode == Instruction::IPUT_WIDE ? src_reg + 1 : src_reg, code_item->RegistersSize()); uint32_t object_arg = object_reg - arg_start; uint32_t src_arg = src_reg - arg_start; |