summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2017-11-06 20:02:24 -0800
committer Mathieu Chartier <mathieuc@google.com> 2017-11-09 19:06:10 -0800
commit69147f165efaa9da152bb37da3a16dd5d8c6cf3c (patch)
tree25dbec549b8c06cf24729a577c76ef0b6d3d4c7f
parent2202d56061941b4fecbdb018d84bcefb05b6c683 (diff)
Add code item accessor helper classes
Add classes to abstract accesses to code item data. These classes handle both standard dex and compact dex. Added: - CodeItemInstructionsAccessor to handle code item instructions. - CodeItemDataAccessor to handle code item data excluding debug info. Moved inline_method_analyzer to use the new classes to test the new APIs. Bug: 63756964 Test: test-art-host Change-Id: I9926acb77b81fa64ed4a3b49b7bed1aab30a0f33
-rw-r--r--compiler/dex/inline_method_analyser.cc104
-rw-r--r--compiler/dex/inline_method_analyser.h12
-rw-r--r--dex2oat/dex2oat_test.cc2
-rw-r--r--runtime/Android.bp1
-rw-r--r--runtime/art_method-inl.h13
-rw-r--r--runtime/art_method.h11
-rw-r--r--runtime/base/casts.h8
-rw-r--r--runtime/cdex/compact_dex_file.h23
-rw-r--r--runtime/code_item_accessors-inl.h130
-rw-r--r--runtime/code_item_accessors.h122
-rw-r--r--runtime/code_item_accessors_test.cc108
-rw-r--r--runtime/dex_file-inl.h12
-rw-r--r--runtime/dex_file.cc6
-rw-r--r--runtime/dex_file.h20
-rw-r--r--runtime/jit/profiling_info.cc3
-rw-r--r--runtime/standard_dex_file.cc10
-rw-r--r--runtime/standard_dex_file.h24
17 files changed, 528 insertions, 81 deletions
diff --git a/compiler/dex/inline_method_analyser.cc b/compiler/dex/inline_method_analyser.cc
index 518b0ece73..b409eb2dbb 100644
--- a/compiler/dex/inline_method_analyser.cc
+++ b/compiler/dex/inline_method_analyser.cc
@@ -20,6 +20,7 @@
#include "art_method-inl.h"
#include "base/enums.h"
#include "class_linker-inl.h"
+#include "code_item_accessors-inl.h"
#include "dex_file-inl.h"
#include "dex_instruction-inl.h"
#include "dex_instruction.h"
@@ -43,7 +44,7 @@ class Matcher {
typedef bool MatchFn(Matcher* matcher);
template <size_t size>
- static bool Match(const DexFile::CodeItem* code_item, MatchFn* const (&pattern)[size]);
+ static bool Match(const CodeItemDataAccessor* code_item, MatchFn* const (&pattern)[size]);
// Match and advance.
@@ -62,22 +63,20 @@ class Matcher {
bool IPutOnThis();
private:
- explicit Matcher(const DexFile::CodeItem* code_item)
+ explicit Matcher(const CodeItemDataAccessor* code_item)
: code_item_(code_item),
- instruction_(code_item->Instructions().begin()),
- pos_(0u),
- mark_(0u) { }
+ instruction_(code_item->begin()) {}
- static bool DoMatch(const DexFile::CodeItem* code_item, MatchFn* const* pattern, size_t size);
+ static bool DoMatch(const CodeItemDataAccessor* code_item, MatchFn* const* pattern, size_t size);
- const DexFile::CodeItem* const code_item_;
+ const CodeItemDataAccessor* const code_item_;
DexInstructionIterator instruction_;
- size_t pos_;
- size_t mark_;
+ size_t pos_ = 0u;
+ size_t mark_ = 0u;
};
template <size_t size>
-bool Matcher::Match(const DexFile::CodeItem* code_item, MatchFn* const (&pattern)[size]) {
+bool Matcher::Match(const CodeItemDataAccessor* code_item, MatchFn* const (&pattern)[size]) {
return DoMatch(code_item, pattern, size);
}
@@ -122,12 +121,12 @@ bool Matcher::Const0() {
}
bool Matcher::IPutOnThis() {
- DCHECK_NE(code_item_->ins_size_, 0u);
+ DCHECK_NE(code_item_->InsSize(), 0u);
return IsInstructionIPut(instruction_->Opcode()) &&
- instruction_->VRegB_22c() == code_item_->registers_size_ - code_item_->ins_size_;
+ instruction_->VRegB_22c() == code_item_->RegistersSize() - code_item_->InsSize();
}
-bool Matcher::DoMatch(const DexFile::CodeItem* code_item, MatchFn* const* pattern, size_t size) {
+bool Matcher::DoMatch(const CodeItemDataAccessor* code_item, MatchFn* const* pattern, size_t size) {
Matcher matcher(code_item);
while (matcher.pos_ != size) {
if (!pattern[matcher.pos_](&matcher)) {
@@ -158,7 +157,7 @@ ArtMethod* GetTargetConstructor(ArtMethod* method, const Instruction* invoke_dir
// Return the forwarded arguments and check that all remaining arguments are zero.
// If the check fails, return static_cast<size_t>(-1).
-size_t CountForwardedConstructorArguments(const DexFile::CodeItem* code_item,
+size_t CountForwardedConstructorArguments(const CodeItemDataAccessor* code_item,
const Instruction* invoke_direct,
uint16_t zero_vreg_mask) {
DCHECK_EQ(invoke_direct->Opcode(), Instruction::INVOKE_DIRECT);
@@ -167,7 +166,7 @@ size_t CountForwardedConstructorArguments(const DexFile::CodeItem* code_item,
uint32_t args[Instruction::kMaxVarArgRegs];
invoke_direct->GetVarArgs(args);
uint16_t this_vreg = args[0];
- DCHECK_EQ(this_vreg, code_item->registers_size_ - code_item->ins_size_); // Checked by verifier.
+ DCHECK_EQ(this_vreg, code_item->RegistersSize() - code_item->InsSize()); // Checked by verifier.
size_t forwarded = 1u;
while (forwarded < number_of_args &&
args[forwarded] == this_vreg + forwarded &&
@@ -249,7 +248,7 @@ bool RecordConstructorIPut(ArtMethod* method,
return true;
}
-bool DoAnalyseConstructor(const DexFile::CodeItem* code_item,
+bool DoAnalyseConstructor(const CodeItemDataAccessor* code_item,
ArtMethod* method,
/*inout*/ ConstructorIPutData (&iputs)[kMaxConstructorIPuts])
REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -292,17 +291,17 @@ bool DoAnalyseConstructor(const DexFile::CodeItem* code_item,
DCHECK(method->IsConstructor());
DCHECK(code_item != nullptr);
if (!method->GetDeclaringClass()->IsVerified() ||
- code_item->insns_size_in_code_units_ > kMaxCodeUnits ||
- code_item->registers_size_ > kMaxVRegs ||
+ code_item->InsnsSizeInCodeUnits() > kMaxCodeUnits ||
+ code_item->RegistersSize() > kMaxVRegs ||
!Matcher::Match(code_item, kConstructorPattern)) {
return false;
}
// Verify the invoke, prevent a few odd cases and collect IPUTs.
- uint16_t this_vreg = code_item->registers_size_ - code_item->ins_size_;
+ uint16_t this_vreg = code_item->RegistersSize() - code_item->InsSize();
uint16_t zero_vreg_mask = 0u;
- for (const DexInstructionPcPair& pair : code_item->Instructions()) {
+ for (const DexInstructionPcPair& pair : *code_item) {
const Instruction& instruction = pair.Inst();
if (instruction.Opcode() == Instruction::RETURN_VOID) {
break;
@@ -314,7 +313,7 @@ bool DoAnalyseConstructor(const DexFile::CodeItem* code_item,
// We allow forwarding constructors only if they pass more arguments
// to prevent infinite recursion.
if (target_method->GetDeclaringClass() == method->GetDeclaringClass() &&
- instruction.VRegA_35c() <= code_item->ins_size_) {
+ instruction.VRegA_35c() <= code_item->InsSize()) {
return false;
}
size_t forwarded = CountForwardedConstructorArguments(code_item, &instruction, zero_vreg_mask);
@@ -322,14 +321,13 @@ bool DoAnalyseConstructor(const DexFile::CodeItem* code_item,
return false;
}
if (target_method->GetDeclaringClass()->IsObjectClass()) {
- DCHECK_EQ(target_method->GetCodeItem()->Instructions().begin()->Opcode(),
- Instruction::RETURN_VOID);
+ DCHECK_EQ(CodeItemDataAccessor(target_method).begin()->Opcode(), Instruction::RETURN_VOID);
} else {
- const DexFile::CodeItem* target_code_item = target_method->GetCodeItem();
- if (target_code_item == nullptr) {
+ CodeItemDataAccessor target_code_item = CodeItemDataAccessor::CreateNullable(target_method);
+ if (!target_code_item.HasCodeItem()) {
return false; // Native constructor?
}
- if (!DoAnalyseConstructor(target_code_item, target_method, iputs)) {
+ if (!DoAnalyseConstructor(&target_code_item, target_method, iputs)) {
return false;
}
// Prune IPUTs with zero input.
@@ -365,7 +363,7 @@ bool DoAnalyseConstructor(const DexFile::CodeItem* code_item,
} // anonymous namespace
-bool AnalyseConstructor(const DexFile::CodeItem* code_item,
+bool AnalyseConstructor(const CodeItemDataAccessor* code_item,
ArtMethod* method,
InlineMethod* result)
REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -429,27 +427,27 @@ static_assert(InlineMethodAnalyser::IGetVariant(Instruction::IGET_SHORT) ==
InlineMethodAnalyser::IPutVariant(Instruction::IPUT_SHORT), "iget/iput_short variant");
bool InlineMethodAnalyser::AnalyseMethodCode(ArtMethod* method, InlineMethod* result) {
- const DexFile::CodeItem* code_item = method->GetCodeItem();
- if (code_item == nullptr) {
+ CodeItemDataAccessor code_item = CodeItemDataAccessor::CreateNullable(method);
+ if (!code_item.HasCodeItem()) {
// Native or abstract.
return false;
}
- return AnalyseMethodCode(code_item,
+ return AnalyseMethodCode(&code_item,
MethodReference(method->GetDexFile(), method->GetDexMethodIndex()),
method->IsStatic(),
method,
result);
}
-bool InlineMethodAnalyser::AnalyseMethodCode(const DexFile::CodeItem* code_item,
+bool InlineMethodAnalyser::AnalyseMethodCode(const CodeItemDataAccessor* code_item,
const MethodReference& method_ref,
bool is_static,
ArtMethod* method,
InlineMethod* result) {
// We currently support only plain return or 2-instruction methods.
- DCHECK_NE(code_item->insns_size_in_code_units_, 0u);
- Instruction::Code opcode = code_item->Instructions().begin()->Opcode();
+ DCHECK_NE(code_item->InsnsSizeInCodeUnits(), 0u);
+ Instruction::Code opcode = code_item->begin()->Opcode();
switch (opcode) {
case Instruction::RETURN_VOID:
@@ -518,15 +516,15 @@ bool InlineMethodAnalyser::IsSyntheticAccessor(MethodReference ref) {
strncmp(method_name, "-", strlen("-")) == 0;
}
-bool InlineMethodAnalyser::AnalyseReturnMethod(const DexFile::CodeItem* code_item,
+bool InlineMethodAnalyser::AnalyseReturnMethod(const CodeItemDataAccessor* code_item,
InlineMethod* result) {
- DexInstructionIterator return_instruction = code_item->Instructions().begin();
+ DexInstructionIterator return_instruction = code_item->begin();
Instruction::Code return_opcode = return_instruction->Opcode();
uint32_t reg = return_instruction->VRegA_11x();
- uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_;
+ uint32_t arg_start = code_item->RegistersSize() - code_item->InsSize();
DCHECK_GE(reg, arg_start);
DCHECK_LT((return_opcode == Instruction::RETURN_WIDE) ? reg + 1 : reg,
- code_item->registers_size_);
+ code_item->RegistersSize());
if (result != nullptr) {
result->opcode = kInlineOpReturnArg;
@@ -540,9 +538,9 @@ bool InlineMethodAnalyser::AnalyseReturnMethod(const DexFile::CodeItem* code_ite
return true;
}
-bool InlineMethodAnalyser::AnalyseConstMethod(const DexFile::CodeItem* code_item,
+bool InlineMethodAnalyser::AnalyseConstMethod(const CodeItemDataAccessor* code_item,
InlineMethod* result) {
- DexInstructionIterator instruction = code_item->Instructions().begin();
+ DexInstructionIterator instruction = code_item->begin();
const Instruction* return_instruction = instruction->Next();
Instruction::Code return_opcode = return_instruction->Opcode();
if (return_opcode != Instruction::RETURN &&
@@ -551,13 +549,13 @@ bool InlineMethodAnalyser::AnalyseConstMethod(const DexFile::CodeItem* code_item
}
int32_t return_reg = return_instruction->VRegA_11x();
- DCHECK_LT(return_reg, code_item->registers_size_);
+ DCHECK_LT(return_reg, code_item->RegistersSize());
int32_t const_value = instruction->VRegB();
if (instruction->Opcode() == Instruction::CONST_HIGH16) {
const_value <<= 16;
}
- DCHECK_LT(instruction->VRegA(), code_item->registers_size_);
+ DCHECK_LT(instruction->VRegA(), code_item->RegistersSize());
if (instruction->VRegA() != return_reg) {
return false; // Not returning the value set by const?
}
@@ -571,12 +569,12 @@ bool InlineMethodAnalyser::AnalyseConstMethod(const DexFile::CodeItem* code_item
return true;
}
-bool InlineMethodAnalyser::AnalyseIGetMethod(const DexFile::CodeItem* code_item,
+bool InlineMethodAnalyser::AnalyseIGetMethod(const CodeItemDataAccessor* code_item,
const MethodReference& method_ref,
bool is_static,
ArtMethod* method,
InlineMethod* result) {
- DexInstructionIterator instruction = code_item->Instructions().begin();
+ DexInstructionIterator instruction = code_item->begin();
Instruction::Code opcode = instruction->Opcode();
DCHECK(IsInstructionIGet(opcode));
@@ -591,17 +589,17 @@ bool InlineMethodAnalyser::AnalyseIGetMethod(const DexFile::CodeItem* code_item,
uint32_t return_reg = return_instruction->VRegA_11x();
DCHECK_LT(return_opcode == Instruction::RETURN_WIDE ? return_reg + 1 : return_reg,
- code_item->registers_size_);
+ code_item->RegistersSize());
uint32_t dst_reg = instruction->VRegA_22c();
uint32_t object_reg = instruction->VRegB_22c();
uint32_t field_idx = instruction->VRegC_22c();
- uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_;
+ uint32_t arg_start = code_item->RegistersSize() - code_item->InsSize();
DCHECK_GE(object_reg, arg_start);
- DCHECK_LT(object_reg, code_item->registers_size_);
+ DCHECK_LT(object_reg, code_item->RegistersSize());
uint32_t object_arg = object_reg - arg_start;
- DCHECK_LT(opcode == Instruction::IGET_WIDE ? dst_reg + 1 : dst_reg, code_item->registers_size_);
+ DCHECK_LT(opcode == Instruction::IGET_WIDE ? dst_reg + 1 : dst_reg, code_item->RegistersSize());
if (dst_reg != return_reg) {
return false; // Not returning the value retrieved by IGET?
}
@@ -635,18 +633,18 @@ bool InlineMethodAnalyser::AnalyseIGetMethod(const DexFile::CodeItem* code_item,
return true;
}
-bool InlineMethodAnalyser::AnalyseIPutMethod(const DexFile::CodeItem* code_item,
+bool InlineMethodAnalyser::AnalyseIPutMethod(const CodeItemDataAccessor* code_item,
const MethodReference& method_ref,
bool is_static,
ArtMethod* method,
InlineMethod* result) {
- DexInstructionIterator instruction = code_item->Instructions().begin();
+ DexInstructionIterator instruction = code_item->begin();
Instruction::Code opcode = instruction->Opcode();
DCHECK(IsInstructionIPut(opcode));
const Instruction* return_instruction = instruction->Next();
Instruction::Code return_opcode = return_instruction->Opcode();
- uint32_t arg_start = code_item->registers_size_ - code_item->ins_size_;
+ uint32_t arg_start = code_item->RegistersSize() - code_item->InsSize();
uint16_t return_arg_plus1 = 0u;
if (return_opcode != Instruction::RETURN_VOID) {
if (return_opcode != Instruction::RETURN &&
@@ -658,7 +656,7 @@ bool InlineMethodAnalyser::AnalyseIPutMethod(const DexFile::CodeItem* code_item,
uint32_t return_reg = return_instruction->VRegA_11x();
DCHECK_GE(return_reg, arg_start);
DCHECK_LT(return_opcode == Instruction::RETURN_WIDE ? return_reg + 1u : return_reg,
- code_item->registers_size_);
+ code_item->RegistersSize());
return_arg_plus1 = return_reg - arg_start + 1u;
}
@@ -666,9 +664,9 @@ bool InlineMethodAnalyser::AnalyseIPutMethod(const DexFile::CodeItem* code_item,
uint32_t object_reg = instruction->VRegB_22c();
uint32_t field_idx = instruction->VRegC_22c();
DCHECK_GE(object_reg, arg_start);
- DCHECK_LT(object_reg, code_item->registers_size_);
+ DCHECK_LT(object_reg, code_item->RegistersSize());
DCHECK_GE(src_reg, arg_start);
- DCHECK_LT(opcode == Instruction::IPUT_WIDE ? src_reg + 1 : src_reg, code_item->registers_size_);
+ DCHECK_LT(opcode == Instruction::IPUT_WIDE ? src_reg + 1 : src_reg, code_item->RegistersSize());
uint32_t object_arg = object_reg - arg_start;
uint32_t src_arg = src_reg - arg_start;
diff --git a/compiler/dex/inline_method_analyser.h b/compiler/dex/inline_method_analyser.h
index a35e97fa11..cde2147995 100644
--- a/compiler/dex/inline_method_analyser.h
+++ b/compiler/dex/inline_method_analyser.h
@@ -30,6 +30,8 @@
namespace art {
+class CodeItemDataAccessor;
+
namespace verifier {
class MethodVerifier;
} // namespace verifier
@@ -121,21 +123,21 @@ class InlineMethodAnalyser {
static bool IsSyntheticAccessor(MethodReference ref);
private:
- static bool AnalyseMethodCode(const DexFile::CodeItem* code_item,
+ static bool AnalyseMethodCode(const CodeItemDataAccessor* code_item,
const MethodReference& method_ref,
bool is_static,
ArtMethod* method,
InlineMethod* result)
REQUIRES_SHARED(Locks::mutator_lock_);
- static bool AnalyseReturnMethod(const DexFile::CodeItem* code_item, InlineMethod* result);
- static bool AnalyseConstMethod(const DexFile::CodeItem* code_item, InlineMethod* result);
- static bool AnalyseIGetMethod(const DexFile::CodeItem* code_item,
+ static bool AnalyseReturnMethod(const CodeItemDataAccessor* code_item, InlineMethod* result);
+ static bool AnalyseConstMethod(const CodeItemDataAccessor* code_item, InlineMethod* result);
+ static bool AnalyseIGetMethod(const CodeItemDataAccessor* code_item,
const MethodReference& method_ref,
bool is_static,
ArtMethod* method,
InlineMethod* result)
REQUIRES_SHARED(Locks::mutator_lock_);
- static bool AnalyseIPutMethod(const DexFile::CodeItem* code_item,
+ static bool AnalyseIPutMethod(const CodeItemDataAccessor* code_item,
const MethodReference& method_ref,
bool is_static,
ArtMethod* method,
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index afca26db71..c2556aa4a6 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -941,7 +941,7 @@ class Dex2oatUnquickenTest : public Dex2oatTest {
class_it.Next()) {
if (class_it.IsAtMethod() && class_it.GetMethodCodeItem() != nullptr) {
for (const DexInstructionPcPair& inst :
- class_it.GetMethodCodeItem()->Instructions()) {
+ class_it.GetMethodCodeItem()->Instructions()) {
ASSERT_FALSE(inst->IsQuickened());
}
}
diff --git a/runtime/Android.bp b/runtime/Android.bp
index e032238324..69e4434fbe 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -567,6 +567,7 @@ art_cc_test {
"class_linker_test.cc",
"class_loader_context_test.cc",
"class_table_test.cc",
+ "code_item_accessors_test.cc",
"compiler_filter_test.cc",
"dex_file_test.cc",
"dex_file_verifier_test.cc",
diff --git a/runtime/art_method-inl.h b/runtime/art_method-inl.h
index 12b4d16b37..eb16e6eaa2 100644
--- a/runtime/art_method-inl.h
+++ b/runtime/art_method-inl.h
@@ -23,6 +23,7 @@
#include "base/callee_save_type.h"
#include "base/logging.h"
#include "class_linker-inl.h"
+#include "code_item_accessors-inl.h"
#include "common_throws.h"
#include "dex_file-inl.h"
#include "dex_file_annotations.h"
@@ -457,6 +458,18 @@ inline void ArtMethod::UpdateEntrypoints(const Visitor& visitor, PointerSize poi
}
}
+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() };
+}
+
} // namespace art
#endif // ART_RUNTIME_ART_METHOD_INL_H_
diff --git a/runtime/art_method.h b/runtime/art_method.h
index 8927481e46..df9b3aa852 100644
--- a/runtime/art_method.h
+++ b/runtime/art_method.h
@@ -22,8 +22,10 @@
#include "base/bit_utils.h"
#include "base/casts.h"
#include "base/enums.h"
+#include "base/iteration_range.h"
#include "base/logging.h"
#include "dex_file.h"
+#include "dex_instruction_iterator.h"
#include "gc_root.h"
#include "modifiers.h"
#include "obj_ptr.h"
@@ -700,6 +702,15 @@ class ArtMethod FINAL {
"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()
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
protected:
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
// The class we are a part of.
diff --git a/runtime/base/casts.h b/runtime/base/casts.h
index 0cbabba6df..92c493ace7 100644
--- a/runtime/base/casts.h
+++ b/runtime/base/casts.h
@@ -77,6 +77,14 @@ inline To down_cast(From* f) { // so we only accept pointers
return static_cast<To>(f);
}
+template<typename To, typename From> // use like this: down_cast<T&>(foo);
+inline To down_cast(From& f) { // so we only accept references
+ static_assert(std::is_base_of<From, typename std::remove_reference<To>::type>::value,
+ "down_cast unsafe as To is not a subtype of From");
+
+ return static_cast<To>(f);
+}
+
template <class Dest, class Source>
inline Dest bit_cast(const Source& source) {
// Compile time assertion: sizeof(Dest) == sizeof(Source)
diff --git a/runtime/cdex/compact_dex_file.h b/runtime/cdex/compact_dex_file.h
index 8ab9247125..f17f8cf68a 100644
--- a/runtime/cdex/compact_dex_file.h
+++ b/runtime/cdex/compact_dex_file.h
@@ -24,11 +24,18 @@ namespace art {
// CompactDex is a currently ART internal dex file format that aims to reduce storage/RAM usage.
class CompactDexFile : public DexFile {
public:
+ static constexpr uint8_t kDexMagic[kDexMagicSize] = { 'c', 'd', 'e', 'x' };
+ static constexpr uint8_t kDexMagicVersion[] = {'0', '0', '1', '\0'};
+
class Header : public DexFile::Header {
// Same for now.
};
- static constexpr uint8_t kDexMagic[kDexMagicSize] = { 'c', 'd', 'e', 'x' };
- static constexpr uint8_t kDexMagicVersion[] = {'0', '0', '1', '\0'};
+
+ struct CodeItem : public DexFile::CodeItem {
+ private:
+ // TODO: Insert compact dex specific fields here.
+ DISALLOW_COPY_AND_ASSIGN(CodeItem);
+ };
// Write the compact dex specific magic.
static void WriteMagic(uint8_t* magic);
@@ -44,10 +51,6 @@ class CompactDexFile : public DexFile {
static bool IsVersionValid(const uint8_t* magic);
virtual bool IsVersionValid() const OVERRIDE;
- bool IsCompactDexFile() const OVERRIDE {
- return true;
- }
-
private:
// Not supported yet.
CompactDexFile(const uint8_t* base,
@@ -56,7 +59,13 @@ class CompactDexFile : public DexFile {
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
DexFileContainer* container)
- : DexFile(base, size, location, location_checksum, oat_dex_file, container) {}
+ : DexFile(base,
+ size,
+ location,
+ location_checksum,
+ oat_dex_file,
+ container,
+ /*is_compact_dex*/ true) {}
friend class DexFile;
friend class DexFileLoader;
diff --git a/runtime/code_item_accessors-inl.h b/runtime/code_item_accessors-inl.h
new file mode 100644
index 0000000000..61b517526d
--- /dev/null
+++ b/runtime/code_item_accessors-inl.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_CODE_ITEM_ACCESSORS_INL_H_
+#define ART_RUNTIME_CODE_ITEM_ACCESSORS_INL_H_
+
+#include "code_item_accessors.h"
+
+#include "art_method-inl.h"
+#include "cdex/compact_dex_file.h"
+#include "standard_dex_file.h"
+
+namespace art {
+
+inline void CodeItemInstructionAccessor::Init(const CompactDexFile::CodeItem& code_item) {
+ insns_size_in_code_units_ = code_item.insns_size_in_code_units_;
+ insns_ = code_item.insns_;
+}
+
+inline void CodeItemInstructionAccessor::Init(const StandardDexFile::CodeItem& code_item) {
+ insns_size_in_code_units_ = code_item.insns_size_in_code_units_;
+ insns_ = code_item.insns_;
+}
+
+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));
+ }
+}
+
+inline CodeItemInstructionAccessor::CodeItemInstructionAccessor(
+ const DexFile* dex_file,
+ const DexFile::CodeItem* code_item) {
+ Init(dex_file, code_item);
+}
+
+inline CodeItemInstructionAccessor::CodeItemInstructionAccessor(ArtMethod* method)
+ : CodeItemInstructionAccessor(method->GetDexFile(), method->GetCodeItem()) {}
+
+inline DexInstructionIterator CodeItemInstructionAccessor::begin() const {
+ return DexInstructionIterator(insns_, 0u);
+}
+
+inline DexInstructionIterator CodeItemInstructionAccessor::end() const {
+ return DexInstructionIterator(insns_, insns_size_in_code_units_);
+}
+
+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 void CodeItemDataAccessor::Init(const CompactDexFile::CodeItem& code_item) {
+ CodeItemInstructionAccessor::Init(code_item);
+ registers_size_ = code_item.registers_size_;
+ ins_size_ = code_item.ins_size_;
+ outs_size_ = code_item.outs_size_;
+ tries_size_ = code_item.tries_size_;
+}
+
+inline void CodeItemDataAccessor::Init(const StandardDexFile::CodeItem& code_item) {
+ CodeItemInstructionAccessor::Init(code_item);
+ registers_size_ = code_item.registers_size_;
+ ins_size_ = code_item.ins_size_;
+ outs_size_ = code_item.outs_size_;
+ tries_size_ = code_item.tries_size_;
+}
+
+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));
+ }
+}
+
+inline CodeItemDataAccessor::CodeItemDataAccessor(const DexFile* dex_file,
+ const DexFile::CodeItem* code_item) {
+ Init(dex_file, code_item);
+}
+
+inline CodeItemDataAccessor::CodeItemDataAccessor(ArtMethod* method)
+ : CodeItemDataAccessor(method->GetDexFile(), method->GetCodeItem()) {}
+
+inline CodeItemDataAccessor CodeItemDataAccessor::CreateNullable(ArtMethod* method) {
+ DCHECK(method != nullptr);
+ CodeItemDataAccessor 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;
+}
+
+} // namespace art
+
+#endif // ART_RUNTIME_CODE_ITEM_ACCESSORS_INL_H_
diff --git a/runtime/code_item_accessors.h b/runtime/code_item_accessors.h
new file mode 100644
index 0000000000..fcece3e0ac
--- /dev/null
+++ b/runtime/code_item_accessors.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// TODO: Dex helpers have ART specific APIs, we may want to refactor these for use in dexdump.
+
+#ifndef ART_RUNTIME_CODE_ITEM_ACCESSORS_H_
+#define ART_RUNTIME_CODE_ITEM_ACCESSORS_H_
+
+#include "base/mutex.h"
+#include "cdex/compact_dex_file.h"
+#include "dex_file.h"
+#include "dex_instruction_iterator.h"
+#include "standard_dex_file.h"
+
+namespace art {
+
+class ArtMethod;
+
+// Abstracts accesses to the instruction fields of code items for CompactDexFile and
+// StandardDexFile.
+class CodeItemInstructionAccessor {
+ public:
+ ALWAYS_INLINE CodeItemInstructionAccessor(const DexFile* dex_file,
+ const DexFile::CodeItem* code_item);
+
+ ALWAYS_INLINE explicit CodeItemInstructionAccessor(ArtMethod* method);
+
+ ALWAYS_INLINE DexInstructionIterator begin() const;
+
+ ALWAYS_INLINE DexInstructionIterator end() const;
+
+ uint32_t InsnsSizeInCodeUnits() const {
+ return insns_size_in_code_units_;
+ }
+
+ const uint16_t* Insns() const {
+ return insns_;
+ }
+
+ // Return true if the accessor has a code item.
+ bool HasCodeItem() const {
+ 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;
+
+ ALWAYS_INLINE void Init(const CompactDexFile::CodeItem& code_item);
+ ALWAYS_INLINE void Init(const StandardDexFile::CodeItem& code_item);
+ ALWAYS_INLINE void Init(const DexFile* dex_file, const DexFile::CodeItem* code_item);
+
+ private:
+ // size of the insns array, in 2 byte code units. 0 if there is no code item.
+ uint32_t insns_size_in_code_units_ = 0;
+
+ // Pointer to the instructions, null if there is no code item.
+ const uint16_t* insns_ = 0;
+};
+
+// Abstracts accesses to code item fields other than debug info for CompactDexFile and
+// StandardDexFile.
+class CodeItemDataAccessor : public CodeItemInstructionAccessor {
+ public:
+ ALWAYS_INLINE CodeItemDataAccessor(const DexFile* dex_file, const DexFile::CodeItem* code_item);
+
+ ALWAYS_INLINE explicit CodeItemDataAccessor(ArtMethod* method);
+
+ uint16_t RegistersSize() const {
+ return registers_size_;
+ }
+
+ uint16_t InsSize() const {
+ return ins_size_;
+ }
+
+ uint16_t OutsSize() const {
+ return outs_size_;
+ }
+
+ uint16_t TriesSize() const {
+ return tries_size_;
+ }
+
+ // CreateNullable allows ArtMethods that have a null code item.
+ ALWAYS_INLINE static CodeItemDataAccessor CreateNullable(ArtMethod* method)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ protected:
+ CodeItemDataAccessor() = default;
+
+ ALWAYS_INLINE void Init(const CompactDexFile::CodeItem& code_item);
+ ALWAYS_INLINE void Init(const StandardDexFile::CodeItem& code_item);
+ ALWAYS_INLINE void Init(const DexFile* dex_file, const DexFile::CodeItem* code_item);
+
+ private:
+ // Fields mirrored from the dex/cdex code item.
+ uint16_t registers_size_;
+ uint16_t ins_size_;
+ uint16_t outs_size_;
+ uint16_t tries_size_;
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_CODE_ITEM_ACCESSORS_H_
diff --git a/runtime/code_item_accessors_test.cc b/runtime/code_item_accessors_test.cc
new file mode 100644
index 0000000000..ef5d246a54
--- /dev/null
+++ b/runtime/code_item_accessors_test.cc
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "code_item_accessors-inl.h"
+
+#include <memory>
+
+#include "common_runtime_test.h"
+#include "dex_file_loader.h"
+#include "mem_map.h"
+
+namespace art {
+
+class CodeItemAccessorsTest : public CommonRuntimeTest {};
+
+std::unique_ptr<const DexFile> CreateFakeDex(bool compact_dex) {
+ std::string error_msg;
+ std::unique_ptr<MemMap> map(
+ MemMap::MapAnonymous(/*name*/ "map",
+ /*addr*/ nullptr,
+ /*byte_count*/ kPageSize,
+ PROT_READ | PROT_WRITE,
+ /*low_4gb*/ false,
+ /*reuse*/ false,
+ &error_msg));
+ CHECK(map != nullptr) << error_msg;
+ if (compact_dex) {
+ CompactDexFile::WriteMagic(map->Begin());
+ CompactDexFile::WriteCurrentVersion(map->Begin());
+ } else {
+ StandardDexFile::WriteMagic(map->Begin());
+ StandardDexFile::WriteCurrentVersion(map->Begin());
+ }
+ std::unique_ptr<const DexFile> dex(
+ DexFileLoader::Open("location",
+ /*location_checksum*/ 123,
+ std::move(map),
+ /*verify*/false,
+ /*verify_checksum*/false,
+ &error_msg));
+ CHECK(dex != nullptr) << error_msg;
+ return dex;
+}
+
+TEST(CodeItemAccessorsTest, TestDexInstructionsAccessor) {
+ MemMap::Init();
+ std::unique_ptr<const DexFile> standard_dex(CreateFakeDex(/*compact_dex*/false));
+ ASSERT_TRUE(standard_dex != nullptr);
+ std::unique_ptr<const DexFile> compact_dex(CreateFakeDex(/*compact_dex*/true));
+ ASSERT_TRUE(compact_dex != nullptr);
+ static constexpr uint16_t kRegisterSize = 1;
+ static constexpr uint16_t kInsSize = 2;
+ static constexpr uint16_t kOutsSize = 3;
+ static constexpr uint16_t kTriesSize = 4;
+ // debug_info_off_ is not accessible from the helpers yet.
+ static constexpr size_t kInsnsSizeInCodeUnits = 5;
+
+ auto verify_code_item = [&](const DexFile* dex,
+ const DexFile::CodeItem* item,
+ const uint16_t* insns) {
+ CodeItemInstructionAccessor insns_accessor(dex, item);
+ EXPECT_TRUE(insns_accessor.HasCodeItem());
+ ASSERT_EQ(insns_accessor.InsnsSizeInCodeUnits(), kInsnsSizeInCodeUnits);
+ EXPECT_EQ(insns_accessor.Insns(), insns);
+
+ CodeItemDataAccessor data_accessor(dex, item);
+ EXPECT_TRUE(data_accessor.HasCodeItem());
+ EXPECT_EQ(data_accessor.InsnsSizeInCodeUnits(), kInsnsSizeInCodeUnits);
+ EXPECT_EQ(data_accessor.Insns(), insns);
+ EXPECT_EQ(data_accessor.RegistersSize(), kRegisterSize);
+ EXPECT_EQ(data_accessor.InsSize(), kInsSize);
+ EXPECT_EQ(data_accessor.OutsSize(), kOutsSize);
+ EXPECT_EQ(data_accessor.TriesSize(), kTriesSize);
+ };
+
+ uint8_t buffer1[sizeof(CompactDexFile::CodeItem) + kInsnsSizeInCodeUnits * sizeof(uint16_t)] = {};
+ CompactDexFile::CodeItem* dex_code_item = reinterpret_cast<CompactDexFile::CodeItem*>(buffer1);
+ dex_code_item->registers_size_ = kRegisterSize;
+ dex_code_item->ins_size_ = kInsSize;
+ dex_code_item->outs_size_ = kOutsSize;
+ dex_code_item->tries_size_ = kTriesSize;
+ dex_code_item->insns_size_in_code_units_ = kInsnsSizeInCodeUnits;
+ verify_code_item(compact_dex.get(), dex_code_item, dex_code_item->insns_);
+
+ uint8_t buffer2[sizeof(CompactDexFile::CodeItem) + kInsnsSizeInCodeUnits * sizeof(uint16_t)] = {};
+ CompactDexFile::CodeItem* cdex_code_item = reinterpret_cast<CompactDexFile::CodeItem*>(buffer2);
+ cdex_code_item->registers_size_ = kRegisterSize;
+ cdex_code_item->ins_size_ = kInsSize;
+ cdex_code_item->outs_size_ = kOutsSize;
+ cdex_code_item->tries_size_ = kTriesSize;
+ cdex_code_item->insns_size_in_code_units_ = kInsnsSizeInCodeUnits;
+ verify_code_item(compact_dex.get(), cdex_code_item, cdex_code_item->insns_);
+}
+
+} // namespace art
diff --git a/runtime/dex_file-inl.h b/runtime/dex_file-inl.h
index 5dfbd9b6a1..58cd48631d 100644
--- a/runtime/dex_file-inl.h
+++ b/runtime/dex_file-inl.h
@@ -21,9 +21,11 @@
#include "base/casts.h"
#include "base/logging.h"
#include "base/stringpiece.h"
+#include "cdex/compact_dex_file.h"
#include "dex_file.h"
#include "invoke_type.h"
#include "leb128.h"
+#include "standard_dex_file.h"
namespace art {
@@ -495,6 +497,16 @@ bool DexFile::DecodeDebugPositionInfo(const CodeItem* code_item,
context);
}
+inline const CompactDexFile* DexFile::AsCompactDexFile() const {
+ DCHECK(IsCompactDexFile());
+ return down_cast<const CompactDexFile*>(this);
+}
+
+inline const StandardDexFile* DexFile::AsStandardDexFile() const {
+ DCHECK(IsStandardDexFile());
+ return down_cast<const StandardDexFile*>(this);
+}
+
} // namespace art
#endif // ART_RUNTIME_DEX_FILE_INL_H_
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 974c7acbb2..7b0c46bcfe 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -77,7 +77,8 @@ DexFile::DexFile(const uint8_t* base,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
- DexFileContainer* container)
+ DexFileContainer* container,
+ bool is_compact_dex)
: begin_(base),
size_(size),
location_(location),
@@ -94,7 +95,8 @@ DexFile::DexFile(const uint8_t* base,
call_site_ids_(nullptr),
num_call_site_ids_(0),
oat_dex_file_(oat_dex_file),
- container_(container) {
+ container_(container),
+ is_compact_dex_(is_compact_dex) {
CHECK(begin_ != nullptr) << GetLocation();
CHECK_GT(size_, 0U) << GetLocation();
// Check base (=header) alignment.
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 5c9b2585eb..5c0093f323 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -32,10 +32,12 @@
namespace art {
+class CompactDexFile;
enum InvokeType : uint32_t;
class MemMap;
class OatDexFile;
class Signature;
+class StandardDexFile;
class StringPiece;
class ZipArchive;
@@ -993,13 +995,15 @@ class DexFile {
// Returns a human-readable form of the type at an index.
std::string PrettyType(dex::TypeIndex type_idx) const;
- // Helper functions.
- virtual bool IsCompactDexFile() const {
- return false;
+ // Not virtual for performance reasons.
+ ALWAYS_INLINE bool IsCompactDexFile() const {
+ return is_compact_dex_;
}
- virtual bool IsStandardDexFile() const {
- return false;
+ ALWAYS_INLINE bool IsStandardDexFile() const {
+ return !is_compact_dex_;
}
+ ALWAYS_INLINE const StandardDexFile* AsStandardDexFile() const;
+ ALWAYS_INLINE const CompactDexFile* AsCompactDexFile() const;
protected:
DexFile(const uint8_t* base,
@@ -1007,7 +1011,8 @@ class DexFile {
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
- DexFileContainer* container);
+ DexFileContainer* container,
+ bool is_compact_dex);
// Top-level initializer that calls other Init methods.
bool Init(std::string* error_msg);
@@ -1073,6 +1078,9 @@ class DexFile {
// Manages the underlying memory allocation.
std::unique_ptr<DexFileContainer> container_;
+ // If the dex file is a compact dex file. If false then the dex file is a standard dex file.
+ const bool is_compact_dex_;
+
friend class DexFileLoader;
friend class DexFileVerifierTest;
friend class OatWriter;
diff --git a/runtime/jit/profiling_info.cc b/runtime/jit/profiling_info.cc
index 1344ca05b4..e54a0179e1 100644
--- a/runtime/jit/profiling_info.cc
+++ b/runtime/jit/profiling_info.cc
@@ -44,8 +44,7 @@ bool ProfilingInfo::Create(Thread* self, ArtMethod* method, bool retry_allocatio
DCHECK(!method->IsNative());
std::vector<uint32_t> entries;
-
- for (const DexInstructionPcPair& inst : method->GetCodeItem()->Instructions()) {
+ for (const DexInstructionPcPair& inst : method->DexInstructions()) {
switch (inst->Opcode()) {
case Instruction::INVOKE_VIRTUAL:
case Instruction::INVOKE_VIRTUAL_RANGE:
diff --git a/runtime/standard_dex_file.cc b/runtime/standard_dex_file.cc
index 36bb37afe9..4c1d3081d8 100644
--- a/runtime/standard_dex_file.cc
+++ b/runtime/standard_dex_file.cc
@@ -31,6 +31,16 @@ const uint8_t StandardDexFile::kDexMagicVersions[StandardDexFile::kNumDexVersion
{'0', '3', '9', '\0'},
};
+void StandardDexFile::WriteMagic(uint8_t* magic) {
+ std::copy_n(kDexMagic, kDexMagicSize, magic);
+}
+
+void StandardDexFile::WriteCurrentVersion(uint8_t* magic) {
+ std::copy_n(kDexMagicVersions[StandardDexFile::kDexVersionLen - 1],
+ kDexVersionLen,
+ magic + kDexMagicSize);
+}
+
bool StandardDexFile::IsMagicValid(const uint8_t* magic) {
return (memcmp(magic, kDexMagic, sizeof(kDexMagic)) == 0);
}
diff --git a/runtime/standard_dex_file.h b/runtime/standard_dex_file.h
index 784ab31821..5d5359776d 100644
--- a/runtime/standard_dex_file.h
+++ b/runtime/standard_dex_file.h
@@ -32,6 +32,18 @@ class StandardDexFile : public DexFile {
// Same for now.
};
+ struct CodeItem : public DexFile::CodeItem {
+ private:
+ // TODO: Insert standard dex specific fields here.
+ DISALLOW_COPY_AND_ASSIGN(CodeItem);
+ };
+
+ // Write the standard dex specific magic.
+ static void WriteMagic(uint8_t* magic);
+
+ // Write the current version, note that the input is the address of the magic.
+ static void WriteCurrentVersion(uint8_t* magic);
+
static const uint8_t kDexMagic[kDexMagicSize];
static constexpr size_t kNumDexVersions = 4;
static const uint8_t kDexMagicVersions[kNumDexVersions][kDexVersionLen];
@@ -44,10 +56,6 @@ class StandardDexFile : public DexFile {
static bool IsVersionValid(const uint8_t* magic);
virtual bool IsVersionValid() const OVERRIDE;
- bool IsStandardDexFile() const OVERRIDE {
- return true;
- }
-
private:
StandardDexFile(const uint8_t* base,
size_t size,
@@ -55,7 +63,13 @@ class StandardDexFile : public DexFile {
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
DexFileContainer* container)
- : DexFile(base, size, location, location_checksum, oat_dex_file, container) {}
+ : DexFile(base,
+ size,
+ location,
+ location_checksum,
+ oat_dex_file,
+ container,
+ /*is_compact_dex*/ false) {}
friend class DexFileLoader;
friend class DexFileVerifierTest;