Make CodeItem fields private
Make code item fields private and use accessors. Added a hand full of
friend classes to reduce the size of the change.
Changed default to be nullable and removed CreateNullable.
CreateNullable was a bad API since it defaulted to the unsafe, may
add a CreateNonNullable if it's important for performance.
Motivation:
Have a different layout for code items in cdex.
Bug: 63756964
Test: test-art-host-gtest
Test: test/testrunner/testrunner.py --host
Test: art/tools/run-jdwp-tests.sh '--mode=host' '--variant=X32' --debug
Change-Id: I42bc7435e20358682075cb6de52713b595f95bf9
diff --git a/compiler/compiler.cc b/compiler/compiler.cc
index bb614ae..47f44ff 100644
--- a/compiler/compiler.cc
+++ b/compiler/compiler.cc
@@ -19,6 +19,7 @@
#include <android-base/logging.h>
#include "base/macros.h"
+#include "code_item_accessors-inl.h"
#include "driver/compiler_driver.h"
#include "optimizing/optimizing_compiler.h"
#include "utils.h"
@@ -46,15 +47,16 @@
* Dalvik uses 16-bit uints for instruction and register counts. We'll limit to a quarter
* of that, which also guarantees we cannot overflow our 16-bit internal Quick SSA name space.
*/
- if (code_item.insns_size_in_code_units_ >= UINT16_MAX / 4) {
+ CodeItemDataAccessor accessor(&dex_file, &code_item);
+ if (accessor.InsnsSizeInCodeUnits() >= UINT16_MAX / 4) {
LOG(INFO) << "Method exceeds compiler instruction limit: "
- << code_item.insns_size_in_code_units_
+ << accessor.InsnsSizeInCodeUnits()
<< " in " << dex_file.PrettyMethod(method_idx);
return true;
}
- if (code_item.registers_size_ >= UINT16_MAX / 4) {
+ if (accessor.RegistersSize() >= UINT16_MAX / 4) {
LOG(INFO) << "Method exceeds compiler virtual register limit: "
- << code_item.registers_size_ << " in " << dex_file.PrettyMethod(method_idx);
+ << accessor.RegistersSize() << " in " << dex_file.PrettyMethod(method_idx);
return true;
}
return false;
diff --git a/compiler/debug/elf_debug_info_writer.h b/compiler/debug/elf_debug_info_writer.h
index 107ed48..0e11e32 100644
--- a/compiler/debug/elf_debug_info_writer.h
+++ b/compiler/debug/elf_debug_info_writer.h
@@ -260,14 +260,10 @@
// Write local variables.
LocalInfos local_infos;
- if (dex->DecodeDebugLocalInfo(accessor.RegistersSize(),
- accessor.InsSize(),
- accessor.InsnsSizeInCodeUnits(),
- accessor.DebugInfoOffset(),
- is_static,
- mi->dex_method_index,
- LocalInfoCallback,
- &local_infos)) {
+ if (accessor.DecodeDebugLocalInfo(is_static,
+ mi->dex_method_index,
+ LocalInfoCallback,
+ &local_infos)) {
for (const DexFile::LocalInfo& var : local_infos) {
if (var.reg_ < accessor.RegistersSize() - accessor.InsSize()) {
info_.StartTag(DW_TAG_variable);
diff --git a/compiler/debug/elf_debug_loc_writer.h b/compiler/debug/elf_debug_loc_writer.h
index 1d609af..34c2919 100644
--- a/compiler/debug/elf_debug_loc_writer.h
+++ b/compiler/debug/elf_debug_loc_writer.h
@@ -149,11 +149,12 @@
DCHECK_LT(stack_map_index, dex_register_maps.size());
DexRegisterMap dex_register_map = dex_register_maps[stack_map_index];
DCHECK(dex_register_map.IsValid());
+ CodeItemDataAccessor accessor(method_info->dex_file, method_info->code_item);
reg_lo = dex_register_map.GetDexRegisterLocation(
- vreg, method_info->code_item->registers_size_, code_info, encoding);
+ vreg, accessor.RegistersSize(), code_info, encoding);
if (is64bitValue) {
reg_hi = dex_register_map.GetDexRegisterLocation(
- vreg + 1, method_info->code_item->registers_size_, code_info, encoding);
+ vreg + 1, accessor.RegistersSize(), code_info, encoding);
}
// Add location entry for this address range.
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc
index b409eb2..80677b9 100644
--- a/compiler/dex/inline_method_analyser.cc
+++ b/compiler/dex/inline_method_analyser.cc
@@ -141,8 +141,11 @@
ArtMethod* GetTargetConstructor(ArtMethod* method, const Instruction* invoke_direct)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK_EQ(invoke_direct->Opcode(), Instruction::INVOKE_DIRECT);
- DCHECK_EQ(invoke_direct->VRegC_35c(),
- method->GetCodeItem()->registers_size_ - method->GetCodeItem()->ins_size_);
+ if (kIsDebugBuild) {
+ CodeItemDataAccessor accessor(method);
+ DCHECK_EQ(invoke_direct->VRegC_35c(),
+ accessor.RegistersSize() - accessor.InsSize());
+ }
uint32_t method_index = invoke_direct->VRegB_35c();
ArtMethod* target_method = Runtime::Current()->GetClassLinker()->LookupResolvedMethod(
method_index, method->GetDexCache(), method->GetClassLoader());
@@ -323,7 +326,7 @@
if (target_method->GetDeclaringClass()->IsObjectClass()) {
DCHECK_EQ(CodeItemDataAccessor(target_method).begin()->Opcode(), Instruction::RETURN_VOID);
} else {
- CodeItemDataAccessor target_code_item = CodeItemDataAccessor::CreateNullable(target_method);
+ CodeItemDataAccessor target_code_item(target_method);
if (!target_code_item.HasCodeItem()) {
return false; // Native constructor?
}
@@ -427,7 +430,7 @@
InlineMethodAnalyser::IPutVariant(Instruction::IPUT_SHORT), "iget/iput_short variant");
bool InlineMethodAnalyser::AnalyseMethodCode(ArtMethod* method, InlineMethod* result) {
- CodeItemDataAccessor code_item = CodeItemDataAccessor::CreateNullable(method);
+ CodeItemDataAccessor code_item(method);
if (!code_item.HasCodeItem()) {
// Native or abstract.
return false;
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 0631c0f..68f963e 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -949,14 +949,14 @@
ArtMethod* method,
std::set<std::pair<dex::TypeIndex, const DexFile*>>* exceptions_to_resolve)
REQUIRES_SHARED(Locks::mutator_lock_) {
- const DexFile::CodeItem* code_item = method->GetCodeItem();
- if (code_item == nullptr) {
+ if (method->GetCodeItem() == nullptr) {
return; // native or abstract method
}
- if (code_item->tries_size_ == 0) {
+ CodeItemDataAccessor accessor(method);
+ if (accessor.TriesSize() == 0) {
return; // nothing to process
}
- const uint8_t* encoded_catch_handler_list = DexFile::GetCatchHandlerData(*code_item, 0);
+ const uint8_t* encoded_catch_handler_list = accessor.GetCatchHandlerData();
size_t num_encoded_catch_handlers = DecodeUnsignedLeb128(&encoded_catch_handler_list);
for (size_t i = 0; i < num_encoded_catch_handlers; i++) {
int32_t encoded_catch_handler_size = DecodeSignedLeb128(&encoded_catch_handler_list);
diff --git a/compiler/exception_test.cc b/compiler/exception_test.cc
index 897b50b..4dbef0d 100644
--- a/compiler/exception_test.cc
+++ b/compiler/exception_test.cc
@@ -20,6 +20,7 @@
#include "base/callee_save_type.h"
#include "base/enums.h"
#include "class_linker.h"
+#include "code_item_accessors-inl.h"
#include "common_runtime_test.h"
#include "dex_file-inl.h"
#include "dex_file.h"
@@ -129,11 +130,12 @@
TEST_F(ExceptionTest, FindCatchHandler) {
ScopedObjectAccess soa(Thread::Current());
const DexFile::CodeItem* code_item = dex_->GetCodeItem(method_f_->GetCodeItemOffset());
+ CodeItemDataAccessor accessor(dex_, code_item);
ASSERT_TRUE(code_item != nullptr);
- ASSERT_EQ(2u, code_item->tries_size_);
- ASSERT_NE(0u, code_item->insns_size_in_code_units_);
+ ASSERT_EQ(2u, accessor.TriesSize());
+ ASSERT_NE(0u, accessor.InsnsSizeInCodeUnits());
const DexFile::TryItem *t0, *t1;
t0 = dex_->GetTryItems(*code_item, 0);
diff --git a/compiler/optimizing/block_builder.cc b/compiler/optimizing/block_builder.cc
index 58f591b..c505efa 100644
--- a/compiler/optimizing/block_builder.cc
+++ b/compiler/optimizing/block_builder.cc
@@ -18,10 +18,31 @@
#include "base/logging.h" // FOR VLOG.
#include "bytecode_utils.h"
+#include "code_item_accessors-inl.h"
#include "quicken_info.h"
namespace art {
+HBasicBlockBuilder::HBasicBlockBuilder(HGraph* graph,
+ const DexFile* const dex_file,
+ const CodeItemDebugInfoAccessor& accessor,
+ ScopedArenaAllocator* local_allocator)
+ : allocator_(graph->GetAllocator()),
+ graph_(graph),
+ dex_file_(dex_file),
+ code_item_accessor_(accessor),
+ local_allocator_(local_allocator),
+ branch_targets_(code_item_accessor_.HasCodeItem()
+ ? code_item_accessor_.InsnsSizeInCodeUnits()
+ : /* fake dex_pc=0 for intrinsic graph */ 1u,
+ nullptr,
+ local_allocator->Adapter(kArenaAllocGraphBuilder)),
+ throwing_blocks_(kDefaultNumberOfThrowingBlocks,
+ local_allocator->Adapter(kArenaAllocGraphBuilder)),
+ number_of_branches_(0u),
+ quicken_index_for_dex_pc_(std::less<uint32_t>(),
+ local_allocator->Adapter(kArenaAllocGraphBuilder)) {}
+
HBasicBlock* HBasicBlockBuilder::MaybeCreateBlockAt(uint32_t dex_pc) {
return MaybeCreateBlockAt(dex_pc, dex_pc);
}
@@ -41,20 +62,19 @@
// Create the first block for the dex instructions, single successor of the entry block.
MaybeCreateBlockAt(0u);
- if (code_item_->tries_size_ != 0) {
+ if (code_item_accessor_.TriesSize() != 0) {
// Create branch targets at the start/end of the TryItem range. These are
// places where the program might fall through into/out of the a block and
// where TryBoundary instructions will be inserted later. Other edges which
// enter/exit the try blocks are a result of branches/switches.
- for (size_t idx = 0; idx < code_item_->tries_size_; ++idx) {
- const DexFile::TryItem* try_item = DexFile::GetTryItems(*code_item_, idx);
- uint32_t dex_pc_start = try_item->start_addr_;
- uint32_t dex_pc_end = dex_pc_start + try_item->insn_count_;
+ for (const DexFile::TryItem& try_item : code_item_accessor_.TryItems()) {
+ uint32_t dex_pc_start = try_item.start_addr_;
+ uint32_t dex_pc_end = dex_pc_start + try_item.insn_count_;
MaybeCreateBlockAt(dex_pc_start);
- if (dex_pc_end < code_item_->insns_size_in_code_units_) {
+ if (dex_pc_end < code_item_accessor_.InsnsSizeInCodeUnits()) {
// TODO: Do not create block if the last instruction cannot fall through.
MaybeCreateBlockAt(dex_pc_end);
- } else if (dex_pc_end == code_item_->insns_size_in_code_units_) {
+ } else if (dex_pc_end == code_item_accessor_.InsnsSizeInCodeUnits()) {
// The TryItem spans until the very end of the CodeItem and therefore
// cannot have any code afterwards.
} else {
@@ -65,7 +85,7 @@
}
// Create branch targets for exception handlers.
- const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0);
+ const uint8_t* handlers_ptr = code_item_accessor_.GetCatchHandlerData();
uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
for (uint32_t idx = 0; idx < handlers_size; ++idx) {
CatchHandlerIterator iterator(handlers_ptr);
@@ -78,8 +98,7 @@
// Iterate over all instructions and find branching instructions. Create blocks for
// the locations these instructions branch to.
- IterationRange<DexInstructionIterator> instructions = code_item_->Instructions();
- for (const DexInstructionPcPair& pair : instructions) {
+ for (const DexInstructionPcPair& pair : code_item_accessor_) {
const uint32_t dex_pc = pair.DexPc();
const Instruction& instruction = pair.Inst();
@@ -109,7 +128,7 @@
if (instruction.CanFlowThrough()) {
DexInstructionIterator next(std::next(DexInstructionIterator(pair)));
- if (next == instructions.end()) {
+ if (next == code_item_accessor_.end()) {
// In the normal case we should never hit this but someone can artificially forge a dex
// file to fall-through out the method code. In this case we bail out compilation.
VLOG(compiler) << "Not compiled: Fall-through beyond the CodeItem";
@@ -130,7 +149,7 @@
bool is_throwing_block = false;
// Calculate the qucikening index here instead of CreateBranchTargets since it's easier to
// calculate in dex_pc order.
- for (const DexInstructionPcPair& pair : code_item_->Instructions()) {
+ for (const DexInstructionPcPair& pair : code_item_accessor_) {
const uint32_t dex_pc = pair.DexPc();
const Instruction& instruction = pair.Inst();
@@ -213,10 +232,12 @@
// successors matches the order in which runtime exception delivery searches
// for a handler.
static void LinkToCatchBlocks(HTryBoundary* try_boundary,
- const DexFile::CodeItem& code_item,
+ const CodeItemDataAccessor& accessor,
const DexFile::TryItem* try_item,
const ScopedArenaSafeMap<uint32_t, HBasicBlock*>& catch_blocks) {
- for (CatchHandlerIterator it(code_item, *try_item); it.HasNext(); it.Next()) {
+ for (CatchHandlerIterator it(accessor.GetCatchHandlerData(try_item->handler_off_));
+ it.HasNext();
+ it.Next()) {
try_boundary->AddExceptionHandler(catch_blocks.Get(it.GetHandlerAddress()));
}
}
@@ -232,7 +253,7 @@
}
}
- const Instruction& first = code_item_->InstructionAt(catch_block->GetDexPc());
+ const Instruction& first = code_item_accessor_.InstructionAt(catch_block->GetDexPc());
if (first.Opcode() == Instruction::MOVE_EXCEPTION) {
// Verifier guarantees that if a catch block begins with MOVE_EXCEPTION then
// it has no live normal predecessors.
@@ -250,7 +271,7 @@
}
void HBasicBlockBuilder::InsertTryBoundaryBlocks() {
- if (code_item_->tries_size_ == 0) {
+ if (code_item_accessor_.TriesSize() == 0) {
return;
}
@@ -272,12 +293,10 @@
// loop for synchronized blocks.
if (ContainsElement(throwing_blocks_, block)) {
// Try to find a TryItem covering the block.
- const int32_t try_item_idx = DexFile::FindTryItem(DexFile::GetTryItems(*code_item_, 0u),
- code_item_->tries_size_,
- block->GetDexPc());
- if (try_item_idx != -1) {
+ const DexFile::TryItem* try_item = code_item_accessor_.FindTryItem(block->GetDexPc());
+ if (try_item != nullptr) {
// Block throwing and in a TryItem. Store the try block information.
- try_block_info.Put(block->GetBlockId(), DexFile::GetTryItems(*code_item_, try_item_idx));
+ try_block_info.Put(block->GetBlockId(), try_item);
}
}
}
@@ -288,7 +307,7 @@
// Iterate over catch blocks, create artifical landing pads if necessary to
// simplify the CFG, and set metadata.
- const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(*code_item_, 0);
+ const uint8_t* handlers_ptr = code_item_accessor_.GetCatchHandlerData();
uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
for (uint32_t idx = 0; idx < handlers_size; ++idx) {
CatchHandlerIterator iterator(handlers_ptr);
@@ -336,7 +355,7 @@
HTryBoundary* try_entry = new (allocator_) HTryBoundary(
HTryBoundary::BoundaryKind::kEntry, try_block->GetDexPc());
try_block->CreateImmediateDominator()->AddInstruction(try_entry);
- LinkToCatchBlocks(try_entry, *code_item_, try_item, catch_blocks);
+ LinkToCatchBlocks(try_entry, code_item_accessor_, try_item, catch_blocks);
break;
}
}
@@ -364,13 +383,13 @@
HTryBoundary* try_exit =
new (allocator_) HTryBoundary(HTryBoundary::BoundaryKind::kExit, successor->GetDexPc());
graph_->SplitEdge(try_block, successor)->AddInstruction(try_exit);
- LinkToCatchBlocks(try_exit, *code_item_, try_item, catch_blocks);
+ LinkToCatchBlocks(try_exit, code_item_accessor_, try_item, catch_blocks);
}
}
}
bool HBasicBlockBuilder::Build() {
- DCHECK(code_item_ != nullptr);
+ DCHECK(code_item_accessor_.HasCodeItem());
DCHECK(graph_->GetBlocks().empty());
graph_->SetEntryBlock(new (allocator_) HBasicBlock(graph_, kNoDexPc));
@@ -388,7 +407,7 @@
}
void HBasicBlockBuilder::BuildIntrinsic() {
- DCHECK(code_item_ == nullptr);
+ DCHECK(!code_item_accessor_.HasCodeItem());
DCHECK(graph_->GetBlocks().empty());
// Create blocks.
diff --git a/compiler/optimizing/block_builder.h b/compiler/optimizing/block_builder.h
index 7d0f56d..e68b95c 100644
--- a/compiler/optimizing/block_builder.h
+++ b/compiler/optimizing/block_builder.h
@@ -19,6 +19,7 @@
#include "base/scoped_arena_allocator.h"
#include "base/scoped_arena_containers.h"
+#include "code_item_accessors.h"
#include "dex_file.h"
#include "nodes.h"
@@ -28,22 +29,8 @@
public:
HBasicBlockBuilder(HGraph* graph,
const DexFile* const dex_file,
- const DexFile::CodeItem* code_item,
- ScopedArenaAllocator* local_allocator)
- : allocator_(graph->GetAllocator()),
- graph_(graph),
- dex_file_(dex_file),
- code_item_(code_item),
- local_allocator_(local_allocator),
- branch_targets_(code_item != nullptr ? code_item->insns_size_in_code_units_
- : /* fake dex_pc=0 for intrinsic graph */ 1u,
- nullptr,
- local_allocator->Adapter(kArenaAllocGraphBuilder)),
- throwing_blocks_(kDefaultNumberOfThrowingBlocks,
- local_allocator->Adapter(kArenaAllocGraphBuilder)),
- number_of_branches_(0u),
- quicken_index_for_dex_pc_(std::less<uint32_t>(),
- local_allocator->Adapter(kArenaAllocGraphBuilder)) {}
+ const CodeItemDebugInfoAccessor& accessor,
+ ScopedArenaAllocator* local_allocator);
// Creates basic blocks in `graph_` at branch target dex_pc positions of the
// `code_item_`. Blocks are connected but left unpopulated with instructions.
@@ -83,7 +70,7 @@
HGraph* const graph_;
const DexFile* const dex_file_;
- const DexFile::CodeItem* const code_item_; // null for intrinsic graph.
+ CodeItemDataAccessor code_item_accessor_; // null code item for intrinsic graph.
ScopedArenaAllocator* const local_allocator_;
ScopedArenaVector<HBasicBlock*> branch_targets_;
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index d73ef1f..af537dd 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -37,7 +37,7 @@
namespace art {
HGraphBuilder::HGraphBuilder(HGraph* graph,
- const DexFile::CodeItem* code_item,
+ const CodeItemDebugInfoAccessor& accessor,
const DexCompilationUnit* dex_compilation_unit,
const DexCompilationUnit* outer_compilation_unit,
CompilerDriver* driver,
@@ -47,7 +47,7 @@
VariableSizedHandleScope* handles)
: graph_(graph),
dex_file_(&graph->GetDexFile()),
- code_item_(code_item),
+ code_item_accessor_(accessor),
dex_compilation_unit_(dex_compilation_unit),
outer_compilation_unit_(outer_compilation_unit),
compiler_driver_(driver),
@@ -57,6 +57,23 @@
handles_(handles),
return_type_(DataType::FromShorty(dex_compilation_unit_->GetShorty()[0])) {}
+HGraphBuilder::HGraphBuilder(HGraph* graph,
+ const DexCompilationUnit* dex_compilation_unit,
+ const CodeItemDebugInfoAccessor& accessor,
+ VariableSizedHandleScope* handles,
+ DataType::Type return_type)
+ : graph_(graph),
+ dex_file_(&graph->GetDexFile()),
+ code_item_accessor_(accessor),
+ dex_compilation_unit_(dex_compilation_unit),
+ outer_compilation_unit_(nullptr),
+ compiler_driver_(nullptr),
+ code_generator_(nullptr),
+ compilation_stats_(nullptr),
+ interpreter_metadata_(nullptr),
+ handles_(handles),
+ return_type_(return_type) {}
+
bool HGraphBuilder::SkipCompilation(size_t number_of_branches) {
if (compiler_driver_ == nullptr) {
// Note that the compiler driver is null when unit testing.
@@ -69,20 +86,20 @@
return false;
}
- if (compiler_options.IsHugeMethod(code_item_->insns_size_in_code_units_)) {
+ const uint32_t code_units = code_item_accessor_.InsnsSizeInCodeUnits();
+ if (compiler_options.IsHugeMethod(code_units)) {
VLOG(compiler) << "Skip compilation of huge method "
<< dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
- << ": " << code_item_->insns_size_in_code_units_ << " code units";
+ << ": " << code_units << " code units";
MaybeRecordStat(compilation_stats_, MethodCompilationStat::kNotCompiledHugeMethod);
return true;
}
// If it's large and contains no branches, it's likely to be machine generated initialization.
- if (compiler_options.IsLargeMethod(code_item_->insns_size_in_code_units_)
- && (number_of_branches == 0)) {
+ if (compiler_options.IsLargeMethod(code_units) && (number_of_branches == 0)) {
VLOG(compiler) << "Skip compilation of large method with no branch "
<< dex_file_->PrettyMethod(dex_compilation_unit_->GetDexMethodIndex())
- << ": " << code_item_->insns_size_in_code_units_ << " code units";
+ << ": " << code_units << " code units";
MaybeRecordStat(compilation_stats_, MethodCompilationStat::kNotCompiledLargeMethodNoBranches);
return true;
}
@@ -91,17 +108,17 @@
}
GraphAnalysisResult HGraphBuilder::BuildGraph() {
- DCHECK(code_item_ != nullptr);
+ DCHECK(code_item_accessor_.HasCodeItem());
DCHECK(graph_->GetBlocks().empty());
- graph_->SetNumberOfVRegs(code_item_->registers_size_);
- graph_->SetNumberOfInVRegs(code_item_->ins_size_);
- graph_->SetMaximumNumberOfOutVRegs(code_item_->outs_size_);
- graph_->SetHasTryCatch(code_item_->tries_size_ != 0);
+ graph_->SetNumberOfVRegs(code_item_accessor_.RegistersSize());
+ graph_->SetNumberOfInVRegs(code_item_accessor_.InsSize());
+ graph_->SetMaximumNumberOfOutVRegs(code_item_accessor_.OutsSize());
+ graph_->SetHasTryCatch(code_item_accessor_.TriesSize() != 0);
// Use ScopedArenaAllocator for all local allocations.
ScopedArenaAllocator local_allocator(graph_->GetArenaStack());
- HBasicBlockBuilder block_builder(graph_, dex_file_, code_item_, &local_allocator);
+ HBasicBlockBuilder block_builder(graph_, dex_file_, code_item_accessor_, &local_allocator);
SsaBuilder ssa_builder(graph_,
dex_compilation_unit_->GetClassLoader(),
dex_compilation_unit_->GetDexCache(),
@@ -111,7 +128,7 @@
&block_builder,
&ssa_builder,
dex_file_,
- code_item_,
+ code_item_accessor_,
return_type_,
dex_compilation_unit_,
outer_compilation_unit_,
@@ -150,7 +167,7 @@
}
void HGraphBuilder::BuildIntrinsicGraph(ArtMethod* method) {
- DCHECK(code_item_ == nullptr);
+ DCHECK(!code_item_accessor_.HasCodeItem());
DCHECK(graph_->GetBlocks().empty());
// Determine the number of arguments and associated vregs.
@@ -170,7 +187,10 @@
// Use ScopedArenaAllocator for all local allocations.
ScopedArenaAllocator local_allocator(graph_->GetArenaStack());
- HBasicBlockBuilder block_builder(graph_, dex_file_, /* code_item */ nullptr, &local_allocator);
+ HBasicBlockBuilder block_builder(graph_,
+ dex_file_,
+ CodeItemDebugInfoAccessor(),
+ &local_allocator);
SsaBuilder ssa_builder(graph_,
dex_compilation_unit_->GetClassLoader(),
dex_compilation_unit_->GetDexCache(),
@@ -180,7 +200,7 @@
&block_builder,
&ssa_builder,
dex_file_,
- /* code_item */ nullptr,
+ CodeItemDebugInfoAccessor(),
return_type_,
dex_compilation_unit_,
outer_compilation_unit_,
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index 0bb3a05..c40e0b4 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -18,6 +18,7 @@
#define ART_COMPILER_OPTIMIZING_BUILDER_H_
#include "base/arena_object.h"
+#include "code_item_accessors.h"
#include "dex_file-inl.h"
#include "dex_file.h"
#include "driver/compiler_driver.h"
@@ -33,7 +34,7 @@
class HGraphBuilder : public ValueObject {
public:
HGraphBuilder(HGraph* graph,
- const DexFile::CodeItem* code_item,
+ const CodeItemDebugInfoAccessor& accessor,
const DexCompilationUnit* dex_compilation_unit,
const DexCompilationUnit* outer_compilation_unit,
CompilerDriver* driver,
@@ -45,20 +46,9 @@
// Only for unit testing.
HGraphBuilder(HGraph* graph,
const DexCompilationUnit* dex_compilation_unit,
- const DexFile::CodeItem& code_item,
+ const CodeItemDebugInfoAccessor& accessor,
VariableSizedHandleScope* handles,
- DataType::Type return_type = DataType::Type::kInt32)
- : graph_(graph),
- dex_file_(&graph->GetDexFile()),
- code_item_(&code_item),
- dex_compilation_unit_(dex_compilation_unit),
- outer_compilation_unit_(nullptr),
- compiler_driver_(nullptr),
- code_generator_(nullptr),
- compilation_stats_(nullptr),
- interpreter_metadata_(nullptr),
- handles_(handles),
- return_type_(return_type) {}
+ DataType::Type return_type = DataType::Type::kInt32);
GraphAnalysisResult BuildGraph();
void BuildIntrinsicGraph(ArtMethod* method);
@@ -70,7 +60,7 @@
HGraph* const graph_;
const DexFile* const dex_file_;
- const DexFile::CodeItem* const code_item_; // null for intrinsic graph.
+ const CodeItemDebugInfoAccessor code_item_accessor_; // null for intrinsic graph.
// The compilation unit of the current method being compiled. Note that
// it can be an inlined method.
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 8750910..7a66d80 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -1381,26 +1381,26 @@
bool same_dex_file = IsSameDexFile(*outer_compilation_unit_.GetDexFile(), *method->GetDexFile());
- const DexFile::CodeItem* code_item = method->GetCodeItem();
+ CodeItemDataAccessor accessor(method);
- if (code_item == nullptr) {
+ if (!accessor.HasCodeItem()) {
LOG_FAIL_NO_STAT()
<< "Method " << method->PrettyMethod() << " is not inlined because it is native";
return false;
}
size_t inline_max_code_units = compiler_driver_->GetCompilerOptions().GetInlineMaxCodeUnits();
- if (code_item->insns_size_in_code_units_ > inline_max_code_units) {
+ if (accessor.InsnsSizeInCodeUnits() > inline_max_code_units) {
LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedCodeItem)
<< "Method " << method->PrettyMethod()
<< " is not inlined because its code item is too big: "
- << code_item->insns_size_in_code_units_
+ << accessor.InsnsSizeInCodeUnits()
<< " > "
<< inline_max_code_units;
return false;
}
- if (code_item->tries_size_ != 0) {
+ if (accessor.TriesSize() != 0) {
LOG_FAIL(stats_, MethodCompilationStat::kNotInlinedTryCatch)
<< "Method " << method->PrettyMethod() << " is not inlined because of try block";
return false;
@@ -1660,6 +1660,7 @@
const DexFile::CodeItem* code_item = resolved_method->GetCodeItem();
const DexFile& callee_dex_file = *resolved_method->GetDexFile();
uint32_t method_index = resolved_method->GetDexMethodIndex();
+ CodeItemDebugInfoAccessor code_item_accessor(&callee_dex_file, code_item);
ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker();
Handle<mirror::DexCache> dex_cache = NewHandleIfDifferent(resolved_method->GetDexCache(),
caller_compilation_unit_.GetDexCache(),
@@ -1714,7 +1715,7 @@
}
}
HGraphBuilder builder(callee_graph,
- code_item,
+ code_item_accessor,
&dex_compilation_unit,
&outer_compilation_unit_,
compiler_driver_,
@@ -1967,6 +1968,7 @@
return;
}
+ CodeItemDataAccessor accessor(&callee_graph->GetDexFile(), code_item);
HInliner inliner(callee_graph,
outermost_graph_,
codegen_,
@@ -1975,7 +1977,7 @@
compiler_driver_,
handles_,
inline_stats_,
- total_number_of_dex_registers_ + code_item->registers_size_,
+ total_number_of_dex_registers_ + accessor.RegistersSize(),
total_number_of_instructions_ + number_of_instructions,
this,
depth_ + 1);
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index e36d91f..3f5923f 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -39,6 +39,44 @@
namespace art {
+HInstructionBuilder::HInstructionBuilder(HGraph* graph,
+ HBasicBlockBuilder* block_builder,
+ SsaBuilder* ssa_builder,
+ const DexFile* dex_file,
+ const CodeItemDebugInfoAccessor& accessor,
+ DataType::Type return_type,
+ const DexCompilationUnit* dex_compilation_unit,
+ const DexCompilationUnit* outer_compilation_unit,
+ CompilerDriver* compiler_driver,
+ CodeGenerator* code_generator,
+ const uint8_t* interpreter_metadata,
+ OptimizingCompilerStats* compiler_stats,
+ VariableSizedHandleScope* handles,
+ ScopedArenaAllocator* local_allocator)
+ : allocator_(graph->GetAllocator()),
+ graph_(graph),
+ handles_(handles),
+ dex_file_(dex_file),
+ code_item_accessor_(accessor),
+ return_type_(return_type),
+ block_builder_(block_builder),
+ ssa_builder_(ssa_builder),
+ compiler_driver_(compiler_driver),
+ code_generator_(code_generator),
+ dex_compilation_unit_(dex_compilation_unit),
+ outer_compilation_unit_(outer_compilation_unit),
+ quicken_info_(interpreter_metadata),
+ compilation_stats_(compiler_stats),
+ local_allocator_(local_allocator),
+ locals_for_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
+ current_block_(nullptr),
+ current_locals_(nullptr),
+ latest_result_(nullptr),
+ current_this_parameter_(nullptr),
+ loop_headers_(local_allocator->Adapter(kArenaAllocGraphBuilder)) {
+ loop_headers_.reserve(kDefaultNumberOfLoops);
+}
+
HBasicBlock* HInstructionBuilder::FindBlockStartingAt(uint32_t dex_pc) const {
return block_builder_->GetBlockAt(dex_pc);
}
@@ -273,7 +311,7 @@
}
bool HInstructionBuilder::Build() {
- DCHECK(code_item_ != nullptr);
+ DCHECK(code_item_accessor_.HasCodeItem());
locals_for_.resize(
graph_->GetBlocks().size(),
ScopedArenaVector<HInstruction*>(local_allocator_->Adapter(kArenaAllocGraphBuilder)));
@@ -323,7 +361,7 @@
quicken_index = block_builder_->GetQuickenIndex(block_dex_pc);
}
- for (const DexInstructionPcPair& pair : code_item_->Instructions(block_dex_pc)) {
+ for (const DexInstructionPcPair& pair : code_item_accessor_.InstructionsFrom(block_dex_pc)) {
if (current_block_ == nullptr) {
// The previous instruction ended this block.
break;
@@ -367,7 +405,7 @@
}
void HInstructionBuilder::BuildIntrinsic(ArtMethod* method) {
- DCHECK(code_item_ == nullptr);
+ DCHECK(!code_item_accessor_.HasCodeItem());
DCHECK(method->IsIntrinsic());
locals_for_.resize(
@@ -442,15 +480,16 @@
return false;
}
};
- CodeItemDebugInfoAccessor accessor(dex_file_, code_item_);
ArenaBitVector* locations = ArenaBitVector::Create(local_allocator_,
- accessor.InsnsSizeInCodeUnits(),
+ code_item_accessor_.InsnsSizeInCodeUnits(),
/* expandable */ false,
kArenaAllocGraphBuilder);
locations->ClearAllBits();
- dex_file_->DecodeDebugPositionInfo(accessor.DebugInfoOffset(), Callback::Position, locations);
+ dex_file_->DecodeDebugPositionInfo(code_item_accessor_.DebugInfoOffset(),
+ Callback::Position,
+ locations);
// Instruction-specific tweaks.
- for (const DexInstructionPcPair& inst : accessor) {
+ for (const DexInstructionPcPair& inst : code_item_accessor_) {
switch (inst->Opcode()) {
case Instruction::MOVE_EXCEPTION: {
// Stop in native debugger after the exception has been moved.
@@ -459,7 +498,7 @@
locations->ClearBit(inst.DexPc());
DexInstructionIterator next = std::next(DexInstructionIterator(inst));
DCHECK(next.DexPc() != inst.DexPc());
- if (next != accessor.end()) {
+ if (next != code_item_accessor_.end()) {
locations->SetBit(next.DexPc());
}
break;
@@ -1706,7 +1745,8 @@
int32_t payload_offset = instruction.VRegB_31t() + dex_pc;
const Instruction::ArrayDataPayload* payload =
- reinterpret_cast<const Instruction::ArrayDataPayload*>(code_item_->insns_ + payload_offset);
+ reinterpret_cast<const Instruction::ArrayDataPayload*>(
+ code_item_accessor_.Insns() + payload_offset);
const uint8_t* data = payload->data;
uint32_t element_count = payload->element_count;
diff --git a/compiler/optimizing/instruction_builder.h b/compiler/optimizing/instruction_builder.h
index 0500d40..b4e3051 100644
--- a/compiler/optimizing/instruction_builder.h
+++ b/compiler/optimizing/instruction_builder.h
@@ -19,6 +19,7 @@
#include "base/scoped_arena_allocator.h"
#include "base/scoped_arena_containers.h"
+#include "code_item_accessors.h"
#include "data_type.h"
#include "dex_file.h"
#include "dex_file_types.h"
@@ -50,7 +51,7 @@
HBasicBlockBuilder* block_builder,
SsaBuilder* ssa_builder,
const DexFile* dex_file,
- const DexFile::CodeItem* code_item,
+ const CodeItemDebugInfoAccessor& accessor,
DataType::Type return_type,
const DexCompilationUnit* dex_compilation_unit,
const DexCompilationUnit* outer_compilation_unit,
@@ -59,30 +60,7 @@
const uint8_t* interpreter_metadata,
OptimizingCompilerStats* compiler_stats,
VariableSizedHandleScope* handles,
- ScopedArenaAllocator* local_allocator)
- : allocator_(graph->GetAllocator()),
- graph_(graph),
- handles_(handles),
- dex_file_(dex_file),
- code_item_(code_item),
- return_type_(return_type),
- block_builder_(block_builder),
- ssa_builder_(ssa_builder),
- compiler_driver_(compiler_driver),
- code_generator_(code_generator),
- dex_compilation_unit_(dex_compilation_unit),
- outer_compilation_unit_(outer_compilation_unit),
- quicken_info_(interpreter_metadata),
- compilation_stats_(compiler_stats),
- local_allocator_(local_allocator),
- locals_for_(local_allocator->Adapter(kArenaAllocGraphBuilder)),
- current_block_(nullptr),
- current_locals_(nullptr),
- latest_result_(nullptr),
- current_this_parameter_(nullptr),
- loop_headers_(local_allocator->Adapter(kArenaAllocGraphBuilder)) {
- loop_headers_.reserve(kDefaultNumberOfLoops);
- }
+ ScopedArenaAllocator* local_allocator);
bool Build();
void BuildIntrinsic(ArtMethod* method);
@@ -329,7 +307,7 @@
// The dex file where the method being compiled is, and the bytecode data.
const DexFile* const dex_file_;
- const DexFile::CodeItem* const code_item_; // null for intrinsic graph.
+ const CodeItemDebugInfoAccessor code_item_accessor_; // null for intrinsic graph.
// The return type of the method being compiled.
const DataType::Type return_type_;
diff --git a/compiler/optimizing/optimization.cc b/compiler/optimizing/optimization.cc
index 7149d93..d8ac696 100644
--- a/compiler/optimizing/optimization.cc
+++ b/compiler/optimizing/optimization.cc
@@ -35,6 +35,7 @@
#include "bounds_check_elimination.h"
#include "cha_guard_optimization.h"
+#include "code_item_accessors-inl.h"
#include "code_sinking.h"
#include "constant_folding.h"
#include "constructor_fence_redundancy_elimination.h"
@@ -241,7 +242,8 @@
opt = new (allocator) HDeadCodeElimination(graph, stats, name);
break;
case OptimizationPass::kInliner: {
- size_t number_of_dex_registers = dex_compilation_unit.GetCodeItem()->registers_size_;
+ CodeItemDataAccessor accessor(dex_compilation_unit.GetDexFile(),
+ dex_compilation_unit.GetCodeItem());
opt = new (allocator) HInliner(graph, // outer_graph
graph, // outermost_graph
codegen,
@@ -250,7 +252,7 @@
driver,
handles,
stats,
- number_of_dex_registers,
+ accessor.RegistersSize(),
/* total_number_of_instructions */ 0,
/* parent */ nullptr,
/* depth */ 0,
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index 24b1a12..9d04dd8 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -766,11 +766,13 @@
static constexpr size_t kSpaceFilterOptimizingThreshold = 128;
const CompilerOptions& compiler_options = compiler_driver->GetCompilerOptions();
if ((compiler_options.GetCompilerFilter() == CompilerFilter::kSpace)
- && (code_item->insns_size_in_code_units_ > kSpaceFilterOptimizingThreshold)) {
+ && (CodeItemInstructionAccessor(&dex_file, code_item).InsnsSizeInCodeUnits() >
+ kSpaceFilterOptimizingThreshold)) {
MaybeRecordStat(compilation_stats_.get(), MethodCompilationStat::kNotCompiledSpaceFilter);
return nullptr;
}
+ CodeItemDebugInfoAccessor code_item_accessor(&dex_file, code_item);
HGraph* graph = new (allocator) HGraph(
allocator,
arena_stack,
@@ -814,7 +816,7 @@
VLOG(compiler) << "Building " << pass_observer.GetMethodName();
PassScope scope(HGraphBuilder::kBuilderPassName, &pass_observer);
HGraphBuilder builder(graph,
- code_item,
+ code_item_accessor,
&dex_compilation_unit,
&dex_compilation_unit,
compiler_driver,
@@ -932,7 +934,7 @@
VLOG(compiler) << "Building intrinsic graph " << pass_observer.GetMethodName();
PassScope scope(HGraphBuilder::kBuilderPassName, &pass_observer);
HGraphBuilder builder(graph,
- /* code_item */ nullptr,
+ CodeItemDebugInfoAccessor(), // Null code item.
&dex_compilation_unit,
&dex_compilation_unit,
compiler_driver,
diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h
index 158c252..7d05262 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -19,6 +19,7 @@
#include "base/scoped_arena_allocator.h"
#include "builder.h"
+#include "code_item_accessors-inl.h"
#include "common_compiler_test.h"
#include "dex_file.h"
#include "dex_instruction.h"
@@ -145,7 +146,8 @@
/* access_flags */ 0u,
/* verified_method */ nullptr,
handles_->NewHandle<mirror::DexCache>(nullptr));
- HGraphBuilder builder(graph, dex_compilation_unit, *code_item, handles_.get(), return_type);
+ CodeItemDebugInfoAccessor accessor(&graph->GetDexFile(), code_item);
+ HGraphBuilder builder(graph, dex_compilation_unit, accessor, handles_.get(), return_type);
bool graph_built = (builder.BuildGraph() == kAnalysisSuccess);
return graph_built ? graph : nullptr;
}
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index f64c89a..730d4b9 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -735,7 +735,7 @@
* Dumps the catches table associated with the code.
*/
static void dumpCatches(const DexFile* pDexFile, const DexFile::CodeItem* pCode) {
- const u4 triesSize = pCode->tries_size_;
+ const u4 triesSize = CodeItemDataAccessor(pDexFile, pCode).TriesSize();
// No catch table.
if (triesSize == 0) {
diff --git a/dexdump/dexdump_cfg.cc b/dexdump/dexdump_cfg.cc
index 23ecf93..dd57a11 100644
--- a/dexdump/dexdump_cfg.cc
+++ b/dexdump/dexdump_cfg.cc
@@ -25,6 +25,7 @@
#include <set>
#include <sstream>
+#include "code_item_accessors-no_art-inl.h"
#include "dex_file-inl.h"
#include "dex_instruction-inl.h"
@@ -37,17 +38,17 @@
os << "digraph {\n";
os << " # /* " << dex_file->PrettyMethod(dex_method_idx, true) << " */\n";
+ CodeItemInstructionAccessor accessor(dex_file, code_item);
+
std::set<uint32_t> dex_pc_is_branch_target;
{
// Go and populate.
- const Instruction* inst = Instruction::At(code_item->insns_);
- for (uint32_t dex_pc = 0;
- dex_pc < code_item->insns_size_in_code_units_;
- dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) {
+ for (const DexInstructionPcPair& pair : accessor) {
+ const Instruction* inst = &pair.Inst();
if (inst->IsBranch()) {
- dex_pc_is_branch_target.insert(dex_pc + inst->GetTargetOffset());
+ dex_pc_is_branch_target.insert(pair.DexPc() + inst->GetTargetOffset());
} else if (inst->IsSwitch()) {
- const uint16_t* insns = code_item->insns_ + dex_pc;
+ const uint16_t* insns = reinterpret_cast<const uint16_t*>(inst);
int32_t switch_offset = insns[1] | (static_cast<int32_t>(insns[2]) << 16);
const uint16_t* switch_insns = insns + switch_offset;
uint32_t switch_count = switch_insns[1];
@@ -63,7 +64,7 @@
int32_t offset =
static_cast<int32_t>(switch_insns[targets_offset + targ * 2]) |
static_cast<int32_t>(switch_insns[targets_offset + targ * 2 + 1] << 16);
- dex_pc_is_branch_target.insert(dex_pc + offset);
+ dex_pc_is_branch_target.insert(pair.DexPc() + offset);
}
}
}
@@ -74,12 +75,10 @@
std::map<uint32_t, uint32_t> dex_pc_to_incl_id; // This has entries for all dex pcs.
{
- const Instruction* inst = Instruction::At(code_item->insns_);
bool first_in_block = true;
bool force_new_block = false;
- for (uint32_t dex_pc = 0;
- dex_pc < code_item->insns_size_in_code_units_;
- dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) {
+ for (const DexInstructionPcPair& pair : accessor) {
+ const uint32_t dex_pc = pair.DexPc();
if (dex_pc == 0 ||
(dex_pc_is_branch_target.find(dex_pc) != dex_pc_is_branch_target.end()) ||
force_new_block) {
@@ -108,7 +107,7 @@
// Dump the instruction. Need to escape '"', '<', '>', '{' and '}'.
os << "<" << "p" << dex_pc << ">";
os << " 0x" << std::hex << dex_pc << std::dec << ": ";
- std::string inst_str = inst->DumpString(dex_file);
+ std::string inst_str = pair.Inst().DumpString(dex_file);
size_t cur_start = 0; // It's OK to start at zero, instruction dumps don't start with chars
// we need to escape.
while (cur_start != std::string::npos) {
@@ -137,7 +136,7 @@
// Force a new block for some fall-throughs and some instructions that terminate the "local"
// control flow.
- force_new_block = inst->IsSwitch() || inst->IsBasicBlockEnd();
+ force_new_block = pair.Inst().IsSwitch() || pair.Inst().IsBasicBlockEnd();
}
// Close last node.
if (dex_pc_to_node_id.size() > 0) {
@@ -162,10 +161,9 @@
uint32_t last_node_id = std::numeric_limits<uint32_t>::max();
uint32_t old_dex_pc = 0;
uint32_t block_start_dex_pc = std::numeric_limits<uint32_t>::max();
- const Instruction* inst = Instruction::At(code_item->insns_);
- for (uint32_t dex_pc = 0;
- dex_pc < code_item->insns_size_in_code_units_;
- old_dex_pc = dex_pc, dex_pc += inst->SizeInCodeUnits(), inst = inst->Next()) {
+ for (const DexInstructionPcPair& pair : accessor) {
+ const Instruction* inst = &pair.Inst();
+ const uint32_t dex_pc = pair.DexPc();
{
auto it = dex_pc_to_node_id.find(dex_pc);
if (it != dex_pc_to_node_id.end()) {
@@ -222,7 +220,7 @@
}
} else if (inst->IsSwitch()) {
// TODO: Iterate through all switch targets.
- const uint16_t* insns = code_item->insns_ + dex_pc;
+ const uint16_t* insns = reinterpret_cast<const uint16_t*>(inst);
/* make sure the start of the switch is in range */
int32_t switch_offset = insns[1] | (static_cast<int32_t>(insns[2]) << 16);
/* offset to switch table is a relative branch-style offset */
@@ -272,6 +270,7 @@
// No fall-through.
last_node_id = std::numeric_limits<uint32_t>::max();
}
+ old_dex_pc = pair.DexPc();
}
// Finish up the last block, if it had common exceptions.
if (!exception_targets.empty()) {
@@ -293,7 +292,7 @@
// TODO
// Exception edges. If this is not the first instruction in the block
for (uint32_t dex_pc : blocks_with_detailed_exceptions) {
- const Instruction* inst = Instruction::At(&code_item->insns_[dex_pc]);
+ const Instruction* inst = &accessor.InstructionAt(dex_pc);
uint32_t this_node_id = dex_pc_to_incl_id.find(dex_pc)->second;
while (true) {
CatchHandlerIterator catch_it(*code_item, dex_pc);
@@ -322,7 +321,7 @@
// Loop update. Have a break-out if the next instruction is a branch target and thus in
// another block.
dex_pc += inst->SizeInCodeUnits();
- if (dex_pc >= code_item->insns_size_in_code_units_) {
+ if (dex_pc >= accessor.InsnsSizeInCodeUnits()) {
break;
}
if (dex_pc_to_node_id.find(dex_pc) != dex_pc_to_node_id.end()) {
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
index 90df2d7..a163bd9 100644
--- a/dexlayout/dex_ir.cc
+++ b/dexlayout/dex_ir.cc
@@ -21,6 +21,8 @@
*/
#include "dex_ir.h"
+
+#include "code_item_accessors-inl.h"
#include "dex_instruction-inl.h"
#include "dex_ir_builder.h"
@@ -564,13 +566,14 @@
CodeItem* Collections::CreateCodeItem(const DexFile& dex_file,
const DexFile::CodeItem& disk_code_item, uint32_t offset) {
- uint16_t registers_size = disk_code_item.registers_size_;
- uint16_t ins_size = disk_code_item.ins_size_;
- uint16_t outs_size = disk_code_item.outs_size_;
- uint32_t tries_size = disk_code_item.tries_size_;
+ CodeItemDebugInfoAccessor accessor(&dex_file, &disk_code_item);
+ const uint16_t registers_size = accessor.RegistersSize();
+ const uint16_t ins_size = accessor.InsSize();
+ const uint16_t outs_size = accessor.OutsSize();
+ const uint32_t tries_size = accessor.TriesSize();
// TODO: Calculate the size of the debug info.
- uint32_t debug_info_offset = dex_file.GetDebugInfoOffset(&disk_code_item);
+ const uint32_t debug_info_offset = accessor.DebugInfoOffset();
const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(debug_info_offset);
DebugInfoItem* debug_info = nullptr;
if (debug_info_stream != nullptr) {
@@ -584,20 +587,19 @@
}
}
- uint32_t insns_size = disk_code_item.insns_size_in_code_units_;
+ uint32_t insns_size = accessor.InsnsSizeInCodeUnits();
uint16_t* insns = new uint16_t[insns_size];
- memcpy(insns, disk_code_item.insns_, insns_size * sizeof(uint16_t));
+ memcpy(insns, accessor.Insns(), insns_size * sizeof(uint16_t));
TryItemVector* tries = nullptr;
CatchHandlerVector* handler_list = nullptr;
if (tries_size > 0) {
tries = new TryItemVector();
handler_list = new CatchHandlerVector();
- for (uint32_t i = 0; i < tries_size; ++i) {
- const DexFile::TryItem* disk_try_item = dex_file.GetTryItems(disk_code_item, i);
- uint32_t start_addr = disk_try_item->start_addr_;
- uint16_t insn_count = disk_try_item->insn_count_;
- uint16_t handler_off = disk_try_item->handler_off_;
+ for (const DexFile::TryItem& disk_try_item : accessor.TryItems()) {
+ uint32_t start_addr = disk_try_item.start_addr_;
+ uint16_t insn_count = disk_try_item.insn_count_;
+ uint16_t handler_off = disk_try_item.handler_off_;
const CatchHandler* handlers = nullptr;
for (std::unique_ptr<const CatchHandler>& existing_handlers : *handler_list) {
if (handler_off == existing_handlers->GetListOffset()) {
@@ -608,7 +610,7 @@
if (handlers == nullptr) {
bool catch_all = false;
TypeAddrPairVector* addr_pairs = new TypeAddrPairVector();
- for (CatchHandlerIterator it(disk_code_item, *disk_try_item); it.HasNext(); it.Next()) {
+ for (CatchHandlerIterator it(disk_code_item, disk_try_item); it.HasNext(); it.Next()) {
const dex::TypeIndex type_index = it.GetHandlerTypeIndex();
const TypeId* type_id = GetTypeIdOrNullPtr(type_index.index_);
catch_all |= type_id == nullptr;
@@ -622,7 +624,7 @@
tries->push_back(std::unique_ptr<const TryItem>(try_item));
}
// Manually walk catch handlers list and add any missing handlers unreferenced by try items.
- const uint8_t* handlers_base = DexFile::GetCatchHandlerData(disk_code_item, 0);
+ const uint8_t* handlers_base = accessor.GetCatchHandlerData();
const uint8_t* handlers_data = handlers_base;
uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_data);
while (handlers_size > handler_list->size()) {
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 1a1d8cc..b2e19a8 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1261,8 +1261,7 @@
bool* addr_found) {
bool success = true;
- CodeItemDataAccessor code_item_accessor(CodeItemDataAccessor::CreateNullable(&dex_file,
- code_item));
+ CodeItemDataAccessor code_item_accessor(&dex_file, code_item);
// TODO: Support regex
std::string method_name = dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx));
diff --git a/openjdkjvmti/ti_breakpoint.cc b/openjdkjvmti/ti_breakpoint.cc
index 8e5b56e..7634fa3 100644
--- a/openjdkjvmti/ti_breakpoint.cc
+++ b/openjdkjvmti/ti_breakpoint.cc
@@ -98,7 +98,7 @@
art::ScopedObjectAccess soa(art::Thread::Current());
art::ArtMethod* art_method = art::jni::DecodeArtMethod(method)->GetCanonicalMethod();
if (location < 0 || static_cast<uint32_t>(location) >=
- art_method->GetCodeItem()->insns_size_in_code_units_) {
+ art_method->DexInstructions().InsnsSizeInCodeUnits()) {
return ERR(INVALID_LOCATION);
}
DeoptManager::Get()->AddMethodBreakpoint(art_method);
diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc
index 4444853..947ba79 100644
--- a/openjdkjvmti/ti_method.cc
+++ b/openjdkjvmti/ti_method.cc
@@ -123,19 +123,19 @@
}
art::ScopedObjectAccess soa(art::Thread::Current());
- const art::DexFile::CodeItem* code_item = art_method->GetCodeItem();
- if (code_item == nullptr) {
+ art::CodeItemInstructionAccessor accessor(art_method);
+ if (!accessor.HasCodeItem()) {
*size_ptr = 0;
*bytecode_ptr = nullptr;
return OK;
}
// 2 bytes per instruction for dex code.
- *size_ptr = code_item->insns_size_in_code_units_ * 2;
+ *size_ptr = accessor.InsnsSizeInCodeUnits() * 2;
jvmtiError err = env->Allocate(*size_ptr, bytecode_ptr);
if (err != OK) {
return err;
}
- memcpy(*bytecode_ptr, code_item->insns_, *size_ptr);
+ memcpy(*bytecode_ptr, accessor.Insns(), *size_ptr);
return OK;
}
@@ -168,7 +168,7 @@
}
DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
- *size_ptr = art_method->GetCodeItem()->ins_size_;
+ *size_ptr = art::CodeItemDataAccessor(art_method).InsSize();
return ERR(NONE);
}
@@ -266,14 +266,10 @@
};
LocalVariableContext context(env);
- if (!dex_file->DecodeDebugLocalInfo(accessor.RegistersSize(),
- accessor.InsSize(),
- accessor.InsnsSizeInCodeUnits(),
- accessor.DebugInfoOffset(),
- art_method->IsStatic(),
- art_method->GetDexMethodIndex(),
- LocalVariableContext::Callback,
- &context)) {
+ if (!accessor.DecodeDebugLocalInfo(art_method->IsStatic(),
+ art_method->GetDexMethodIndex(),
+ LocalVariableContext::Callback,
+ &context)) {
// Something went wrong with decoding the debug information. It might as well not be there.
return ERR(ABSENT_INFORMATION);
} else {
@@ -305,7 +301,7 @@
}
DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
- *max_ptr = art_method->GetCodeItem()->registers_size_;
+ *max_ptr = art::CodeItemDataAccessor(art_method).RegistersSize();
return ERR(NONE);
}
@@ -420,7 +416,7 @@
DCHECK_NE(art_method->GetCodeItemOffset(), 0u);
*start_location_ptr = 0;
- *end_location_ptr = art_method->GetCodeItem()->insns_size_in_code_units_ - 1;
+ *end_location_ptr = art_method->DexInstructions().InsnsSizeInCodeUnits() - 1;
return ERR(NONE);
}
@@ -571,7 +567,7 @@
// TODO It might be useful to fake up support for get at least on proxy frames.
result_ = ERR(OPAQUE_FRAME);
return;
- } else if (method->GetCodeItem()->registers_size_ <= slot_) {
+ } else if (art::CodeItemDataAccessor(method).RegistersSize() <= slot_) {
result_ = ERR(INVALID_SLOT);
return;
}
diff --git a/openjdkjvmti/ti_stack.cc b/openjdkjvmti/ti_stack.cc
index b43eaa0..17b4243 100644
--- a/openjdkjvmti/ti_stack.cc
+++ b/openjdkjvmti/ti_stack.cc
@@ -44,6 +44,7 @@
#include "base/bit_utils.h"
#include "base/enums.h"
#include "base/mutex.h"
+#include "code_item_accessors-inl.h"
#include "dex_file.h"
#include "dex_file_annotations.h"
#include "dex_file_types.h"
@@ -1044,7 +1045,7 @@
if (shadow_frame == nullptr) {
needs_instrument = true;
const size_t frame_id = visitor.GetFrameId();
- const uint16_t num_regs = method->GetCodeItem()->registers_size_;
+ const uint16_t num_regs = art::CodeItemDataAccessor(method).RegistersSize();
shadow_frame = target->FindOrCreateDebuggerShadowFrame(frame_id,
num_regs,
method,
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 869394c..c6c4f4a 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -459,16 +459,8 @@
}
}
-inline IterationRange<DexInstructionIterator> ArtMethod::DexInstructions() {
- CodeItemInstructionAccessor accessor(this);
- return { accessor.begin(),
- accessor.end() };
-}
-
-inline IterationRange<DexInstructionIterator> ArtMethod::NullableDexInstructions() {
- CodeItemInstructionAccessor accessor(CodeItemInstructionAccessor::CreateNullable(this));
- return { accessor.begin(),
- accessor.end() };
+inline CodeItemInstructionAccessor ArtMethod::DexInstructions() {
+ return CodeItemInstructionAccessor(this);
}
} // namespace art
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index 9005120..7ddaa7e 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -297,9 +297,8 @@
}
}
if (found_dex_pc != dex::kDexNoIndex) {
- const Instruction* first_catch_instr =
- Instruction::At(&code_item->insns_[found_dex_pc]);
- *has_no_move_exception = (first_catch_instr->Opcode() != Instruction::MOVE_EXCEPTION);
+ const Instruction& first_catch_instr = DexInstructions().InstructionAt(found_dex_pc);
+ *has_no_move_exception = (first_catch_instr.Opcode() != Instruction::MOVE_EXCEPTION);
}
// Put the exception back.
if (exception != nullptr) {
diff --git a/runtime/art_method.h b/runtime/art_method.h
index f433223..ab90a10 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -27,6 +27,7 @@
#include "base/iteration_range.h"
#include "base/macros.h"
#include "base/runtime_debug.h"
+#include "code_item_accessors.h"
#include "dex_file.h"
#include "dex_instruction_iterator.h"
#include "gc_root.h"
@@ -716,13 +717,9 @@
"ptr_sized_fields_.entry_point_from_quick_compiled_code_");
}
- // Returns the dex instructions of the code item for the art method. Must not be called on null
- // code items.
- ALWAYS_INLINE IterationRange<DexInstructionIterator> DexInstructions()
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- // Handles a null code item by returning iterators that have a null address.
- ALWAYS_INLINE IterationRange<DexInstructionIterator> NullableDexInstructions()
+ // Returns the dex instructions of the code item for the art method. Returns an empty array for
+ // the null code item case.
+ ALWAYS_INLINE CodeItemInstructionAccessor DexInstructions()
REQUIRES_SHARED(Locks::mutator_lock_);
protected:
diff --git a/runtime/check_reference_map_visitor.h b/runtime/check_reference_map_visitor.h
index d9e8915..c4a613a 100644
--- a/runtime/check_reference_map_visitor.h
+++ b/runtime/check_reference_map_visitor.h
@@ -18,6 +18,7 @@
#define ART_RUNTIME_CHECK_REFERENCE_MAP_VISITOR_H_
#include "art_method-inl.h"
+#include "code_item_accessors-inl.h"
#include "dex_file_types.h"
#include "oat_quick_method_header.h"
#include "scoped_thread_state_change-inl.h"
@@ -66,14 +67,15 @@
CodeInfo code_info = GetCurrentOatQuickMethodHeader()->GetOptimizedCodeInfo();
CodeInfoEncoding encoding = code_info.ExtractEncoding();
StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
- uint16_t number_of_dex_registers = m->GetCodeItem()->registers_size_;
+ CodeItemDataAccessor accessor(m);
+ uint16_t number_of_dex_registers = accessor.RegistersSize();
DexRegisterMap dex_register_map =
code_info.GetDexRegisterMapOf(stack_map, encoding, number_of_dex_registers);
uint32_t register_mask = code_info.GetRegisterMaskOf(encoding, stack_map);
BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, stack_map);
for (int i = 0; i < number_of_references; ++i) {
int reg = registers[i];
- CHECK(reg < m->GetCodeItem()->registers_size_);
+ CHECK_LT(reg, accessor.RegistersSize());
DexRegisterLocation location = dex_register_map.GetDexRegisterLocation(
reg, number_of_dex_registers, code_info, encoding);
switch (location.GetKind()) {
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 55fa632..45b7618 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4317,15 +4317,14 @@
void ClassLinker::ResolveMethodExceptionHandlerTypes(ArtMethod* method) {
// similar to DexVerifier::ScanTryCatchBlocks and dex2oat's ResolveExceptionsForMethod.
- const DexFile::CodeItem* code_item =
- method->GetDexFile()->GetCodeItem(method->GetCodeItemOffset());
- if (code_item == nullptr) {
+ CodeItemDataAccessor accessor(method);
+ if (!accessor.HasCodeItem()) {
return; // native or abstract method
}
- if (code_item->tries_size_ == 0) {
+ if (accessor.TriesSize() == 0) {
return; // nothing to process
}
- const uint8_t* handlers_ptr = DexFile::GetCatchHandlerData(*code_item, 0);
+ const uint8_t* handlers_ptr = accessor.GetCatchHandlerData(0);
uint32_t handlers_size = DecodeUnsignedLeb128(&handlers_ptr);
for (uint32_t idx = 0; idx < handlers_size; idx++) {
CatchHandlerIterator iterator(handlers_ptr);
diff --git a/runtime/code_item_accessors-inl.h b/runtime/code_item_accessors-inl.h
index 1ba3c55..f63ea69 100644
--- a/runtime/code_item_accessors-inl.h
+++ b/runtime/code_item_accessors-inl.h
@@ -30,27 +30,9 @@
inline CodeItemInstructionAccessor::CodeItemInstructionAccessor(ArtMethod* method)
: CodeItemInstructionAccessor(method->GetDexFile(), method->GetCodeItem()) {}
-inline CodeItemInstructionAccessor CodeItemInstructionAccessor::CreateNullable(
- ArtMethod* method) {
- DCHECK(method != nullptr);
- CodeItemInstructionAccessor ret;
- const DexFile::CodeItem* code_item = method->GetCodeItem();
- if (code_item != nullptr) {
- ret.Init(method->GetDexFile(), code_item);
- } else {
- DCHECK(!ret.HasCodeItem()) << "Should be null initialized";
- }
- return ret;
-}
-
inline CodeItemDataAccessor::CodeItemDataAccessor(ArtMethod* method)
: CodeItemDataAccessor(method->GetDexFile(), method->GetCodeItem()) {}
-inline CodeItemDataAccessor CodeItemDataAccessor::CreateNullable(ArtMethod* method) {
- DCHECK(method != nullptr);
- return CreateNullable(method->GetDexFile(), method->GetCodeItem());
-}
-
inline CodeItemDebugInfoAccessor::CodeItemDebugInfoAccessor(ArtMethod* method)
: CodeItemDebugInfoAccessor(method->GetDexFile(), method->GetCodeItem()) {}
@@ -59,7 +41,7 @@
if (code_item == nullptr) {
return;
}
- Init(dex_file, code_item, OatFile::GetDebugInfoOffset(*dex_file, code_item));
+ Init(dex_file, code_item, OatFile::GetDebugInfoOffset(*dex_file, code_item->debug_info_off_));
}
} // namespace art
diff --git a/runtime/code_item_accessors-no_art-inl.h b/runtime/code_item_accessors-no_art-inl.h
index 96321b5..ebdd78b 100644
--- a/runtime/code_item_accessors-no_art-inl.h
+++ b/runtime/code_item_accessors-no_art-inl.h
@@ -24,7 +24,6 @@
#include "standard_dex_file.h"
// The no ART version is used by binaries that don't include the whole runtime.
-
namespace art {
inline void CodeItemInstructionAccessor::Init(const CompactDexFile::CodeItem& code_item) {
@@ -39,13 +38,14 @@
inline void CodeItemInstructionAccessor::Init(const DexFile* dex_file,
const DexFile::CodeItem* code_item) {
- DCHECK(dex_file != nullptr);
- DCHECK(code_item != nullptr);
- if (dex_file->IsCompactDexFile()) {
- Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
- } else {
- DCHECK(dex_file->IsStandardDexFile());
- Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
+ if (code_item != nullptr) {
+ DCHECK(dex_file != nullptr);
+ if (dex_file->IsCompactDexFile()) {
+ Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
+ } else {
+ DCHECK(dex_file->IsStandardDexFile());
+ Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
+ }
}
}
@@ -63,6 +63,14 @@
return DexInstructionIterator(insns_, insns_size_in_code_units_);
}
+inline IterationRange<DexInstructionIterator> CodeItemInstructionAccessor::InstructionsFrom(
+ uint32_t start_dex_pc) const {
+ DCHECK_LT(start_dex_pc, InsnsSizeInCodeUnits());
+ return {
+ DexInstructionIterator(insns_, start_dex_pc),
+ DexInstructionIterator(insns_, insns_size_in_code_units_) };
+}
+
inline void CodeItemDataAccessor::Init(const CompactDexFile::CodeItem& code_item) {
CodeItemInstructionAccessor::Init(code_item);
registers_size_ = code_item.registers_size_;
@@ -81,13 +89,14 @@
inline void CodeItemDataAccessor::Init(const DexFile* dex_file,
const DexFile::CodeItem* code_item) {
- DCHECK(dex_file != nullptr);
- DCHECK(code_item != nullptr);
- if (dex_file->IsCompactDexFile()) {
- CodeItemDataAccessor::Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
- } else {
- DCHECK(dex_file->IsStandardDexFile());
- CodeItemDataAccessor::Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
+ if (code_item != nullptr) {
+ DCHECK(dex_file != nullptr);
+ if (dex_file->IsCompactDexFile()) {
+ CodeItemDataAccessor::Init(down_cast<const CompactDexFile::CodeItem&>(*code_item));
+ } else {
+ DCHECK(dex_file->IsStandardDexFile());
+ CodeItemDataAccessor::Init(down_cast<const StandardDexFile::CodeItem&>(*code_item));
+ }
}
}
@@ -96,18 +105,6 @@
Init(dex_file, code_item);
}
-inline CodeItemDataAccessor CodeItemDataAccessor::CreateNullable(
- const DexFile* dex_file,
- const DexFile::CodeItem* code_item) {
- CodeItemDataAccessor ret;
- if (code_item != nullptr) {
- ret.Init(dex_file, code_item);
- } else {
- DCHECK(!ret.HasCodeItem()) << "Should be null initialized";
- }
- return ret;
-}
-
inline IterationRange<const DexFile::TryItem*> CodeItemDataAccessor::TryItems() const {
const DexFile::TryItem* try_items = DexFile::GetTryItems(end(), 0u);
return {
@@ -163,7 +160,6 @@
context);
}
-
} // namespace art
#endif // ART_RUNTIME_CODE_ITEM_ACCESSORS_NO_ART_INL_H_
diff --git a/runtime/code_item_accessors.h b/runtime/code_item_accessors.h
index 9f40114..4cbe7a1 100644
--- a/runtime/code_item_accessors.h
+++ b/runtime/code_item_accessors.h
@@ -42,6 +42,8 @@
ALWAYS_INLINE DexInstructionIterator end() const;
+ IterationRange<DexInstructionIterator> InstructionsFrom(uint32_t start_dex_pc) const;
+
uint32_t InsnsSizeInCodeUnits() const {
return insns_size_in_code_units_;
}
@@ -52,6 +54,7 @@
// Return the instruction for a dex pc.
const Instruction& InstructionAt(uint32_t dex_pc) const {
+ DCHECK_LT(dex_pc, InsnsSizeInCodeUnits());
return *Instruction::At(insns_ + dex_pc);
}
@@ -60,10 +63,6 @@
return Insns() != nullptr;
}
- // CreateNullable allows ArtMethods that have a null code item.
- ALWAYS_INLINE static CodeItemInstructionAccessor CreateNullable(ArtMethod* method)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
protected:
CodeItemInstructionAccessor() = default;
@@ -109,14 +108,6 @@
const DexFile::TryItem* FindTryItem(uint32_t try_dex_pc) const;
- // CreateNullable allows ArtMethods that have a null code item.
- ALWAYS_INLINE static CodeItemDataAccessor CreateNullable(ArtMethod* method)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
- ALWAYS_INLINE static CodeItemDataAccessor CreateNullable(
- const DexFile* dex_file,
- const DexFile::CodeItem* code_item);
-
protected:
CodeItemDataAccessor() = default;
diff --git a/runtime/common_dex_operations.h b/runtime/common_dex_operations.h
index 267735f..8988702 100644
--- a/runtime/common_dex_operations.h
+++ b/runtime/common_dex_operations.h
@@ -23,6 +23,7 @@
#include "base/macros.h"
#include "base/mutex.h"
#include "class_linker.h"
+#include "code_item_accessors.h"
#include "handle_scope-inl.h"
#include "instrumentation.h"
#include "interpreter/shadow_frame.h"
@@ -52,7 +53,7 @@
} // namespace interpreter
inline void PerformCall(Thread* self,
- const DexFile::CodeItem* code_item,
+ const CodeItemDataAccessor& accessor,
ArtMethod* caller_method,
const size_t first_dest_reg,
ShadowFrame* callee_frame,
@@ -61,13 +62,13 @@
REQUIRES_SHARED(Locks::mutator_lock_) {
if (LIKELY(Runtime::Current()->IsStarted())) {
if (use_interpreter_entrypoint) {
- interpreter::ArtInterpreterToInterpreterBridge(self, code_item, callee_frame, result);
+ interpreter::ArtInterpreterToInterpreterBridge(self, accessor, callee_frame, result);
} else {
interpreter::ArtInterpreterToCompiledCodeBridge(
self, caller_method, callee_frame, first_dest_reg, result);
}
} else {
- interpreter::UnstartedRuntime::Invoke(self, code_item, callee_frame, result, first_dest_reg);
+ interpreter::UnstartedRuntime::Invoke(self, accessor, callee_frame, result, first_dest_reg);
}
}
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 575d18e..707885c 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -551,43 +551,43 @@
void ThrowNullPointerExceptionFromDexPC(bool check_address, uintptr_t addr) {
uint32_t throw_dex_pc;
ArtMethod* method = Thread::Current()->GetCurrentMethod(&throw_dex_pc);
- const DexFile::CodeItem* code = method->GetCodeItem();
- CHECK_LT(throw_dex_pc, code->insns_size_in_code_units_);
- const Instruction* instr = Instruction::At(&code->insns_[throw_dex_pc]);
- if (check_address && !IsValidImplicitCheck(addr, *instr)) {
+ CodeItemInstructionAccessor accessor(method);
+ CHECK_LT(throw_dex_pc, accessor.InsnsSizeInCodeUnits());
+ const Instruction& instr = accessor.InstructionAt(throw_dex_pc);
+ if (check_address && !IsValidImplicitCheck(addr, instr)) {
const DexFile* dex_file = method->GetDeclaringClass()->GetDexCache()->GetDexFile();
LOG(FATAL) << "Invalid address for an implicit NullPointerException check: "
<< "0x" << std::hex << addr << std::dec
<< ", at "
- << instr->DumpString(dex_file)
+ << instr.DumpString(dex_file)
<< " in "
<< method->PrettyMethod();
}
- switch (instr->Opcode()) {
+ switch (instr.Opcode()) {
case Instruction::INVOKE_DIRECT:
- ThrowNullPointerExceptionForMethodAccess(instr->VRegB_35c(), kDirect);
+ ThrowNullPointerExceptionForMethodAccess(instr.VRegB_35c(), kDirect);
break;
case Instruction::INVOKE_DIRECT_RANGE:
- ThrowNullPointerExceptionForMethodAccess(instr->VRegB_3rc(), kDirect);
+ ThrowNullPointerExceptionForMethodAccess(instr.VRegB_3rc(), kDirect);
break;
case Instruction::INVOKE_VIRTUAL:
- ThrowNullPointerExceptionForMethodAccess(instr->VRegB_35c(), kVirtual);
+ ThrowNullPointerExceptionForMethodAccess(instr.VRegB_35c(), kVirtual);
break;
case Instruction::INVOKE_VIRTUAL_RANGE:
- ThrowNullPointerExceptionForMethodAccess(instr->VRegB_3rc(), kVirtual);
+ ThrowNullPointerExceptionForMethodAccess(instr.VRegB_3rc(), kVirtual);
break;
case Instruction::INVOKE_INTERFACE:
- ThrowNullPointerExceptionForMethodAccess(instr->VRegB_35c(), kInterface);
+ ThrowNullPointerExceptionForMethodAccess(instr.VRegB_35c(), kInterface);
break;
case Instruction::INVOKE_INTERFACE_RANGE:
- ThrowNullPointerExceptionForMethodAccess(instr->VRegB_3rc(), kInterface);
+ ThrowNullPointerExceptionForMethodAccess(instr.VRegB_3rc(), kInterface);
break;
case Instruction::INVOKE_POLYMORPHIC:
- ThrowNullPointerExceptionForMethodAccess(instr->VRegB_45cc(), kVirtual);
+ ThrowNullPointerExceptionForMethodAccess(instr.VRegB_45cc(), kVirtual);
break;
case Instruction::INVOKE_POLYMORPHIC_RANGE:
- ThrowNullPointerExceptionForMethodAccess(instr->VRegB_4rcc(), kVirtual);
+ ThrowNullPointerExceptionForMethodAccess(instr.VRegB_4rcc(), kVirtual);
break;
case Instruction::INVOKE_VIRTUAL_QUICK:
case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
@@ -612,7 +612,7 @@
case Instruction::IGET_CHAR:
case Instruction::IGET_SHORT: {
ArtField* field =
- Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), method, false);
+ Runtime::Current()->GetClassLinker()->ResolveField(instr.VRegC_22c(), method, false);
ThrowNullPointerExceptionForFieldAccess(field, true /* read */);
break;
}
@@ -644,7 +644,7 @@
case Instruction::IPUT_CHAR:
case Instruction::IPUT_SHORT: {
ArtField* field =
- Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), method, false);
+ Runtime::Current()->GetClassLinker()->ResolveField(instr.VRegC_22c(), method, false);
ThrowNullPointerExceptionForFieldAccess(field, false /* write */);
break;
}
@@ -707,7 +707,7 @@
const DexFile* dex_file =
method->GetDeclaringClass()->GetDexCache()->GetDexFile();
LOG(FATAL) << "NullPointerException at an unexpected instruction: "
- << instr->DumpString(dex_file)
+ << instr.DumpString(dex_file)
<< " in "
<< method->PrettyMethod();
break;
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index c85c233..2be00f5 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -278,11 +278,8 @@
}
private:
- static bool IsReturn(ArtMethod* method, uint32_t dex_pc)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- const DexFile::CodeItem* code_item = method->GetCodeItem();
- const Instruction* instruction = Instruction::At(&code_item->insns_[dex_pc]);
- return instruction->IsReturn();
+ static bool IsReturn(ArtMethod* method, uint32_t dex_pc) REQUIRES_SHARED(Locks::mutator_lock_) {
+ return method->DexInstructions().InstructionAt(dex_pc).IsReturn();
}
static bool IsListeningToDexPcMoved() REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -1535,15 +1532,15 @@
*/
static uint16_t MangleSlot(uint16_t slot, ArtMethod* m)
REQUIRES_SHARED(Locks::mutator_lock_) {
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- if (code_item == nullptr) {
+ CodeItemDataAccessor accessor(m);
+ if (!accessor.HasCodeItem()) {
// We should not get here for a method without code (native, proxy or abstract). Log it and
// return the slot as is since all registers are arguments.
LOG(WARNING) << "Trying to mangle slot for method without code " << m->PrettyMethod();
return slot;
}
- uint16_t ins_size = code_item->ins_size_;
- uint16_t locals_size = code_item->registers_size_ - ins_size;
+ uint16_t ins_size = accessor.InsSize();
+ uint16_t locals_size = accessor.RegistersSize() - ins_size;
if (slot >= locals_size) {
return slot - locals_size;
} else {
@@ -1566,8 +1563,8 @@
*/
static uint16_t DemangleSlot(uint16_t slot, ArtMethod* m, JDWP::JdwpError* error)
REQUIRES_SHARED(Locks::mutator_lock_) {
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- if (code_item == nullptr) {
+ CodeItemDataAccessor accessor(m);
+ if (!accessor.HasCodeItem()) {
// We should not get here for a method without code (native, proxy or abstract). Log it and
// return the slot as is since all registers are arguments.
LOG(WARNING) << "Trying to demangle slot for method without code "
@@ -1578,9 +1575,9 @@
return slot;
}
} else {
- if (slot < code_item->registers_size_) {
- uint16_t ins_size = code_item->ins_size_;
- uint16_t locals_size = code_item->registers_size_ - ins_size;
+ if (slot < accessor.RegistersSize()) {
+ uint16_t ins_size = accessor.InsSize();
+ uint16_t locals_size = accessor.RegistersSize() - ins_size;
*error = JDWP::ERR_NONE;
return (slot < ins_size) ? slot + locals_size : slot - ins_size;
}
@@ -1793,9 +1790,9 @@
if (m == nullptr) {
return JDWP::ERR_INVALID_METHODID;
}
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- size_t byte_count = code_item->insns_size_in_code_units_ * 2;
- const uint8_t* begin = reinterpret_cast<const uint8_t*>(code_item->insns_);
+ CodeItemDataAccessor accessor(m);
+ size_t byte_count = accessor.InsnsSizeInCodeUnits() * 2;
+ const uint8_t* begin = reinterpret_cast<const uint8_t*>(accessor.Insns());
const uint8_t* end = begin + byte_count;
for (const uint8_t* p = begin; p != end; ++p) {
bytecodes->push_back(*p);
@@ -2978,9 +2975,8 @@
Handle<mirror::Throwable> pending_exception(hs.NewHandle(self->GetException()));
self->ClearException();
if (kIsDebugBuild && pending_exception != nullptr) {
- const DexFile::CodeItem* code_item = location.method->GetCodeItem();
- const Instruction* instr = Instruction::At(&code_item->insns_[location.dex_pc]);
- CHECK_EQ(Instruction::MOVE_EXCEPTION, instr->Opcode());
+ const Instruction& instr = location.method->DexInstructions().InstructionAt(location.dex_pc);
+ CHECK_EQ(Instruction::MOVE_EXCEPTION, instr.Opcode());
}
gJdwpState->PostLocationEvent(&location, this_object, event_flags, return_value);
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 76110f2..f3a88f7 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -320,6 +320,7 @@
debug_info_off_ = new_offset;
}
+ private:
uint16_t registers_size_; // the number of registers used by this code
// (locals + parameters)
uint16_t ins_size_; // the number of words of incoming arguments to the method
@@ -340,6 +341,14 @@
uint16_t insns_[1]; // actual array of bytecode.
private:
+ ART_FRIEND_TEST(CodeItemAccessorsTest, TestDexInstructionsAccessor);
+ friend class CatchHandlerIterator;
+ friend class CodeItemDataAccessor;
+ friend class CodeItemDebugInfoAccessor;
+ friend class CodeItemInstructionAccessor;
+ friend class DexFile; // TODO: Remove this one when it's cleaned up.
+ friend class DexFileVerifier;
+ friend class VdexFile; // TODO: Remove this one when it's cleaned up.
DISALLOW_COPY_AND_ASSIGN(CodeItem);
};
diff --git a/runtime/dex_file_test.cc b/runtime/dex_file_test.cc
index 6905504..87eec57 100644
--- a/runtime/dex_file_test.cc
+++ b/runtime/dex_file_test.cc
@@ -22,6 +22,7 @@
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
+#include "code_item_accessors-inl.h"
#include "common_runtime_test.h"
#include "dex_file-inl.h"
#include "dex_file_loader.h"
@@ -730,15 +731,8 @@
kRawDexDebugInfoLocalNullType, tmp.GetFilename().c_str(), 0xf25f2b38U, true);
const DexFile::ClassDef& class_def = raw->GetClassDef(0);
const DexFile::CodeItem* code_item = raw->GetCodeItem(raw->FindCodeItemOffset(class_def, 1));
- uint32_t debug_info_offset = raw->GetDebugInfoOffset(code_item);
- ASSERT_TRUE(raw->DecodeDebugLocalInfo(code_item->registers_size_,
- code_item->ins_size_,
- code_item->insns_size_in_code_units_,
- debug_info_offset,
- true,
- 1,
- Callback,
- nullptr));
+ CodeItemDebugInfoAccessor accessor(raw.get(), code_item);
+ ASSERT_TRUE(accessor.DecodeDebugLocalInfo(true, 1, Callback, nullptr));
}
} // namespace art
diff --git a/runtime/dex_file_tracking_registrar.cc b/runtime/dex_file_tracking_registrar.cc
index 4de4376..c157ddc 100644
--- a/runtime/dex_file_tracking_registrar.cc
+++ b/runtime/dex_file_tracking_registrar.cc
@@ -30,6 +30,7 @@
#endif
#include "base/memory_tool.h"
+#include "code_item_accessors-inl.h"
#include "dex_file-inl.h"
namespace art {
@@ -184,9 +185,12 @@
if (code_item != nullptr) {
const void* code_item_begin = reinterpret_cast<const void*>(code_item);
size_t code_item_start = reinterpret_cast<size_t>(code_item);
- size_t code_item_start_end = reinterpret_cast<size_t>(&code_item->insns_[1]);
+ CodeItemInstructionAccessor accessor(dex_file_, code_item);
+ size_t code_item_start_end = reinterpret_cast<size_t>(accessor.Insns());
size_t code_item_start_size = code_item_start_end - code_item_start;
- range_values_.push_back(std::make_tuple(code_item_begin, code_item_start_size, should_poison));
+ range_values_.push_back(std::make_tuple(code_item_begin,
+ code_item_start_size,
+ should_poison));
}
cdit.Next();
}
@@ -204,9 +208,10 @@
while (cdit.HasNextMethod()) {
const DexFile::CodeItem* code_item = cdit.GetMethodCodeItem();
if (code_item != nullptr) {
- const void* insns_begin = reinterpret_cast<const void*>(&code_item->insns_);
+ CodeItemInstructionAccessor accessor(dex_file_, code_item);
+ const void* insns_begin = reinterpret_cast<const void*>(accessor.Insns());
// Member insns_size_in_code_units_ is in 2-byte units
- size_t insns_size = code_item->insns_size_in_code_units_ * 2;
+ size_t insns_size = accessor.InsnsSizeInCodeUnits() * 2;
range_values_.push_back(std::make_tuple(insns_begin, insns_size, should_poison));
}
cdit.Next();
diff --git a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
index d4bc1c7..d22f180 100644
--- a/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_fillarray_entrypoints.cc
@@ -28,7 +28,7 @@
ArtMethod* method, Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) {
ScopedQuickEntrypointChecks sqec(self);
- const uint16_t* const insns = method->GetCodeItem()->insns_;
+ const uint16_t* const insns = method->DexInstructions().Insns();
const Instruction::ArrayDataPayload* payload =
reinterpret_cast<const Instruction::ArrayDataPayload*>(insns + payload_offset);
bool success = FillArrayData(array, payload);
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index ca5b799..a4d14ec 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -784,8 +784,8 @@
DCHECK(!method->IsNative()) << method->PrettyMethod();
uint32_t shorty_len = 0;
ArtMethod* non_proxy_method = method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
- const DexFile::CodeItem* code_item = non_proxy_method->GetCodeItem();
- DCHECK(code_item != nullptr) << method->PrettyMethod();
+ DCHECK(non_proxy_method->GetCodeItem() != nullptr) << method->PrettyMethod();
+ CodeItemDataAccessor accessor(non_proxy_method);
const char* shorty = non_proxy_method->GetShorty(&shorty_len);
JValue result;
@@ -795,12 +795,12 @@
} else {
const char* old_cause = self->StartAssertNoThreadSuspension(
"Building interpreter shadow frame");
- uint16_t num_regs = code_item->registers_size_;
+ uint16_t num_regs = accessor.RegistersSize();
// No last shadow coming from quick.
ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
CREATE_SHADOW_FRAME(num_regs, /* link */ nullptr, method, /* dex pc */ 0);
ShadowFrame* shadow_frame = shadow_frame_unique_ptr.get();
- size_t first_arg_reg = code_item->registers_size_ - code_item->ins_size_;
+ size_t first_arg_reg = accessor.RegistersSize() - accessor.InsSize();
BuildQuickShadowFrameVisitor shadow_frame_builder(sp, method->IsStatic(), shorty, shorty_len,
shadow_frame, first_arg_reg);
shadow_frame_builder.VisitArguments();
@@ -823,7 +823,7 @@
}
}
- result = interpreter::EnterInterpreterFromEntryPoint(self, code_item, shadow_frame);
+ result = interpreter::EnterInterpreterFromEntryPoint(self, accessor, shadow_frame);
}
// Pop transition.
@@ -1121,10 +1121,9 @@
// code.
if (!found_stack_map || kIsDebugBuild) {
uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
- const DexFile::CodeItem* code;
- code = caller->GetCodeItem();
- CHECK_LT(dex_pc, code->insns_size_in_code_units_);
- const Instruction& instr = code->InstructionAt(dex_pc);
+ CodeItemInstructionAccessor accessor(caller);
+ CHECK_LT(dex_pc, accessor.InsnsSizeInCodeUnits());
+ const Instruction& instr = accessor.InstructionAt(dex_pc);
Instruction::Code instr_code = instr.Opcode();
bool is_range;
switch (instr_code) {
@@ -2450,9 +2449,7 @@
// Fetch the dex_method_idx of the target interface method from the caller.
uint32_t dex_method_idx;
uint32_t dex_pc = QuickArgumentVisitor::GetCallingDexPc(sp);
- const DexFile::CodeItem* code_item = caller_method->GetCodeItem();
- DCHECK_LT(dex_pc, code_item->insns_size_in_code_units_);
- const Instruction& instr = code_item->InstructionAt(dex_pc);
+ const Instruction& instr = caller_method->DexInstructions().InstructionAt(dex_pc);
Instruction::Code instr_code = instr.Opcode();
DCHECK(instr_code == Instruction::INVOKE_INTERFACE ||
instr_code == Instruction::INVOKE_INTERFACE_RANGE)
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 49f2021..a4ee21d 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -1246,18 +1246,17 @@
shorty = m->GetInterfaceMethodIfProxy(kRuntimePointerSize)->GetShorty()[0];
return false;
}
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- const Instruction* instr = Instruction::At(&code_item->insns_[GetDexPc()]);
- if (instr->IsInvoke()) {
+ const Instruction& instr = m->DexInstructions().InstructionAt(GetDexPc());
+ if (instr.IsInvoke()) {
const DexFile* dex_file = m->GetDexFile();
- if (interpreter::IsStringInit(dex_file, instr->VRegB())) {
+ if (interpreter::IsStringInit(dex_file, instr.VRegB())) {
// Invoking string init constructor is turned into invoking
// StringFactory.newStringFromChars() which returns a string.
shorty = 'L';
return false;
}
// A regular invoke, use callee's shorty.
- uint32_t method_idx = instr->VRegB();
+ uint32_t method_idx = instr.VRegB();
shorty = dex_file->GetMethodShorty(method_idx)[0];
}
// Stop stack walking since we've seen a Java frame.
diff --git a/runtime/interpreter/interpreter.cc b/runtime/interpreter/interpreter.cc
index 01b7d4e..9b81819 100644
--- a/runtime/interpreter/interpreter.cc
+++ b/runtime/interpreter/interpreter.cc
@@ -240,7 +240,7 @@
static inline JValue Execute(
Thread* self,
- const DexFile::CodeItem* code_item,
+ const CodeItemDataAccessor& accessor,
ShadowFrame& shadow_frame,
JValue result_register,
bool stay_in_interpreter = false) REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -254,11 +254,13 @@
ArtMethod *method = shadow_frame.GetMethod();
if (UNLIKELY(instrumentation->HasMethodEntryListeners())) {
- instrumentation->MethodEnterEvent(self, shadow_frame.GetThisObject(code_item->ins_size_),
- method, 0);
+ instrumentation->MethodEnterEvent(self,
+ shadow_frame.GetThisObject(accessor.InsSize()),
+ method,
+ 0);
if (UNLIKELY(self->IsExceptionPending())) {
instrumentation->MethodUnwindEvent(self,
- shadow_frame.GetThisObject(code_item->ins_size_),
+ shadow_frame.GetThisObject(accessor.InsSize()),
method,
0);
return JValue();
@@ -277,7 +279,7 @@
// Calculate the offset of the first input reg. The input registers are in the high regs.
// It's ok to access the code item here since JIT code will have been touched by the
// interpreter and compiler already.
- uint16_t arg_offset = code_item->registers_size_ - code_item->ins_size_;
+ uint16_t arg_offset = accessor.RegistersSize() - accessor.InsSize();
ArtInterpreterToCompiledCodeBridge(self, nullptr, &shadow_frame, arg_offset, &result);
// Push the shadow frame back as the caller will expect it.
self->PushShadowFrame(&shadow_frame);
@@ -302,27 +304,27 @@
if (kInterpreterImplKind == kMterpImplKind) {
if (transaction_active) {
// No Mterp variant - just use the switch interpreter.
- return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register,
+ return ExecuteSwitchImpl<false, true>(self, accessor, shadow_frame, result_register,
false);
} else if (UNLIKELY(!Runtime::Current()->IsStarted())) {
- return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register,
+ return ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame, result_register,
false);
} else {
while (true) {
// Mterp does not support all instrumentation/debugging.
if (MterpShouldSwitchInterpreters() != 0) {
- return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register,
+ return ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame, result_register,
false);
}
bool returned = ExecuteMterpImpl(self,
- code_item->insns_,
+ accessor.Insns(),
&shadow_frame,
&result_register);
if (returned) {
return result_register;
} else {
// Mterp didn't like that instruction. Single-step it with the reference interpreter.
- result_register = ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame,
+ result_register = ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame,
result_register, true);
if (shadow_frame.GetDexPC() == dex::kDexNoIndex) {
// Single-stepped a return or an exception not handled locally. Return to caller.
@@ -334,10 +336,10 @@
} else {
DCHECK_EQ(kInterpreterImplKind, kSwitchImplKind);
if (transaction_active) {
- return ExecuteSwitchImpl<false, true>(self, code_item, shadow_frame, result_register,
+ return ExecuteSwitchImpl<false, true>(self, accessor, shadow_frame, result_register,
false);
} else {
- return ExecuteSwitchImpl<false, false>(self, code_item, shadow_frame, result_register,
+ return ExecuteSwitchImpl<false, false>(self, accessor, shadow_frame, result_register,
false);
}
}
@@ -346,19 +348,19 @@
if (kInterpreterImplKind == kMterpImplKind) {
// No access check variants for Mterp. Just use the switch version.
if (transaction_active) {
- return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register,
+ return ExecuteSwitchImpl<true, true>(self, accessor, shadow_frame, result_register,
false);
} else {
- return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register,
+ return ExecuteSwitchImpl<true, false>(self, accessor, shadow_frame, result_register,
false);
}
} else {
DCHECK_EQ(kInterpreterImplKind, kSwitchImplKind);
if (transaction_active) {
- return ExecuteSwitchImpl<true, true>(self, code_item, shadow_frame, result_register,
+ return ExecuteSwitchImpl<true, true>(self, accessor, shadow_frame, result_register,
false);
} else {
- return ExecuteSwitchImpl<true, false>(self, code_item, shadow_frame, result_register,
+ return ExecuteSwitchImpl<true, false>(self, accessor, shadow_frame, result_register,
false);
}
}
@@ -387,12 +389,12 @@
}
const char* old_cause = self->StartAssertNoThreadSuspension("EnterInterpreterFromInvoke");
- const DexFile::CodeItem* code_item = method->GetCodeItem();
+ CodeItemDataAccessor accessor(method);
uint16_t num_regs;
uint16_t num_ins;
- if (code_item != nullptr) {
- num_regs = code_item->registers_size_;
- num_ins = code_item->ins_size_;
+ if (accessor.HasCodeItem()) {
+ num_regs = accessor.RegistersSize();
+ num_ins = accessor.InsSize();
} else if (!method->IsInvokable()) {
self->EndAssertNoThreadSuspension(old_cause);
method->ThrowInvocationTimeError();
@@ -454,7 +456,7 @@
}
}
if (LIKELY(!method->IsNative())) {
- JValue r = Execute(self, code_item, *shadow_frame, JValue(), stay_in_interpreter);
+ JValue r = Execute(self, accessor, *shadow_frame, JValue(), stay_in_interpreter);
if (result != nullptr) {
*result = r;
}
@@ -497,7 +499,7 @@
DCHECK(!shadow_frame->GetMethod()->MustCountLocks());
self->SetTopOfShadowStack(shadow_frame);
- const DexFile::CodeItem* code_item = shadow_frame->GetMethod()->GetCodeItem();
+ CodeItemDataAccessor accessor(shadow_frame->GetMethod());
const uint32_t dex_pc = shadow_frame->GetDexPC();
uint32_t new_dex_pc = dex_pc;
if (UNLIKELY(self->IsExceptionPending())) {
@@ -510,7 +512,7 @@
self, *shadow_frame, instrumentation) ? shadow_frame->GetDexPC() : dex::kDexNoIndex;
} else if (!from_code) {
// Deoptimization is not called from code directly.
- const Instruction* instr = Instruction::At(&code_item->insns_[dex_pc]);
+ const Instruction* instr = &accessor.InstructionAt(dex_pc);
if (deopt_method_type == DeoptimizationMethodType::kKeepDexPc) {
DCHECK(first);
// Need to re-execute the dex instruction.
@@ -566,7 +568,7 @@
}
if (new_dex_pc != dex::kDexNoIndex) {
shadow_frame->SetDexPC(new_dex_pc);
- value = Execute(self, code_item, *shadow_frame, value);
+ value = Execute(self, accessor, *shadow_frame, value);
}
ShadowFrame* old_frame = shadow_frame;
shadow_frame = shadow_frame->GetLink();
@@ -580,7 +582,7 @@
ret_val->SetJ(value.GetJ());
}
-JValue EnterInterpreterFromEntryPoint(Thread* self, const DexFile::CodeItem* code_item,
+JValue EnterInterpreterFromEntryPoint(Thread* self, const CodeItemDataAccessor& accessor,
ShadowFrame* shadow_frame) {
DCHECK_EQ(self, Thread::Current());
bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
@@ -593,11 +595,11 @@
if (jit != nullptr) {
jit->NotifyCompiledCodeToInterpreterTransition(self, shadow_frame->GetMethod());
}
- return Execute(self, code_item, *shadow_frame, JValue());
+ return Execute(self, accessor, *shadow_frame, JValue());
}
void ArtInterpreterToInterpreterBridge(Thread* self,
- const DexFile::CodeItem* code_item,
+ const CodeItemDataAccessor& accessor,
ShadowFrame* shadow_frame,
JValue* result) {
bool implicit_check = !Runtime::Current()->ExplicitStackOverflowChecks();
@@ -626,7 +628,7 @@
}
if (LIKELY(!shadow_frame->GetMethod()->IsNative())) {
- result->SetJ(Execute(self, code_item, *shadow_frame, JValue()).GetJ());
+ result->SetJ(Execute(self, accessor, *shadow_frame, JValue()).GetJ());
} else {
// We don't expect to be asked to interpret native code (which is entered via a JNI compiler
// generated stub) except during testing and image writing.
diff --git a/runtime/interpreter/interpreter.h b/runtime/interpreter/interpreter.h
index df8568e..f9d7774 100644
--- a/runtime/interpreter/interpreter.h
+++ b/runtime/interpreter/interpreter.h
@@ -27,6 +27,7 @@
} // namespace mirror
class ArtMethod;
+class CodeItemDataAccessor;
union JValue;
class ShadowFrame;
class Thread;
@@ -52,12 +53,15 @@
DeoptimizationMethodType method_type)
REQUIRES_SHARED(Locks::mutator_lock_);
-extern JValue EnterInterpreterFromEntryPoint(Thread* self, const DexFile::CodeItem* code_item,
+extern JValue EnterInterpreterFromEntryPoint(Thread* self,
+ const CodeItemDataAccessor& accessor,
ShadowFrame* shadow_frame)
REQUIRES_SHARED(Locks::mutator_lock_);
-void ArtInterpreterToInterpreterBridge(Thread* self, const DexFile::CodeItem* code_item,
- ShadowFrame* shadow_frame, JValue* result)
+void ArtInterpreterToInterpreterBridge(Thread* self,
+ const CodeItemDataAccessor& accessor,
+ ShadowFrame* shadow_frame,
+ JValue* result)
REQUIRES_SHARED(Locks::mutator_lock_);
// One-time sanity check.
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index 122d1a8..deed16b 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -1320,7 +1320,7 @@
}
// Compute method information.
- const DexFile::CodeItem* code_item = called_method->GetCodeItem();
+ CodeItemDataAccessor accessor(called_method);
// Number of registers for the callee's call frame.
uint16_t num_regs;
// Test whether to use the interpreter or compiler entrypoint, and save that result to pass to
@@ -1334,7 +1334,7 @@
ClassLinker::ShouldUseInterpreterEntrypoint(
called_method,
called_method->GetEntryPointFromQuickCompiledCode());
- if (LIKELY(code_item != nullptr)) {
+ if (LIKELY(accessor.HasCodeItem())) {
// When transitioning to compiled code, space only needs to be reserved for the input registers.
// The rest of the frame gets discarded. This also prevents accessing the called method's code
// item, saving memory by keeping code items of compiled code untouched.
@@ -1342,8 +1342,8 @@
DCHECK(!Runtime::Current()->IsAotCompiler()) << "Compiler should use interpreter entrypoint";
num_regs = number_of_inputs;
} else {
- num_regs = code_item->registers_size_;
- DCHECK_EQ(string_init ? number_of_inputs - 1 : number_of_inputs, code_item->ins_size_);
+ num_regs = accessor.RegistersSize();
+ DCHECK_EQ(string_init ? number_of_inputs - 1 : number_of_inputs, accessor.InsSize());
}
} else {
DCHECK(called_method->IsNative() || called_method->IsProxyMethod());
@@ -1367,7 +1367,7 @@
DCHECK_GT(num_regs, 0u); // As the method is an instance method, there should be at least 1.
// The new StringFactory call is static and has one fewer argument.
- if (code_item == nullptr) {
+ if (!accessor.HasCodeItem()) {
DCHECK(called_method->IsNative() || called_method->IsProxyMethod());
num_regs--;
} // else ... don't need to change num_regs since it comes up from the string_init's code item
@@ -1499,7 +1499,7 @@
}
PerformCall(self,
- code_item,
+ accessor,
shadow_frame.GetMethod(),
first_dest_reg,
new_shadow_frame,
diff --git a/runtime/interpreter/interpreter_switch_impl.cc b/runtime/interpreter/interpreter_switch_impl.cc
index 094f086..81c1e1d 100644
--- a/runtime/interpreter/interpreter_switch_impl.cc
+++ b/runtime/interpreter/interpreter_switch_impl.cc
@@ -67,7 +67,7 @@
{ \
if (UNLIKELY(instrumentation->HasDexPcListeners()) && \
UNLIKELY(!DoDexPcMoveEvent(self, \
- code_item, \
+ accessor, \
shadow_frame, \
dex_pc, \
instrumentation, \
@@ -125,7 +125,7 @@
// jvmti-agents while handling breakpoint or single step events. We had to move this into its own
// function because it was making ExecuteSwitchImpl have too large a stack.
NO_INLINE static bool DoDexPcMoveEvent(Thread* self,
- const DexFile::CodeItem* code_item,
+ const CodeItemDataAccessor& accessor,
const ShadowFrame& shadow_frame,
uint32_t dex_pc,
const instrumentation::Instrumentation* instrumentation,
@@ -139,7 +139,7 @@
hs.NewHandleWrapper(LIKELY(save_ref == nullptr) ? &null_obj : save_ref->GetGCRoot()));
self->ClearException();
instrumentation->DexPcMovedEvent(self,
- shadow_frame.GetThisObject(code_item->ins_size_),
+ shadow_frame.GetThisObject(accessor.InsSize()),
shadow_frame.GetMethod(),
dex_pc);
if (UNLIKELY(self->IsExceptionPending())) {
@@ -188,7 +188,7 @@
}
template<bool do_access_check, bool transaction_active>
-JValue ExecuteSwitchImpl(Thread* self, const DexFile::CodeItem* code_item,
+JValue ExecuteSwitchImpl(Thread* self, const CodeItemDataAccessor& accessor,
ShadowFrame& shadow_frame, JValue result_register,
bool interpret_one_instruction) {
constexpr bool do_assignability_check = do_access_check;
@@ -200,10 +200,10 @@
uint32_t dex_pc = shadow_frame.GetDexPC();
const auto* const instrumentation = Runtime::Current()->GetInstrumentation();
- const uint16_t* const insns = code_item->insns_;
+ ArtMethod* method = shadow_frame.GetMethod();
+ const uint16_t* const insns = accessor.Insns();
const Instruction* inst = Instruction::At(insns + dex_pc);
uint16_t inst_data;
- ArtMethod* method = shadow_frame.GetMethod();
jit::Jit* jit = Runtime::Current()->GetJit();
do {
@@ -303,7 +303,7 @@
!SendMethodExitEvents(self,
instrumentation,
shadow_frame,
- shadow_frame.GetThisObject(code_item->ins_size_),
+ shadow_frame.GetThisObject(accessor.InsSize()),
shadow_frame.GetMethod(),
inst->GetDexPc(insns),
result))) {
@@ -325,7 +325,7 @@
!SendMethodExitEvents(self,
instrumentation,
shadow_frame,
- shadow_frame.GetThisObject(code_item->ins_size_),
+ shadow_frame.GetThisObject(accessor.InsSize()),
shadow_frame.GetMethod(),
inst->GetDexPc(insns),
result))) {
@@ -348,7 +348,7 @@
!SendMethodExitEvents(self,
instrumentation,
shadow_frame,
- shadow_frame.GetThisObject(code_item->ins_size_),
+ shadow_frame.GetThisObject(accessor.InsSize()),
shadow_frame.GetMethod(),
inst->GetDexPc(insns),
result))) {
@@ -370,7 +370,7 @@
!SendMethodExitEvents(self,
instrumentation,
shadow_frame,
- shadow_frame.GetThisObject(code_item->ins_size_),
+ shadow_frame.GetThisObject(accessor.InsSize()),
shadow_frame.GetMethod(),
inst->GetDexPc(insns),
result))) {
@@ -412,7 +412,7 @@
!SendMethodExitEvents(self,
instrumentation,
shadow_frame,
- shadow_frame.GetThisObject(code_item->ins_size_),
+ shadow_frame.GetThisObject(accessor.InsSize()),
shadow_frame.GetMethod(),
inst->GetDexPc(insns),
result))) {
@@ -2484,19 +2484,19 @@
// Explicit definitions of ExecuteSwitchImpl.
template HOT_ATTR
-JValue ExecuteSwitchImpl<true, false>(Thread* self, const DexFile::CodeItem* code_item,
+JValue ExecuteSwitchImpl<true, false>(Thread* self, const CodeItemDataAccessor& accessor,
ShadowFrame& shadow_frame, JValue result_register,
bool interpret_one_instruction);
template HOT_ATTR
-JValue ExecuteSwitchImpl<false, false>(Thread* self, const DexFile::CodeItem* code_item,
+JValue ExecuteSwitchImpl<false, false>(Thread* self, const CodeItemDataAccessor& accessor,
ShadowFrame& shadow_frame, JValue result_register,
bool interpret_one_instruction);
template
-JValue ExecuteSwitchImpl<true, true>(Thread* self, const DexFile::CodeItem* code_item,
+JValue ExecuteSwitchImpl<true, true>(Thread* self, const CodeItemDataAccessor& accessor,
ShadowFrame& shadow_frame, JValue result_register,
bool interpret_one_instruction);
template
-JValue ExecuteSwitchImpl<false, true>(Thread* self, const DexFile::CodeItem* code_item,
+JValue ExecuteSwitchImpl<false, true>(Thread* self, const CodeItemDataAccessor& accessor,
ShadowFrame& shadow_frame, JValue result_register,
bool interpret_one_instruction);
diff --git a/runtime/interpreter/interpreter_switch_impl.h b/runtime/interpreter/interpreter_switch_impl.h
index 267df2e..aa0f854 100644
--- a/runtime/interpreter/interpreter_switch_impl.h
+++ b/runtime/interpreter/interpreter_switch_impl.h
@@ -25,6 +25,7 @@
namespace art {
+class CodeItemDataAccessor;
class ShadowFrame;
class Thread;
@@ -32,7 +33,7 @@
template<bool do_access_check, bool transaction_active>
JValue ExecuteSwitchImpl(Thread* self,
- const DexFile::CodeItem* code_item,
+ const CodeItemDataAccessor& accessor,
ShadowFrame& shadow_frame,
JValue result_register,
bool interpret_one_instruction) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/interpreter/shadow_frame.cc b/runtime/interpreter/shadow_frame.cc
index ab154cf..fe7e3e0 100644
--- a/runtime/interpreter/shadow_frame.cc
+++ b/runtime/interpreter/shadow_frame.cc
@@ -27,9 +27,9 @@
} else if (m->IsNative()) {
return GetVRegReference(0);
} else {
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- CHECK(code_item != nullptr) << ArtMethod::PrettyMethod(m);
- uint16_t reg = code_item->registers_size_ - code_item->ins_size_;
+ CHECK(m->GetCodeItem() != nullptr) << ArtMethod::PrettyMethod(m);
+ CodeItemDataAccessor accessor(m);
+ uint16_t reg = accessor.RegistersSize() - accessor.InsSize();
return GetVRegReference(reg);
}
}
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index dece830..d1436fa 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -1910,7 +1910,7 @@
tables_initialized_ = true;
}
-void UnstartedRuntime::Invoke(Thread* self, const DexFile::CodeItem* code_item,
+void UnstartedRuntime::Invoke(Thread* self, const CodeItemDataAccessor& accessor,
ShadowFrame* shadow_frame, JValue* result, size_t arg_offset) {
// In a runtime that's not started we intercept certain methods to avoid complicated dependency
// problems in core libraries.
@@ -1930,7 +1930,7 @@
self->PopShadowFrame();
} else {
// Not special, continue with regular interpreter execution.
- ArtInterpreterToInterpreterBridge(self, code_item, shadow_frame, result);
+ ArtInterpreterToInterpreterBridge(self, accessor, shadow_frame, result);
}
}
diff --git a/runtime/interpreter/unstarted_runtime.h b/runtime/interpreter/unstarted_runtime.h
index bc9ead8..2e86dea 100644
--- a/runtime/interpreter/unstarted_runtime.h
+++ b/runtime/interpreter/unstarted_runtime.h
@@ -25,6 +25,7 @@
namespace art {
class ArtMethod;
+class CodeItemDataAccessor;
class Thread;
class ShadowFrame;
@@ -48,7 +49,7 @@
static void Initialize();
static void Invoke(Thread* self,
- const DexFile::CodeItem* code_item,
+ const CodeItemDataAccessor& accessor,
ShadowFrame* shadow_frame,
JValue* result,
size_t arg_offset)
diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc
index 278bc57..12bf79d 100644
--- a/runtime/jit/jit.cc
+++ b/runtime/jit/jit.cc
@@ -467,7 +467,8 @@
// Fetch some data before looking up for an OSR method. We don't want thread
// suspension once we hold an OSR method, as the JIT code cache could delete the OSR
// method while we are being suspended.
- const size_t number_of_vregs = method->GetCodeItem()->registers_size_;
+ CodeItemDataAccessor accessor(method);
+ const size_t number_of_vregs = accessor.RegistersSize();
const char* shorty = method->GetShorty();
std::string method_name(VLOG_IS_ON(jit) ? method->PrettyMethod() : "");
void** memory = nullptr;
diff --git a/runtime/method_handles.cc b/runtime/method_handles.cc
index 8eb31c1..88f30a8 100644
--- a/runtime/method_handles.cc
+++ b/runtime/method_handles.cc
@@ -408,7 +408,7 @@
const InstructionOperands* const operands,
JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) {
// Compute method information.
- const DexFile::CodeItem* code_item = called_method->GetCodeItem();
+ CodeItemDataAccessor accessor(called_method);
// Number of registers for the callee's call frame. Note that for non-exact
// invokes, we always derive this information from the callee method. We
@@ -419,10 +419,10 @@
uint16_t num_regs;
size_t num_input_regs;
size_t first_dest_reg;
- if (LIKELY(code_item != nullptr)) {
- num_regs = code_item->registers_size_;
- first_dest_reg = num_regs - code_item->ins_size_;
- num_input_regs = code_item->ins_size_;
+ if (LIKELY(accessor.HasCodeItem())) {
+ num_regs = accessor.RegistersSize();
+ first_dest_reg = num_regs - accessor.InsSize();
+ num_input_regs = accessor.InsSize();
// Parameter registers go at the end of the shadow frame.
DCHECK_NE(first_dest_reg, (size_t)-1);
} else {
@@ -496,7 +496,7 @@
bool use_interpreter_entrypoint = ClassLinker::ShouldUseInterpreterEntrypoint(
called_method, called_method->GetEntryPointFromQuickCompiledCode());
PerformCall(self,
- code_item,
+ accessor,
shadow_frame.GetMethod(),
first_dest_reg,
new_shadow_frame,
@@ -550,10 +550,9 @@
// - One for the only method argument (an EmulatedStackFrame).
static constexpr size_t kNumRegsForTransform = 2;
- const DexFile::CodeItem* code_item = called_method->GetCodeItem();
- DCHECK(code_item != nullptr);
- DCHECK_EQ(kNumRegsForTransform, code_item->registers_size_);
- DCHECK_EQ(kNumRegsForTransform, code_item->ins_size_);
+ CodeItemDataAccessor accessor(called_method);
+ DCHECK_EQ(kNumRegsForTransform, accessor.RegistersSize());
+ DCHECK_EQ(kNumRegsForTransform, accessor.InsSize());
ShadowFrameAllocaUniquePtr shadow_frame_unique_ptr =
CREATE_SHADOW_FRAME(kNumRegsForTransform, &shadow_frame, called_method, /* dex pc */ 0);
@@ -589,7 +588,7 @@
bool use_interpreter_entrypoint = ClassLinker::ShouldUseInterpreterEntrypoint(
called_method, called_method->GetEntryPointFromQuickCompiledCode());
PerformCall(self,
- code_item,
+ accessor,
shadow_frame.GetMethod(),
0 /* first destination register */,
new_shadow_frame,
@@ -1035,14 +1034,14 @@
}
// Compute method information.
- const DexFile::CodeItem* code_item = called_method->GetCodeItem();
+ CodeItemDataAccessor accessor(called_method);
uint16_t num_regs;
size_t num_input_regs;
size_t first_dest_reg;
- if (LIKELY(code_item != nullptr)) {
- num_regs = code_item->registers_size_;
- first_dest_reg = num_regs - code_item->ins_size_;
- num_input_regs = code_item->ins_size_;
+ if (LIKELY(accessor.HasCodeItem())) {
+ num_regs = accessor.RegistersSize();
+ first_dest_reg = num_regs - accessor.InsSize();
+ num_input_regs = accessor.InsSize();
// Parameter registers go at the end of the shadow frame.
DCHECK_NE(first_dest_reg, (size_t)-1);
} else {
@@ -1066,7 +1065,7 @@
bool use_interpreter_entrypoint = ClassLinker::ShouldUseInterpreterEntrypoint(
called_method, called_method->GetEntryPointFromQuickCompiledCode());
PerformCall(self,
- code_item,
+ accessor,
shadow_frame.GetMethod(),
first_dest_reg,
new_shadow_frame,
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index cfef9c7..542692f 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -1377,9 +1377,9 @@
}
// Is there any reason to believe there's any synchronization in this method?
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- CHECK(code_item != nullptr) << m->PrettyMethod();
- if (code_item->tries_size_ == 0) {
+ CHECK(m->GetCodeItem() != nullptr) << m->PrettyMethod();
+ CodeItemDataAccessor accessor(m);
+ if (accessor.TriesSize() == 0) {
return; // No "tries" implies no synchronization, so no held locks to report.
}
@@ -1399,11 +1399,10 @@
for (verifier::MethodVerifier::DexLockInfo& dex_lock_info : monitor_enter_dex_pcs) {
// As a debug check, check that dex PC corresponds to a monitor-enter.
if (kIsDebugBuild) {
- const Instruction* monitor_enter_instruction =
- Instruction::At(&code_item->insns_[dex_lock_info.dex_pc]);
- CHECK_EQ(monitor_enter_instruction->Opcode(), Instruction::MONITOR_ENTER)
+ const Instruction& monitor_enter_instruction = accessor.InstructionAt(dex_lock_info.dex_pc);
+ CHECK_EQ(monitor_enter_instruction.Opcode(), Instruction::MONITOR_ENTER)
<< "expected monitor-enter @" << dex_lock_info.dex_pc << "; was "
- << reinterpret_cast<const void*>(monitor_enter_instruction);
+ << reinterpret_cast<const void*>(&monitor_enter_instruction);
}
// Iterate through the set of dex registers, as the compiler may not have held all of them
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 32f8df7..f437db2 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -1500,14 +1500,10 @@
}
}
-uint32_t OatFile::GetDebugInfoOffset(const DexFile& dex_file,
- const DexFile::CodeItem* code_item) {
- if (code_item == nullptr) {
- return 0;
- }
- const uint32_t debug_info_off = code_item->debug_info_off_;
+uint32_t OatFile::GetDebugInfoOffset(const DexFile& dex_file, uint32_t debug_info_off) {
// Note that although the specification says that 0 should be used if there
// is no debug information, some applications incorrectly use 0xFFFFFFFF.
+ // The following check also handles debug_info_off == 0.
if (debug_info_off < dex_file.Size() || debug_info_off == 0xFFFFFFFF) {
return debug_info_off;
}
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 36a4d7b..1fb17a4 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -114,9 +114,9 @@
const char* abs_dex_location,
std::string* error_msg);
- // Return the debug info offset of the code item `item` located in `dex_file`.
- static uint32_t GetDebugInfoOffset(const DexFile& dex_file,
- const DexFile::CodeItem* item);
+ // Return the actual debug info offset for an offset that might be actually pointing to
+ // dequickening info. The returned debug info offset is the one originally in the the dex file.
+ static uint32_t GetDebugInfoOffset(const DexFile& dex_file, uint32_t debug_info_off);
virtual ~OatFile();
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index a7771ab..06b94c3 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -222,7 +222,8 @@
self_->DumpStack(LOG_STREAM(INFO) << "Setting catch phis: ");
}
- const size_t number_of_vregs = handler_method_->GetCodeItem()->registers_size_;
+ CodeItemDataAccessor accessor(handler_method_);
+ const size_t number_of_vregs = accessor.RegistersSize();
CodeInfo code_info = handler_method_header_->GetOptimizedCodeInfo();
CodeInfoEncoding encoding = code_info.ExtractEncoding();
@@ -359,7 +360,8 @@
const size_t frame_id = GetFrameId();
ShadowFrame* new_frame = GetThread()->FindDebuggerShadowFrame(frame_id);
const bool* updated_vregs;
- const size_t num_regs = method->GetCodeItem()->registers_size_;
+ CodeItemDataAccessor accessor(method);
+ const size_t num_regs = accessor.RegistersSize();
if (new_frame == nullptr) {
new_frame = ShadowFrame::CreateDeoptimizedFrame(num_regs, nullptr, method, GetDexPc());
updated_vregs = nullptr;
@@ -406,7 +408,8 @@
uintptr_t native_pc_offset = method_header->NativeQuickPcOffset(GetCurrentQuickFramePc());
CodeInfoEncoding encoding = code_info.ExtractEncoding();
StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset, encoding);
- const size_t number_of_vregs = m->GetCodeItem()->registers_size_;
+ CodeItemDataAccessor accessor(m);
+ const size_t number_of_vregs = accessor.RegistersSize();
uint32_t register_mask = code_info.GetRegisterMaskOf(encoding, stack_map);
BitMemoryRegion stack_mask = code_info.GetStackMaskOf(encoding, stack_map);
DexRegisterMap vreg_map = IsInInlinedFrame()
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 5ad1f7c..bbea48b 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -154,13 +154,13 @@
return cur_shadow_frame_->GetVRegReference(0);
}
} else {
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- if (code_item == nullptr) {
+ CodeItemDataAccessor accessor(m);
+ if (!accessor.HasCodeItem()) {
UNIMPLEMENTED(ERROR) << "Failed to determine this object of abstract or proxy method: "
<< ArtMethod::PrettyMethod(m);
return nullptr;
} else {
- uint16_t reg = code_item->registers_size_ - code_item->ins_size_;
+ uint16_t reg = accessor.RegistersSize() - accessor.InsSize();
uint32_t value = 0;
bool success = GetVReg(m, reg, kReferenceVReg, &value);
// We currently always guarantee the `this` object is live throughout the method.
@@ -223,11 +223,11 @@
bool StackVisitor::GetVRegFromOptimizedCode(ArtMethod* m, uint16_t vreg, VRegKind kind,
uint32_t* val) const {
DCHECK_EQ(m, GetMethod());
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- DCHECK(code_item != nullptr) << m->PrettyMethod(); // Can't be null or how would we compile
- // its instructions?
- uint16_t number_of_dex_registers = code_item->registers_size_;
- DCHECK_LT(vreg, code_item->registers_size_);
+ // Can't be null or how would we compile its instructions?
+ DCHECK(m->GetCodeItem() != nullptr) << m->PrettyMethod();
+ CodeItemDataAccessor accessor(m);
+ uint16_t number_of_dex_registers = accessor.RegistersSize();
+ DCHECK_LT(vreg, number_of_dex_registers);
const OatQuickMethodHeader* method_header = GetCurrentOatQuickMethodHeader();
CodeInfo code_info = method_header->GetOptimizedCodeInfo();
CodeInfoEncoding encoding = code_info.ExtractEncoding();
@@ -395,8 +395,8 @@
uint16_t vreg,
uint32_t new_value,
VRegKind kind) {
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- if (code_item == nullptr) {
+ CodeItemDataAccessor accessor(m);
+ if (!accessor.HasCodeItem()) {
return false;
}
ShadowFrame* shadow_frame = GetCurrentShadowFrame();
@@ -404,7 +404,7 @@
// This is a compiled frame: we must prepare and update a shadow frame that will
// be executed by the interpreter after deoptimization of the stack.
const size_t frame_id = GetFrameId();
- const uint16_t num_regs = code_item->registers_size_;
+ const uint16_t num_regs = accessor.RegistersSize();
shadow_frame = thread_->FindOrCreateDebuggerShadowFrame(frame_id, num_regs, m, GetDexPc());
CHECK(shadow_frame != nullptr);
// Remember the vreg has been set for debugging and must not be overwritten by the
@@ -432,15 +432,15 @@
LOG(FATAL) << "Expected long or double: kind_lo=" << kind_lo << ", kind_hi=" << kind_hi;
UNREACHABLE();
}
- const DexFile::CodeItem* code_item = m->GetCodeItem();
- if (code_item == nullptr) {
+ CodeItemDataAccessor accessor(m);
+ if (!accessor.HasCodeItem()) {
return false;
}
ShadowFrame* shadow_frame = GetCurrentShadowFrame();
if (shadow_frame == nullptr) {
// This is a compiled frame: we must prepare for deoptimization (see SetVRegFromDebugger).
const size_t frame_id = GetFrameId();
- const uint16_t num_regs = code_item->registers_size_;
+ const uint16_t num_regs = accessor.RegistersSize();
shadow_frame = thread_->FindOrCreateDebuggerShadowFrame(frame_id, num_regs, m, GetDexPc());
CHECK(shadow_frame != nullptr);
// Remember the vreg pair has been set for debugging and must not be overwritten by the
diff --git a/runtime/thread.cc b/runtime/thread.cc
index b86e56b..6babd75 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -3425,7 +3425,7 @@
const CodeInfoEncoding& _encoding,
const StackMap& map,
RootVisitor& _visitor)
- : number_of_dex_registers(method->GetCodeItem()->registers_size_),
+ : number_of_dex_registers(CodeItemDataAccessor(method).RegistersSize()),
code_info(_code_info),
encoding(_encoding),
dex_register_map(code_info.GetDexRegisterMapOf(map,
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 4ff49ed..be6915f 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -350,13 +350,13 @@
}
}
-static bool IsLargeMethod(const DexFile::CodeItem* const code_item) {
- if (code_item == nullptr) {
+static bool IsLargeMethod(const CodeItemDataAccessor& accessor) {
+ if (!accessor.HasCodeItem()) {
return false;
}
- uint16_t registers_size = code_item->registers_size_;
- uint32_t insns_size = code_item->insns_size_in_code_units_;
+ uint16_t registers_size = accessor.RegistersSize();
+ uint32_t insns_size = accessor.InsnsSizeInCodeUnits();
return registers_size * insns_size > 4*1024*1024;
}
@@ -494,7 +494,7 @@
if (duration_ns > MsToNs(100)) {
LOG(WARNING) << "Verification of " << dex_file->PrettyMethod(method_idx)
<< " took " << PrettyDuration(duration_ns)
- << (IsLargeMethod(code_item) ? " (large method)" : "");
+ << (IsLargeMethod(verifier.CodeItem()) ? " (large method)" : "");
}
}
result.types = verifier.encountered_failure_types_;
@@ -567,7 +567,7 @@
dex_cache_(dex_cache),
class_loader_(class_loader),
class_def_(class_def),
- code_item_accessor_(CodeItemDataAccessor::CreateNullable(dex_file, code_item)),
+ code_item_accessor_(dex_file, code_item),
declaring_class_(nullptr),
interesting_dex_pc_(-1),
monitor_enter_dex_pcs_(nullptr),
diff --git a/test/466-get-live-vreg/get_live_vreg_jni.cc b/test/466-get-live-vreg/get_live_vreg_jni.cc
index 6cea673..24792f1 100644
--- a/test/466-get-live-vreg/get_live_vreg_jni.cc
+++ b/test/466-get-live-vreg/get_live_vreg_jni.cc
@@ -16,6 +16,7 @@
#include "arch/context.h"
#include "art_method-inl.h"
+#include "code_item_accessors-inl.h"
#include "jni.h"
#include "oat_quick_method_header.h"
#include "scoped_thread_state_change-inl.h"
@@ -41,7 +42,7 @@
CHECK(GetVReg(m, 0, kIntVReg, &value));
CHECK_EQ(value, 42u);
} else if (m_name.compare("$opt$noinline$testIntervalHole") == 0) {
- uint32_t number_of_dex_registers = m->GetCodeItem()->registers_size_;
+ uint32_t number_of_dex_registers = CodeItemDataAccessor(m).RegistersSize();
uint32_t dex_register_of_first_parameter = number_of_dex_registers - 2;
found_method_ = true;
uint32_t value = 0;