Merge "Remove unused build code"
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index 3ce786e..c902d28 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -90,7 +90,7 @@
// Compiles a virtual method invocation into a quick virtual method invocation.
// The method index is replaced by the vtable index where the corresponding
- // AbstractMethod can be found. Therefore, this does not involve any resolution
+ // Executable can be found. Therefore, this does not involve any resolution
// at runtime.
// Since the method index is encoded with 16 bits, we can replace it only if the
// vtable index can be encoded with 16 bits too.
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 6d86f7d..cdb57a9 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -48,12 +48,12 @@
#include "intern_table.h"
#include "linear_alloc.h"
#include "lock_word.h"
-#include "mirror/abstract_method.h"
#include "mirror/array-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/dex_cache.h"
#include "mirror/dex_cache-inl.h"
+#include "mirror/executable.h"
#include "mirror/method.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
@@ -1989,14 +1989,10 @@
} else {
if (klass == mirror::Method::StaticClass() || klass == mirror::Constructor::StaticClass()) {
// Need to go update the ArtMethod.
- auto* dest = down_cast<mirror::AbstractMethod*>(copy);
- auto* src = down_cast<mirror::AbstractMethod*>(orig);
+ auto* dest = down_cast<mirror::Executable*>(copy);
+ auto* src = down_cast<mirror::Executable*>(orig);
ArtMethod* src_method = src->GetArtMethod();
- auto it = native_object_relocations_.find(src_method);
- CHECK(it != native_object_relocations_.end())
- << "Missing relocation for AbstractMethod.artMethod " << PrettyMethod(src_method);
- dest->SetArtMethod(
- reinterpret_cast<ArtMethod*>(global_image_begin_ + it->second.offset));
+ dest->SetArtMethod(GetImageMethodAddress(src_method));
} else if (!klass->IsArrayClass()) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
if (klass == class_linker->GetClassRoot(ClassLinker::kJavaLangDexCache)) {
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index d629c0c..9045817 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -55,6 +55,7 @@
#include "utils/dex_cache_arrays_layout-inl.h"
#include "vdex_file.h"
#include "verifier/method_verifier.h"
+#include "verifier/verifier_deps.h"
#include "zip_archive.h"
namespace art {
@@ -297,6 +298,7 @@
dex_files_(nullptr),
vdex_size_(0u),
vdex_dex_files_offset_(0u),
+ vdex_verifier_deps_offset_(0u),
oat_size_(0u),
bss_size_(0u),
oat_data_offset_(0u),
@@ -307,6 +309,8 @@
size_oat_header_(0),
size_oat_header_key_value_store_(0),
size_dex_file_(0),
+ size_verifier_deps_(0),
+ size_verifier_deps_alignment_(0),
size_interpreter_to_interpreter_bridge_(0),
size_interpreter_to_compiled_code_bridge_(0),
size_jni_dlsym_lookup_(0),
@@ -476,11 +480,6 @@
!OpenDexFiles(vdex_file, verify, &dex_files_map, &dex_files)) {
return false;
}
-
- // VDEX is finalized. Seek to the beginning of the file and write the header.
- if (!WriteVdexHeader(vdex_out.get())) {
- return false;
- }
} else {
// Write DEX files into OAT, mmap and open them.
if (!WriteDexFiles(oat_rodata, vdex_file) ||
@@ -1595,6 +1594,52 @@
return true;
}
+bool OatWriter::WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps) {
+ if (!kIsVdexEnabled) {
+ return true;
+ }
+
+ if (verifier_deps == nullptr) {
+ // Nothing to write. Record the offset, but no need
+ // for alignment.
+ vdex_verifier_deps_offset_ = vdex_size_;
+ return true;
+ }
+
+ size_t initial_offset = vdex_size_;
+ size_t start_offset = RoundUp(initial_offset, 4u);
+
+ vdex_size_ = start_offset;
+ vdex_verifier_deps_offset_ = vdex_size_;
+ size_verifier_deps_alignment_ = start_offset - initial_offset;
+
+ off_t actual_offset = vdex_out->Seek(start_offset, kSeekSet);
+ if (actual_offset != static_cast<off_t>(start_offset)) {
+ PLOG(ERROR) << "Failed to seek to verifier deps section. Actual: " << actual_offset
+ << " Expected: " << start_offset
+ << " Output: " << vdex_out->GetLocation();
+ return false;
+ }
+
+ std::vector<uint8_t> buffer;
+ verifier_deps->Encode(&buffer);
+
+ if (!vdex_out->WriteFully(buffer.data(), buffer.size())) {
+ PLOG(ERROR) << "Failed to write verifier deps."
+ << " File: " << vdex_out->GetLocation();
+ return false;
+ }
+ if (!vdex_out->Flush()) {
+ PLOG(ERROR) << "Failed to flush stream after writing verifier deps."
+ << " File: " << vdex_out->GetLocation();
+ return false;
+ }
+
+ size_verifier_deps_ = buffer.size();
+ vdex_size_ += size_verifier_deps_;
+ return true;
+}
+
bool OatWriter::WriteCode(OutputStream* out) {
CHECK(write_state_ == WriteState::kWriteText);
@@ -1638,6 +1683,8 @@
DO_STAT(size_oat_header_);
DO_STAT(size_oat_header_key_value_store_);
DO_STAT(size_dex_file_);
+ DO_STAT(size_verifier_deps_);
+ DO_STAT(size_verifier_deps_alignment_);
DO_STAT(size_interpreter_to_interpreter_bridge_);
DO_STAT(size_interpreter_to_compiled_code_bridge_);
DO_STAT(size_jni_dlsym_lookup_);
@@ -2341,6 +2388,9 @@
}
bool OatWriter::WriteVdexHeader(OutputStream* vdex_out) {
+ if (!kIsVdexEnabled) {
+ return true;
+ }
off_t actual_offset = vdex_out->Seek(0, kSeekSet);
if (actual_offset != 0) {
PLOG(ERROR) << "Failed to seek to the beginning of vdex file. Actual: " << actual_offset
@@ -2348,12 +2398,24 @@
return false;
}
- VdexFile::Header vdex_header;
+ DCHECK_NE(vdex_dex_files_offset_, 0u);
+ DCHECK_NE(vdex_verifier_deps_offset_, 0u);
+
+ size_t dex_section_size = vdex_verifier_deps_offset_ - vdex_dex_files_offset_;
+ size_t verifier_deps_section_size = vdex_size_ - vdex_verifier_deps_offset_;
+
+ VdexFile::Header vdex_header(dex_section_size, verifier_deps_section_size);
if (!vdex_out->WriteFully(&vdex_header, sizeof(VdexFile::Header))) {
PLOG(ERROR) << "Failed to write vdex header. File: " << vdex_out->GetLocation();
return false;
}
+ if (!vdex_out->Flush()) {
+ PLOG(ERROR) << "Failed to flush stream after writing to vdex file."
+ << " File: " << vdex_out->GetLocation();
+ return false;
+ }
+
return true;
}
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index dd7d699..670accb 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -50,6 +50,10 @@
class MultiOatRelativePatcher;
} // namespace linker
+namespace verifier {
+ class VerifierDeps;
+} // namespace verifier
+
// OatHeader variable length with count of D OatDexFiles
//
// OatDexFile[0] one variable sized OatDexFile with offsets to Dex and OatClasses
@@ -149,6 +153,9 @@
bool verify,
/*out*/ std::unique_ptr<MemMap>* opened_dex_files_map,
/*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
+ bool WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps);
+ bool WriteVdexHeader(OutputStream* vdex_out);
+
// Prepare layout of remaining data.
void PrepareLayout(const CompilerDriver* compiler,
ImageWriter* image_writer,
@@ -232,8 +239,6 @@
// with a given DexMethodVisitor.
bool VisitDexMethods(DexMethodVisitor* visitor);
- bool WriteVdexHeader(OutputStream* vdex_out);
-
bool WriteDexFiles(OutputStream* out, File* file);
bool WriteDexFile(OutputStream* out, File* file, OatDexFile* oat_dex_file);
bool SeekToDexFile(OutputStream* out, File* file, OatDexFile* oat_dex_file);
@@ -311,6 +316,9 @@
// Offset of section holding Dex files inside Vdex.
size_t vdex_dex_files_offset_;
+ // Offset of section holding VerifierDeps inside Vdex.
+ size_t vdex_verifier_deps_offset_;
+
// Size required for Oat data structures.
size_t oat_size_;
@@ -341,6 +349,8 @@
uint32_t size_oat_header_;
uint32_t size_oat_header_key_value_store_;
uint32_t size_dex_file_;
+ uint32_t size_verifier_deps_;
+ uint32_t size_verifier_deps_alignment_;
uint32_t size_interpreter_to_interpreter_bridge_;
uint32_t size_interpreter_to_compiled_code_bridge_;
uint32_t size_jni_dlsym_lookup_;
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 51ba187..137cd21 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -1117,7 +1117,8 @@
}
}
-LocationSummary* CodeGenerator::CreateNullCheckLocations(HNullCheck* null_check) {
+LocationSummary* CodeGenerator::CreateThrowingSlowPathLocations(HInstruction* instruction,
+ RegisterSet caller_saves) {
// Note: Using kNoCall allows the method to be treated as leaf (and eliminate the
// HSuspendCheck from entry block). However, it will still get a valid stack frame
// because the HNullCheck needs an environment.
@@ -1125,16 +1126,15 @@
// When throwing from a try block, we may need to retrieve dalvik registers from
// physical registers and we also need to set up stack mask for GC. This is
// implicitly achieved by passing kCallOnSlowPath to the LocationSummary.
- bool can_throw_into_catch_block = null_check->CanThrowIntoCatchBlock();
+ bool can_throw_into_catch_block = instruction->CanThrowIntoCatchBlock();
if (can_throw_into_catch_block) {
call_kind = LocationSummary::kCallOnSlowPath;
}
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(null_check, call_kind);
+ LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
if (can_throw_into_catch_block && compiler_options_.GetImplicitNullChecks()) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(caller_saves); // Default: no caller-save registers.
}
- locations->SetInAt(0, Location::RequiresRegister());
- DCHECK(!null_check->HasUses());
+ DCHECK(!instruction->HasUses());
return locations;
}
@@ -1273,7 +1273,7 @@
}
const uint32_t fp_spills = codegen->GetSlowPathSpills(locations, /* core_registers */ false);
- for (size_t i : LowToHighBits(fp_spills)) {
+ for (uint32_t i : LowToHighBits(fp_spills)) {
DCHECK_LT(stack_offset, codegen->GetFrameSize() - codegen->FrameEntrySpillSize());
DCHECK_LT(i, kMaximumNumberOfExpectedRegisters);
saved_fpu_stack_offsets_[i] = stack_offset;
@@ -1292,7 +1292,7 @@
}
const uint32_t fp_spills = codegen->GetSlowPathSpills(locations, /* core_registers */ false);
- for (size_t i : LowToHighBits(fp_spills)) {
+ for (uint32_t i : LowToHighBits(fp_spills)) {
DCHECK_LT(stack_offset, codegen->GetFrameSize() - codegen->FrameEntrySpillSize());
DCHECK_LT(i, kMaximumNumberOfExpectedRegisters);
stack_offset += codegen->RestoreFloatingPointRegister(stack_offset, i);
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 22b5c9c..c0c798d 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -313,7 +313,8 @@
bool CanMoveNullCheckToUser(HNullCheck* null_check);
void MaybeRecordImplicitNullCheck(HInstruction* instruction);
- LocationSummary* CreateNullCheckLocations(HNullCheck* null_check);
+ LocationSummary* CreateThrowingSlowPathLocations(
+ HInstruction* instruction, RegisterSet caller_saves = RegisterSet::Empty());
void GenerateNullCheck(HNullCheck* null_check);
virtual void GenerateImplicitNullCheck(HNullCheck* null_check) = 0;
virtual void GenerateExplicitNullCheck(HNullCheck* null_check) = 0;
@@ -579,6 +580,7 @@
core_spill_mask_(0),
fpu_spill_mask_(0),
first_register_slot_in_slow_path_(0),
+ allocated_registers_(RegisterSet::Empty()),
blocked_core_registers_(graph->GetArena()->AllocArray<bool>(number_of_core_registers,
kArenaAllocCodeGenerator)),
blocked_fpu_registers_(graph->GetArena()->AllocArray<bool>(number_of_fpu_registers,
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 3b2758b..a052873 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -191,7 +191,7 @@
uint32_t fp_spills = codegen->GetSlowPathSpills(locations, /* core_registers */ false);
orig_offset = stack_offset;
- for (size_t i : LowToHighBits(fp_spills)) {
+ for (uint32_t i : LowToHighBits(fp_spills)) {
DCHECK_LT(i, kMaximumNumberOfExpectedRegisters);
saved_fpu_stack_offsets_[i] = stack_offset;
stack_offset += kArmWordSize;
@@ -275,10 +275,6 @@
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
CodeGeneratorARM* arm_codegen = down_cast<CodeGeneratorARM*>(codegen);
__ Bind(GetEntryLabel());
- if (instruction_->CanThrowIntoCatchBlock()) {
- // Live registers will be restored in the catch block if caught.
- SaveLiveRegisters(codegen, instruction_->GetLocations());
- }
arm_codegen->InvokeRuntime(kQuickThrowDivZero, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickThrowDivZero, void, void>();
}
@@ -1681,7 +1677,7 @@
void LocationsBuilderARM::VisitDeoptimize(HDeoptimize* deoptimize) {
LocationSummary* locations = new (GetGraph()->GetArena())
LocationSummary(deoptimize, LocationSummary::kCallOnSlowPath);
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
if (IsBooleanValueOrMaterializedCondition(deoptimize->InputAt(0))) {
locations->SetInAt(0, Location::RequiresRegister());
}
@@ -3264,14 +3260,8 @@
}
void LocationsBuilderARM::VisitDivZeroCheck(HDivZeroCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
}
void InstructionCodeGeneratorARM::VisitDivZeroCheck(HDivZeroCheck* instruction) {
@@ -4110,7 +4100,7 @@
LocationSummary::kCallOnSlowPath :
LocationSummary::kNoCall);
if (object_field_get_with_read_barrier && kUseBakerReadBarrier) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::RequiresRegister());
@@ -4430,7 +4420,8 @@
}
void LocationsBuilderARM::VisitNullCheck(HNullCheck* instruction) {
- codegen_->CreateNullCheckLocations(instruction);
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
+ locations->SetInAt(0, Location::RequiresRegister());
}
void CodeGeneratorARM::GenerateImplicitNullCheck(HNullCheck* instruction) {
@@ -4582,7 +4573,7 @@
LocationSummary::kCallOnSlowPath :
LocationSummary::kNoCall);
if (object_array_get_with_read_barrier && kUseBakerReadBarrier) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
@@ -5067,15 +5058,13 @@
}
void LocationsBuilderARM::VisitBoundsCheck(HBoundsCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+ RegisterSet caller_saves = RegisterSet::Empty();
+ InvokeRuntimeCallingConvention calling_convention;
+ caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+ caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction, caller_saves);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
}
void InstructionCodeGeneratorARM::VisitBoundsCheck(HBoundsCheck* instruction) {
@@ -5119,7 +5108,7 @@
void LocationsBuilderARM::VisitSuspendCheck(HSuspendCheck* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
void InstructionCodeGeneratorARM::VisitSuspendCheck(HSuspendCheck* instruction) {
@@ -5441,7 +5430,7 @@
: LocationSummary::kNoCall;
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(cls, call_kind);
if (kUseBakerReadBarrier && requires_read_barrier && !cls->NeedsEnvironment()) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
HLoadClass::LoadKind load_kind = cls->GetLoadKind();
@@ -5745,7 +5734,7 @@
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
if (baker_read_barrier_slow_path) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 7f542da..a29e9f3 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -139,18 +139,18 @@
// Calculate memory accessing operand for save/restore live registers.
static void SaveRestoreLiveRegistersHelper(CodeGenerator* codegen,
- RegisterSet* register_set,
+ LocationSummary* locations,
int64_t spill_offset,
bool is_save) {
- DCHECK(ArtVixlRegCodeCoherentForRegSet(register_set->GetCoreRegisters(),
+ const uint32_t core_spills = codegen->GetSlowPathSpills(locations, /* core_registers */ true);
+ const uint32_t fp_spills = codegen->GetSlowPathSpills(locations, /* core_registers */ false);
+ DCHECK(ArtVixlRegCodeCoherentForRegSet(core_spills,
codegen->GetNumberOfCoreRegisters(),
- register_set->GetFloatingPointRegisters(),
+ fp_spills,
codegen->GetNumberOfFloatingPointRegisters()));
- CPURegList core_list = CPURegList(CPURegister::kRegister, kXRegSize,
- register_set->GetCoreRegisters() & (~callee_saved_core_registers.GetList()));
- CPURegList fp_list = CPURegList(CPURegister::kFPRegister, kDRegSize,
- register_set->GetFloatingPointRegisters() & (~callee_saved_fp_registers.GetList()));
+ CPURegList core_list = CPURegList(CPURegister::kRegister, kXRegSize, core_spills);
+ CPURegList fp_list = CPURegList(CPURegister::kFPRegister, kDRegSize, fp_spills);
MacroAssembler* masm = down_cast<CodeGeneratorARM64*>(codegen)->GetVIXLAssembler();
UseScratchRegisterScope temps(masm);
@@ -184,38 +184,35 @@
}
void SlowPathCodeARM64::SaveLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) {
- RegisterSet* register_set = locations->GetLiveRegisters();
size_t stack_offset = codegen->GetFirstRegisterSlotInSlowPath();
- for (size_t i = 0, e = codegen->GetNumberOfCoreRegisters(); i < e; ++i) {
- if (!codegen->IsCoreCalleeSaveRegister(i) && register_set->ContainsCoreRegister(i)) {
- // If the register holds an object, update the stack mask.
- if (locations->RegisterContainsObject(i)) {
- locations->SetStackBit(stack_offset / kVRegSize);
- }
- DCHECK_LT(stack_offset, codegen->GetFrameSize() - codegen->FrameEntrySpillSize());
- DCHECK_LT(i, kMaximumNumberOfExpectedRegisters);
- saved_core_stack_offsets_[i] = stack_offset;
- stack_offset += kXRegSizeInBytes;
+ const uint32_t core_spills = codegen->GetSlowPathSpills(locations, /* core_registers */ true);
+ for (uint32_t i : LowToHighBits(core_spills)) {
+ // If the register holds an object, update the stack mask.
+ if (locations->RegisterContainsObject(i)) {
+ locations->SetStackBit(stack_offset / kVRegSize);
}
+ DCHECK_LT(stack_offset, codegen->GetFrameSize() - codegen->FrameEntrySpillSize());
+ DCHECK_LT(i, kMaximumNumberOfExpectedRegisters);
+ saved_core_stack_offsets_[i] = stack_offset;
+ stack_offset += kXRegSizeInBytes;
}
- for (size_t i = 0, e = codegen->GetNumberOfFloatingPointRegisters(); i < e; ++i) {
- if (!codegen->IsFloatingPointCalleeSaveRegister(i) &&
- register_set->ContainsFloatingPointRegister(i)) {
- DCHECK_LT(stack_offset, codegen->GetFrameSize() - codegen->FrameEntrySpillSize());
- DCHECK_LT(i, kMaximumNumberOfExpectedRegisters);
- saved_fpu_stack_offsets_[i] = stack_offset;
- stack_offset += kDRegSizeInBytes;
- }
+ const uint32_t fp_spills = codegen->GetSlowPathSpills(locations, /* core_registers */ false);
+ for (uint32_t i : LowToHighBits(fp_spills)) {
+ DCHECK_LT(stack_offset, codegen->GetFrameSize() - codegen->FrameEntrySpillSize());
+ DCHECK_LT(i, kMaximumNumberOfExpectedRegisters);
+ saved_fpu_stack_offsets_[i] = stack_offset;
+ stack_offset += kDRegSizeInBytes;
}
- SaveRestoreLiveRegistersHelper(codegen, register_set,
+ SaveRestoreLiveRegistersHelper(codegen,
+ locations,
codegen->GetFirstRegisterSlotInSlowPath(), true /* is_save */);
}
void SlowPathCodeARM64::RestoreLiveRegisters(CodeGenerator* codegen, LocationSummary* locations) {
- RegisterSet* register_set = locations->GetLiveRegisters();
- SaveRestoreLiveRegistersHelper(codegen, register_set,
+ SaveRestoreLiveRegistersHelper(codegen,
+ locations,
codegen->GetFirstRegisterSlotInSlowPath(), false /* is_save */);
}
@@ -261,10 +258,6 @@
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
CodeGeneratorARM64* arm64_codegen = down_cast<CodeGeneratorARM64*>(codegen);
__ Bind(GetEntryLabel());
- if (instruction_->CanThrowIntoCatchBlock()) {
- // Live registers will be restored in the catch block if caught.
- SaveLiveRegisters(codegen, instruction_->GetLocations());
- }
arm64_codegen->InvokeRuntime(kQuickThrowDivZero, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickThrowDivZero, void, void>();
}
@@ -1608,7 +1601,7 @@
LocationSummary::kCallOnSlowPath :
LocationSummary::kNoCall);
if (object_field_get_with_read_barrier && kUseBakerReadBarrier) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::RequiresRegister());
if (Primitive::IsFloatingPointType(instruction->GetType())) {
@@ -2036,7 +2029,7 @@
LocationSummary::kCallOnSlowPath :
LocationSummary::kNoCall);
if (object_array_get_with_read_barrier && kUseBakerReadBarrier) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
@@ -2306,15 +2299,13 @@
}
void LocationsBuilderARM64::VisitBoundsCheck(HBoundsCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+ RegisterSet caller_saves = RegisterSet::Empty();
+ InvokeRuntimeCallingConvention calling_convention;
+ caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(0).GetCode()));
+ caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(1).GetCode()));
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction, caller_saves);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, ARM64EncodableConstantOrRegister(instruction->InputAt(1), instruction));
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
}
void InstructionCodeGeneratorARM64::VisitBoundsCheck(HBoundsCheck* instruction) {
@@ -2685,14 +2676,8 @@
}
void LocationsBuilderARM64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
}
void InstructionCodeGeneratorARM64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
@@ -2924,7 +2909,7 @@
void LocationsBuilderARM64::VisitDeoptimize(HDeoptimize* deoptimize) {
LocationSummary* locations = new (GetGraph()->GetArena())
LocationSummary(deoptimize, LocationSummary::kCallOnSlowPath);
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
if (IsBooleanValueOrMaterializedCondition(deoptimize->InputAt(0))) {
locations->SetInAt(0, Location::RequiresRegister());
}
@@ -3077,7 +3062,7 @@
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
if (baker_read_barrier_slow_path) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
@@ -3944,7 +3929,7 @@
: LocationSummary::kNoCall;
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(cls, call_kind);
if (kUseBakerReadBarrier && requires_read_barrier && !cls->NeedsEnvironment()) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
HLoadClass::LoadKind load_kind = cls->GetLoadKind();
@@ -4384,7 +4369,8 @@
}
void LocationsBuilderARM64::VisitNullCheck(HNullCheck* instruction) {
- codegen_->CreateNullCheckLocations(instruction);
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
+ locations->SetInAt(0, Location::RequiresRegister());
}
void CodeGeneratorARM64::GenerateImplicitNullCheck(HNullCheck* instruction) {
@@ -4670,7 +4656,7 @@
void LocationsBuilderARM64::VisitSuspendCheck(HSuspendCheck* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
void InstructionCodeGeneratorARM64::VisitSuspendCheck(HSuspendCheck* instruction) {
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index b2e7595..2211ea3 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -194,10 +194,6 @@
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
CodeGeneratorMIPS* mips_codegen = down_cast<CodeGeneratorMIPS*>(codegen);
__ Bind(GetEntryLabel());
- if (instruction_->CanThrowIntoCatchBlock()) {
- // Live registers will be restored in the catch block if caught.
- SaveLiveRegisters(codegen, instruction_->GetLocations());
- }
mips_codegen->InvokeRuntime(kQuickThrowDivZero, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickThrowDivZero, void, void>();
}
@@ -2141,15 +2137,13 @@
}
void LocationsBuilderMIPS::VisitBoundsCheck(HBoundsCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+ RegisterSet caller_saves = RegisterSet::Empty();
+ InvokeRuntimeCallingConvention calling_convention;
+ caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+ caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction, caller_saves);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
}
void InstructionCodeGeneratorMIPS::VisitBoundsCheck(HBoundsCheck* instruction) {
@@ -2664,14 +2658,8 @@
}
void LocationsBuilderMIPS::VisitDivZeroCheck(HDivZeroCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
}
void InstructionCodeGeneratorMIPS::VisitDivZeroCheck(HDivZeroCheck* instruction) {
@@ -3725,7 +3713,7 @@
void LocationsBuilderMIPS::VisitDeoptimize(HDeoptimize* deoptimize) {
LocationSummary* locations = new (GetGraph()->GetArena())
LocationSummary(deoptimize, LocationSummary::kCallOnSlowPath);
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
if (IsBooleanValueOrMaterializedCondition(deoptimize->InputAt(0))) {
locations->SetInAt(0, Location::RequiresRegister());
}
@@ -5112,7 +5100,8 @@
}
void LocationsBuilderMIPS::VisitNullCheck(HNullCheck* instruction) {
- codegen_->CreateNullCheckLocations(instruction);
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
+ locations->SetInAt(0, Location::RequiresRegister());
}
void CodeGeneratorMIPS::GenerateImplicitNullCheck(HNullCheck* instruction) {
@@ -5406,7 +5395,7 @@
void LocationsBuilderMIPS::VisitSuspendCheck(HSuspendCheck* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
void InstructionCodeGeneratorMIPS::VisitSuspendCheck(HSuspendCheck* instruction) {
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index 557e5da..5039fad 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -150,10 +150,6 @@
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
CodeGeneratorMIPS64* mips64_codegen = down_cast<CodeGeneratorMIPS64*>(codegen);
__ Bind(GetEntryLabel());
- if (instruction_->CanThrowIntoCatchBlock()) {
- // Live registers will be restored in the catch block if caught.
- SaveLiveRegisters(codegen, instruction_->GetLocations());
- }
mips64_codegen->InvokeRuntime(kQuickThrowDivZero, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickThrowDivZero, void, void>();
}
@@ -1558,15 +1554,13 @@
}
void LocationsBuilderMIPS64::VisitBoundsCheck(HBoundsCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+ RegisterSet caller_saves = RegisterSet::Empty();
+ InvokeRuntimeCallingConvention calling_convention;
+ caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+ caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction, caller_saves);
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
}
void InstructionCodeGeneratorMIPS64::VisitBoundsCheck(HBoundsCheck* instruction) {
@@ -2110,14 +2104,8 @@
}
void LocationsBuilderMIPS64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
}
void InstructionCodeGeneratorMIPS64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
@@ -2630,7 +2618,7 @@
void LocationsBuilderMIPS64::VisitDeoptimize(HDeoptimize* deoptimize) {
LocationSummary* locations = new (GetGraph()->GetArena())
LocationSummary(deoptimize, LocationSummary::kCallOnSlowPath);
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
if (IsBooleanValueOrMaterializedCondition(deoptimize->InputAt(0))) {
locations->SetInAt(0, Location::RequiresRegister());
}
@@ -3461,7 +3449,8 @@
}
void LocationsBuilderMIPS64::VisitNullCheck(HNullCheck* instruction) {
- codegen_->CreateNullCheckLocations(instruction);
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
+ locations->SetInAt(0, Location::RequiresRegister());
}
void CodeGeneratorMIPS64::GenerateImplicitNullCheck(HNullCheck* instruction) {
@@ -3741,7 +3730,7 @@
void LocationsBuilderMIPS64::VisitSuspendCheck(HSuspendCheck* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
void InstructionCodeGeneratorMIPS64::VisitSuspendCheck(HSuspendCheck* instruction) {
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 172ce4a..cc9fe83 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -84,10 +84,6 @@
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
CodeGeneratorX86* x86_codegen = down_cast<CodeGeneratorX86*>(codegen);
__ Bind(GetEntryLabel());
- if (instruction_->CanThrowIntoCatchBlock()) {
- // Live registers will be restored in the catch block if caught.
- SaveLiveRegisters(codegen, instruction_->GetLocations());
- }
x86_codegen->InvokeRuntime(kQuickThrowDivZero, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickThrowDivZero, void, void>();
}
@@ -1458,7 +1454,7 @@
void LocationsBuilderX86::VisitDeoptimize(HDeoptimize* deoptimize) {
LocationSummary* locations = new (GetGraph()->GetArena())
LocationSummary(deoptimize, LocationSummary::kCallOnSlowPath);
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
if (IsBooleanValueOrMaterializedCondition(deoptimize->InputAt(0))) {
locations->SetInAt(0, Location::Any());
}
@@ -3548,10 +3544,7 @@
}
void LocationsBuilderX86::VisitDivZeroCheck(HDivZeroCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
switch (instruction->GetType()) {
case Primitive::kPrimBoolean:
case Primitive::kPrimByte:
@@ -3571,9 +3564,6 @@
default:
LOG(FATAL) << "Unexpected type for HDivZeroCheck " << instruction->GetType();
}
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
}
void InstructionCodeGeneratorX86::VisitDivZeroCheck(HDivZeroCheck* instruction) {
@@ -4517,7 +4507,7 @@
LocationSummary::kCallOnSlowPath :
LocationSummary::kNoCall);
if (object_field_get_with_read_barrier && kUseBakerReadBarrier) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::RequiresRegister());
@@ -4927,11 +4917,11 @@
}
void LocationsBuilderX86::VisitNullCheck(HNullCheck* instruction) {
- LocationSummary* locations = codegen_->CreateNullCheckLocations(instruction);
- if (!codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
- // Explicit null checks can use any location.
- locations->SetInAt(0, Location::Any());
- }
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
+ Location loc = codegen_->GetCompilerOptions().GetImplicitNullChecks()
+ ? Location::RequiresRegister()
+ : Location::Any();
+ locations->SetInAt(0, loc);
}
void CodeGeneratorX86::GenerateImplicitNullCheck(HNullCheck* instruction) {
@@ -4978,7 +4968,7 @@
LocationSummary::kCallOnSlowPath :
LocationSummary::kNoCall);
if (object_array_get_with_read_barrier && kUseBakerReadBarrier) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
@@ -5369,18 +5359,16 @@
}
void LocationsBuilderX86::VisitBoundsCheck(HBoundsCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+ RegisterSet caller_saves = RegisterSet::Empty();
+ InvokeRuntimeCallingConvention calling_convention;
+ caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+ caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction, caller_saves);
locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
HInstruction* length = instruction->InputAt(1);
if (!length->IsEmittedAtUseSite()) {
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
}
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
}
void InstructionCodeGeneratorX86::VisitBoundsCheck(HBoundsCheck* instruction) {
@@ -5444,7 +5432,7 @@
void LocationsBuilderX86::VisitSuspendCheck(HSuspendCheck* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
void InstructionCodeGeneratorX86::VisitSuspendCheck(HSuspendCheck* instruction) {
@@ -5802,7 +5790,7 @@
: LocationSummary::kNoCall;
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(cls, call_kind);
if (kUseBakerReadBarrier && requires_read_barrier && !cls->NeedsEnvironment()) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
HLoadClass::LoadKind load_kind = cls->GetLoadKind();
@@ -6099,7 +6087,7 @@
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
if (baker_read_barrier_slow_path) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::Any());
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index 1943ddc..1d87bf6 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -88,10 +88,6 @@
void EmitNativeCode(CodeGenerator* codegen) OVERRIDE {
CodeGeneratorX86_64* x86_64_codegen = down_cast<CodeGeneratorX86_64*>(codegen);
__ Bind(GetEntryLabel());
- if (instruction_->CanThrowIntoCatchBlock()) {
- // Live registers will be restored in the catch block if caught.
- SaveLiveRegisters(codegen, instruction_->GetLocations());
- }
x86_64_codegen->InvokeRuntime(kQuickThrowDivZero, instruction_, instruction_->GetDexPc(), this);
CheckEntrypointTypes<kQuickThrowDivZero, void, void>();
}
@@ -1498,7 +1494,7 @@
void LocationsBuilderX86_64::VisitDeoptimize(HDeoptimize* deoptimize) {
LocationSummary* locations = new (GetGraph()->GetArena())
LocationSummary(deoptimize, LocationSummary::kCallOnSlowPath);
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
if (IsBooleanValueOrMaterializedCondition(deoptimize->InputAt(0))) {
locations->SetInAt(0, Location::Any());
}
@@ -3618,14 +3614,8 @@
}
void LocationsBuilderX86_64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
locations->SetInAt(0, Location::Any());
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
}
void InstructionCodeGeneratorX86_64::VisitDivZeroCheck(HDivZeroCheck* instruction) {
@@ -4021,7 +4011,7 @@
LocationSummary::kCallOnSlowPath :
LocationSummary::kNoCall);
if (object_field_get_with_read_barrier && kUseBakerReadBarrier) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::RequiresRegister());
if (Primitive::IsFloatingPointType(instruction->GetType())) {
@@ -4396,11 +4386,11 @@
}
void LocationsBuilderX86_64::VisitNullCheck(HNullCheck* instruction) {
- LocationSummary* locations = codegen_->CreateNullCheckLocations(instruction);
- if (!codegen_->GetCompilerOptions().GetImplicitNullChecks()) {
- // Explicit null checks can use any location.
- locations->SetInAt(0, Location::Any());
- }
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction);
+ Location loc = codegen_->GetCompilerOptions().GetImplicitNullChecks()
+ ? Location::RequiresRegister()
+ : Location::Any();
+ locations->SetInAt(0, loc);
}
void CodeGeneratorX86_64::GenerateImplicitNullCheck(HNullCheck* instruction) {
@@ -4447,7 +4437,7 @@
LocationSummary::kCallOnSlowPath :
LocationSummary::kNoCall);
if (object_array_get_with_read_barrier && kUseBakerReadBarrier) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
@@ -4818,18 +4808,16 @@
}
void LocationsBuilderX86_64::VisitBoundsCheck(HBoundsCheck* instruction) {
- LocationSummary::CallKind call_kind = instruction->CanThrowIntoCatchBlock()
- ? LocationSummary::kCallOnSlowPath
- : LocationSummary::kNoCall;
- LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
+ RegisterSet caller_saves = RegisterSet::Empty();
+ InvokeRuntimeCallingConvention calling_convention;
+ caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
+ caller_saves.Add(Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
+ LocationSummary* locations = codegen_->CreateThrowingSlowPathLocations(instruction, caller_saves);
locations->SetInAt(0, Location::RegisterOrConstant(instruction->InputAt(0)));
HInstruction* length = instruction->InputAt(1);
if (!length->IsEmittedAtUseSite()) {
locations->SetInAt(1, Location::RegisterOrConstant(length));
}
- if (instruction->HasUses()) {
- locations->SetOut(Location::SameAsFirstInput());
- }
}
void InstructionCodeGeneratorX86_64::VisitBoundsCheck(HBoundsCheck* instruction) {
@@ -4912,7 +4900,7 @@
void LocationsBuilderX86_64::VisitSuspendCheck(HSuspendCheck* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCallOnSlowPath);
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
void InstructionCodeGeneratorX86_64::VisitSuspendCheck(HSuspendCheck* instruction) {
@@ -5213,7 +5201,7 @@
: LocationSummary::kNoCall;
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(cls, call_kind);
if (kUseBakerReadBarrier && requires_read_barrier && !cls->NeedsEnvironment()) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
HLoadClass::LoadKind load_kind = cls->GetLoadKind();
@@ -5488,7 +5476,7 @@
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instruction, call_kind);
if (baker_read_barrier_slow_path) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::Any());
diff --git a/compiler/optimizing/common_arm64.h b/compiler/optimizing/common_arm64.h
index eda0971..776a483 100644
--- a/compiler/optimizing/common_arm64.h
+++ b/compiler/optimizing/common_arm64.h
@@ -273,9 +273,9 @@
// only SP/WSP and ZXR/WZR codes are different between art and vixl.
// Note: This function is only used for debug checks.
inline bool ArtVixlRegCodeCoherentForRegSet(uint32_t art_core_registers,
- size_t num_core,
- uint32_t art_fpu_registers,
- size_t num_fpu) {
+ size_t num_core,
+ uint32_t art_fpu_registers,
+ size_t num_fpu) {
// The register masks won't work if the number of register is larger than 32.
DCHECK_GE(sizeof(art_core_registers) * 8, num_core);
DCHECK_GE(sizeof(art_fpu_registers) * 8, num_fpu);
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc
index 67640a1..fd2da10 100644
--- a/compiler/optimizing/intrinsics_arm.cc
+++ b/compiler/optimizing/intrinsics_arm.cc
@@ -657,7 +657,7 @@
LocationSummary::kNoCall,
kIntrinsified);
if (can_call && kUseBakerReadBarrier) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::NoLocation()); // Unused receiver.
locations->SetInAt(1, Location::RequiresRegister());
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index 082076d..ce58657 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -895,7 +895,7 @@
LocationSummary::kNoCall,
kIntrinsified);
if (can_call && kUseBakerReadBarrier) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::NoLocation()); // Unused receiver.
locations->SetInAt(1, Location::RequiresRegister());
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index d17f85e..e61aba0 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -1977,7 +1977,7 @@
LocationSummary::kNoCall,
kIntrinsified);
if (can_call && kUseBakerReadBarrier) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::NoLocation()); // Unused receiver.
locations->SetInAt(1, Location::RequiresRegister());
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index f8f30d9..0f31fab 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -2110,7 +2110,7 @@
LocationSummary::kNoCall,
kIntrinsified);
if (can_call && kUseBakerReadBarrier) {
- locations->SetCustomSlowPathCallerSaves(RegisterSet()); // No caller-save registers.
+ locations->SetCustomSlowPathCallerSaves(RegisterSet::Empty()); // No caller-save registers.
}
locations->SetInAt(0, Location::NoLocation()); // Unused receiver.
locations->SetInAt(1, Location::RequiresRegister());
diff --git a/compiler/optimizing/locations.cc b/compiler/optimizing/locations.cc
index 1b1b3a7..d157509 100644
--- a/compiler/optimizing/locations.cc
+++ b/compiler/optimizing/locations.cc
@@ -33,8 +33,8 @@
output_overlaps_(Location::kOutputOverlap),
stack_mask_(nullptr),
register_mask_(0),
- live_registers_(),
- custom_slow_path_caller_saves_() {
+ live_registers_(RegisterSet::Empty()),
+ custom_slow_path_caller_saves_(RegisterSet::Empty()) {
instruction->SetLocations(this);
if (NeedsSafepoint()) {
diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h
index c97c4a6..da27928 100644
--- a/compiler/optimizing/locations.h
+++ b/compiler/optimizing/locations.h
@@ -420,7 +420,7 @@
class RegisterSet : public ValueObject {
public:
- RegisterSet() : core_registers_(0), floating_point_registers_(0) {}
+ static RegisterSet Empty() { return RegisterSet(); }
void Add(Location loc) {
if (loc.IsRegister()) {
@@ -465,6 +465,8 @@
}
private:
+ RegisterSet() : core_registers_(0), floating_point_registers_(0) {}
+
uint32_t core_registers_;
uint32_t floating_point_registers_;
};
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index d99d2d6..245653d 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -64,6 +64,8 @@
#include "interpreter/unstarted_runtime.h"
#include "jit/offline_profiling_info.h"
#include "leb128.h"
+#include "linker/buffered_output_stream.h"
+#include "linker/file_output_stream.h"
#include "linker/multi_oat_relative_patcher.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
@@ -1753,6 +1755,28 @@
}
}
+ {
+ TimingLogger::ScopedTiming t2("dex2oat Write VDEX", timings_);
+ DCHECK(IsBootImage() || oat_files_.size() == 1u);
+ DCHECK_EQ(IsBootImage(), verifier_deps_ == nullptr);
+ for (size_t i = 0, size = oat_files_.size(); i != size; ++i) {
+ File* vdex_file = vdex_files_[i].get();
+ std::unique_ptr<BufferedOutputStream> vdex_out(
+ MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(vdex_file)));
+
+ if (!oat_writers_[i]->WriteVerifierDeps(vdex_out.get(), verifier_deps_.get())) {
+ LOG(ERROR) << "Failed to write verifier dependencies into VDEX " << vdex_file->GetPath();
+ return false;
+ }
+
+ // VDEX finalized, seek back to the beginning and write the header.
+ if (!oat_writers_[i]->WriteVdexHeader(vdex_out.get())) {
+ LOG(ERROR) << "Failed to write vdex header into VDEX " << vdex_file->GetPath();
+ return false;
+ }
+ }
+ }
+
linker::MultiOatRelativePatcher patcher(instruction_set_, instruction_set_features_.get());
{
TimingLogger::ScopedTiming t2("dex2oat Write ELF", timings_);
@@ -2604,6 +2628,7 @@
std::vector<std::unique_ptr<ElfWriter>> elf_writers_;
std::vector<std::unique_ptr<OatWriter>> oat_writers_;
std::vector<OutputStream*> rodata_;
+ std::vector<std::unique_ptr<OutputStream>> vdex_out_;
std::unique_ptr<ImageWriter> image_writer_;
std::unique_ptr<CompilerDriver> driver_;
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index 163cb01..c411572 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -18,6 +18,7 @@
srcs: [
"dexlayout_main.cc",
"dexlayout.cc",
+ "dex_ir.cc",
"dex_ir_builder.cc",
],
cflags: ["-Wall"],
diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc
new file mode 100644
index 0000000..aff03cd
--- /dev/null
+++ b/dexlayout/dex_ir.cc
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2016 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.
+ *
+ * Implementation file of the dexlayout utility.
+ *
+ * This is a tool to read dex files into an internal representation,
+ * reorganize the representation, and emit dex files with a better
+ * file layout.
+ */
+
+#include "dex_ir.h"
+#include "dex_ir_builder.h"
+
+namespace art {
+namespace dex_ir {
+
+static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) {
+ uint64_t value = 0;
+ for (uint32_t i = 0; i <= length; i++) {
+ value |= static_cast<uint64_t>(*(*data)++) << (i * 8);
+ }
+ if (sign_extend) {
+ int shift = (7 - length) * 8;
+ return (static_cast<int64_t>(value) << shift) >> shift;
+ }
+ return value;
+}
+
+static bool GetPositionsCb(void* context, const DexFile::PositionInfo& entry) {
+ DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
+ PositionInfoVector& positions = debug_info->GetPositionInfo();
+ positions.push_back(std::unique_ptr<PositionInfo>(new PositionInfo(entry.address_, entry.line_)));
+ return false;
+}
+
+static void GetLocalsCb(void* context, const DexFile::LocalInfo& entry) {
+ DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
+ LocalInfoVector& locals = debug_info->GetLocalInfo();
+ const char* name = entry.name_ != nullptr ? entry.name_ : "(null)";
+ const char* signature = entry.signature_ != nullptr ? entry.signature_ : "";
+ locals.push_back(std::unique_ptr<LocalInfo>(
+ new LocalInfo(name, entry.descriptor_, signature, entry.start_address_,
+ entry.end_address_, entry.reg_)));
+}
+
+EncodedValue* Collections::ReadEncodedValue(const uint8_t** data) {
+ const uint8_t encoded_value = *(*data)++;
+ const uint8_t type = encoded_value & 0x1f;
+ EncodedValue* item = new EncodedValue(type);
+ ReadEncodedValue(data, type, encoded_value >> 5, item);
+ return item;
+}
+
+EncodedValue* Collections::ReadEncodedValue(const uint8_t** data, uint8_t type, uint8_t length) {
+ EncodedValue* item = new EncodedValue(type);
+ ReadEncodedValue(data, type, length, item);
+ return item;
+}
+
+void Collections::ReadEncodedValue(
+ const uint8_t** data, uint8_t type, uint8_t length, EncodedValue* item) {
+ switch (type) {
+ case DexFile::kDexAnnotationByte:
+ item->SetByte(static_cast<int8_t>(ReadVarWidth(data, length, false)));
+ break;
+ case DexFile::kDexAnnotationShort:
+ item->SetShort(static_cast<int16_t>(ReadVarWidth(data, length, true)));
+ break;
+ case DexFile::kDexAnnotationChar:
+ item->SetChar(static_cast<uint16_t>(ReadVarWidth(data, length, false)));
+ break;
+ case DexFile::kDexAnnotationInt:
+ item->SetInt(static_cast<int32_t>(ReadVarWidth(data, length, true)));
+ break;
+ case DexFile::kDexAnnotationLong:
+ item->SetLong(static_cast<int64_t>(ReadVarWidth(data, length, true)));
+ break;
+ case DexFile::kDexAnnotationFloat: {
+ // Fill on right.
+ union {
+ float f;
+ uint32_t data;
+ } conv;
+ conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8;
+ item->SetFloat(conv.f);
+ break;
+ }
+ case DexFile::kDexAnnotationDouble: {
+ // Fill on right.
+ union {
+ double d;
+ uint64_t data;
+ } conv;
+ conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8;
+ item->SetDouble(conv.d);
+ break;
+ }
+ case DexFile::kDexAnnotationString: {
+ const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetStringId(GetStringId(string_index));
+ break;
+ }
+ case DexFile::kDexAnnotationType: {
+ const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetTypeId(GetTypeId(string_index));
+ break;
+ }
+ case DexFile::kDexAnnotationField:
+ case DexFile::kDexAnnotationEnum: {
+ const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetFieldId(GetFieldId(field_index));
+ break;
+ }
+ case DexFile::kDexAnnotationMethod: {
+ const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
+ item->SetMethodId(GetMethodId(method_index));
+ break;
+ }
+ case DexFile::kDexAnnotationArray: {
+ EncodedValueVector* values = new EncodedValueVector();
+ const uint32_t size = DecodeUnsignedLeb128(data);
+ // Decode all elements.
+ for (uint32_t i = 0; i < size; i++) {
+ values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(data)));
+ }
+ item->SetEncodedArray(new EncodedArrayItem(values));
+ break;
+ }
+ case DexFile::kDexAnnotationAnnotation: {
+ AnnotationElementVector* elements = new AnnotationElementVector();
+ const uint32_t type_idx = DecodeUnsignedLeb128(data);
+ const uint32_t size = DecodeUnsignedLeb128(data);
+ // Decode all name=value pairs.
+ for (uint32_t i = 0; i < size; i++) {
+ const uint32_t name_index = DecodeUnsignedLeb128(data);
+ elements->push_back(std::unique_ptr<AnnotationElement>(
+ new AnnotationElement(GetStringId(name_index), ReadEncodedValue(data))));
+ }
+ item->SetEncodedAnnotation(new EncodedAnnotation(GetTypeId(type_idx), elements));
+ break;
+ }
+ case DexFile::kDexAnnotationNull:
+ break;
+ case DexFile::kDexAnnotationBoolean:
+ item->SetBoolean(length != 0);
+ break;
+ default:
+ break;
+ }
+}
+
+void Collections::CreateStringId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::StringId& disk_string_id = dex_file.GetStringId(i);
+ StringData* string_data = new StringData(dex_file.GetStringData(disk_string_id));
+ string_datas_.AddItem(string_data, disk_string_id.string_data_off_);
+
+ StringId* string_id = new StringId(string_data);
+ string_ids_.AddIndexedItem(string_id, StringIdsOffset() + i * StringId::ItemSize(), i);
+}
+
+void Collections::CreateTypeId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(i);
+ TypeId* type_id = new TypeId(GetStringId(disk_type_id.descriptor_idx_));
+ type_ids_.AddIndexedItem(type_id, TypeIdsOffset() + i * TypeId::ItemSize(), i);
+}
+
+void Collections::CreateProtoId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(i);
+ const DexFile::TypeList* type_list = dex_file.GetProtoParameters(disk_proto_id);
+ TypeList* parameter_type_list = CreateTypeList(type_list, disk_proto_id.parameters_off_, true);
+
+ ProtoId* proto_id = new ProtoId(GetStringId(disk_proto_id.shorty_idx_),
+ GetTypeId(disk_proto_id.return_type_idx_),
+ parameter_type_list);
+ proto_ids_.AddIndexedItem(proto_id, ProtoIdsOffset() + i * ProtoId::ItemSize(), i);
+}
+
+void Collections::CreateFieldId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
+ FieldId* field_id = new FieldId(GetTypeId(disk_field_id.class_idx_),
+ GetTypeId(disk_field_id.type_idx_),
+ GetStringId(disk_field_id.name_idx_));
+ field_ids_.AddIndexedItem(field_id, FieldIdsOffset() + i * FieldId::ItemSize(), i);
+}
+
+void Collections::CreateMethodId(const DexFile& dex_file, uint32_t i) {
+ const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
+ MethodId* method_id = new MethodId(GetTypeId(disk_method_id.class_idx_),
+ GetProtoId(disk_method_id.proto_idx_),
+ GetStringId(disk_method_id.name_idx_));
+ method_ids_.AddIndexedItem(method_id, MethodIdsOffset() + i * MethodId::ItemSize(), i);
+}
+
+void Collections::CreateClassDef(const DexFile& dex_file, uint32_t i) {
+ const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i);
+ const TypeId* class_type = GetTypeId(disk_class_def.class_idx_);
+ uint32_t access_flags = disk_class_def.access_flags_;
+ const TypeId* superclass = GetTypeIdOrNullPtr(disk_class_def.superclass_idx_);
+
+ const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
+ TypeList* interfaces_type_list = CreateTypeList(type_list, disk_class_def.interfaces_off_, false);
+
+ const StringId* source_file = GetStringIdOrNullPtr(disk_class_def.source_file_idx_);
+ // Annotations.
+ AnnotationsDirectoryItem* annotations = nullptr;
+ const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
+ dex_file.GetAnnotationsDirectory(disk_class_def);
+ if (disk_annotations_directory_item != nullptr) {
+ annotations = CreateAnnotationsDirectoryItem(
+ dex_file, disk_annotations_directory_item, disk_class_def.annotations_off_);
+ }
+ // Static field initializers.
+ const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def);
+ EncodedArrayItem* static_values =
+ CreateEncodedArrayItem(static_data, disk_class_def.static_values_off_);
+ ClassData* class_data = CreateClassData(
+ dex_file, dex_file.GetClassData(disk_class_def), disk_class_def.class_data_off_);
+ ClassDef* class_def = new ClassDef(class_type, access_flags, superclass, interfaces_type_list,
+ source_file, annotations, static_values, class_data);
+ class_defs_.AddIndexedItem(class_def, ClassDefsOffset() + i * ClassDef::ItemSize(), i);
+}
+
+TypeList* Collections::CreateTypeList(
+ const DexFile::TypeList* dex_type_list, uint32_t offset, bool allow_empty) {
+ if (dex_type_list == nullptr && !allow_empty) {
+ return nullptr;
+ }
+ // TODO: Create more efficient lookup for existing type lists.
+ for (std::unique_ptr<TypeList>& type_list : TypeLists()) {
+ if (type_list->GetOffset() == offset) {
+ return type_list.get();
+ }
+ }
+ TypeIdVector* type_vector = new TypeIdVector();
+ uint32_t size = dex_type_list == nullptr ? 0 : dex_type_list->Size();
+ for (uint32_t index = 0; index < size; ++index) {
+ type_vector->push_back(GetTypeId(dex_type_list->GetTypeItem(index).type_idx_));
+ }
+ TypeList* new_type_list = new TypeList(type_vector);
+ type_lists_.AddItem(new_type_list, offset);
+ return new_type_list;
+}
+
+EncodedArrayItem* Collections::CreateEncodedArrayItem(const uint8_t* static_data, uint32_t offset) {
+ if (static_data == nullptr) {
+ return nullptr;
+ }
+ uint32_t size = DecodeUnsignedLeb128(&static_data);
+ EncodedValueVector* values = new EncodedValueVector();
+ for (uint32_t i = 0; i < size; ++i) {
+ values->push_back(std::unique_ptr<EncodedValue>(ReadEncodedValue(&static_data)));
+ }
+ // TODO: Calculate the size of the encoded array.
+ EncodedArrayItem* encoded_array_item = new EncodedArrayItem(values);
+ encoded_array_items_.AddItem(encoded_array_item, offset);
+ return encoded_array_item;
+}
+
+AnnotationItem* Collections::CreateAnnotationItem(const DexFile::AnnotationItem* annotation,
+ uint32_t offset) {
+ uint8_t visibility = annotation->visibility_;
+ const uint8_t* annotation_data = annotation->annotation_;
+ EncodedValue* encoded_value =
+ ReadEncodedValue(&annotation_data, DexFile::kDexAnnotationAnnotation, 0);
+ // TODO: Calculate the size of the annotation.
+ AnnotationItem* annotation_item =
+ new AnnotationItem(visibility, encoded_value->ReleaseEncodedAnnotation());
+ annotation_items_.AddItem(annotation_item, offset);
+ return annotation_item;
+}
+
+
+AnnotationSetItem* Collections::CreateAnnotationSetItem(const DexFile& dex_file,
+ const DexFile::AnnotationSetItem& disk_annotations_item, uint32_t offset) {
+ if (disk_annotations_item.size_ == 0) {
+ return nullptr;
+ }
+ std::vector<AnnotationItem*>* items = new std::vector<AnnotationItem*>();
+ for (uint32_t i = 0; i < disk_annotations_item.size_; ++i) {
+ const DexFile::AnnotationItem* annotation =
+ dex_file.GetAnnotationItem(&disk_annotations_item, i);
+ if (annotation == nullptr) {
+ continue;
+ }
+ AnnotationItem* annotation_item =
+ CreateAnnotationItem(annotation, disk_annotations_item.entries_[i]);
+ items->push_back(annotation_item);
+ }
+ AnnotationSetItem* annotation_set_item = new AnnotationSetItem(items);
+ annotation_set_items_.AddItem(annotation_set_item, offset);
+ return annotation_set_item;
+}
+
+AnnotationsDirectoryItem* Collections::CreateAnnotationsDirectoryItem(const DexFile& dex_file,
+ const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset) {
+ const DexFile::AnnotationSetItem* class_set_item =
+ dex_file.GetClassAnnotationSet(disk_annotations_item);
+ AnnotationSetItem* class_annotation = nullptr;
+ if (class_set_item != nullptr) {
+ uint32_t offset = disk_annotations_item->class_annotations_off_;
+ class_annotation = CreateAnnotationSetItem(dex_file, *class_set_item, offset);
+ }
+ const DexFile::FieldAnnotationsItem* fields =
+ dex_file.GetFieldAnnotations(disk_annotations_item);
+ FieldAnnotationVector* field_annotations = nullptr;
+ if (fields != nullptr) {
+ field_annotations = new FieldAnnotationVector();
+ for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) {
+ FieldId* field_id = GetFieldId(fields[i].field_idx_);
+ const DexFile::AnnotationSetItem* field_set_item =
+ dex_file.GetFieldAnnotationSetItem(fields[i]);
+ uint32_t annotation_set_offset = fields[i].annotations_off_;
+ AnnotationSetItem* annotation_set_item =
+ CreateAnnotationSetItem(dex_file, *field_set_item, annotation_set_offset);
+ field_annotations->push_back(std::unique_ptr<FieldAnnotation>(
+ new FieldAnnotation(field_id, annotation_set_item)));
+ }
+ }
+ const DexFile::MethodAnnotationsItem* methods =
+ dex_file.GetMethodAnnotations(disk_annotations_item);
+ MethodAnnotationVector* method_annotations = nullptr;
+ if (methods != nullptr) {
+ method_annotations = new MethodAnnotationVector();
+ for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) {
+ MethodId* method_id = GetMethodId(methods[i].method_idx_);
+ const DexFile::AnnotationSetItem* method_set_item =
+ dex_file.GetMethodAnnotationSetItem(methods[i]);
+ uint32_t annotation_set_offset = methods[i].annotations_off_;
+ AnnotationSetItem* annotation_set_item =
+ CreateAnnotationSetItem(dex_file, *method_set_item, annotation_set_offset);
+ method_annotations->push_back(std::unique_ptr<MethodAnnotation>(
+ new MethodAnnotation(method_id, annotation_set_item)));
+ }
+ }
+ const DexFile::ParameterAnnotationsItem* parameters =
+ dex_file.GetParameterAnnotations(disk_annotations_item);
+ ParameterAnnotationVector* parameter_annotations = nullptr;
+ if (parameters != nullptr) {
+ parameter_annotations = new ParameterAnnotationVector();
+ for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) {
+ MethodId* method_id = GetMethodId(parameters[i].method_idx_);
+ const DexFile::AnnotationSetRefList* list =
+ dex_file.GetParameterAnnotationSetRefList(¶meters[i]);
+ parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>(
+ GenerateParameterAnnotation(dex_file, method_id, list, parameters[i].annotations_off_)));
+ }
+ }
+ // TODO: Calculate the size of the annotations directory.
+ AnnotationsDirectoryItem* annotations_directory_item = new AnnotationsDirectoryItem(
+ class_annotation, field_annotations, method_annotations, parameter_annotations);
+ annotations_directory_items_.AddItem(annotations_directory_item, offset);
+ return annotations_directory_item;
+}
+
+ParameterAnnotation* Collections::GenerateParameterAnnotation(
+ const DexFile& dex_file, MethodId* method_id,
+ const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset) {
+ std::vector<AnnotationSetItem*>* annotations = new std::vector<AnnotationSetItem*>();
+ for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
+ const DexFile::AnnotationSetItem* annotation_set_item =
+ dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
+ uint32_t set_offset = annotation_set_ref_list->list_[i].annotations_off_;
+ annotations->push_back(CreateAnnotationSetItem(dex_file, *annotation_set_item, set_offset));
+ }
+ AnnotationSetRefList* new_ref_list = new AnnotationSetRefList(annotations);
+ annotation_set_ref_lists_.AddItem(new_ref_list, offset);
+ return new ParameterAnnotation(method_id, new_ref_list);
+}
+
+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_;
+
+ // TODO: Calculate the size of the debug info.
+ const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(&disk_code_item);
+ DebugInfoItem* debug_info = nullptr;
+ if (debug_info_stream != nullptr) {
+ debug_info = new DebugInfoItem();
+ debug_info_items_.AddItem(debug_info, disk_code_item.debug_info_off_);
+ }
+
+ uint32_t insns_size = disk_code_item.insns_size_in_code_units_;
+ uint16_t* insns = new uint16_t[insns_size];
+ memcpy(insns, disk_code_item.insns_, insns_size * sizeof(uint16_t));
+
+ TryItemVector* tries = nullptr;
+ if (tries_size > 0) {
+ tries = new TryItemVector();
+ 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_;
+ CatchHandlerVector* handlers = new CatchHandlerVector();
+ for (CatchHandlerIterator it(disk_code_item, *disk_try_item); it.HasNext(); it.Next()) {
+ const uint16_t type_index = it.GetHandlerTypeIndex();
+ const TypeId* type_id = GetTypeIdOrNullPtr(type_index);
+ handlers->push_back(std::unique_ptr<const CatchHandler>(
+ new CatchHandler(type_id, it.GetHandlerAddress())));
+ }
+ TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
+ tries->push_back(std::unique_ptr<const TryItem>(try_item));
+ }
+ }
+ // TODO: Calculate the size of the code item.
+ CodeItem* code_item =
+ new CodeItem(registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries);
+ code_items_.AddItem(code_item, offset);
+ return code_item;
+}
+
+MethodItem* Collections::GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii) {
+ MethodId* method_item = GetMethodId(cdii.GetMemberIndex());
+ uint32_t access_flags = cdii.GetRawMemberAccessFlags();
+ const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
+ CodeItem* code_item = nullptr;
+ DebugInfoItem* debug_info = nullptr;
+ if (disk_code_item != nullptr) {
+ code_item = CreateCodeItem(dex_file, *disk_code_item, cdii.GetMethodCodeItemOffset());
+ debug_info = code_item->DebugInfo();
+ }
+ if (debug_info != nullptr) {
+ bool is_static = (access_flags & kAccStatic) != 0;
+ dex_file.DecodeDebugLocalInfo(
+ disk_code_item, is_static, cdii.GetMemberIndex(), GetLocalsCb, debug_info);
+ dex_file.DecodeDebugPositionInfo(disk_code_item, GetPositionsCb, debug_info);
+ }
+ return new MethodItem(access_flags, method_item, code_item);
+}
+
+ClassData* Collections::CreateClassData(
+ const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset) {
+ // Read the fields and methods defined by the class, resolving the circular reference from those
+ // to classes by setting class at the same time.
+ ClassData* class_data = nullptr;
+ if (encoded_data != nullptr) {
+ ClassDataItemIterator cdii(dex_file, encoded_data);
+ // Static fields.
+ FieldItemVector* static_fields = new FieldItemVector();
+ for (uint32_t i = 0; cdii.HasNextStaticField(); i++, cdii.Next()) {
+ FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
+ uint32_t access_flags = cdii.GetRawMemberAccessFlags();
+ static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
+ }
+ // Instance fields.
+ FieldItemVector* instance_fields = new FieldItemVector();
+ for (uint32_t i = 0; cdii.HasNextInstanceField(); i++, cdii.Next()) {
+ FieldId* field_item = GetFieldId(cdii.GetMemberIndex());
+ uint32_t access_flags = cdii.GetRawMemberAccessFlags();
+ instance_fields->push_back(
+ std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
+ }
+ // Direct methods.
+ MethodItemVector* direct_methods = new MethodItemVector();
+ for (uint32_t i = 0; cdii.HasNextDirectMethod(); i++, cdii.Next()) {
+ direct_methods->push_back(
+ std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
+ }
+ // Virtual methods.
+ MethodItemVector* virtual_methods = new MethodItemVector();
+ for (uint32_t i = 0; cdii.HasNextVirtualMethod(); i++, cdii.Next()) {
+ virtual_methods->push_back(
+ std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, cdii)));
+ }
+ // TODO: Calculate the size of the class data.
+ class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods);
+ class_datas_.AddItem(class_data, offset);
+ }
+ return class_data;
+}
+
+} // namespace dex_ir
+} // namespace art
diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h
index cbb4404..6ae9f1c 100644
--- a/dexlayout/dex_ir.h
+++ b/dexlayout/dex_ir.h
@@ -23,18 +23,23 @@
#include <stdint.h>
#include "dex_file-inl.h"
+#include "leb128.h"
namespace art {
namespace dex_ir {
// Forward declarations for classes used in containers or pointed to.
+class AnnotationItem;
class AnnotationsDirectoryItem;
class AnnotationSetItem;
-class ArrayItem;
+class AnnotationSetRefList;
class ClassData;
class ClassDef;
class CodeItem;
class DebugInfoItem;
+class EncodedAnnotation;
+class EncodedArrayItem;
+class EncodedValue;
class FieldId;
class FieldItem;
class Header;
@@ -42,10 +47,22 @@
class MapItem;
class MethodId;
class MethodItem;
+class ParameterAnnotation;
class ProtoId;
+class StringData;
class StringId;
class TryItem;
class TypeId;
+class TypeList;
+
+// Item size constants.
+static constexpr size_t kHeaderItemSize = 112;
+static constexpr size_t kStringIdItemSize = 4;
+static constexpr size_t kTypeIdItemSize = 4;
+static constexpr size_t kProtoIdItemSize = 12;
+static constexpr size_t kFieldIdItemSize = 8;
+static constexpr size_t kMethodIdItemSize = 8;
+static constexpr size_t kClassDefItemSize = 32;
// Visitor support
class AbstractDispatcher {
@@ -54,6 +71,7 @@
virtual ~AbstractDispatcher() { }
virtual void Dispatch(Header* header) = 0;
+ virtual void Dispatch(const StringData* string_data) = 0;
virtual void Dispatch(const StringId* string_id) = 0;
virtual void Dispatch(const TypeId* type_id) = 0;
virtual void Dispatch(const ProtoId* proto_id) = 0;
@@ -63,11 +81,13 @@
virtual void Dispatch(ClassDef* class_def) = 0;
virtual void Dispatch(FieldItem* field_item) = 0;
virtual void Dispatch(MethodItem* method_item) = 0;
- virtual void Dispatch(ArrayItem* array_item) = 0;
+ virtual void Dispatch(EncodedArrayItem* array_item) = 0;
virtual void Dispatch(CodeItem* code_item) = 0;
virtual void Dispatch(TryItem* try_item) = 0;
virtual void Dispatch(DebugInfoItem* debug_info_item) = 0;
+ virtual void Dispatch(AnnotationItem* annotation_item) = 0;
virtual void Dispatch(AnnotationSetItem* annotation_set_item) = 0;
+ virtual void Dispatch(AnnotationSetRefList* annotation_set_ref_list) = 0;
virtual void Dispatch(AnnotationsDirectoryItem* annotations_directory_item) = 0;
virtual void Dispatch(MapList* map_list) = 0;
virtual void Dispatch(MapItem* map_item) = 0;
@@ -82,9 +102,14 @@
CollectionWithOffset() = default;
std::vector<std::unique_ptr<T>>& Collection() { return collection_; }
// Read-time support methods
- void AddWithPosition(uint32_t position, T* object) {
+ void AddItem(T* object, uint32_t offset) {
+ object->SetOffset(offset);
collection_.push_back(std::unique_ptr<T>(object));
- collection_.back()->SetOffset(position);
+ }
+ void AddIndexedItem(T* object, uint32_t offset, uint32_t index) {
+ object->SetOffset(offset);
+ object->SetIndex(index);
+ collection_.push_back(std::unique_ptr<T>(object));
}
// Ordinary object insertion into collection.
void Insert(T object ATTRIBUTE_UNUSED) {
@@ -98,18 +123,160 @@
private:
std::vector<std::unique_ptr<T>> collection_;
uint32_t offset_ = 0;
+
DISALLOW_COPY_AND_ASSIGN(CollectionWithOffset);
};
+class Collections {
+ public:
+ Collections() = default;
+
+ std::vector<std::unique_ptr<StringId>>& StringIds() { return string_ids_.Collection(); }
+ std::vector<std::unique_ptr<TypeId>>& TypeIds() { return type_ids_.Collection(); }
+ std::vector<std::unique_ptr<ProtoId>>& ProtoIds() { return proto_ids_.Collection(); }
+ std::vector<std::unique_ptr<FieldId>>& FieldIds() { return field_ids_.Collection(); }
+ std::vector<std::unique_ptr<MethodId>>& MethodIds() { return method_ids_.Collection(); }
+ std::vector<std::unique_ptr<ClassDef>>& ClassDefs() { return class_defs_.Collection(); }
+
+ std::vector<std::unique_ptr<TypeList>>& TypeLists() { return type_lists_.Collection(); }
+ std::vector<std::unique_ptr<EncodedArrayItem>>& EncodedArrayItems()
+ { return encoded_array_items_.Collection(); }
+
+ void CreateStringId(const DexFile& dex_file, uint32_t i);
+ void CreateTypeId(const DexFile& dex_file, uint32_t i);
+ void CreateProtoId(const DexFile& dex_file, uint32_t i);
+ void CreateFieldId(const DexFile& dex_file, uint32_t i);
+ void CreateMethodId(const DexFile& dex_file, uint32_t i);
+ void CreateClassDef(const DexFile& dex_file, uint32_t i);
+
+ TypeList* CreateTypeList(const DexFile::TypeList* type_list, uint32_t offset, bool allow_empty);
+ EncodedArrayItem* CreateEncodedArrayItem(const uint8_t* static_data, uint32_t offset);
+ AnnotationItem* CreateAnnotationItem(const DexFile::AnnotationItem* annotation, uint32_t offset);
+ AnnotationSetItem* CreateAnnotationSetItem(const DexFile& dex_file,
+ const DexFile::AnnotationSetItem& disk_annotations_item, uint32_t offset);
+ AnnotationsDirectoryItem* CreateAnnotationsDirectoryItem(const DexFile& dex_file,
+ const DexFile::AnnotationsDirectoryItem* disk_annotations_item, uint32_t offset);
+ CodeItem* CreateCodeItem(
+ const DexFile& dex_file, const DexFile::CodeItem& disk_code_item, uint32_t offset);
+ ClassData* CreateClassData(const DexFile& dex_file, const uint8_t* encoded_data, uint32_t offset);
+
+ StringId* GetStringId(uint32_t index) { return StringIds()[index].get(); }
+ TypeId* GetTypeId(uint32_t index) { return TypeIds()[index].get(); }
+ ProtoId* GetProtoId(uint32_t index) { return ProtoIds()[index].get(); }
+ FieldId* GetFieldId(uint32_t index) { return FieldIds()[index].get(); }
+ MethodId* GetMethodId(uint32_t index) { return MethodIds()[index].get(); }
+ ClassDef* GetClassDef(uint32_t index) { return ClassDefs()[index].get(); }
+
+ StringId* GetStringIdOrNullPtr(uint32_t index) {
+ return index == DexFile::kDexNoIndex ? nullptr : GetStringId(index);
+ }
+ TypeId* GetTypeIdOrNullPtr(uint16_t index) {
+ return index == DexFile::kDexNoIndex16 ? nullptr : GetTypeId(index);
+ }
+
+ uint32_t StringIdsOffset() const { return string_ids_.GetOffset(); }
+ uint32_t TypeIdsOffset() const { return type_ids_.GetOffset(); }
+ uint32_t ProtoIdsOffset() const { return proto_ids_.GetOffset(); }
+ uint32_t FieldIdsOffset() const { return field_ids_.GetOffset(); }
+ uint32_t MethodIdsOffset() const { return method_ids_.GetOffset(); }
+ uint32_t ClassDefsOffset() const { return class_defs_.GetOffset(); }
+ uint32_t StringDatasOffset() const { return string_datas_.GetOffset(); }
+ uint32_t TypeListsOffset() const { return type_lists_.GetOffset(); }
+ uint32_t EncodedArrayOffset() const { return encoded_array_items_.GetOffset(); }
+ uint32_t AnnotationOffset() const { return annotation_items_.GetOffset(); }
+ uint32_t AnnotationSetOffset() const { return annotation_set_items_.GetOffset(); }
+ uint32_t AnnotationSetRefListsOffset() const { return annotation_set_ref_lists_.GetOffset(); }
+ uint32_t AnnotationsDirectoryOffset() const { return annotations_directory_items_.GetOffset(); }
+ uint32_t DebugInfoOffset() const { return debug_info_items_.GetOffset(); }
+ uint32_t CodeItemsOffset() const { return code_items_.GetOffset(); }
+ uint32_t ClassDatasOffset() const { return class_datas_.GetOffset(); }
+
+ void SetStringIdsOffset(uint32_t new_offset) { string_ids_.SetOffset(new_offset); }
+ void SetTypeIdsOffset(uint32_t new_offset) { type_ids_.SetOffset(new_offset); }
+ void SetProtoIdsOffset(uint32_t new_offset) { proto_ids_.SetOffset(new_offset); }
+ void SetFieldIdsOffset(uint32_t new_offset) { field_ids_.SetOffset(new_offset); }
+ void SetMethodIdsOffset(uint32_t new_offset) { method_ids_.SetOffset(new_offset); }
+ void SetClassDefsOffset(uint32_t new_offset) { class_defs_.SetOffset(new_offset); }
+ void SetStringDatasOffset(uint32_t new_offset) { string_datas_.SetOffset(new_offset); }
+ void SetTypeListsOffset(uint32_t new_offset) { type_lists_.SetOffset(new_offset); }
+ void SetEncodedArrayOffset(uint32_t new_offset) { encoded_array_items_.SetOffset(new_offset); }
+ void SetAnnotationOffset(uint32_t new_offset) { annotation_items_.SetOffset(new_offset); }
+ void SetAnnotationSetOffset(uint32_t new_offset) { annotation_set_items_.SetOffset(new_offset); }
+ void SetAnnotationSetRefListsOffset(uint32_t new_offset)
+ { annotation_set_ref_lists_.SetOffset(new_offset); }
+ void SetAnnotationsDirectoryOffset(uint32_t new_offset)
+ { annotations_directory_items_.SetOffset(new_offset); }
+ void SetDebugInfoOffset(uint32_t new_offset) { debug_info_items_.SetOffset(new_offset); }
+ void SetCodeItemsOffset(uint32_t new_offset) { code_items_.SetOffset(new_offset); }
+ void SetClassDatasOffset(uint32_t new_offset) { class_datas_.SetOffset(new_offset); }
+
+ uint32_t StringIdsSize() const { return string_ids_.Size(); }
+ uint32_t TypeIdsSize() const { return type_ids_.Size(); }
+ uint32_t ProtoIdsSize() const { return proto_ids_.Size(); }
+ uint32_t FieldIdsSize() const { return field_ids_.Size(); }
+ uint32_t MethodIdsSize() const { return method_ids_.Size(); }
+ uint32_t ClassDefsSize() const { return class_defs_.Size(); }
+
+ private:
+ EncodedValue* ReadEncodedValue(const uint8_t** data);
+ EncodedValue* ReadEncodedValue(const uint8_t** data, uint8_t type, uint8_t length);
+ void ReadEncodedValue(const uint8_t** data, uint8_t type, uint8_t length, EncodedValue* item);
+
+ ParameterAnnotation* GenerateParameterAnnotation(const DexFile& dex_file, MethodId* method_id,
+ const DexFile::AnnotationSetRefList* annotation_set_ref_list, uint32_t offset);
+ MethodItem* GenerateMethodItem(const DexFile& dex_file, ClassDataItemIterator& cdii);
+
+ CollectionWithOffset<StringId> string_ids_;
+ CollectionWithOffset<TypeId> type_ids_;
+ CollectionWithOffset<ProtoId> proto_ids_;
+ CollectionWithOffset<FieldId> field_ids_;
+ CollectionWithOffset<MethodId> method_ids_;
+ CollectionWithOffset<ClassDef> class_defs_;
+
+ CollectionWithOffset<StringData> string_datas_;
+ CollectionWithOffset<TypeList> type_lists_;
+ CollectionWithOffset<EncodedArrayItem> encoded_array_items_;
+ CollectionWithOffset<AnnotationItem> annotation_items_;
+ CollectionWithOffset<AnnotationSetItem> annotation_set_items_;
+ CollectionWithOffset<AnnotationSetRefList> annotation_set_ref_lists_;
+ CollectionWithOffset<AnnotationsDirectoryItem> annotations_directory_items_;
+ CollectionWithOffset<DebugInfoItem> debug_info_items_;
+ CollectionWithOffset<CodeItem> code_items_;
+ CollectionWithOffset<ClassData> class_datas_;
+
+ DISALLOW_COPY_AND_ASSIGN(Collections);
+};
+
class Item {
public:
+ Item() { }
virtual ~Item() { }
uint32_t GetOffset() const { return offset_; }
+ uint32_t GetSize() const { return size_; }
void SetOffset(uint32_t offset) { offset_ = offset; }
+ void SetSize(uint32_t size) { size_ = size; }
protected:
+ Item(uint32_t offset, uint32_t size) : offset_(offset), size_(size) { }
+
uint32_t offset_ = 0;
+ uint32_t size_ = 0;
+};
+
+class IndexedItem : public Item {
+ public:
+ IndexedItem() { }
+ virtual ~IndexedItem() { }
+
+ uint32_t GetIndex() const { return index_; }
+ void SetIndex(uint32_t index) { index_ = index; }
+
+ protected:
+ IndexedItem(uint32_t offset, uint32_t size, uint32_t index)
+ : Item(offset, size), index_(index) { }
+
+ uint32_t index_ = 0;
};
class Header : public Item {
@@ -124,7 +291,8 @@
uint32_t link_offset,
uint32_t data_size,
uint32_t data_offset)
- : checksum_(checksum),
+ : Item(0, kHeaderItemSize),
+ checksum_(checksum),
endian_tag_(endian_tag),
file_size_(file_size),
header_size_(header_size),
@@ -137,6 +305,8 @@
}
~Header() OVERRIDE { }
+ static size_t ItemSize() { return kHeaderItemSize; }
+
const uint8_t* Magic() const { return magic_; }
uint32_t Checksum() const { return checksum_; }
const uint8_t* Signature() const { return signature_; }
@@ -159,39 +329,7 @@
void SetDataSize(uint32_t new_data_size) { data_size_ = new_data_size; }
void SetDataOffset(uint32_t new_data_offset) { data_offset_ = new_data_offset; }
- // Collections.
- std::vector<std::unique_ptr<StringId>>& StringIds() { return string_ids_.Collection(); }
- std::vector<std::unique_ptr<TypeId>>& TypeIds() { return type_ids_.Collection(); }
- std::vector<std::unique_ptr<ProtoId>>& ProtoIds() { return proto_ids_.Collection(); }
- std::vector<std::unique_ptr<FieldId>>& FieldIds() { return field_ids_.Collection(); }
- std::vector<std::unique_ptr<MethodId>>& MethodIds() { return method_ids_.Collection(); }
- std::vector<std::unique_ptr<ClassDef>>& ClassDefs() { return class_defs_.Collection(); }
- uint32_t StringIdsOffset() const { return string_ids_.GetOffset(); }
- uint32_t TypeIdsOffset() const { return type_ids_.GetOffset(); }
- uint32_t ProtoIdsOffset() const { return proto_ids_.GetOffset(); }
- uint32_t FieldIdsOffset() const { return field_ids_.GetOffset(); }
- uint32_t MethodIdsOffset() const { return method_ids_.GetOffset(); }
- uint32_t ClassDefsOffset() const { return class_defs_.GetOffset(); }
- void SetStringIdsOffset(uint32_t new_offset) { string_ids_.SetOffset(new_offset); }
- void SetTypeIdsOffset(uint32_t new_offset) { type_ids_.SetOffset(new_offset); }
- void SetProtoIdsOffset(uint32_t new_offset) { proto_ids_.SetOffset(new_offset); }
- void SetFieldIdsOffset(uint32_t new_offset) { field_ids_.SetOffset(new_offset); }
- void SetMethodIdsOffset(uint32_t new_offset) { method_ids_.SetOffset(new_offset); }
- void SetClassDefsOffset(uint32_t new_offset) { class_defs_.SetOffset(new_offset); }
- uint32_t StringIdsSize() const { return string_ids_.Size(); }
- uint32_t TypeIdsSize() const { return type_ids_.Size(); }
- uint32_t ProtoIdsSize() const { return proto_ids_.Size(); }
- uint32_t FieldIdsSize() const { return field_ids_.Size(); }
- uint32_t MethodIdsSize() const { return method_ids_.Size(); }
- uint32_t ClassDefsSize() const { return class_defs_.Size(); }
-
- TypeId* GetTypeIdOrNullPtr(uint16_t index) {
- return index == DexFile::kDexNoIndex16 ? nullptr : TypeIds()[index].get();
- }
-
- StringId* GetStringIdOrNullPtr(uint32_t index) {
- return index == DexFile::kDexNoIndex ? nullptr : StringIds()[index].get();
- }
+ Collections& GetCollections() { return collections_; }
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
@@ -207,19 +345,16 @@
uint32_t data_size_;
uint32_t data_offset_;
- CollectionWithOffset<StringId> string_ids_;
- CollectionWithOffset<TypeId> type_ids_;
- CollectionWithOffset<ProtoId> proto_ids_;
- CollectionWithOffset<FieldId> field_ids_;
- CollectionWithOffset<MethodId> method_ids_;
- CollectionWithOffset<ClassDef> class_defs_;
+ Collections collections_;
+
DISALLOW_COPY_AND_ASSIGN(Header);
};
-class StringId : public Item {
+class StringData : public Item {
public:
- explicit StringId(const char* data) : data_(strdup(data)) { }
- ~StringId() OVERRIDE { }
+ explicit StringData(const char* data) : data_(strdup(data)) {
+ size_ = UnsignedLeb128Size(strlen(data)) + strlen(data);
+ }
const char* Data() const { return data_.get(); }
@@ -227,50 +362,95 @@
private:
std::unique_ptr<const char> data_;
+
+ DISALLOW_COPY_AND_ASSIGN(StringData);
+};
+
+class StringId : public IndexedItem {
+ public:
+ explicit StringId(StringData* string_data) : string_data_(string_data) {
+ size_ = kStringIdItemSize;
+ }
+ ~StringId() OVERRIDE { }
+
+ static size_t ItemSize() { return kStringIdItemSize; }
+
+ const char* Data() const { return string_data_->Data(); }
+ StringData* DataItem() const { return string_data_; }
+
+ void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }
+
+ private:
+ StringData* string_data_;
+
DISALLOW_COPY_AND_ASSIGN(StringId);
};
-class TypeId : public Item {
+class TypeId : public IndexedItem {
public:
- explicit TypeId(StringId* string_id) : string_id_(string_id) { }
+ explicit TypeId(StringId* string_id) : string_id_(string_id) { size_ = kTypeIdItemSize; }
~TypeId() OVERRIDE { }
+ static size_t ItemSize() { return kTypeIdItemSize; }
+
StringId* GetStringId() const { return string_id_; }
void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }
private:
StringId* string_id_;
+
DISALLOW_COPY_AND_ASSIGN(TypeId);
};
using TypeIdVector = std::vector<const TypeId*>;
-class ProtoId : public Item {
+class TypeList : public Item {
public:
- ProtoId(const StringId* shorty, const TypeId* return_type, TypeIdVector* parameters)
- : shorty_(shorty), return_type_(return_type), parameters_(parameters) { }
+ explicit TypeList(TypeIdVector* type_list) : type_list_(type_list) {
+ size_ = sizeof(uint32_t) + (type_list->size() * sizeof(uint16_t));
+ }
+ ~TypeList() OVERRIDE { }
+
+ const TypeIdVector* GetTypeList() const { return type_list_.get(); }
+
+ private:
+ std::unique_ptr<TypeIdVector> type_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(TypeList);
+};
+
+class ProtoId : public IndexedItem {
+ public:
+ ProtoId(const StringId* shorty, const TypeId* return_type, TypeList* parameters)
+ : shorty_(shorty), return_type_(return_type), parameters_(parameters)
+ { size_ = kProtoIdItemSize; }
~ProtoId() OVERRIDE { }
+ static size_t ItemSize() { return kProtoIdItemSize; }
+
const StringId* Shorty() const { return shorty_; }
const TypeId* ReturnType() const { return return_type_; }
- const std::vector<const TypeId*>& Parameters() const { return *parameters_; }
+ const TypeIdVector& Parameters() const { return *parameters_->GetTypeList(); }
void Accept(AbstractDispatcher* dispatch) const { dispatch->Dispatch(this); }
private:
const StringId* shorty_;
const TypeId* return_type_;
- std::unique_ptr<TypeIdVector> parameters_;
+ TypeList* parameters_;
+
DISALLOW_COPY_AND_ASSIGN(ProtoId);
};
-class FieldId : public Item {
+class FieldId : public IndexedItem {
public:
FieldId(const TypeId* klass, const TypeId* type, const StringId* name)
- : class_(klass), type_(type), name_(name) { }
+ : class_(klass), type_(type), name_(name) { size_ = kFieldIdItemSize; }
~FieldId() OVERRIDE { }
+ static size_t ItemSize() { return kFieldIdItemSize; }
+
const TypeId* Class() const { return class_; }
const TypeId* Type() const { return type_; }
const StringId* Name() const { return name_; }
@@ -281,15 +461,18 @@
const TypeId* class_;
const TypeId* type_;
const StringId* name_;
+
DISALLOW_COPY_AND_ASSIGN(FieldId);
};
-class MethodId : public Item {
+class MethodId : public IndexedItem {
public:
MethodId(const TypeId* klass, const ProtoId* proto, const StringId* name)
- : class_(klass), proto_(proto), name_(name) { }
+ : class_(klass), proto_(proto), name_(name) { size_ = kMethodIdItemSize; }
~MethodId() OVERRIDE { }
+ static size_t ItemSize() { return kMethodIdItemSize; }
+
const TypeId* Class() const { return class_; }
const ProtoId* Proto() const { return proto_; }
const StringId* Name() const { return name_; }
@@ -300,6 +483,7 @@
const TypeId* class_;
const ProtoId* proto_;
const StringId* name_;
+
DISALLOW_COPY_AND_ASSIGN(MethodId);
};
@@ -317,6 +501,7 @@
private:
uint32_t access_flags_;
const FieldId* field_id_;
+
DISALLOW_COPY_AND_ASSIGN(FieldItem);
};
@@ -330,93 +515,126 @@
uint32_t GetAccessFlags() const { return access_flags_; }
const MethodId* GetMethodId() const { return method_id_; }
- const CodeItem* GetCodeItem() const { return code_.get(); }
+ const CodeItem* GetCodeItem() const { return code_; }
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
private:
uint32_t access_flags_;
const MethodId* method_id_;
- std::unique_ptr<const CodeItem> code_;
+ const CodeItem* code_;
+
DISALLOW_COPY_AND_ASSIGN(MethodItem);
};
using MethodItemVector = std::vector<std::unique_ptr<MethodItem>>;
-class ArrayItem : public Item {
+class EncodedValue {
public:
- class NameValuePair {
- public:
- NameValuePair(StringId* name, ArrayItem* value)
- : name_(name), value_(value) { }
-
- StringId* Name() const { return name_; }
- ArrayItem* Value() const { return value_.get(); }
-
- private:
- StringId* name_;
- std::unique_ptr<ArrayItem> value_;
- DISALLOW_COPY_AND_ASSIGN(NameValuePair);
- };
-
- struct ArrayItemVariant {
- public:
- union {
- bool bool_val_;
- int8_t byte_val_;
- int16_t short_val_;
- uint16_t char_val_;
- int32_t int_val_;
- int64_t long_val_;
- float float_val_;
- double double_val_;
- StringId* string_val_;
- FieldId* field_val_;
- MethodId* method_val_;
- } u_;
- std::unique_ptr<std::vector<std::unique_ptr<ArrayItem>>> annotation_array_val_;
- struct {
- StringId* string_;
- std::unique_ptr<std::vector<std::unique_ptr<NameValuePair>>> array_;
- } annotation_annotation_val_;
- };
-
- explicit ArrayItem(uint8_t type) : type_(type) { }
- ~ArrayItem() OVERRIDE { }
+ explicit EncodedValue(uint8_t type) : type_(type) { }
int8_t Type() const { return type_; }
- bool GetBoolean() const { return item_.u_.bool_val_; }
- int8_t GetByte() const { return item_.u_.byte_val_; }
- int16_t GetShort() const { return item_.u_.short_val_; }
- uint16_t GetChar() const { return item_.u_.char_val_; }
- int32_t GetInt() const { return item_.u_.int_val_; }
- int64_t GetLong() const { return item_.u_.long_val_; }
- float GetFloat() const { return item_.u_.float_val_; }
- double GetDouble() const { return item_.u_.double_val_; }
- StringId* GetStringId() const { return item_.u_.string_val_; }
- FieldId* GetFieldId() const { return item_.u_.field_val_; }
- MethodId* GetMethodId() const { return item_.u_.method_val_; }
- std::vector<std::unique_ptr<ArrayItem>>* GetAnnotationArray() const {
- return item_.annotation_array_val_.get();
- }
- StringId* GetAnnotationAnnotationString() const {
- return item_.annotation_annotation_val_.string_;
- }
- std::vector<std::unique_ptr<NameValuePair>>* GetAnnotationAnnotationNameValuePairArray() const {
- return item_.annotation_annotation_val_.array_.get();
- }
- // Used to construct the item union. Ugly, but necessary.
- ArrayItemVariant* GetArrayItemVariant() { return &item_; }
- void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
+ void SetBoolean(bool z) { u_.bool_val_ = z; }
+ void SetByte(int8_t b) { u_.byte_val_ = b; }
+ void SetShort(int16_t s) { u_.short_val_ = s; }
+ void SetChar(uint16_t c) { u_.char_val_ = c; }
+ void SetInt(int32_t i) { u_.int_val_ = i; }
+ void SetLong(int64_t l) { u_.long_val_ = l; }
+ void SetFloat(float f) { u_.float_val_ = f; }
+ void SetDouble(double d) { u_.double_val_ = d; }
+ void SetStringId(StringId* string_id) { u_.string_val_ = string_id; }
+ void SetTypeId(TypeId* type_id) { u_.type_val_ = type_id; }
+ void SetFieldId(FieldId* field_id) { u_.field_val_ = field_id; }
+ void SetMethodId(MethodId* method_id) { u_.method_val_ = method_id; }
+ void SetEncodedArray(EncodedArrayItem* encoded_array) { encoded_array_.reset(encoded_array); }
+ void SetEncodedAnnotation(EncodedAnnotation* encoded_annotation)
+ { encoded_annotation_.reset(encoded_annotation); }
+
+ bool GetBoolean() const { return u_.bool_val_; }
+ int8_t GetByte() const { return u_.byte_val_; }
+ int16_t GetShort() const { return u_.short_val_; }
+ uint16_t GetChar() const { return u_.char_val_; }
+ int32_t GetInt() const { return u_.int_val_; }
+ int64_t GetLong() const { return u_.long_val_; }
+ float GetFloat() const { return u_.float_val_; }
+ double GetDouble() const { return u_.double_val_; }
+ StringId* GetStringId() const { return u_.string_val_; }
+ TypeId* GetTypeId() const { return u_.type_val_; }
+ FieldId* GetFieldId() const { return u_.field_val_; }
+ MethodId* GetMethodId() const { return u_.method_val_; }
+ EncodedArrayItem* GetEncodedArray() const { return encoded_array_.get(); }
+ EncodedAnnotation* GetEncodedAnnotation() const { return encoded_annotation_.get(); }
+
+ EncodedAnnotation* ReleaseEncodedAnnotation() { return encoded_annotation_.release(); }
private:
uint8_t type_;
- ArrayItemVariant item_;
- DISALLOW_COPY_AND_ASSIGN(ArrayItem);
+ union {
+ bool bool_val_;
+ int8_t byte_val_;
+ int16_t short_val_;
+ uint16_t char_val_;
+ int32_t int_val_;
+ int64_t long_val_;
+ float float_val_;
+ double double_val_;
+ StringId* string_val_;
+ TypeId* type_val_;
+ FieldId* field_val_;
+ MethodId* method_val_;
+ } u_;
+ std::unique_ptr<EncodedArrayItem> encoded_array_;
+ std::unique_ptr<EncodedAnnotation> encoded_annotation_;
+
+ DISALLOW_COPY_AND_ASSIGN(EncodedValue);
};
-using ArrayItemVector = std::vector<std::unique_ptr<ArrayItem>>;
+using EncodedValueVector = std::vector<std::unique_ptr<EncodedValue>>;
+
+class AnnotationElement {
+ public:
+ AnnotationElement(StringId* name, EncodedValue* value) : name_(name), value_(value) { }
+
+ StringId* GetName() const { return name_; }
+ EncodedValue* GetValue() const { return value_.get(); }
+
+ private:
+ StringId* name_;
+ std::unique_ptr<EncodedValue> value_;
+
+ DISALLOW_COPY_AND_ASSIGN(AnnotationElement);
+};
+
+using AnnotationElementVector = std::vector<std::unique_ptr<AnnotationElement>>;
+
+class EncodedAnnotation {
+ public:
+ EncodedAnnotation(TypeId* type, AnnotationElementVector* elements)
+ : type_(type), elements_(elements) { }
+
+ TypeId* GetType() const { return type_; }
+ AnnotationElementVector* GetAnnotationElements() const { return elements_.get(); }
+
+ private:
+ TypeId* type_;
+ std::unique_ptr<AnnotationElementVector> elements_;
+
+ DISALLOW_COPY_AND_ASSIGN(EncodedAnnotation);
+};
+
+class EncodedArrayItem : public Item {
+ public:
+ explicit EncodedArrayItem(EncodedValueVector* encoded_values)
+ : encoded_values_(encoded_values) { }
+
+ EncodedValueVector* GetEncodedValues() const { return encoded_values_.get(); }
+
+ private:
+ std::unique_ptr<EncodedValueVector> encoded_values_;
+
+ DISALLOW_COPY_AND_ASSIGN(EncodedArrayItem);
+};
class ClassData : public Item {
public:
@@ -442,42 +660,43 @@
std::unique_ptr<FieldItemVector> instance_fields_;
std::unique_ptr<MethodItemVector> direct_methods_;
std::unique_ptr<MethodItemVector> virtual_methods_;
+
DISALLOW_COPY_AND_ASSIGN(ClassData);
};
-class ClassDef : public Item {
+class ClassDef : public IndexedItem {
public:
ClassDef(const TypeId* class_type,
uint32_t access_flags,
const TypeId* superclass,
- TypeIdVector* interfaces,
- uint32_t interfaces_offset,
+ TypeList* interfaces,
const StringId* source_file,
AnnotationsDirectoryItem* annotations,
- ArrayItemVector* static_values,
+ EncodedArrayItem* static_values,
ClassData* class_data)
: class_type_(class_type),
access_flags_(access_flags),
superclass_(superclass),
interfaces_(interfaces),
- interfaces_offset_(interfaces_offset),
source_file_(source_file),
annotations_(annotations),
static_values_(static_values),
- class_data_(class_data) { }
+ class_data_(class_data) { size_ = kClassDefItemSize; }
~ClassDef() OVERRIDE { }
+ static size_t ItemSize() { return kClassDefItemSize; }
+
const TypeId* ClassType() const { return class_type_; }
uint32_t GetAccessFlags() const { return access_flags_; }
const TypeId* Superclass() const { return superclass_; }
- TypeIdVector* Interfaces() { return interfaces_.get(); }
- uint32_t InterfacesOffset() const { return interfaces_offset_; }
- void SetInterfacesOffset(uint32_t new_offset) { interfaces_offset_ = new_offset; }
+ const TypeIdVector* Interfaces()
+ { return interfaces_ == nullptr ? nullptr: interfaces_->GetTypeList(); }
+ uint32_t InterfacesOffset() { return interfaces_ == nullptr ? 0 : interfaces_->GetOffset(); }
const StringId* SourceFile() const { return source_file_; }
- AnnotationsDirectoryItem* Annotations() const { return annotations_.get(); }
- ArrayItemVector* StaticValues() { return static_values_.get(); }
- ClassData* GetClassData() { return class_data_.get(); }
+ AnnotationsDirectoryItem* Annotations() const { return annotations_; }
+ EncodedArrayItem* StaticValues() { return static_values_; }
+ ClassData* GetClassData() { return class_data_; }
MethodItem* GenerateMethodItem(Header& header, ClassDataItemIterator& cdii);
@@ -487,12 +706,12 @@
const TypeId* class_type_;
uint32_t access_flags_;
const TypeId* superclass_;
- std::unique_ptr<TypeIdVector> interfaces_;
- uint32_t interfaces_offset_;
+ TypeList* interfaces_;
const StringId* source_file_;
- std::unique_ptr<AnnotationsDirectoryItem> annotations_;
- std::unique_ptr<ArrayItemVector> static_values_;
- std::unique_ptr<ClassData> class_data_;
+ AnnotationsDirectoryItem* annotations_;
+ EncodedArrayItem* static_values_;
+ ClassData* class_data_;
+
DISALLOW_COPY_AND_ASSIGN(ClassDef);
};
@@ -506,6 +725,7 @@
private:
const TypeId* type_id_;
uint32_t address_;
+
DISALLOW_COPY_AND_ASSIGN(CatchHandler);
};
@@ -527,6 +747,7 @@
uint32_t start_addr_;
uint16_t insn_count_;
std::unique_ptr<CatchHandlerVector> handlers_;
+
DISALLOW_COPY_AND_ASSIGN(TryItem);
};
@@ -555,7 +776,7 @@
uint16_t InsSize() const { return ins_size_; }
uint16_t OutsSize() const { return outs_size_; }
uint16_t TriesSize() const { return tries_ == nullptr ? 0 : tries_->size(); }
- DebugInfoItem* DebugInfo() const { return debug_info_.get(); }
+ DebugInfoItem* DebugInfo() const { return debug_info_; }
uint32_t InsnsSize() const { return insns_size_; }
uint16_t* Insns() const { return insns_.get(); }
TryItemVector* Tries() const { return tries_.get(); }
@@ -566,14 +787,14 @@
uint16_t registers_size_;
uint16_t ins_size_;
uint16_t outs_size_;
- std::unique_ptr<DebugInfoItem> debug_info_;
+ DebugInfoItem* debug_info_;
uint32_t insns_size_;
std::unique_ptr<uint16_t[]> insns_;
std::unique_ptr<TryItemVector> tries_;
+
DISALLOW_COPY_AND_ASSIGN(CodeItem);
};
-
struct PositionInfo {
PositionInfo(uint32_t address, uint32_t line) : address_(address), line_(line) { }
@@ -617,39 +838,60 @@
private:
PositionInfoVector positions_;
LocalInfoVector locals_;
+
DISALLOW_COPY_AND_ASSIGN(DebugInfoItem);
};
-class AnnotationItem {
+class AnnotationItem : public Item {
public:
- AnnotationItem(uint8_t visibility, ArrayItem* item) : visibility_(visibility), item_(item) { }
+ AnnotationItem(uint8_t visibility, EncodedAnnotation* annotation)
+ : visibility_(visibility), annotation_(annotation) { }
uint8_t GetVisibility() const { return visibility_; }
- ArrayItem* GetItem() const { return item_.get(); }
-
- private:
- uint8_t visibility_;
- std::unique_ptr<ArrayItem> item_;
- DISALLOW_COPY_AND_ASSIGN(AnnotationItem);
-};
-
-using AnnotationItemVector = std::vector<std::unique_ptr<AnnotationItem>>;
-
-class AnnotationSetItem : public Item {
- public:
- explicit AnnotationSetItem(AnnotationItemVector* items) : items_(items) { }
- ~AnnotationSetItem() OVERRIDE { }
-
- AnnotationItemVector* GetItems() { return items_.get(); }
+ EncodedAnnotation* GetAnnotation() const { return annotation_.get(); }
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
private:
- std::unique_ptr<AnnotationItemVector> items_;
+ uint8_t visibility_;
+ std::unique_ptr<EncodedAnnotation> annotation_;
+
+ DISALLOW_COPY_AND_ASSIGN(AnnotationItem);
+};
+
+class AnnotationSetItem : public Item {
+ public:
+ explicit AnnotationSetItem(std::vector<AnnotationItem*>* items) : items_(items) {
+ size_ = sizeof(uint32_t) + items->size() * sizeof(uint32_t);
+ }
+ ~AnnotationSetItem() OVERRIDE { }
+
+ std::vector<AnnotationItem*>* GetItems() { return items_.get(); }
+
+ void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
+
+ private:
+ std::unique_ptr<std::vector<AnnotationItem*>> items_;
+
DISALLOW_COPY_AND_ASSIGN(AnnotationSetItem);
};
-using AnnotationSetItemVector = std::vector<std::unique_ptr<AnnotationSetItem>>;
+class AnnotationSetRefList : public Item {
+ public:
+ explicit AnnotationSetRefList(std::vector<AnnotationSetItem*>* items) : items_(items) {
+ size_ = sizeof(uint32_t) + items->size() * sizeof(uint32_t);
+ }
+ ~AnnotationSetRefList() OVERRIDE { }
+
+ std::vector<AnnotationSetItem*>* GetItems() { return items_.get(); }
+
+ void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
+
+ private:
+ std::unique_ptr<std::vector<AnnotationSetItem*>> items_;
+
+ DISALLOW_COPY_AND_ASSIGN(AnnotationSetRefList);
+};
class FieldAnnotation {
public:
@@ -657,11 +899,12 @@
: field_id_(field_id), annotation_set_item_(annotation_set_item) { }
FieldId* GetFieldId() const { return field_id_; }
- AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_.get(); }
+ AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_; }
private:
FieldId* field_id_;
- std::unique_ptr<AnnotationSetItem> annotation_set_item_;
+ AnnotationSetItem* annotation_set_item_;
+
DISALLOW_COPY_AND_ASSIGN(FieldAnnotation);
};
@@ -673,11 +916,12 @@
: method_id_(method_id), annotation_set_item_(annotation_set_item) { }
MethodId* GetMethodId() const { return method_id_; }
- AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_.get(); }
+ AnnotationSetItem* GetAnnotationSetItem() const { return annotation_set_item_; }
private:
MethodId* method_id_;
- std::unique_ptr<AnnotationSetItem> annotation_set_item_;
+ AnnotationSetItem* annotation_set_item_;
+
DISALLOW_COPY_AND_ASSIGN(MethodAnnotation);
};
@@ -685,15 +929,16 @@
class ParameterAnnotation {
public:
- ParameterAnnotation(MethodId* method_id, AnnotationSetItemVector* annotations)
+ ParameterAnnotation(MethodId* method_id, AnnotationSetRefList* annotations)
: method_id_(method_id), annotations_(annotations) { }
MethodId* GetMethodId() const { return method_id_; }
- AnnotationSetItemVector* GetAnnotations() { return annotations_.get(); }
+ AnnotationSetRefList* GetAnnotations() { return annotations_; }
private:
MethodId* method_id_;
- std::unique_ptr<AnnotationSetItemVector> annotations_;
+ AnnotationSetRefList* annotations_;
+
DISALLOW_COPY_AND_ASSIGN(ParameterAnnotation);
};
@@ -710,7 +955,7 @@
method_annotations_(method_annotations),
parameter_annotations_(parameter_annotations) { }
- AnnotationSetItem* GetClassAnnotation() const { return class_annotation_.get(); }
+ AnnotationSetItem* GetClassAnnotation() const { return class_annotation_; }
FieldAnnotationVector* GetFieldAnnotations() { return field_annotations_.get(); }
MethodAnnotationVector* GetMethodAnnotations() { return method_annotations_.get(); }
ParameterAnnotationVector* GetParameterAnnotations() { return parameter_annotations_.get(); }
@@ -718,10 +963,11 @@
void Accept(AbstractDispatcher* dispatch) { dispatch->Dispatch(this); }
private:
- std::unique_ptr<AnnotationSetItem> class_annotation_;
+ AnnotationSetItem* class_annotation_;
std::unique_ptr<FieldAnnotationVector> field_annotations_;
std::unique_ptr<MethodAnnotationVector> method_annotations_;
std::unique_ptr<ParameterAnnotationVector> parameter_annotations_;
+
DISALLOW_COPY_AND_ASSIGN(AnnotationsDirectoryItem);
};
diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc
index 30f57d9..e6868d7 100644
--- a/dexlayout/dex_ir_builder.cc
+++ b/dexlayout/dex_ir_builder.cc
@@ -24,401 +24,6 @@
namespace art {
namespace dex_ir {
-namespace {
-
-static uint64_t ReadVarWidth(const uint8_t** data, uint8_t length, bool sign_extend) {
- uint64_t value = 0;
- for (uint32_t i = 0; i <= length; i++) {
- value |= static_cast<uint64_t>(*(*data)++) << (i * 8);
- }
- if (sign_extend) {
- int shift = (7 - length) * 8;
- return (static_cast<int64_t>(value) << shift) >> shift;
- }
- return value;
-}
-
-// Prototype to break cyclic dependency.
-void ReadArrayItemVariant(Header& header,
- const uint8_t** data,
- uint8_t type,
- uint8_t length,
- ArrayItem::ArrayItemVariant* item);
-
-ArrayItem* ReadArrayItem(Header& header, const uint8_t** data, uint8_t type, uint8_t length) {
- ArrayItem* item = new ArrayItem(type);
- ReadArrayItemVariant(header, data, type, length, item->GetArrayItemVariant());
- return item;
-}
-
-ArrayItem* ReadArrayItem(Header& header, const uint8_t** data) {
- const uint8_t encoded_value = *(*data)++;
- const uint8_t type = encoded_value & 0x1f;
- ArrayItem* item = new ArrayItem(type);
- ReadArrayItemVariant(header, data, type, encoded_value >> 5, item->GetArrayItemVariant());
- return item;
-}
-
-void ReadArrayItemVariant(Header& header,
- const uint8_t** data,
- uint8_t type,
- uint8_t length,
- ArrayItem::ArrayItemVariant* item) {
- switch (type) {
- case DexFile::kDexAnnotationByte:
- item->u_.byte_val_ = static_cast<int8_t>(ReadVarWidth(data, length, false));
- break;
- case DexFile::kDexAnnotationShort:
- item->u_.short_val_ = static_cast<int16_t>(ReadVarWidth(data, length, true));
- break;
- case DexFile::kDexAnnotationChar:
- item->u_.char_val_ = static_cast<uint16_t>(ReadVarWidth(data, length, false));
- break;
- case DexFile::kDexAnnotationInt:
- item->u_.int_val_ = static_cast<int32_t>(ReadVarWidth(data, length, true));
- break;
- case DexFile::kDexAnnotationLong:
- item->u_.long_val_ = static_cast<int64_t>(ReadVarWidth(data, length, true));
- break;
- case DexFile::kDexAnnotationFloat: {
- // Fill on right.
- union {
- float f;
- uint32_t data;
- } conv;
- conv.data = static_cast<uint32_t>(ReadVarWidth(data, length, false)) << (3 - length) * 8;
- item->u_.float_val_ = conv.f;
- break;
- }
- case DexFile::kDexAnnotationDouble: {
- // Fill on right.
- union {
- double d;
- uint64_t data;
- } conv;
- conv.data = ReadVarWidth(data, length, false) << (7 - length) * 8;
- item->u_.double_val_ = conv.d;
- break;
- }
- case DexFile::kDexAnnotationString: {
- const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
- item->u_.string_val_ = header.StringIds()[string_index].get();
- break;
- }
- case DexFile::kDexAnnotationType: {
- const uint32_t string_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
- item->u_.string_val_ = header.TypeIds()[string_index]->GetStringId();
- break;
- }
- case DexFile::kDexAnnotationField:
- case DexFile::kDexAnnotationEnum: {
- const uint32_t field_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
- item->u_.field_val_ = header.FieldIds()[field_index].get();
- break;
- }
- case DexFile::kDexAnnotationMethod: {
- const uint32_t method_index = static_cast<uint32_t>(ReadVarWidth(data, length, false));
- item->u_.method_val_ = header.MethodIds()[method_index].get();
- break;
- }
- case DexFile::kDexAnnotationArray: {
- item->annotation_array_val_.reset(new ArrayItemVector());
- // Decode all elements.
- const uint32_t size = DecodeUnsignedLeb128(data);
- for (uint32_t i = 0; i < size; i++) {
- item->annotation_array_val_->push_back(
- std::unique_ptr<ArrayItem>(ReadArrayItem(header, data)));
- }
- break;
- }
- case DexFile::kDexAnnotationAnnotation: {
- const uint32_t type_idx = DecodeUnsignedLeb128(data);
- item->annotation_annotation_val_.string_ = header.TypeIds()[type_idx]->GetStringId();
- item->annotation_annotation_val_.array_.reset(
- new std::vector<std::unique_ptr<ArrayItem::NameValuePair>>());
- // Decode all name=value pairs.
- const uint32_t size = DecodeUnsignedLeb128(data);
- for (uint32_t i = 0; i < size; i++) {
- const uint32_t name_index = DecodeUnsignedLeb128(data);
- item->annotation_annotation_val_.array_->push_back(
- std::unique_ptr<ArrayItem::NameValuePair>(
- new ArrayItem::NameValuePair(header.StringIds()[name_index].get(),
- ReadArrayItem(header, data))));
- }
- break;
- }
- case DexFile::kDexAnnotationNull:
- break;
- case DexFile::kDexAnnotationBoolean:
- item->u_.bool_val_ = (length != 0);
- break;
- default:
- break;
- }
-}
-
-static bool GetPositionsCb(void* context, const DexFile::PositionInfo& entry) {
- DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
- PositionInfoVector& positions = debug_info->GetPositionInfo();
- positions.push_back(std::unique_ptr<PositionInfo>(new PositionInfo(entry.address_, entry.line_)));
- return false;
-}
-
-static void GetLocalsCb(void* context, const DexFile::LocalInfo& entry) {
- DebugInfoItem* debug_info = reinterpret_cast<DebugInfoItem*>(context);
- LocalInfoVector& locals = debug_info->GetLocalInfo();
- const char* name = entry.name_ != nullptr ? entry.name_ : "(null)";
- const char* signature = entry.signature_ != nullptr ? entry.signature_ : "";
- locals.push_back(std::unique_ptr<LocalInfo>(
- new LocalInfo(name, entry.descriptor_, signature, entry.start_address_,
- entry.end_address_, entry.reg_)));
-}
-
-CodeItem* ReadCodeItem(const DexFile& dex_file,
- const DexFile::CodeItem& disk_code_item,
- Header& header) {
- 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_;
-
- const uint8_t* debug_info_stream = dex_file.GetDebugInfoStream(&disk_code_item);
- DebugInfoItem* debug_info = nullptr;
- if (debug_info_stream != nullptr) {
- debug_info = new DebugInfoItem();
- }
-
- uint32_t insns_size = disk_code_item.insns_size_in_code_units_;
- uint16_t* insns = new uint16_t[insns_size];
- memcpy(insns, disk_code_item.insns_, insns_size * sizeof(uint16_t));
-
- TryItemVector* tries = nullptr;
- if (tries_size > 0) {
- tries = new TryItemVector();
- 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_;
- CatchHandlerVector* handlers = new CatchHandlerVector();
- for (CatchHandlerIterator it(disk_code_item, *disk_try_item); it.HasNext(); it.Next()) {
- const uint16_t type_index = it.GetHandlerTypeIndex();
- const TypeId* type_id = header.GetTypeIdOrNullPtr(type_index);
- handlers->push_back(std::unique_ptr<const CatchHandler>(
- new CatchHandler(type_id, it.GetHandlerAddress())));
- }
- TryItem* try_item = new TryItem(start_addr, insn_count, handlers);
- tries->push_back(std::unique_ptr<const TryItem>(try_item));
- }
- }
- return new CodeItem(registers_size, ins_size, outs_size, debug_info, insns_size, insns, tries);
-}
-
-MethodItem* GenerateMethodItem(const DexFile& dex_file,
- dex_ir::Header& header,
- ClassDataItemIterator& cdii) {
- MethodId* method_item = header.MethodIds()[cdii.GetMemberIndex()].get();
- uint32_t access_flags = cdii.GetRawMemberAccessFlags();
- const DexFile::CodeItem* disk_code_item = cdii.GetMethodCodeItem();
- CodeItem* code_item = nullptr;
- DebugInfoItem* debug_info = nullptr;
- if (disk_code_item != nullptr) {
- code_item = ReadCodeItem(dex_file, *disk_code_item, header);
- code_item->SetOffset(cdii.GetMethodCodeItemOffset());
- debug_info = code_item->DebugInfo();
- }
- if (debug_info != nullptr) {
- bool is_static = (access_flags & kAccStatic) != 0;
- dex_file.DecodeDebugLocalInfo(
- disk_code_item, is_static, cdii.GetMemberIndex(), GetLocalsCb, debug_info);
- dex_file.DecodeDebugPositionInfo(disk_code_item, GetPositionsCb, debug_info);
- }
- return new MethodItem(access_flags, method_item, code_item);
-}
-
-AnnotationSetItem* ReadAnnotationSetItem(const DexFile& dex_file,
- const DexFile::AnnotationSetItem& disk_annotations_item,
- Header& header) {
- if (disk_annotations_item.size_ == 0) {
- return nullptr;
- }
- AnnotationItemVector* items = new AnnotationItemVector();
- for (uint32_t i = 0; i < disk_annotations_item.size_; ++i) {
- const DexFile::AnnotationItem* annotation =
- dex_file.GetAnnotationItem(&disk_annotations_item, i);
- if (annotation == nullptr) {
- continue;
- }
- uint8_t visibility = annotation->visibility_;
- const uint8_t* annotation_data = annotation->annotation_;
- ArrayItem* array_item =
- ReadArrayItem(header, &annotation_data, DexFile::kDexAnnotationAnnotation, 0);
- items->push_back(std::unique_ptr<AnnotationItem>(new AnnotationItem(visibility, array_item)));
- }
- return new AnnotationSetItem(items);
-}
-
-ParameterAnnotation* ReadParameterAnnotation(
- const DexFile& dex_file,
- MethodId* method_id,
- const DexFile::AnnotationSetRefList* annotation_set_ref_list,
- Header& header) {
- AnnotationSetItemVector* annotations = new AnnotationSetItemVector();
- for (uint32_t i = 0; i < annotation_set_ref_list->size_; ++i) {
- const DexFile::AnnotationSetItem* annotation_set_item =
- dex_file.GetSetRefItemItem(&annotation_set_ref_list->list_[i]);
- annotations->push_back(std::unique_ptr<AnnotationSetItem>(
- ReadAnnotationSetItem(dex_file, *annotation_set_item, header)));
- }
- return new ParameterAnnotation(method_id, annotations);
-}
-
-AnnotationsDirectoryItem* ReadAnnotationsDirectoryItem(
- const DexFile& dex_file,
- const DexFile::AnnotationsDirectoryItem* disk_annotations_item,
- Header& header) {
- const DexFile::AnnotationSetItem* class_set_item =
- dex_file.GetClassAnnotationSet(disk_annotations_item);
- AnnotationSetItem* class_annotation = nullptr;
- if (class_set_item != nullptr) {
- class_annotation = ReadAnnotationSetItem(dex_file, *class_set_item, header);
- }
- const DexFile::FieldAnnotationsItem* fields =
- dex_file.GetFieldAnnotations(disk_annotations_item);
- FieldAnnotationVector* field_annotations = nullptr;
- if (fields != nullptr) {
- field_annotations = new FieldAnnotationVector();
- for (uint32_t i = 0; i < disk_annotations_item->fields_size_; ++i) {
- FieldId* field_id = header.FieldIds()[fields[i].field_idx_].get();
- const DexFile::AnnotationSetItem* field_set_item =
- dex_file.GetFieldAnnotationSetItem(fields[i]);
- AnnotationSetItem* annotation_set_item =
- ReadAnnotationSetItem(dex_file, *field_set_item, header);
- field_annotations->push_back(std::unique_ptr<FieldAnnotation>(
- new FieldAnnotation(field_id, annotation_set_item)));
- }
- }
- const DexFile::MethodAnnotationsItem* methods =
- dex_file.GetMethodAnnotations(disk_annotations_item);
- MethodAnnotationVector* method_annotations = nullptr;
- if (methods != nullptr) {
- method_annotations = new MethodAnnotationVector();
- for (uint32_t i = 0; i < disk_annotations_item->methods_size_; ++i) {
- MethodId* method_id = header.MethodIds()[methods[i].method_idx_].get();
- const DexFile::AnnotationSetItem* method_set_item =
- dex_file.GetMethodAnnotationSetItem(methods[i]);
- AnnotationSetItem* annotation_set_item =
- ReadAnnotationSetItem(dex_file, *method_set_item, header);
- method_annotations->push_back(std::unique_ptr<MethodAnnotation>(
- new MethodAnnotation(method_id, annotation_set_item)));
- }
- }
- const DexFile::ParameterAnnotationsItem* parameters =
- dex_file.GetParameterAnnotations(disk_annotations_item);
- ParameterAnnotationVector* parameter_annotations = nullptr;
- if (parameters != nullptr) {
- parameter_annotations = new ParameterAnnotationVector();
- for (uint32_t i = 0; i < disk_annotations_item->parameters_size_; ++i) {
- MethodId* method_id = header.MethodIds()[parameters[i].method_idx_].get();
- const DexFile::AnnotationSetRefList* list =
- dex_file.GetParameterAnnotationSetRefList(¶meters[i]);
- parameter_annotations->push_back(std::unique_ptr<ParameterAnnotation>(
- ReadParameterAnnotation(dex_file, method_id, list, header)));
- }
- }
-
- return new AnnotationsDirectoryItem(class_annotation,
- field_annotations,
- method_annotations,
- parameter_annotations);
-}
-
-ClassDef* ReadClassDef(const DexFile& dex_file,
- const DexFile::ClassDef& disk_class_def,
- Header& header) {
- const TypeId* class_type = header.TypeIds()[disk_class_def.class_idx_].get();
- uint32_t access_flags = disk_class_def.access_flags_;
- const TypeId* superclass = header.GetTypeIdOrNullPtr(disk_class_def.superclass_idx_);
-
- TypeIdVector* interfaces = nullptr;
- const DexFile::TypeList* type_list = dex_file.GetInterfacesList(disk_class_def);
- uint32_t interfaces_offset = disk_class_def.interfaces_off_;
- if (type_list != nullptr) {
- interfaces = new TypeIdVector();
- for (uint32_t index = 0; index < type_list->Size(); ++index) {
- interfaces->push_back(header.TypeIds()[type_list->GetTypeItem(index).type_idx_].get());
- }
- }
- const StringId* source_file = header.GetStringIdOrNullPtr(disk_class_def.source_file_idx_);
- // Annotations.
- AnnotationsDirectoryItem* annotations = nullptr;
- const DexFile::AnnotationsDirectoryItem* disk_annotations_directory_item =
- dex_file.GetAnnotationsDirectory(disk_class_def);
- if (disk_annotations_directory_item != nullptr) {
- annotations = ReadAnnotationsDirectoryItem(dex_file, disk_annotations_directory_item, header);
- annotations->SetOffset(disk_class_def.annotations_off_);
- }
- // Static field initializers.
- ArrayItemVector* static_values = nullptr;
- const uint8_t* static_data = dex_file.GetEncodedStaticFieldValuesArray(disk_class_def);
- if (static_data != nullptr) {
- uint32_t static_value_count = static_data == nullptr ? 0 : DecodeUnsignedLeb128(&static_data);
- if (static_value_count > 0) {
- static_values = new ArrayItemVector();
- for (uint32_t i = 0; i < static_value_count; ++i) {
- static_values->push_back(std::unique_ptr<ArrayItem>(ReadArrayItem(header, &static_data)));
- }
- }
- }
- // Read the fields and methods defined by the class, resolving the circular reference from those
- // to classes by setting class at the same time.
- const uint8_t* encoded_data = dex_file.GetClassData(disk_class_def);
- ClassData* class_data = nullptr;
- if (encoded_data != nullptr) {
- uint32_t offset = disk_class_def.class_data_off_;
- ClassDataItemIterator cdii(dex_file, encoded_data);
- // Static fields.
- FieldItemVector* static_fields = new FieldItemVector();
- for (uint32_t i = 0; cdii.HasNextStaticField(); i++, cdii.Next()) {
- FieldId* field_item = header.FieldIds()[cdii.GetMemberIndex()].get();
- uint32_t access_flags = cdii.GetRawMemberAccessFlags();
- static_fields->push_back(std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
- }
- // Instance fields.
- FieldItemVector* instance_fields = new FieldItemVector();
- for (uint32_t i = 0; cdii.HasNextInstanceField(); i++, cdii.Next()) {
- FieldId* field_item = header.FieldIds()[cdii.GetMemberIndex()].get();
- uint32_t access_flags = cdii.GetRawMemberAccessFlags();
- instance_fields->push_back(
- std::unique_ptr<FieldItem>(new FieldItem(access_flags, field_item)));
- }
- // Direct methods.
- MethodItemVector* direct_methods = new MethodItemVector();
- for (uint32_t i = 0; cdii.HasNextDirectMethod(); i++, cdii.Next()) {
- direct_methods->push_back(
- std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, header, cdii)));
- }
- // Virtual methods.
- MethodItemVector* virtual_methods = new MethodItemVector();
- for (uint32_t i = 0; cdii.HasNextVirtualMethod(); i++, cdii.Next()) {
- virtual_methods->push_back(
- std::unique_ptr<MethodItem>(GenerateMethodItem(dex_file, header, cdii)));
- }
- class_data = new ClassData(static_fields, instance_fields, direct_methods, virtual_methods);
- class_data->SetOffset(offset);
- }
- return new ClassDef(class_type,
- access_flags,
- superclass,
- interfaces,
- interfaces_offset,
- source_file,
- annotations,
- static_values,
- class_data);
-}
-
-} // namespace
-
Header* DexIrBuilder(const DexFile& dex_file) {
const DexFile::Header& disk_header = dex_file.GetHeader();
Header* header = new Header(disk_header.magic_,
@@ -431,73 +36,37 @@
disk_header.link_off_,
disk_header.data_size_,
disk_header.data_off_);
+ Collections& collections = header->GetCollections();
// Walk the rest of the header fields.
// StringId table.
- std::vector<std::unique_ptr<StringId>>& string_ids = header->StringIds();
- header->SetStringIdsOffset(disk_header.string_ids_off_);
+ collections.SetStringIdsOffset(disk_header.string_ids_off_);
for (uint32_t i = 0; i < dex_file.NumStringIds(); ++i) {
- const DexFile::StringId& disk_string_id = dex_file.GetStringId(i);
- StringId* string_id = new StringId(dex_file.GetStringData(disk_string_id));
- string_id->SetOffset(i);
- string_ids.push_back(std::unique_ptr<StringId>(string_id));
+ collections.CreateStringId(dex_file, i);
}
// TypeId table.
- std::vector<std::unique_ptr<TypeId>>& type_ids = header->TypeIds();
- header->SetTypeIdsOffset(disk_header.type_ids_off_);
+ collections.SetTypeIdsOffset(disk_header.type_ids_off_);
for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
- const DexFile::TypeId& disk_type_id = dex_file.GetTypeId(i);
- TypeId* type_id = new TypeId(header->StringIds()[disk_type_id.descriptor_idx_].get());
- type_id->SetOffset(i);
- type_ids.push_back(std::unique_ptr<TypeId>(type_id));
+ collections.CreateTypeId(dex_file, i);
}
// ProtoId table.
- std::vector<std::unique_ptr<ProtoId>>& proto_ids = header->ProtoIds();
- header->SetProtoIdsOffset(disk_header.proto_ids_off_);
+ collections.SetProtoIdsOffset(disk_header.proto_ids_off_);
for (uint32_t i = 0; i < dex_file.NumProtoIds(); ++i) {
- const DexFile::ProtoId& disk_proto_id = dex_file.GetProtoId(i);
- // Build the parameter type vector.
- TypeIdVector* parameters = new TypeIdVector();
- DexFileParameterIterator dfpi(dex_file, disk_proto_id);
- while (dfpi.HasNext()) {
- parameters->push_back(header->TypeIds()[dfpi.GetTypeIdx()].get());
- dfpi.Next();
- }
- ProtoId* proto_id = new ProtoId(header->StringIds()[disk_proto_id.shorty_idx_].get(),
- header->TypeIds()[disk_proto_id.return_type_idx_].get(),
- parameters);
- proto_id->SetOffset(i);
- proto_ids.push_back(std::unique_ptr<ProtoId>(proto_id));
+ collections.CreateProtoId(dex_file, i);
}
// FieldId table.
- std::vector<std::unique_ptr<FieldId>>& field_ids = header->FieldIds();
- header->SetFieldIdsOffset(disk_header.field_ids_off_);
+ collections.SetFieldIdsOffset(disk_header.field_ids_off_);
for (uint32_t i = 0; i < dex_file.NumFieldIds(); ++i) {
- const DexFile::FieldId& disk_field_id = dex_file.GetFieldId(i);
- FieldId* field_id = new FieldId(header->TypeIds()[disk_field_id.class_idx_].get(),
- header->TypeIds()[disk_field_id.type_idx_].get(),
- header->StringIds()[disk_field_id.name_idx_].get());
- field_id->SetOffset(i);
- field_ids.push_back(std::unique_ptr<FieldId>(field_id));
+ collections.CreateFieldId(dex_file, i);
}
// MethodId table.
- std::vector<std::unique_ptr<MethodId>>& method_ids = header->MethodIds();
- header->SetMethodIdsOffset(disk_header.method_ids_off_);
+ collections.SetMethodIdsOffset(disk_header.method_ids_off_);
for (uint32_t i = 0; i < dex_file.NumMethodIds(); ++i) {
- const DexFile::MethodId& disk_method_id = dex_file.GetMethodId(i);
- MethodId* method_id = new MethodId(header->TypeIds()[disk_method_id.class_idx_].get(),
- header->ProtoIds()[disk_method_id.proto_idx_].get(),
- header->StringIds()[disk_method_id.name_idx_].get());
- method_id->SetOffset(i);
- method_ids.push_back(std::unique_ptr<MethodId>(method_id));
+ collections.CreateMethodId(dex_file, i);
}
// ClassDef table.
- std::vector<std::unique_ptr<ClassDef>>& class_defs = header->ClassDefs();
- header->SetClassDefsOffset(disk_header.class_defs_off_);
+ collections.SetClassDefsOffset(disk_header.class_defs_off_);
for (uint32_t i = 0; i < dex_file.NumClassDefs(); ++i) {
- const DexFile::ClassDef& disk_class_def = dex_file.GetClassDef(i);
- ClassDef* class_def = ReadClassDef(dex_file, disk_class_def, *header);
- class_def->SetOffset(i);
- class_defs.push_back(std::unique_ptr<ClassDef>(class_def));
+ collections.CreateClassDef(dex_file, i);
}
return header;
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 3a3f417..6f34a33 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -30,9 +30,11 @@
#include <sstream>
#include <vector>
+#include "base/unix_file/fd_file.h"
#include "dex_ir_builder.h"
#include "dex_file-inl.h"
#include "dex_instruction-inl.h"
+#include "os.h"
#include "utils.h"
namespace art {
@@ -348,10 +350,26 @@
} // for
}
+// Forward declare to resolve circular dependence.
+static void DumpEncodedValue(const dex_ir::EncodedValue* data);
+
+/*
+ * Dumps encoded annotation.
+ */
+static void DumpEncodedAnnotation(dex_ir::EncodedAnnotation* annotation) {
+ fputs(annotation->GetType()->GetStringId()->Data(), out_file_);
+ // Display all name=value pairs.
+ for (auto& subannotation : *annotation->GetAnnotationElements()) {
+ fputc(' ', out_file_);
+ fputs(subannotation->GetName()->Data(), out_file_);
+ fputc('=', out_file_);
+ DumpEncodedValue(subannotation->GetValue());
+ }
+}
/*
* Dumps encoded value.
*/
-static void DumpEncodedValue(const dex_ir::ArrayItem* data) {
+static void DumpEncodedValue(const dex_ir::EncodedValue* data) {
switch (data->Type()) {
case DexFile::kDexAnnotationByte:
fprintf(out_file_, "%" PRId8, data->GetByte());
@@ -386,8 +404,8 @@
break;
}
case DexFile::kDexAnnotationType: {
- dex_ir::StringId* string_id = data->GetStringId();
- fputs(string_id->Data(), out_file_);
+ dex_ir::TypeId* type_id = data->GetTypeId();
+ fputs(type_id->GetStringId()->Data(), out_file_);
break;
}
case DexFile::kDexAnnotationField:
@@ -404,22 +422,15 @@
case DexFile::kDexAnnotationArray: {
fputc('{', out_file_);
// Display all elements.
- for (auto& array : *data->GetAnnotationArray()) {
+ for (auto& value : *data->GetEncodedArray()->GetEncodedValues()) {
fputc(' ', out_file_);
- DumpEncodedValue(array.get());
+ DumpEncodedValue(value.get());
}
fputs(" }", out_file_);
break;
}
case DexFile::kDexAnnotationAnnotation: {
- fputs(data->GetAnnotationAnnotationString()->Data(), out_file_);
- // Display all name=value pairs.
- for (auto& subannotation : *data->GetAnnotationAnnotationNameValuePairArray()) {
- fputc(' ', out_file_);
- fputs(subannotation->Name()->Data(), out_file_);
- fputc('=', out_file_);
- DumpEncodedValue(subannotation->Value());
- }
+ DumpEncodedAnnotation(data->GetEncodedAnnotation());
break;
}
case DexFile::kDexAnnotationNull:
@@ -437,8 +448,9 @@
/*
* Dumps the file header.
*/
-static void DumpFileHeader(const dex_ir::Header* header) {
+static void DumpFileHeader(dex_ir::Header* header) {
char sanitized[8 * 2 + 1];
+ dex_ir::Collections& collections = header->GetCollections();
fprintf(out_file_, "DEX file header:\n");
Asciify(sanitized, header->Magic(), 8);
fprintf(out_file_, "magic : '%s'\n", sanitized);
@@ -452,24 +464,24 @@
fprintf(out_file_, "link_size : %d\n", header->LinkSize());
fprintf(out_file_, "link_off : %d (0x%06x)\n",
header->LinkOffset(), header->LinkOffset());
- fprintf(out_file_, "string_ids_size : %d\n", header->StringIdsSize());
+ fprintf(out_file_, "string_ids_size : %d\n", collections.StringIdsSize());
fprintf(out_file_, "string_ids_off : %d (0x%06x)\n",
- header->StringIdsOffset(), header->StringIdsOffset());
- fprintf(out_file_, "type_ids_size : %d\n", header->TypeIdsSize());
+ collections.StringIdsOffset(), collections.StringIdsOffset());
+ fprintf(out_file_, "type_ids_size : %d\n", collections.TypeIdsSize());
fprintf(out_file_, "type_ids_off : %d (0x%06x)\n",
- header->TypeIdsOffset(), header->TypeIdsOffset());
- fprintf(out_file_, "proto_ids_size : %d\n", header->ProtoIdsSize());
+ collections.TypeIdsOffset(), collections.TypeIdsOffset());
+ fprintf(out_file_, "proto_ids_size : %d\n", collections.ProtoIdsSize());
fprintf(out_file_, "proto_ids_off : %d (0x%06x)\n",
- header->ProtoIdsOffset(), header->ProtoIdsOffset());
- fprintf(out_file_, "field_ids_size : %d\n", header->FieldIdsSize());
+ collections.ProtoIdsOffset(), collections.ProtoIdsOffset());
+ fprintf(out_file_, "field_ids_size : %d\n", collections.FieldIdsSize());
fprintf(out_file_, "field_ids_off : %d (0x%06x)\n",
- header->FieldIdsOffset(), header->FieldIdsOffset());
- fprintf(out_file_, "method_ids_size : %d\n", header->MethodIdsSize());
+ collections.FieldIdsOffset(), collections.FieldIdsOffset());
+ fprintf(out_file_, "method_ids_size : %d\n", collections.MethodIdsSize());
fprintf(out_file_, "method_ids_off : %d (0x%06x)\n",
- header->MethodIdsOffset(), header->MethodIdsOffset());
- fprintf(out_file_, "class_defs_size : %d\n", header->ClassDefsSize());
+ collections.MethodIdsOffset(), collections.MethodIdsOffset());
+ fprintf(out_file_, "class_defs_size : %d\n", collections.ClassDefsSize());
fprintf(out_file_, "class_defs_off : %d (0x%06x)\n",
- header->ClassDefsOffset(), header->ClassDefsOffset());
+ collections.ClassDefsOffset(), collections.ClassDefsOffset());
fprintf(out_file_, "data_size : %d\n", header->DataSize());
fprintf(out_file_, "data_off : %d (0x%06x)\n\n",
header->DataOffset(), header->DataOffset());
@@ -480,19 +492,19 @@
*/
static void DumpClassDef(dex_ir::Header* header, int idx) {
// General class information.
- dex_ir::ClassDef* class_def = header->ClassDefs()[idx].get();
+ dex_ir::ClassDef* class_def = header->GetCollections().GetClassDef(idx);
fprintf(out_file_, "Class #%d header:\n", idx);
- fprintf(out_file_, "class_idx : %d\n", class_def->ClassType()->GetOffset());
+ fprintf(out_file_, "class_idx : %d\n", class_def->ClassType()->GetIndex());
fprintf(out_file_, "access_flags : %d (0x%04x)\n",
class_def->GetAccessFlags(), class_def->GetAccessFlags());
uint32_t superclass_idx = class_def->Superclass() == nullptr ?
- DexFile::kDexNoIndex16 : class_def->Superclass()->GetOffset();
+ DexFile::kDexNoIndex16 : class_def->Superclass()->GetIndex();
fprintf(out_file_, "superclass_idx : %d\n", superclass_idx);
fprintf(out_file_, "interfaces_off : %d (0x%06x)\n",
class_def->InterfacesOffset(), class_def->InterfacesOffset());
uint32_t source_file_offset = 0xffffffffU;
if (class_def->SourceFile() != nullptr) {
- source_file_offset = class_def->SourceFile()->GetOffset();
+ source_file_offset = class_def->SourceFile()->GetIndex();
}
fprintf(out_file_, "source_file_idx : %d\n", source_file_offset);
uint32_t annotations_offset = 0;
@@ -541,7 +553,7 @@
fputs(" empty-annotation-set\n", out_file_);
return;
}
- for (std::unique_ptr<dex_ir::AnnotationItem>& annotation : *set_item->GetItems()) {
+ for (dex_ir::AnnotationItem* annotation : *set_item->GetItems()) {
if (annotation == nullptr) {
continue;
}
@@ -552,10 +564,7 @@
case DexFile::kDexVisibilitySystem: fputs("VISIBILITY_SYSTEM ", out_file_); break;
default: fputs("VISIBILITY_UNKNOWN ", out_file_); break;
} // switch
- // Decode raw bytes in annotation.
- // const uint8_t* rData = annotation->annotation_;
- dex_ir::ArrayItem* data = annotation->GetItem();
- DumpEncodedValue(data);
+ DumpEncodedAnnotation(annotation->GetAnnotation());
fputc('\n', out_file_);
}
}
@@ -564,7 +573,7 @@
* Dumps class annotations.
*/
static void DumpClassAnnotations(dex_ir::Header* header, int idx) {
- dex_ir::ClassDef* class_def = header->ClassDefs()[idx].get();
+ dex_ir::ClassDef* class_def = header->GetCollections().GetClassDef(idx);
dex_ir::AnnotationsDirectoryItem* annotations_directory = class_def->Annotations();
if (annotations_directory == nullptr) {
return; // none
@@ -587,7 +596,7 @@
if (fields != nullptr) {
for (auto& field : *fields) {
const dex_ir::FieldId* field_id = field->GetFieldId();
- const uint32_t field_idx = field_id->GetOffset();
+ const uint32_t field_idx = field_id->GetIndex();
const char* field_name = field_id->Name()->Data();
fprintf(out_file_, "Annotations on field #%u '%s'\n", field_idx, field_name);
DumpAnnotationSetItem(field->GetAnnotationSetItem());
@@ -598,7 +607,7 @@
if (methods != nullptr) {
for (auto& method : *methods) {
const dex_ir::MethodId* method_id = method->GetMethodId();
- const uint32_t method_idx = method_id->GetOffset();
+ const uint32_t method_idx = method_id->GetIndex();
const char* method_name = method_id->Name()->Data();
fprintf(out_file_, "Annotations on method #%u '%s'\n", method_idx, method_name);
DumpAnnotationSetItem(method->GetAnnotationSetItem());
@@ -609,13 +618,13 @@
if (parameters != nullptr) {
for (auto& parameter : *parameters) {
const dex_ir::MethodId* method_id = parameter->GetMethodId();
- const uint32_t method_idx = method_id->GetOffset();
+ const uint32_t method_idx = method_id->GetIndex();
const char* method_name = method_id->Name()->Data();
fprintf(out_file_, "Annotations on method #%u '%s' parameters\n", method_idx, method_name);
uint32_t j = 0;
- for (auto& annotation : *parameter->GetAnnotations()) {
+ for (dex_ir::AnnotationSetItem* annotation : *parameter->GetAnnotations()->GetItems()) {
fprintf(out_file_, "#%u\n", j);
- DumpAnnotationSetItem(annotation.get());
+ DumpAnnotationSetItem(annotation);
++j;
}
}
@@ -748,24 +757,24 @@
outSize = snprintf(buf.get(), buf_size, "<no-index>");
break;
case Instruction::kIndexTypeRef:
- if (index < header->TypeIdsSize()) {
- const char* tp = header->TypeIds()[index]->GetStringId()->Data();
+ if (index < header->GetCollections().TypeIdsSize()) {
+ const char* tp = header->GetCollections().GetTypeId(index)->GetStringId()->Data();
outSize = snprintf(buf.get(), buf_size, "%s // type@%0*x", tp, width, index);
} else {
outSize = snprintf(buf.get(), buf_size, "<type?> // type@%0*x", width, index);
}
break;
case Instruction::kIndexStringRef:
- if (index < header->StringIdsSize()) {
- const char* st = header->StringIds()[index]->Data();
+ if (index < header->GetCollections().StringIdsSize()) {
+ const char* st = header->GetCollections().GetStringId(index)->Data();
outSize = snprintf(buf.get(), buf_size, "\"%s\" // string@%0*x", st, width, index);
} else {
outSize = snprintf(buf.get(), buf_size, "<string?> // string@%0*x", width, index);
}
break;
case Instruction::kIndexMethodRef:
- if (index < header->MethodIdsSize()) {
- dex_ir::MethodId* method_id = header->MethodIds()[index].get();
+ if (index < header->GetCollections().MethodIdsSize()) {
+ dex_ir::MethodId* method_id = header->GetCollections().GetMethodId(index);
const char* name = method_id->Name()->Data();
std::string type_descriptor = GetSignatureForProtoId(method_id->Proto());
const char* back_descriptor = method_id->Class()->GetStringId()->Data();
@@ -776,8 +785,8 @@
}
break;
case Instruction::kIndexFieldRef:
- if (index < header->FieldIdsSize()) {
- dex_ir::FieldId* field_id = header->FieldIds()[index].get();
+ if (index < header->GetCollections().FieldIdsSize()) {
+ dex_ir::FieldId* field_id = header->GetCollections().GetFieldId(index);
const char* name = field_id->Name()->Data();
const char* type_descriptor = field_id->Type()->GetStringId()->Data();
const char* back_descriptor = field_id->Class()->GetStringId()->Data();
@@ -1028,7 +1037,7 @@
*/
static void DumpBytecodes(dex_ir::Header* header, uint32_t idx,
const dex_ir::CodeItem* code, uint32_t code_offset) {
- dex_ir::MethodId* method_id = header->MethodIds()[idx].get();
+ dex_ir::MethodId* method_id = header->GetCollections().GetMethodId(idx);
const char* name = method_id->Name()->Data();
std::string type_descriptor = GetSignatureForProtoId(method_id->Proto());
const char* back_descriptor = method_id->Class()->GetStringId()->Data();
@@ -1088,7 +1097,7 @@
return;
}
- dex_ir::MethodId* method_id = header->MethodIds()[idx].get();
+ dex_ir::MethodId* method_id = header->GetCollections().GetMethodId(idx);
const char* name = method_id->Name()->Data();
char* type_descriptor = strdup(GetSignatureForProtoId(method_id->Proto()).c_str());
const char* back_descriptor = method_id->Class()->GetStringId()->Data();
@@ -1187,13 +1196,13 @@
* Dumps a static (class) field.
*/
static void DumpSField(dex_ir::Header* header, uint32_t idx, uint32_t flags,
- int i, dex_ir::ArrayItem* init) {
+ int i, dex_ir::EncodedValue* init) {
// Bail for anything private if export only requested.
if (options_.exports_only_ && (flags & (kAccPublic | kAccProtected)) == 0) {
return;
}
- dex_ir::FieldId* field_id = header->FieldIds()[idx].get();
+ dex_ir::FieldId* field_id = header->GetCollections().GetFieldId(idx);
const char* name = field_id->Name()->Data();
const char* type_descriptor = field_id->Type()->GetStringId()->Data();
const char* back_descriptor = field_id->Class()->GetStringId()->Data();
@@ -1293,7 +1302,7 @@
dex_ir::Header* header,
int idx,
char** last_package) {
- dex_ir::ClassDef* class_def = header->ClassDefs()[idx].get();
+ dex_ir::ClassDef* class_def = header->GetCollections().GetClassDef(idx);
// Omitting non-public class.
if (options_.exports_only_ && (class_def->GetAccessFlags() & kAccPublic) == 0) {
return;
@@ -1316,7 +1325,8 @@
// up the classes, sort them, and dump them alphabetically so the
// package name wouldn't jump around, but that's not a great plan
// for something that needs to run on the device.
- const char* class_descriptor = header->ClassDefs()[idx]->ClassType()->GetStringId()->Data();
+ const char* class_descriptor =
+ header->GetCollections().GetClassDef(idx)->ClassType()->GetStringId()->Data();
if (!(class_descriptor[0] == 'L' &&
class_descriptor[strlen(class_descriptor)-1] == ';')) {
// Arrays and primitives should not be defined explicitly. Keep going?
@@ -1386,7 +1396,7 @@
}
// Interfaces.
- dex_ir::TypeIdVector* interfaces = class_def->Interfaces();
+ const dex_ir::TypeIdVector* interfaces = class_def->Interfaces();
if (interfaces != nullptr) {
for (uint32_t i = 0; i < interfaces->size(); i++) {
DumpInterface((*interfaces)[i], i);
@@ -1396,8 +1406,10 @@
// Fields and methods.
dex_ir::ClassData* class_data = class_def->GetClassData();
// Prepare data for static fields.
- std::vector<std::unique_ptr<dex_ir::ArrayItem>>* static_values = class_def->StaticValues();
- const uint32_t static_values_size = (static_values == nullptr) ? 0 : static_values->size();
+ dex_ir::EncodedArrayItem* static_values = class_def->StaticValues();
+ dex_ir::EncodedValueVector* encoded_values =
+ static_values == nullptr ? nullptr : static_values->GetEncodedValues();
+ const uint32_t encoded_values_size = (encoded_values == nullptr) ? 0 : encoded_values->size();
// Static fields.
if (options_.output_format_ == kOutputPlain) {
@@ -1408,10 +1420,10 @@
if (static_fields != nullptr) {
for (uint32_t i = 0; i < static_fields->size(); i++) {
DumpSField(header,
- (*static_fields)[i]->GetFieldId()->GetOffset(),
+ (*static_fields)[i]->GetFieldId()->GetIndex(),
(*static_fields)[i]->GetAccessFlags(),
i,
- i < static_values_size ? (*static_values)[i].get() : nullptr);
+ i < encoded_values_size ? (*encoded_values)[i].get() : nullptr);
} // for
}
}
@@ -1425,7 +1437,7 @@
if (instance_fields != nullptr) {
for (uint32_t i = 0; i < instance_fields->size(); i++) {
DumpIField(header,
- (*instance_fields)[i]->GetFieldId()->GetOffset(),
+ (*instance_fields)[i]->GetFieldId()->GetIndex(),
(*instance_fields)[i]->GetAccessFlags(),
i);
} // for
@@ -1441,7 +1453,7 @@
if (direct_methods != nullptr) {
for (uint32_t i = 0; i < direct_methods->size(); i++) {
DumpMethod(header,
- (*direct_methods)[i]->GetMethodId()->GetOffset(),
+ (*direct_methods)[i]->GetMethodId()->GetIndex(),
(*direct_methods)[i]->GetAccessFlags(),
(*direct_methods)[i]->GetCodeItem(),
i);
@@ -1458,7 +1470,7 @@
if (virtual_methods != nullptr) {
for (uint32_t i = 0; i < virtual_methods->size(); i++) {
DumpMethod(header,
- (*virtual_methods)[i]->GetMethodId()->GetOffset(),
+ (*virtual_methods)[i]->GetMethodId()->GetIndex(),
(*virtual_methods)[i]->GetAccessFlags(),
(*virtual_methods)[i]->GetCodeItem(),
i);
@@ -1474,7 +1486,7 @@
}
const dex_ir::StringId* source_file = class_def->SourceFile();
fprintf(out_file_, " source_file_idx : %d (%s)\n\n",
- source_file == nullptr ? 0xffffffffU : source_file->GetOffset(), file_name);
+ source_file == nullptr ? 0xffffffffU : source_file->GetIndex(), file_name);
} else if (options_.output_format_ == kOutputXml) {
fprintf(out_file_, "</class>\n");
}
@@ -1483,6 +1495,96 @@
}
/*
+static uint32_t GetDataSectionOffset(dex_ir::Header& header) {
+ return dex_ir::Header::ItemSize() +
+ header.GetCollections().StringIdsSize() * dex_ir::StringId::ItemSize() +
+ header.GetCollections().TypeIdsSize() * dex_ir::TypeId::ItemSize() +
+ header.GetCollections().ProtoIdsSize() * dex_ir::ProtoId::ItemSize() +
+ header.GetCollections().FieldIdsSize() * dex_ir::FieldId::ItemSize() +
+ header.GetCollections().MethodIdsSize() * dex_ir::MethodId::ItemSize() +
+ header.GetCollections().ClassDefsSize() * dex_ir::ClassDef::ItemSize();
+}
+
+static bool Align(File* file, uint32_t& offset) {
+ uint8_t zero_buffer[] = { 0, 0, 0 };
+ uint32_t zeroes = (-offset) & 3;
+ if (zeroes > 0) {
+ if (!file->PwriteFully(zero_buffer, zeroes, offset)) {
+ return false;
+ }
+ offset += zeroes;
+ }
+ return true;
+}
+
+static bool WriteStrings(File* dex_file, dex_ir::Header& header,
+ uint32_t& index_offset, uint32_t& data_offset) {
+ uint32_t index = 0;
+ uint32_t index_buffer[1];
+ uint32_t string_length;
+ uint32_t length_length;
+ uint8_t length_buffer[8];
+ for (std::unique_ptr<dex_ir::StringId>& string_id : header.GetCollections().StringIds()) {
+ string_id->SetOffset(index);
+ index_buffer[0] = data_offset;
+ string_length = strlen(string_id->Data());
+ length_length = UnsignedLeb128Size(string_length);
+ EncodeUnsignedLeb128(length_buffer, string_length);
+
+ if (!dex_file->PwriteFully(index_buffer, 4, index_offset) ||
+ !dex_file->PwriteFully(length_buffer, length_length, data_offset) ||
+ !dex_file->PwriteFully(string_id->Data(), string_length, data_offset + length_length)) {
+ return false;
+ }
+
+ index++;
+ index_offset += 4;
+ data_offset += string_length + length_length;
+ }
+ return true;
+}
+
+static bool WriteTypes(File* dex_file, dex_ir::Header& header, uint32_t& index_offset) {
+ uint32_t index = 0;
+ uint32_t index_buffer[1];
+ for (std::unique_ptr<dex_ir::TypeId>& type_id : header.GetCollections().TypeIds()) {
+ type_id->SetIndex(index);
+ index_buffer[0] = type_id->GetStringId()->GetOffset();
+
+ if (!dex_file->PwriteFully(index_buffer, 4, index_offset)) {
+ return false;
+ }
+
+ index++;
+ index_offset += 4;
+ }
+ return true;
+}
+
+static bool WriteTypeLists(File* dex_file, dex_ir::Header& header, uint32_t& data_offset) {
+ if (!Align(dex_file, data_offset)) {
+ return false;
+ }
+
+ return true;
+}
+
+static void OutputDexFile(dex_ir::Header& header, const char* file_name) {
+ LOG(INFO) << "FILE NAME: " << file_name;
+ std::unique_ptr<File> dex_file(OS::CreateEmptyFileWriteOnly(file_name));
+ if (dex_file == nullptr) {
+ fprintf(stderr, "Can't open %s\n", file_name);
+ return;
+ }
+
+ uint32_t index_offset = dex_ir::Header::ItemSize();
+ uint32_t data_offset = GetDataSectionOffset(header);
+ WriteStrings(dex_file.get(), header, index_offset, data_offset);
+ WriteTypes(dex_file.get(), header, index_offset);
+}
+*/
+
+/*
* Dumps the requested sections of the file.
*/
static void ProcessDexFile(const char* file_name, const DexFile* dex_file) {
@@ -1504,7 +1606,7 @@
// Iterate over all classes.
char* package = nullptr;
- const uint32_t class_defs_size = header->ClassDefsSize();
+ const uint32_t class_defs_size = header->GetCollections().ClassDefsSize();
for (uint32_t i = 0; i < class_defs_size; i++) {
DumpClass(dex_file, header.get(), i, &package);
} // for
@@ -1519,6 +1621,14 @@
if (options_.output_format_ == kOutputXml) {
fprintf(out_file_, "</api>\n");
}
+
+ /*
+ // Output dex file.
+ if (options_.output_dex_files_) {
+ std::string output_dex_filename = dex_file->GetLocation() + ".out";
+ OutputDexFile(*header, output_dex_filename.c_str());
+ }
+ */
}
/*
diff --git a/dexlayout/dexlayout.h b/dexlayout/dexlayout.h
index bae587d..736d230 100644
--- a/dexlayout/dexlayout.h
+++ b/dexlayout/dexlayout.h
@@ -41,6 +41,7 @@
bool disassemble_;
bool exports_only_;
bool ignore_bad_checksum_;
+ bool output_dex_files_;
bool show_annotations_;
bool show_cfg_;
bool show_file_headers_;
diff --git a/dexlayout/dexlayout_main.cc b/dexlayout/dexlayout_main.cc
index 09fa0ef..ec5edf4 100644
--- a/dexlayout/dexlayout_main.cc
+++ b/dexlayout/dexlayout_main.cc
@@ -38,7 +38,7 @@
*/
static void Usage(void) {
fprintf(stderr, "Copyright (C) 2007 The Android Open Source Project\n\n");
- fprintf(stderr, "%s: [-a] [-c] [-d] [-e] [-f] [-h] [-i] [-l layout] [-o outfile]"
+ fprintf(stderr, "%s: [-a] [-c] [-d] [-e] [-f] [-h] [-i] [-l layout] [-o outfile] [-w]"
" dexfile...\n\n", kProgramName);
fprintf(stderr, " -a : display annotations\n");
fprintf(stderr, " -b : build dex_ir\n");
@@ -51,6 +51,7 @@
fprintf(stderr, " -i : ignore checksum failures\n");
fprintf(stderr, " -l : output layout, either 'plain' or 'xml'\n");
fprintf(stderr, " -o : output file name (defaults to stdout)\n");
+ fprintf(stderr, " -w : output dex files\n");
}
/*
@@ -68,7 +69,7 @@
// Parse all arguments.
while (1) {
- const int ic = getopt(argc, argv, "abcdefghil:o:");
+ const int ic = getopt(argc, argv, "abcdefghil:o:w");
if (ic < 0) {
break; // done
}
@@ -113,6 +114,9 @@
case 'o': // output file
options_.output_file_name_ = optarg;
break;
+ case 'w': // output dex files
+ options_.output_dex_files_ = true;
+ break;
default:
want_usage = true;
break;
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index 5240011..1af3660 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -37,8 +37,8 @@
#include "elf_file_impl.h"
#include "gc/space/image_space.h"
#include "image-inl.h"
-#include "mirror/abstract_method.h"
#include "mirror/dex_cache.h"
+#include "mirror/executable.h"
#include "mirror/object-inl.h"
#include "mirror/method.h"
#include "mirror/reference.h"
@@ -770,8 +770,8 @@
} else if (object->GetClass() == mirror::Method::StaticClass() ||
object->GetClass() == mirror::Constructor::StaticClass()) {
// Need to go update the ArtMethod.
- auto* dest = down_cast<mirror::AbstractMethod*>(copy);
- auto* src = down_cast<mirror::AbstractMethod*>(object);
+ auto* dest = down_cast<mirror::Executable*>(copy);
+ auto* src = down_cast<mirror::Executable*>(object);
dest->SetArtMethod(RelocatedAddressOfPointer(src->GetArtMethod()));
}
}
diff --git a/profman/profman.cc b/profman/profman.cc
index a5fefa7..7722e80 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -280,18 +280,11 @@
for (size_t i = 0; i < dex_locations_.size(); ++i) {
std::string error_msg;
std::vector<std::unique_ptr<const DexFile>> dex_files_for_location;
- std::unique_ptr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(apks_fd_[i],
- dex_locations_[i].c_str(),
- &error_msg));
- if (zip_archive == nullptr) {
- LOG(WARNING) << "OpenFromFd failed for '" << dex_locations_[i] << "' " << error_msg;
- continue;
- }
- if (DexFile::OpenFromZip(*zip_archive,
- dex_locations_[i],
- kVerifyChecksum,
- &error_msg,
- &dex_files_for_location)) {
+ if (DexFile::OpenZip(apks_fd_[i],
+ dex_locations_[i],
+ kVerifyChecksum,
+ &error_msg,
+ &dex_files_for_location)) {
} else {
LOG(WARNING) << "OpenFromZip failed for '" << dex_locations_[i] << "' " << error_msg;
continue;
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 8c17653..6234a84 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -120,10 +120,10 @@
"linear_alloc.cc",
"mem_map.cc",
"memory_region.cc",
- "mirror/abstract_method.cc",
"mirror/array.cc",
"mirror/class.cc",
"mirror/dex_cache.cc",
+ "mirror/executable.cc",
"mirror/field.cc",
"mirror/method.cc",
"mirror/object.cc",
@@ -151,9 +151,9 @@
"native/java_lang_VMClassLoader.cc",
"native/java_lang_ref_FinalizerReference.cc",
"native/java_lang_ref_Reference.cc",
- "native/java_lang_reflect_AbstractMethod.cc",
"native/java_lang_reflect_Array.cc",
"native/java_lang_reflect_Constructor.cc",
+ "native/java_lang_reflect_Executable.cc",
"native/java_lang_reflect_Field.cc",
"native/java_lang_reflect_Method.cc",
"native/java_lang_reflect_Parameter.cc",
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index 0b04480..5d53062 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -272,6 +272,15 @@
END \c_name
.endm
+.macro NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING c_name, cxx_name
+ .extern \cxx_name
+ENTRY \c_name
+ SETUP_SAVE_EVERYTHING_FRAME r0 @ save all registers as basis for long jump context
+ mov r0, r9 @ pass Thread::Current
+ bl \cxx_name @ \cxx_name(Thread*)
+END \c_name
+.endm
+
.macro ONE_ARG_RUNTIME_EXCEPTION c_name, cxx_name
.extern \cxx_name
ENTRY \c_name
@@ -281,10 +290,10 @@
END \c_name
.endm
-.macro TWO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
+.macro TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING c_name, cxx_name
.extern \cxx_name
ENTRY \c_name
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME r2 @ save all registers as basis for long jump context
+ SETUP_SAVE_EVERYTHING_FRAME r2 @ save all registers as basis for long jump context
mov r2, r9 @ pass Thread::Current
bl \cxx_name @ \cxx_name(Thread*)
END \c_name
@@ -361,7 +370,7 @@
/*
* Called by managed code to create and deliver a NullPointerException.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
+NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
/*
* Call installed by a signal handler to create and deliver a NullPointerException.
@@ -398,19 +407,19 @@
/*
* Called by managed code to create and deliver an ArithmeticException.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
+NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_div_zero, artThrowDivZeroFromCode
/*
* Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
* index, arg2 holds limit.
*/
-TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
+TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
/*
* Called by managed code to create and deliver a StringIndexOutOfBoundsException
* as if thrown from a call to String.charAt(). Arg1 holds index, arg2 holds limit.
*/
-TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_string_bounds, artThrowStringBoundsFromCode
+TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_string_bounds, artThrowStringBoundsFromCode
/*
* Called by managed code to create and deliver a StackOverflowError.
diff --git a/runtime/arch/arm64/quick_entrypoints_arm64.S b/runtime/arch/arm64/quick_entrypoints_arm64.S
index e9d03d7..eee949d 100644
--- a/runtime/arch/arm64/quick_entrypoints_arm64.S
+++ b/runtime/arch/arm64/quick_entrypoints_arm64.S
@@ -434,6 +434,17 @@
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME // save all registers as basis for long jump context
mov x0, xSELF // pass Thread::Current
bl \cxx_name // \cxx_name(Thread*)
+ brk 0
+END \c_name
+.endm
+
+.macro NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING c_name, cxx_name
+ .extern \cxx_name
+ENTRY \c_name
+ SETUP_SAVE_EVERYTHING_FRAME // save all registers as basis for long jump context
+ mov x0, xSELF // pass Thread::Current
+ bl \cxx_name // \cxx_name(Thread*)
+ brk 0
END \c_name
.endm
@@ -447,10 +458,10 @@
END \c_name
.endm
-.macro TWO_ARG_RUNTIME_EXCEPTION c_name, cxx_name
+.macro TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING c_name, cxx_name
.extern \cxx_name
ENTRY \c_name
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME // save all registers as basis for long jump context
+ SETUP_SAVE_EVERYTHING_FRAME // save all registers as basis for long jump context
mov x2, xSELF // pass Thread::Current
bl \cxx_name // \cxx_name(arg1, arg2, Thread*)
brk 0
@@ -466,7 +477,7 @@
/*
* Called by managed code to create and deliver a NullPointerException.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
+NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
/*
* Call installed by a signal handler to create and deliver a NullPointerException.
@@ -490,19 +501,19 @@
/*
* Called by managed code to create and deliver an ArithmeticException.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
+NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_div_zero, artThrowDivZeroFromCode
/*
* Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
* index, arg2 holds limit.
*/
-TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
+TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
/*
* Called by managed code to create and deliver a StringIndexOutOfBoundsException
* as if thrown from a call to String.charAt(). Arg1 holds index, arg2 holds limit.
*/
-TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_string_bounds, artThrowStringBoundsFromCode
+TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_string_bounds, artThrowStringBoundsFromCode
/*
* Called by managed code to create and deliver a StackOverflowError.
diff --git a/runtime/arch/mips/asm_support_mips.S b/runtime/arch/mips/asm_support_mips.S
index 7955b1d..948b06c 100644
--- a/runtime/arch/mips/asm_support_mips.S
+++ b/runtime/arch/mips/asm_support_mips.S
@@ -26,22 +26,6 @@
// Register holding Thread::Current().
#define rSELF $s1
- // Declare a function called name, sets up $gp.
-.macro ENTRY name
- .type \name, %function
- .global \name
- // Cache alignment for function entry.
- .balign 16
-\name:
- .cfi_startproc
- // Ensure we get a sane starting CFA.
- .cfi_def_cfa $sp,0
- // Load $gp. We expect that ".set noreorder" is in effect.
- .cpload $t9
- // Declare a local convenience label to be branched to when $gp is already set up.
-.L\name\()_gp_set:
-.endm
-
// Declare a function called name, doesn't set up $gp.
.macro ENTRY_NO_GP_CUSTOM_CFA name, cfa_offset
.type \name, %function
@@ -59,6 +43,15 @@
ENTRY_NO_GP_CUSTOM_CFA \name, 0
.endm
+ // Declare a function called name, sets up $gp.
+.macro ENTRY name
+ ENTRY_NO_GP \name
+ // Load $gp. We expect that ".set noreorder" is in effect.
+ .cpload $t9
+ // Declare a local convenience label to be branched to when $gp is already set up.
+.L\name\()_gp_set:
+.endm
+
.macro END name
.cfi_endproc
.size \name, .-\name
diff --git a/runtime/arch/mips/fault_handler_mips.cc b/runtime/arch/mips/fault_handler_mips.cc
index b6a63ca..1792f31 100644
--- a/runtime/arch/mips/fault_handler_mips.cc
+++ b/runtime/arch/mips/fault_handler_mips.cc
@@ -90,7 +90,7 @@
sc->sc_regs[mips::RA] = sc->sc_pc + 4; // RA needs to point to gc map location
sc->sc_pc = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception_from_signal);
- sc->sc_regs[mips::T9] = sc->sc_pc; // make sure T9 points to the function
+ // Note: This entrypoint does not rely on T9 pointing to it, so we may as well preserve T9.
VLOG(signals) << "Generating null pointer exception";
return true;
}
diff --git a/runtime/arch/mips/quick_entrypoints_mips.S b/runtime/arch/mips/quick_entrypoints_mips.S
index 4563004..c3c1882 100644
--- a/runtime/arch/mips/quick_entrypoints_mips.S
+++ b/runtime/arch/mips/quick_entrypoints_mips.S
@@ -710,8 +710,10 @@
* Called by managed code to create and deliver a NullPointerException
*/
.extern artThrowNullPointerExceptionFromCode
-ENTRY art_quick_throw_null_pointer_exception
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
+ENTRY_NO_GP art_quick_throw_null_pointer_exception
+ // Note that setting up $gp does not rely on $t9 here, so branching here directly is OK,
+ // even after clobbering any registers we don't need to preserve, such as $gp or $t0.
+ SETUP_SAVE_EVERYTHING_FRAME
la $t9, artThrowNullPointerExceptionFromCode
jalr $zero, $t9 # artThrowNullPointerExceptionFromCode(Thread*)
move $a0, rSELF # pass Thread::Current
@@ -735,8 +737,8 @@
* Called by managed code to create and deliver an ArithmeticException
*/
.extern artThrowDivZeroFromCode
-ENTRY art_quick_throw_div_zero
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
+ENTRY_NO_GP art_quick_throw_div_zero
+ SETUP_SAVE_EVERYTHING_FRAME
la $t9, artThrowDivZeroFromCode
jalr $zero, $t9 # artThrowDivZeroFromCode(Thread*)
move $a0, rSELF # pass Thread::Current
@@ -746,8 +748,10 @@
* Called by managed code to create and deliver an ArrayIndexOutOfBoundsException
*/
.extern artThrowArrayBoundsFromCode
-ENTRY art_quick_throw_array_bounds
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
+ENTRY_NO_GP art_quick_throw_array_bounds
+ // Note that setting up $gp does not rely on $t9 here, so branching here directly is OK,
+ // even after clobbering any registers we don't need to preserve, such as $gp or $t0.
+ SETUP_SAVE_EVERYTHING_FRAME
la $t9, artThrowArrayBoundsFromCode
jalr $zero, $t9 # artThrowArrayBoundsFromCode(index, limit, Thread*)
move $a2, rSELF # pass Thread::Current
@@ -758,8 +762,8 @@
* as if thrown from a call to String.charAt().
*/
.extern artThrowStringBoundsFromCode
-ENTRY art_quick_throw_string_bounds
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
+ENTRY_NO_GP art_quick_throw_string_bounds
+ SETUP_SAVE_EVERYTHING_FRAME
la $t9, artThrowStringBoundsFromCode
jalr $zero, $t9 # artThrowStringBoundsFromCode(index, limit, Thread*)
move $a2, rSELF # pass Thread::Current
@@ -1123,7 +1127,7 @@
*/
.extern artLockObjectFromCode
ENTRY art_quick_lock_object
- beqz $a0, .Lart_quick_throw_null_pointer_exception_gp_set
+ beqz $a0, art_quick_throw_null_pointer_exception
nop
SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case we block
la $t9, artLockObjectFromCode
@@ -1133,7 +1137,7 @@
END art_quick_lock_object
ENTRY art_quick_lock_object_no_inline
- beqz $a0, .Lart_quick_throw_null_pointer_exception_gp_set
+ beqz $a0, art_quick_throw_null_pointer_exception
nop
SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case we block
la $t9, artLockObjectFromCode
@@ -1147,7 +1151,7 @@
*/
.extern artUnlockObjectFromCode
ENTRY art_quick_unlock_object
- beqz $a0, .Lart_quick_throw_null_pointer_exception_gp_set
+ beqz $a0, art_quick_throw_null_pointer_exception
nop
SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case exception allocation triggers GC
la $t9, artUnlockObjectFromCode
@@ -1157,7 +1161,7 @@
END art_quick_unlock_object
ENTRY art_quick_unlock_object_no_inline
- beqz $a0, .Lart_quick_throw_null_pointer_exception_gp_set
+ beqz $a0, art_quick_throw_null_pointer_exception
nop
SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case exception allocation triggers GC
la $t9, artUnlockObjectFromCode
@@ -1280,7 +1284,7 @@
ENTRY art_quick_aput_obj_with_null_and_bound_check
bnez $a0, .Lart_quick_aput_obj_with_bound_check_gp_set
nop
- b .Lart_quick_throw_null_pointer_exception_gp_set
+ b art_quick_throw_null_pointer_exception
nop
END art_quick_aput_obj_with_null_and_bound_check
@@ -1290,7 +1294,7 @@
bnez $t1, .Lart_quick_aput_obj_gp_set
nop
move $a0, $a1
- b .Lart_quick_throw_array_bounds_gp_set
+ b art_quick_throw_array_bounds
move $a1, $t0
END art_quick_aput_obj_with_bound_check
diff --git a/runtime/arch/mips64/asm_support_mips64.S b/runtime/arch/mips64/asm_support_mips64.S
index 6c58fcf..35f20fb 100644
--- a/runtime/arch/mips64/asm_support_mips64.S
+++ b/runtime/arch/mips64/asm_support_mips64.S
@@ -27,24 +27,6 @@
#define rSELF $s1
- // Declare a function called name, sets up $gp.
- // This macro modifies t8.
-.macro ENTRY name
- .type \name, %function
- .global \name
- // Cache alignment for function entry.
- .balign 16
-\name:
- .cfi_startproc
- // Set up $gp and store the previous $gp value to $t8. It will be pushed to the
- // stack after the frame has been constructed.
- .cpsetup $t9, $t8, \name
- // Ensure we get a sane starting CFA.
- .cfi_def_cfa $sp,0
- // Declare a local convenience label to be branched to when $gp is already set up.
-.L\name\()_gp_set:
-.endm
-
// Declare a function called name, doesn't set up $gp.
.macro ENTRY_NO_GP_CUSTOM_CFA name, cfa_offset
.type \name, %function
@@ -62,6 +44,17 @@
ENTRY_NO_GP_CUSTOM_CFA \name, 0
.endm
+ // Declare a function called name, sets up $gp.
+ // This macro modifies t8.
+.macro ENTRY name
+ ENTRY_NO_GP \name
+ // Set up $gp and store the previous $gp value to $t8. It will be pushed to the
+ // stack after the frame has been constructed.
+ .cpsetup $t9, $t8, \name
+ // Declare a local convenience label to be branched to when $gp is already set up.
+.L\name\()_gp_set:
+.endm
+
.macro END name
.cfi_endproc
.size \name, .-\name
diff --git a/runtime/arch/mips64/fault_handler_mips64.cc b/runtime/arch/mips64/fault_handler_mips64.cc
index e52dc73..709cab5 100644
--- a/runtime/arch/mips64/fault_handler_mips64.cc
+++ b/runtime/arch/mips64/fault_handler_mips64.cc
@@ -91,7 +91,7 @@
sc->sc_regs[mips64::RA] = sc->sc_pc + 4; // RA needs to point to gc map location
sc->sc_pc = reinterpret_cast<uintptr_t>(art_quick_throw_null_pointer_exception_from_signal);
- sc->sc_regs[mips64::T9] = sc->sc_pc; // make sure T9 points to the function
+ // Note: This entrypoint does not rely on T9 pointing to it, so we may as well preserve T9.
VLOG(signals) << "Generating null pointer exception";
return true;
}
diff --git a/runtime/arch/mips64/quick_entrypoints_mips64.S b/runtime/arch/mips64/quick_entrypoints_mips64.S
index c16e855..8fc7bc3 100644
--- a/runtime/arch/mips64/quick_entrypoints_mips64.S
+++ b/runtime/arch/mips64/quick_entrypoints_mips64.S
@@ -817,9 +817,10 @@
* Called by managed code to create and deliver a NullPointerException
*/
.extern artThrowNullPointerExceptionFromCode
-ENTRY art_quick_throw_null_pointer_exception
-.Lart_quick_throw_null_pointer_exception_gp_set:
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
+ENTRY_NO_GP art_quick_throw_null_pointer_exception
+ // Note that setting up $gp does not rely on $t9 here, so branching here directly is OK,
+ // even after clobbering any registers we don't need to preserve, such as $gp or $t0.
+ SETUP_SAVE_EVERYTHING_FRAME
dla $t9, artThrowNullPointerExceptionFromCode
jalr $zero, $t9 # artThrowNullPointerExceptionFromCode(Thread*)
move $a0, rSELF # pass Thread::Current
@@ -842,8 +843,8 @@
* Called by managed code to create and deliver an ArithmeticException
*/
.extern artThrowDivZeroFromCode
-ENTRY art_quick_throw_div_zero
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
+ENTRY_NO_GP art_quick_throw_div_zero
+ SETUP_SAVE_EVERYTHING_FRAME
dla $t9, artThrowDivZeroFromCode
jalr $zero, $t9 # artThrowDivZeroFromCode(Thread*)
move $a0, rSELF # pass Thread::Current
@@ -854,9 +855,10 @@
* ArrayIndexOutOfBoundsException
*/
.extern artThrowArrayBoundsFromCode
-ENTRY art_quick_throw_array_bounds
-.Lart_quick_throw_array_bounds_gp_set:
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
+ENTRY_NO_GP art_quick_throw_array_bounds
+ // Note that setting up $gp does not rely on $t9 here, so branching here directly is OK,
+ // even after clobbering any registers we don't need to preserve, such as $gp or $t0.
+ SETUP_SAVE_EVERYTHING_FRAME
dla $t9, artThrowArrayBoundsFromCode
jalr $zero, $t9 # artThrowArrayBoundsFromCode(index, limit, Thread*)
move $a2, rSELF # pass Thread::Current
@@ -867,9 +869,8 @@
* as if thrown from a call to String.charAt().
*/
.extern artThrowStringBoundsFromCode
-ENTRY art_quick_throw_string_bounds
-.Lart_quick_throw_string_bounds_gp_set:
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME
+ENTRY_NO_GP art_quick_throw_string_bounds
+ SETUP_SAVE_EVERYTHING_FRAME
dla $t9, artThrowStringBoundsFromCode
jalr $zero, $t9 # artThrowStringBoundsFromCode(index, limit, Thread*)
move $a2, rSELF # pass Thread::Current
@@ -1210,18 +1211,20 @@
* Entry from managed code that calls artLockObjectFromCode, may block for GC.
*/
.extern artLockObjectFromCode
-ENTRY art_quick_lock_object
- beq $a0, $zero, .Lart_quick_throw_null_pointer_exception_gp_set
+ENTRY_NO_GP art_quick_lock_object
+ beq $a0, $zero, art_quick_throw_null_pointer_exception
nop
+ .cpsetup $t9, $t8, art_quick_lock_object
SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case we block
jal artLockObjectFromCode # (Object* obj, Thread*)
move $a1, rSELF # pass Thread::Current
RETURN_IF_ZERO
END art_quick_lock_object
-ENTRY art_quick_lock_object_no_inline
- beq $a0, $zero, .Lart_quick_throw_null_pointer_exception_gp_set
+ENTRY_NO_GP art_quick_lock_object_no_inline
+ beq $a0, $zero, art_quick_throw_null_pointer_exception
nop
+ .cpsetup $t9, $t8, art_quick_lock_object_no_inline
SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case we block
jal artLockObjectFromCode # (Object* obj, Thread*)
move $a1, rSELF # pass Thread::Current
@@ -1232,18 +1235,20 @@
* Entry from managed code that calls artUnlockObjectFromCode and delivers exception on failure.
*/
.extern artUnlockObjectFromCode
-ENTRY art_quick_unlock_object
- beq $a0, $zero, .Lart_quick_throw_null_pointer_exception_gp_set
+ENTRY_NO_GP art_quick_unlock_object
+ beq $a0, $zero, art_quick_throw_null_pointer_exception
nop
+ .cpsetup $t9, $t8, art_quick_unlock_object
SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case exception allocation triggers GC
jal artUnlockObjectFromCode # (Object* obj, Thread*)
move $a1, rSELF # pass Thread::Current
RETURN_IF_ZERO
END art_quick_unlock_object
-ENTRY art_quick_unlock_object_no_inline
- beq $a0, $zero, .Lart_quick_throw_null_pointer_exception_gp_set
+ENTRY_NO_GP art_quick_unlock_object_no_inline
+ beq $a0, $zero, art_quick_throw_null_pointer_exception
nop
+ .cpsetup $t9, $t8, art_quick_unlock_object_no_inline
SETUP_SAVE_REFS_ONLY_FRAME # save callee saves in case exception allocation triggers GC
jal artUnlockObjectFromCode # (Object* obj, Thread*)
move $a1, rSELF # pass Thread::Current
@@ -1362,7 +1367,7 @@
ENTRY art_quick_aput_obj_with_null_and_bound_check
bne $a0, $zero, .Lart_quick_aput_obj_with_bound_check_gp_set
nop
- b .Lart_quick_throw_null_pointer_exception_gp_set
+ b art_quick_throw_null_pointer_exception
nop
END art_quick_aput_obj_with_null_and_bound_check
@@ -1372,7 +1377,7 @@
bne $t1, $zero, .Lart_quick_aput_obj_gp_set
nop
move $a0, $a1
- b .Lart_quick_throw_array_bounds_gp_set
+ b art_quick_throw_array_bounds
move $a1, $t0
END art_quick_aput_obj_with_bound_check
diff --git a/runtime/arch/x86/quick_entrypoints_x86.S b/runtime/arch/x86/quick_entrypoints_x86.S
index f3793e1..879d496 100644
--- a/runtime/arch/x86/quick_entrypoints_x86.S
+++ b/runtime/arch/x86/quick_entrypoints_x86.S
@@ -327,6 +327,19 @@
END_FUNCTION VAR(c_name)
END_MACRO
+MACRO2(NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING, c_name, cxx_name)
+ DEFINE_FUNCTION VAR(c_name)
+ SETUP_SAVE_EVERYTHING_FRAME ebx, ebx // save all registers as basis for long jump context
+ // Outgoing argument set up
+ subl MACRO_LITERAL(12), %esp // alignment padding
+ CFI_ADJUST_CFA_OFFSET(12)
+ pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
+ CFI_ADJUST_CFA_OFFSET(4)
+ call CALLVAR(cxx_name) // cxx_name(Thread*)
+ UNREACHABLE
+ END_FUNCTION VAR(c_name)
+END_MACRO
+
MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
DEFINE_FUNCTION VAR(c_name)
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME ebx, ebx // save all registers as basis for long jump context
@@ -341,9 +354,9 @@
END_FUNCTION VAR(c_name)
END_MACRO
-MACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
+MACRO2(TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING, c_name, cxx_name)
DEFINE_FUNCTION VAR(c_name)
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME ebx, ebx // save all registers as basis for long jump context
+ SETUP_SAVE_EVERYTHING_FRAME ebx, ebx // save all registers as basis for long jump context
// Outgoing argument set up
PUSH eax // alignment padding
pushl %fs:THREAD_SELF_OFFSET // pass Thread::Current()
@@ -358,7 +371,7 @@
/*
* Called by managed code to create and deliver a NullPointerException.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
+NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
/*
* Call installed by a signal handler to create and deliver a NullPointerException.
@@ -384,7 +397,7 @@
/*
* Called by managed code to create and deliver an ArithmeticException.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
+NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_div_zero, artThrowDivZeroFromCode
/*
* Called by managed code to create and deliver a StackOverflowError.
@@ -401,13 +414,13 @@
* Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
* index, arg2 holds limit.
*/
-TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
+TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
/*
* Called by managed code to create and deliver a StringIndexOutOfBoundsException
* as if thrown from a call to String.charAt(). Arg1 holds index, arg2 holds limit.
*/
-TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_string_bounds, artThrowStringBoundsFromCode
+TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_string_bounds, artThrowStringBoundsFromCode
/*
* All generated callsites for interface invokes and invocation slow paths will load arguments
diff --git a/runtime/arch/x86_64/quick_entrypoints_x86_64.S b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
index bfba543..a11e402 100644
--- a/runtime/arch/x86_64/quick_entrypoints_x86_64.S
+++ b/runtime/arch/x86_64/quick_entrypoints_x86_64.S
@@ -395,6 +395,16 @@
END_FUNCTION VAR(c_name)
END_MACRO
+MACRO2(NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING, c_name, cxx_name)
+ DEFINE_FUNCTION VAR(c_name)
+ SETUP_SAVE_EVERYTHING_FRAME // save all registers as basis for long jump context
+ // Outgoing argument set up
+ movq %gs:THREAD_SELF_OFFSET, %rdi // pass Thread::Current()
+ call CALLVAR(cxx_name) // cxx_name(Thread*)
+ UNREACHABLE
+ END_FUNCTION VAR(c_name)
+END_MACRO
+
MACRO2(ONE_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
DEFINE_FUNCTION VAR(c_name)
SETUP_SAVE_ALL_CALLEE_SAVES_FRAME // save all registers as basis for long jump context
@@ -405,9 +415,9 @@
END_FUNCTION VAR(c_name)
END_MACRO
-MACRO2(TWO_ARG_RUNTIME_EXCEPTION, c_name, cxx_name)
+MACRO2(TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING, c_name, cxx_name)
DEFINE_FUNCTION VAR(c_name)
- SETUP_SAVE_ALL_CALLEE_SAVES_FRAME // save all registers as basis for long jump context
+ SETUP_SAVE_EVERYTHING_FRAME // save all registers as basis for long jump context
// Outgoing argument set up
movq %gs:THREAD_SELF_OFFSET, %rdx // pass Thread::Current()
call CALLVAR(cxx_name) // cxx_name(Thread*)
@@ -418,7 +428,7 @@
/*
* Called by managed code to create and deliver a NullPointerException.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
+NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_null_pointer_exception, artThrowNullPointerExceptionFromCode
/*
* Call installed by a signal handler to create and deliver a NullPointerException.
@@ -440,7 +450,7 @@
/*
* Called by managed code to create and deliver an ArithmeticException.
*/
-NO_ARG_RUNTIME_EXCEPTION art_quick_throw_div_zero, artThrowDivZeroFromCode
+NO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_div_zero, artThrowDivZeroFromCode
/*
* Called by managed code to create and deliver a StackOverflowError.
@@ -457,13 +467,13 @@
* Called by managed code to create and deliver an ArrayIndexOutOfBoundsException. Arg1 holds
* index, arg2 holds limit.
*/
-TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
+TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_array_bounds, artThrowArrayBoundsFromCode
/*
* Called by managed code to create and deliver a StringIndexOutOfBoundsException
* as if thrown from a call to String.charAt(). Arg1 holds index, arg2 holds limit.
*/
-TWO_ARG_RUNTIME_EXCEPTION art_quick_throw_string_bounds, artThrowStringBoundsFromCode
+TWO_ARG_RUNTIME_EXCEPTION_SAVE_EVERYTHING art_quick_throw_string_bounds, artThrowStringBoundsFromCode
/*
* All generated callsites for interface invokes and invocation slow paths will load arguments
diff --git a/runtime/art_method.cc b/runtime/art_method.cc
index fd6c37a..193bea1 100644
--- a/runtime/art_method.cc
+++ b/runtime/art_method.cc
@@ -34,8 +34,8 @@
#include "jit/jit_code_cache.h"
#include "jit/profiling_info.h"
#include "jni_internal.h"
-#include "mirror/abstract_method.h"
#include "mirror/class-inl.h"
+#include "mirror/executable.h"
#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
#include "mirror/string.h"
@@ -52,9 +52,9 @@
ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
jobject jlr_method) {
- auto* abstract_method = soa.Decode<mirror::AbstractMethod*>(jlr_method);
- DCHECK(abstract_method != nullptr);
- return abstract_method->GetArtMethod();
+ auto* executable = soa.Decode<mirror::Executable*>(jlr_method);
+ DCHECK(executable != nullptr);
+ return executable->GetArtMethod();
}
mirror::String* ArtMethod::GetNameAsString(Thread* self) {
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 5e0ee6f..7023081 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -28,7 +28,6 @@
#include "experimental_flags.h"
#include "entrypoints/entrypoint_utils-inl.h"
#include "gc/heap.h"
-#include "mirror/abstract_method.h"
#include "mirror/accessible_object.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache.h"
@@ -697,24 +696,18 @@
struct ExecutableOffsets : public CheckOffsets<mirror::Executable> {
ExecutableOffsets() : CheckOffsets<mirror::Executable>(
false, "Ljava/lang/reflect/Executable;") {
+ addOffset(OFFSETOF_MEMBER(mirror::Executable, access_flags_), "accessFlags");
+ addOffset(OFFSETOF_MEMBER(mirror::Executable, art_method_), "artMethod");
+ addOffset(OFFSETOF_MEMBER(mirror::Executable, declaring_class_), "declaringClass");
+ addOffset(OFFSETOF_MEMBER(mirror::Executable, declaring_class_of_overridden_method_),
+ "declaringClassOfOverriddenMethod");
+ addOffset(OFFSETOF_MEMBER(mirror::Executable, dex_method_index_), "dexMethodIndex");
addOffset(OFFSETOF_MEMBER(mirror::Executable, has_real_parameter_data_),
"hasRealParameterData");
addOffset(OFFSETOF_MEMBER(mirror::Executable, parameters_), "parameters");
};
};
-struct AbstractMethodOffsets : public CheckOffsets<mirror::AbstractMethod> {
- AbstractMethodOffsets() : CheckOffsets<mirror::AbstractMethod>(
- false, "Ljava/lang/reflect/AbstractMethod;") {
- addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, access_flags_), "accessFlags");
- addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, art_method_), "artMethod");
- addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, declaring_class_), "declaringClass");
- addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, declaring_class_of_overridden_method_),
- "declaringClassOfOverriddenMethod");
- addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, dex_method_index_), "dexMethodIndex");
- };
-};
-
// C++ fields must exactly match the fields in the Java classes. If this fails,
// reorder the fields in the C++ class. Managed class fields are ordered by
// ClassLinker::LinkFields.
@@ -733,7 +726,6 @@
EXPECT_TRUE(AccessibleObjectOffsets().Check());
EXPECT_TRUE(FieldOffsets().Check());
EXPECT_TRUE(ExecutableOffsets().Check());
- EXPECT_TRUE(AbstractMethodOffsets().Check());
}
TEST_F(ClassLinkerTest, FindClassNonexistent) {
@@ -1269,7 +1261,6 @@
old_dex_file->Size(),
location->ToModifiedUtf8(),
0u,
- nullptr,
nullptr));
{
WriterMutexLock mu(soa.Self(), *class_linker->DexLock());
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 03223b0..70b7f87 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -52,6 +52,10 @@
namespace art {
+static constexpr OatDexFile* kNoOatDexFile = nullptr;
+
+const char* DexFile::kClassesDex = "classes.dex";
+
const uint8_t DexFile::kDexMagic[] = { 'd', 'e', 'x', '\n' };
const uint8_t DexFile::kDexMagicVersions[DexFile::kNumDexVersions][DexFile::kDexVersionLen] = {
{'0', '3', '5', '\0'},
@@ -118,64 +122,6 @@
return false;
}
-bool DexFile::Open(const char* filename,
- const char* location,
- bool verify_checksum,
- std::string* error_msg,
- std::vector<std::unique_ptr<const DexFile>>* dex_files) {
- ScopedTrace trace(std::string("Open dex file ") + location);
- DCHECK(dex_files != nullptr) << "DexFile::Open: out-param is nullptr";
- uint32_t magic;
- File fd = OpenAndReadMagic(filename, &magic, error_msg);
- if (fd.Fd() == -1) {
- DCHECK(!error_msg->empty());
- return false;
- }
- if (IsZipMagic(magic)) {
- return DexFile::OpenZip(fd.Release(), location, verify_checksum, error_msg, dex_files);
- }
- if (IsDexMagic(magic)) {
- std::unique_ptr<const DexFile> dex_file(DexFile::OpenFile(fd.Release(),
- location,
- /* verify */ true,
- verify_checksum,
- error_msg));
- if (dex_file.get() != nullptr) {
- dex_files->push_back(std::move(dex_file));
- return true;
- } else {
- return false;
- }
- }
- *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename);
- return false;
-}
-
-static bool ContainsClassesDex(int fd, const char* filename) {
- std::string error_msg;
- std::unique_ptr<ZipArchive> zip_archive(ZipArchive::OpenFromFd(fd, filename, &error_msg));
- if (zip_archive.get() == nullptr) {
- return false;
- }
- std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(DexFile::kClassesDex, &error_msg));
- return (zip_entry.get() != nullptr);
-}
-
-bool DexFile::MaybeDex(const char* filename) {
- uint32_t magic;
- std::string error_msg;
- File fd = OpenAndReadMagic(filename, &magic, &error_msg);
- if (fd.Fd() == -1) {
- return false;
- }
- if (IsZipMagic(magic)) {
- return ContainsClassesDex(fd.Release(), filename);
- } else if (IsDexMagic(magic)) {
- return true;
- }
- return false;
-}
-
int DexFile::GetPermissions() const {
if (mem_map_.get() == nullptr) {
return 0;
@@ -206,7 +152,9 @@
}
}
-std::unique_ptr<const DexFile> DexFile::Open(const uint8_t* base, size_t size,
+
+std::unique_ptr<const DexFile> DexFile::Open(const uint8_t* base,
+ size_t size,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
@@ -214,118 +162,78 @@
bool verify_checksum,
std::string* error_msg) {
ScopedTrace trace(std::string("Open dex file from RAM ") + location);
- std::unique_ptr<const DexFile> dex_file = OpenMemory(base,
- size,
- location,
- location_checksum,
- nullptr,
- oat_dex_file,
- error_msg);
- if (dex_file == nullptr) {
- return nullptr;
- }
-
- if (verify && !DexFileVerifier::Verify(dex_file.get(),
- dex_file->Begin(),
- dex_file->Size(),
- location.c_str(),
- verify_checksum,
- error_msg)) {
- return nullptr;
- }
- return dex_file;
+ return OpenCommon(base,
+ size,
+ location,
+ location_checksum,
+ oat_dex_file,
+ verify,
+ verify_checksum,
+ error_msg);
}
std::unique_ptr<const DexFile> DexFile::Open(const std::string& location,
uint32_t location_checksum,
- std::unique_ptr<MemMap> mem_map,
+ std::unique_ptr<MemMap> map,
bool verify,
bool verify_checksum,
std::string* error_msg) {
ScopedTrace trace(std::string("Open dex file from mapped-memory ") + location);
- std::unique_ptr<const DexFile> dex_file = OpenMemory(location,
- location_checksum,
- std::move(mem_map),
- error_msg);
- if (dex_file == nullptr) {
- return nullptr;
- }
-
- if (verify && !DexFileVerifier::Verify(dex_file.get(),
- dex_file->Begin(),
- dex_file->Size(),
- location.c_str(),
- verify_checksum,
- error_msg)) {
- return nullptr;
+ CHECK(map.get() != nullptr);
+ std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
+ map->Size(),
+ location,
+ location_checksum,
+ kNoOatDexFile,
+ verify,
+ verify_checksum,
+ error_msg);
+ if (dex_file != nullptr) {
+ dex_file->mem_map_.reset(map.release());
}
return dex_file;
}
-std::unique_ptr<const DexFile> DexFile::OpenFile(int fd,
- const char* location,
- bool verify,
- bool verify_checksum,
- std::string* error_msg) {
- ScopedTrace trace(std::string("Open dex file ") + location);
- CHECK(location != nullptr);
- std::unique_ptr<MemMap> map;
- {
- File delayed_close(fd, /* check_usage */ false);
- struct stat sbuf;
- memset(&sbuf, 0, sizeof(sbuf));
- if (fstat(fd, &sbuf) == -1) {
- *error_msg = StringPrintf("DexFile: fstat '%s' failed: %s", location, strerror(errno));
- return nullptr;
- }
- if (S_ISDIR(sbuf.st_mode)) {
- *error_msg = StringPrintf("Attempt to mmap directory '%s'", location);
- return nullptr;
- }
- size_t length = sbuf.st_size;
- map.reset(MemMap::MapFile(length,
- PROT_READ,
- MAP_PRIVATE,
- fd,
- 0,
- /*low_4gb*/false,
- location,
- error_msg));
- if (map == nullptr) {
- DCHECK(!error_msg->empty());
- return nullptr;
+bool DexFile::Open(const char* filename,
+ const std::string& location,
+ bool verify_checksum,
+ std::string* error_msg,
+ std::vector<std::unique_ptr<const DexFile>>* dex_files) {
+ ScopedTrace trace(std::string("Open dex file ") + std::string(location));
+ DCHECK(dex_files != nullptr) << "DexFile::Open: out-param is nullptr";
+ uint32_t magic;
+ File fd = OpenAndReadMagic(filename, &magic, error_msg);
+ if (fd.Fd() == -1) {
+ DCHECK(!error_msg->empty());
+ return false;
+ }
+ if (IsZipMagic(magic)) {
+ return DexFile::OpenZip(fd.Release(), location, verify_checksum, error_msg, dex_files);
+ }
+ if (IsDexMagic(magic)) {
+ std::unique_ptr<const DexFile> dex_file(DexFile::OpenFile(fd.Release(),
+ location,
+ /* verify */ true,
+ verify_checksum,
+ error_msg));
+ if (dex_file.get() != nullptr) {
+ dex_files->push_back(std::move(dex_file));
+ return true;
+ } else {
+ return false;
}
}
-
- if (map->Size() < sizeof(DexFile::Header)) {
- *error_msg = StringPrintf(
- "DexFile: failed to open dex file '%s' that is too short to have a header", location);
- return nullptr;
- }
-
- const Header* dex_header = reinterpret_cast<const Header*>(map->Begin());
-
- std::unique_ptr<const DexFile> dex_file(OpenMemory(location,
- dex_header->checksum_,
- std::move(map),
- error_msg));
- if (dex_file.get() == nullptr) {
- *error_msg = StringPrintf("Failed to open dex file '%s' from memory: %s", location,
- error_msg->c_str());
- return nullptr;
- }
-
- if (verify && !DexFileVerifier::Verify(dex_file.get(), dex_file->Begin(), dex_file->Size(),
- location,
- verify_checksum,
- error_msg)) {
- return nullptr;
- }
-
- return dex_file;
+ *error_msg = StringPrintf("Expected valid zip or dex file: '%s'", filename);
+ return false;
}
-const char* DexFile::kClassesDex = "classes.dex";
+std::unique_ptr<const DexFile> DexFile::OpenDex(int fd,
+ const std::string& location,
+ bool verify_checksum,
+ std::string* error_msg) {
+ ScopedTrace trace("Open dex file " + std::string(location));
+ return OpenFile(fd, location, true /* verify */, verify_checksum, error_msg);
+}
bool DexFile::OpenZip(int fd,
const std::string& location,
@@ -339,28 +247,79 @@
DCHECK(!error_msg->empty());
return false;
}
- return DexFile::OpenFromZip(*zip_archive, location, verify_checksum, error_msg, dex_files);
+ return DexFile::OpenAllDexFilesFromZip(*zip_archive,
+ location,
+ verify_checksum,
+ error_msg,
+ dex_files);
}
-std::unique_ptr<const DexFile> DexFile::OpenMemory(const std::string& location,
- uint32_t location_checksum,
- std::unique_ptr<MemMap> mem_map,
- std::string* error_msg) {
- return OpenMemory(mem_map->Begin(),
- mem_map->Size(),
- location,
- location_checksum,
- std::move(mem_map),
- nullptr,
- error_msg);
+std::unique_ptr<const DexFile> DexFile::OpenFile(int fd,
+ const std::string& location,
+ bool verify,
+ bool verify_checksum,
+ std::string* error_msg) {
+ ScopedTrace trace(std::string("Open dex file ") + std::string(location));
+ CHECK(!location.empty());
+ std::unique_ptr<MemMap> map;
+ {
+ File delayed_close(fd, /* check_usage */ false);
+ struct stat sbuf;
+ memset(&sbuf, 0, sizeof(sbuf));
+ if (fstat(fd, &sbuf) == -1) {
+ *error_msg = StringPrintf("DexFile: fstat '%s' failed: %s", location.c_str(),
+ strerror(errno));
+ return nullptr;
+ }
+ if (S_ISDIR(sbuf.st_mode)) {
+ *error_msg = StringPrintf("Attempt to mmap directory '%s'", location.c_str());
+ return nullptr;
+ }
+ size_t length = sbuf.st_size;
+ map.reset(MemMap::MapFile(length,
+ PROT_READ,
+ MAP_PRIVATE,
+ fd,
+ 0,
+ /*low_4gb*/false,
+ location.c_str(),
+ error_msg));
+ if (map == nullptr) {
+ DCHECK(!error_msg->empty());
+ return nullptr;
+ }
+ }
+
+ if (map->Size() < sizeof(DexFile::Header)) {
+ *error_msg = StringPrintf(
+ "DexFile: failed to open dex file '%s' that is too short to have a header",
+ location.c_str());
+ return nullptr;
+ }
+
+ const Header* dex_header = reinterpret_cast<const Header*>(map->Begin());
+
+ std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
+ map->Size(),
+ location,
+ dex_header->checksum_,
+ kNoOatDexFile,
+ verify,
+ verify_checksum,
+ error_msg);
+ if (dex_file != nullptr) {
+ dex_file->mem_map_.reset(map.release());
+ }
+
+ return dex_file;
}
-std::unique_ptr<const DexFile> DexFile::Open(const ZipArchive& zip_archive,
- const char* entry_name,
- const std::string& location,
- bool verify_checksum,
- std::string* error_msg,
- ZipOpenErrorCode* error_code) {
+std::unique_ptr<const DexFile> DexFile::OpenOneDexFileFromZip(const ZipArchive& zip_archive,
+ const char* entry_name,
+ const std::string& location,
+ bool verify_checksum,
+ std::string* error_msg,
+ ZipOpenErrorCode* error_code) {
ScopedTrace trace("Dex file open from Zip Archive " + std::string(location));
CHECK(!location.empty());
std::unique_ptr<ZipEntry> zip_entry(zip_archive.Find(entry_name, error_msg));
@@ -380,15 +339,18 @@
*error_code = ZipOpenErrorCode::kExtractToMemoryError;
return nullptr;
}
- std::unique_ptr<const DexFile> dex_file(OpenMemory(location,
- zip_entry->GetCrc32(),
- std::move(map),
- error_msg));
- if (dex_file == nullptr) {
- *error_msg = StringPrintf("Failed to open dex file '%s' from memory: %s", location.c_str(),
- error_msg->c_str());
- *error_code = ZipOpenErrorCode::kDexFileError;
- return nullptr;
+ VerifyResult verify_result;
+ std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(),
+ map->Size(),
+ location,
+ zip_entry->GetCrc32(),
+ kNoOatDexFile,
+ /* verify */ true,
+ verify_checksum,
+ error_msg,
+ &verify_result);
+ if (dex_file != nullptr) {
+ dex_file->mem_map_.reset(map.release());
}
if (!dex_file->DisableWrite()) {
*error_msg = StringPrintf("Failed to make dex file '%s' read only", location.c_str());
@@ -396,10 +358,7 @@
return nullptr;
}
CHECK(dex_file->IsReadOnly()) << location;
- if (!DexFileVerifier::Verify(dex_file.get(), dex_file->Begin(), dex_file->Size(),
- location.c_str(),
- verify_checksum,
- error_msg)) {
+ if (verify_result != VerifyResult::kVerifySucceeded) {
*error_code = ZipOpenErrorCode::kVerifyError;
return nullptr;
}
@@ -413,16 +372,20 @@
// seems an excessive number.
static constexpr size_t kWarnOnManyDexFilesThreshold = 100;
-bool DexFile::OpenFromZip(const ZipArchive& zip_archive,
- const std::string& location,
- bool verify_checksum,
- std::string* error_msg,
- std::vector<std::unique_ptr<const DexFile>>* dex_files) {
+bool DexFile::OpenAllDexFilesFromZip(const ZipArchive& zip_archive,
+ const std::string& location,
+ bool verify_checksum,
+ std::string* error_msg,
+ std::vector<std::unique_ptr<const DexFile>>* dex_files) {
ScopedTrace trace("Dex file open from Zip " + std::string(location));
DCHECK(dex_files != nullptr) << "DexFile::OpenFromZip: out-param is nullptr";
ZipOpenErrorCode error_code;
- std::unique_ptr<const DexFile> dex_file(
- Open(zip_archive, kClassesDex, location, verify_checksum, error_msg, &error_code));
+ std::unique_ptr<const DexFile> dex_file(OpenOneDexFileFromZip(zip_archive,
+ kClassesDex,
+ location,
+ verify_checksum,
+ error_msg,
+ &error_code));
if (dex_file.get() == nullptr) {
return false;
} else {
@@ -437,8 +400,12 @@
for (size_t i = 1; ; ++i) {
std::string name = GetMultiDexClassesDexName(i);
std::string fake_location = GetMultiDexLocation(i, location.c_str());
- std::unique_ptr<const DexFile> next_dex_file(
- Open(zip_archive, name.c_str(), fake_location, verify_checksum, error_msg, &error_code));
+ std::unique_ptr<const DexFile> next_dex_file(OpenOneDexFileFromZip(zip_archive,
+ name.c_str(),
+ fake_location,
+ verify_checksum,
+ error_msg,
+ &error_code));
if (next_dex_file.get() == nullptr) {
if (error_code != ZipOpenErrorCode::kEntryNotFound) {
LOG(WARNING) << error_msg;
@@ -464,35 +431,55 @@
}
}
-
-std::unique_ptr<const DexFile> DexFile::OpenMemory(const uint8_t* base,
- size_t size,
- const std::string& location,
- uint32_t location_checksum,
- std::unique_ptr<MemMap> mem_map,
- const OatDexFile* oat_dex_file,
- std::string* error_msg) {
- DCHECK(base != nullptr);
- DCHECK_NE(size, 0U);
- CHECK_ALIGNED(base, 4); // various dex file structures must be word aligned
- std::unique_ptr<DexFile> dex_file(
- new DexFile(base, size, location, location_checksum, std::move(mem_map), oat_dex_file));
+std::unique_ptr<DexFile> DexFile::OpenCommon(const uint8_t* base,
+ size_t size,
+ const std::string& location,
+ uint32_t location_checksum,
+ const OatDexFile* oat_dex_file,
+ bool verify,
+ bool verify_checksum,
+ std::string* error_msg,
+ VerifyResult* verify_result) {
+ std::unique_ptr<DexFile> dex_file(new DexFile(base,
+ size,
+ location,
+ location_checksum,
+ oat_dex_file));
+ if (dex_file == nullptr) {
+ *error_msg = StringPrintf("Failed to open dex file '%s' from memory: %s", location.c_str(),
+ error_msg->c_str());
+ return nullptr;
+ }
if (!dex_file->Init(error_msg)) {
dex_file.reset();
+ return nullptr;
}
- return std::unique_ptr<const DexFile>(dex_file.release());
+ if (verify && !DexFileVerifier::Verify(dex_file.get(),
+ dex_file->Begin(),
+ dex_file->Size(),
+ location.c_str(),
+ verify_checksum,
+ error_msg)) {
+ if (verify_result != nullptr) {
+ *verify_result = VerifyResult::kVerifyFailed;
+ }
+ return nullptr;
+ }
+ if (verify_result != nullptr) {
+ *verify_result = VerifyResult::kVerifySucceeded;
+ }
+ return dex_file;
}
-DexFile::DexFile(const uint8_t* base, size_t size,
+DexFile::DexFile(const uint8_t* base,
+ size_t size,
const std::string& location,
uint32_t location_checksum,
- std::unique_ptr<MemMap> mem_map,
const OatDexFile* oat_dex_file)
: begin_(base),
size_(size),
location_(location),
location_checksum_(location_checksum),
- mem_map_(std::move(mem_map)),
header_(reinterpret_cast<const Header*>(base)),
string_ids_(reinterpret_cast<const StringId*>(base + header_->string_ids_off_)),
type_ids_(reinterpret_cast<const TypeId*>(base + header_->type_ids_off_)),
diff --git a/runtime/dex_file.h b/runtime/dex_file.h
index 97c2596..14bde09 100644
--- a/runtime/dex_file.h
+++ b/runtime/dex_file.h
@@ -397,15 +397,9 @@
// Return true if the checksum could be found, false otherwise.
static bool GetChecksum(const char* filename, uint32_t* checksum, std::string* error_msg);
- // Opens .dex files found in the container, guessing the container format based on file extension.
- static bool Open(const char* filename,
- const char* location,
- bool verify_checksum,
- std::string* error_msg,
- std::vector<std::unique_ptr<const DexFile>>* dex_files);
-
// Opens .dex file, backed by existing memory
- static std::unique_ptr<const DexFile> Open(const uint8_t* base, size_t size,
+ static std::unique_ptr<const DexFile> Open(const uint8_t* base,
+ size_t size,
const std::string& location,
uint32_t location_checksum,
const OatDexFile* oat_dex_file,
@@ -421,16 +415,25 @@
bool verify_checksum,
std::string* error_msg);
- // Checks whether the given file has the dex magic, or is a zip file with a classes.dex entry.
- // If this function returns false, Open will not succeed. The inverse is not true, however.
- static bool MaybeDex(const char* filename);
+ // Opens all .dex files found in the file, guessing the container format based on file extension.
+ static bool Open(const char* filename,
+ const std::string& location,
+ bool verify_checksum,
+ std::string* error_msg,
+ std::vector<std::unique_ptr<const DexFile>>* dex_files);
- // Open all classesXXX.dex files from a zip archive.
- static bool OpenFromZip(const ZipArchive& zip_archive,
- const std::string& location,
- bool verify_checksum,
- std::string* error_msg,
- std::vector<std::unique_ptr<const DexFile>>* dex_files);
+ // Open a single dex file from an fd.
+ static std::unique_ptr<const DexFile> OpenDex(int fd,
+ const std::string& location,
+ bool verify_checksum,
+ std::string* error_msg);
+
+ // Opens dex files from within a .jar, .zip, or .apk file
+ static bool OpenZip(int fd,
+ const std::string& location,
+ bool verify_checksum,
+ std::string* error_msg,
+ std::vector<std::unique_ptr<const DexFile>>* dex_files);
// Closes a .dex file.
virtual ~DexFile();
@@ -1011,20 +1014,12 @@
static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right);
private:
- // Opens a .dex file
static std::unique_ptr<const DexFile> OpenFile(int fd,
- const char* location,
+ const std::string& location,
bool verify,
bool verify_checksum,
std::string* error_msg);
- // Opens dex files from within a .jar, .zip, or .apk file
- static bool OpenZip(int fd,
- const std::string& location,
- bool verify_checksum,
- std::string* error_msg,
- std::vector<std::unique_ptr<const DexFile>>* dex_files);
-
enum class ZipOpenErrorCode { // private
kNoError,
kEntryNotFound,
@@ -1034,34 +1029,41 @@
kVerifyError
};
+ // Open all classesXXX.dex files from a zip archive.
+ static bool OpenAllDexFilesFromZip(const ZipArchive& zip_archive,
+ const std::string& location,
+ bool verify_checksum,
+ std::string* error_msg,
+ std::vector<std::unique_ptr<const DexFile>>* dex_files);
+
// Opens .dex file from the entry_name in a zip archive. error_code is undefined when non-null
// return.
- static std::unique_ptr<const DexFile> Open(const ZipArchive& zip_archive,
- const char* entry_name,
+ static std::unique_ptr<const DexFile> OpenOneDexFileFromZip(const ZipArchive& zip_archive,
+ const char* entry_name,
+ const std::string& location,
+ bool verify_checksum,
+ std::string* error_msg,
+ ZipOpenErrorCode* error_code);
+
+ enum class VerifyResult { // private
+ kVerifySucceeded,
+ kVerifyFailed
+ };
+
+ static std::unique_ptr<DexFile> OpenCommon(const uint8_t* base,
+ size_t size,
const std::string& location,
+ uint32_t location_checksum,
+ const OatDexFile* oat_dex_file,
+ bool verify,
bool verify_checksum,
std::string* error_msg,
- ZipOpenErrorCode* error_code);
+ VerifyResult* verify_result = nullptr);
- // Opens a .dex file at the given address backed by a MemMap
- static std::unique_ptr<const DexFile> OpenMemory(const std::string& location,
- uint32_t location_checksum,
- std::unique_ptr<MemMap> mem_map,
- std::string* error_msg);
-
- // Opens a .dex file at the given address, optionally backed by a MemMap
- static std::unique_ptr<const DexFile> OpenMemory(const uint8_t* dex_file,
- size_t size,
- const std::string& location,
- uint32_t location_checksum,
- std::unique_ptr<MemMap> mem_map,
- const OatDexFile* oat_dex_file,
- std::string* error_msg);
-
- DexFile(const uint8_t* base, size_t size,
+ DexFile(const uint8_t* base,
+ size_t size,
const std::string& location,
uint32_t location_checksum,
- std::unique_ptr<MemMap> mem_map,
const OatDexFile* oat_dex_file);
// Top-level initializer that calls other Init methods.
diff --git a/runtime/dex_file_verifier_test.cc b/runtime/dex_file_verifier_test.cc
index 71c0ad9..5939ef3 100644
--- a/runtime/dex_file_verifier_test.cc
+++ b/runtime/dex_file_verifier_test.cc
@@ -123,7 +123,7 @@
class DexFileVerifierTest : public CommonRuntimeTest {
protected:
DexFile* GetDexFile(const uint8_t* dex_bytes, size_t length) {
- return new DexFile(dex_bytes, length, "tmp", 0, nullptr, nullptr);
+ return new DexFile(dex_bytes, length, "tmp", 0, nullptr);
}
void VerifyModification(const char* dex_file_base64_content,
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index a434442..d9cb1c6 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -375,7 +375,7 @@
CHECK_NON_NULL_ARGUMENT(mid);
ScopedObjectAccess soa(env);
ArtMethod* m = soa.DecodeMethod(mid);
- mirror::AbstractMethod* method;
+ mirror::Executable* method;
DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), kRuntimePointerSize);
DCHECK(!Runtime::Current()->IsActiveTransaction());
if (m->IsConstructor()) {
diff --git a/runtime/mirror/abstract_method.h b/runtime/mirror/abstract_method.h
deleted file mode 100644
index 9c20613..0000000
--- a/runtime/mirror/abstract_method.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2015 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_MIRROR_ABSTRACT_METHOD_H_
-#define ART_RUNTIME_MIRROR_ABSTRACT_METHOD_H_
-
-#include "executable.h"
-#include "gc_root.h"
-#include "object.h"
-#include "object_callbacks.h"
-#include "read_barrier_option.h"
-
-namespace art {
-
-struct AbstractMethodOffsets;
-class ArtMethod;
-
-namespace mirror {
-
-// C++ mirror of java.lang.reflect.AbstractMethod.
-class MANAGED AbstractMethod : public Executable {
- public:
- // Called from Constructor::CreateFromArtMethod, Method::CreateFromArtMethod.
- template <PointerSize kPointerSize, bool kTransactionActive>
- bool CreateFromArtMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_)
- REQUIRES(!Roles::uninterruptible_);
-
- ArtMethod* GetArtMethod() REQUIRES_SHARED(Locks::mutator_lock_);
- // Only used by the image writer.
- template <bool kTransactionActive = false>
- void SetArtMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::Class* GetDeclaringClass() REQUIRES_SHARED(Locks::mutator_lock_);
-
- private:
- static MemberOffset ArtMethodOffset() {
- return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, art_method_));
- }
- static MemberOffset DeclaringClassOffset() {
- return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_));
- }
- static MemberOffset DeclaringClassOfOverriddenMethodOffset() {
- return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_of_overridden_method_));
- }
- static MemberOffset AccessFlagsOffset() {
- return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, access_flags_));
- }
- static MemberOffset DexMethodIndexOffset() {
- return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, dex_method_index_));
- }
-
- HeapReference<mirror::Class> declaring_class_;
- HeapReference<mirror::Class> declaring_class_of_overridden_method_;
- uint64_t art_method_;
- uint32_t access_flags_;
- uint32_t dex_method_index_;
-
- friend struct art::AbstractMethodOffsets; // for verifying offset information
- DISALLOW_IMPLICIT_CONSTRUCTORS(AbstractMethod);
-};
-
-} // namespace mirror
-} // namespace art
-
-#endif // ART_RUNTIME_MIRROR_ABSTRACT_METHOD_H_
diff --git a/runtime/mirror/abstract_method.cc b/runtime/mirror/executable.cc
similarity index 70%
rename from runtime/mirror/abstract_method.cc
rename to runtime/mirror/executable.cc
index b4dce58..33ebd81 100644
--- a/runtime/mirror/abstract_method.cc
+++ b/runtime/mirror/executable.cc
@@ -14,15 +14,14 @@
* limitations under the License.
*/
-#include "abstract_method.h"
-
#include "art_method-inl.h"
+#include "executable.h"
namespace art {
namespace mirror {
template <PointerSize kPointerSize, bool kTransactionActive>
-bool AbstractMethod::CreateFromArtMethod(ArtMethod* method) {
+bool Executable::CreateFromArtMethod(ArtMethod* method) {
auto* interface_method = method->GetInterfaceMethodIfProxy(kPointerSize);
SetArtMethod<kTransactionActive>(method);
SetFieldObject<kTransactionActive>(DeclaringClassOffset(), method->GetDeclaringClass());
@@ -33,28 +32,28 @@
return true;
}
-template bool AbstractMethod::CreateFromArtMethod<PointerSize::k32, false>(
+template bool Executable::CreateFromArtMethod<PointerSize::k32, false>(
ArtMethod* method);
-template bool AbstractMethod::CreateFromArtMethod<PointerSize::k32, true>(
+template bool Executable::CreateFromArtMethod<PointerSize::k32, true>(
ArtMethod* method);
-template bool AbstractMethod::CreateFromArtMethod<PointerSize::k64, false>(
+template bool Executable::CreateFromArtMethod<PointerSize::k64, false>(
ArtMethod* method);
-template bool AbstractMethod::CreateFromArtMethod<PointerSize::k64, true>(
+template bool Executable::CreateFromArtMethod<PointerSize::k64, true>(
ArtMethod* method);
-ArtMethod* AbstractMethod::GetArtMethod() {
+ArtMethod* Executable::GetArtMethod() {
return reinterpret_cast<ArtMethod*>(GetField64(ArtMethodOffset()));
}
template <bool kTransactionActive>
-void AbstractMethod::SetArtMethod(ArtMethod* method) {
+void Executable::SetArtMethod(ArtMethod* method) {
SetField64<kTransactionActive>(ArtMethodOffset(), reinterpret_cast<uint64_t>(method));
}
-template void AbstractMethod::SetArtMethod<false>(ArtMethod* method);
-template void AbstractMethod::SetArtMethod<true>(ArtMethod* method);
+template void Executable::SetArtMethod<false>(ArtMethod* method);
+template void Executable::SetArtMethod<true>(ArtMethod* method);
-mirror::Class* AbstractMethod::GetDeclaringClass() {
+mirror::Class* Executable::GetDeclaringClass() {
return GetFieldObject<mirror::Class>(DeclaringClassOffset());
}
diff --git a/runtime/mirror/executable.h b/runtime/mirror/executable.h
index 232fce8..6c465f6 100644
--- a/runtime/mirror/executable.h
+++ b/runtime/mirror/executable.h
@@ -32,9 +32,42 @@
// C++ mirror of java.lang.reflect.Executable.
class MANAGED Executable : public AccessibleObject {
+ public:
+ // Called from Constructor::CreateFromArtMethod, Method::CreateFromArtMethod.
+ template <PointerSize kPointerSize, bool kTransactionActive>
+ bool CreateFromArtMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_)
+ REQUIRES(!Roles::uninterruptible_);
+
+ ArtMethod* GetArtMethod() REQUIRES_SHARED(Locks::mutator_lock_);
+ // Only used by the image writer.
+ template <bool kTransactionActive = false>
+ void SetArtMethod(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
+ mirror::Class* GetDeclaringClass() REQUIRES_SHARED(Locks::mutator_lock_);
+
private:
uint16_t has_real_parameter_data_;
+ HeapReference<mirror::Class> declaring_class_;
+ HeapReference<mirror::Class> declaring_class_of_overridden_method_;
HeapReference<mirror::Array> parameters_;
+ uint64_t art_method_;
+ uint32_t access_flags_;
+ uint32_t dex_method_index_;
+
+ static MemberOffset ArtMethodOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(Executable, art_method_));
+ }
+ static MemberOffset DeclaringClassOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(Executable, declaring_class_));
+ }
+ static MemberOffset DeclaringClassOfOverriddenMethodOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(Executable, declaring_class_of_overridden_method_));
+ }
+ static MemberOffset AccessFlagsOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(Executable, access_flags_));
+ }
+ static MemberOffset DexMethodIndexOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(Executable, dex_method_index_));
+ }
friend struct art::ExecutableOffsets; // for verifying offset information
DISALLOW_IMPLICIT_CONSTRUCTORS(Executable);
diff --git a/runtime/mirror/method.cc b/runtime/mirror/method.cc
index ef16719..71bac7e 100644
--- a/runtime/mirror/method.cc
+++ b/runtime/mirror/method.cc
@@ -56,7 +56,7 @@
DCHECK(!method->IsConstructor()) << PrettyMethod(method);
auto* ret = down_cast<Method*>(StaticClass()->AllocObject(self));
if (LIKELY(ret != nullptr)) {
- static_cast<AbstractMethod*>(ret)->
+ static_cast<Executable*>(ret)->
CreateFromArtMethod<kPointerSize, kTransactionActive>(method);
}
return ret;
@@ -108,7 +108,7 @@
DCHECK(method->IsConstructor()) << PrettyMethod(method);
auto* ret = down_cast<Constructor*>(StaticClass()->AllocObject(self));
if (LIKELY(ret != nullptr)) {
- static_cast<AbstractMethod*>(ret)->
+ static_cast<Executable*>(ret)->
CreateFromArtMethod<kPointerSize, kTransactionActive>(method);
}
return ret;
diff --git a/runtime/mirror/method.h b/runtime/mirror/method.h
index 6881991..205ea7a 100644
--- a/runtime/mirror/method.h
+++ b/runtime/mirror/method.h
@@ -17,8 +17,8 @@
#ifndef ART_RUNTIME_MIRROR_METHOD_H_
#define ART_RUNTIME_MIRROR_METHOD_H_
-#include "abstract_method.h"
#include "gc_root.h"
+#include "executable.h"
namespace art {
namespace mirror {
@@ -26,7 +26,7 @@
class Class;
// C++ mirror of java.lang.reflect.Method.
-class MANAGED Method : public AbstractMethod {
+class MANAGED Method : public Executable {
public:
template <PointerSize kPointerSize, bool kTransactionActive>
static Method* CreateFromArtMethod(Thread* self, ArtMethod* method)
@@ -58,7 +58,7 @@
};
// C++ mirror of java.lang.reflect.Constructor.
-class MANAGED Constructor: public AbstractMethod {
+class MANAGED Constructor: public Executable {
public:
template <PointerSize kPointerSize, bool kTransactionActive>
static Constructor* CreateFromArtMethod(Thread* self, ArtMethod* method)
diff --git a/runtime/native/java_lang_reflect_AbstractMethod.cc b/runtime/native/java_lang_reflect_Executable.cc
similarity index 77%
rename from runtime/native/java_lang_reflect_AbstractMethod.cc
rename to runtime/native/java_lang_reflect_Executable.cc
index 254f8db..8fcf6ac 100644
--- a/runtime/native/java_lang_reflect_AbstractMethod.cc
+++ b/runtime/native/java_lang_reflect_Executable.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "java_lang_reflect_AbstractMethod.h"
+#include "java_lang_reflect_Executable.h"
#include "art_method-inl.h"
#include "dex_file_annotations.h"
@@ -28,7 +28,7 @@
namespace art {
-static jobjectArray AbstractMethod_getDeclaredAnnotations(JNIEnv* env, jobject javaMethod) {
+static jobjectArray Executable_getDeclaredAnnotationsNative(JNIEnv* env, jobject javaMethod) {
ScopedFastNativeObjectAccess soa(env);
ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
if (method->GetDeclaringClass()->IsProxyClass()) {
@@ -42,7 +42,7 @@
return soa.AddLocalReference<jobjectArray>(annotations::GetAnnotationsForMethod(method));
}
-static jobject AbstractMethod_getAnnotationNative(JNIEnv* env,
+static jobject Executable_getAnnotationNative(JNIEnv* env,
jobject javaMethod,
jclass annotationType) {
ScopedFastNativeObjectAccess soa(env);
@@ -56,7 +56,7 @@
}
}
-static jobjectArray AbstractMethod_getSignatureAnnotation(JNIEnv* env, jobject javaMethod) {
+static jobjectArray Executable_getSignatureAnnotation(JNIEnv* env, jobject javaMethod) {
ScopedFastNativeObjectAccess soa(env);
ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
if (method->GetDeclaringClass()->IsProxyClass()) {
@@ -67,7 +67,7 @@
}
-static jobjectArray AbstractMethod_getParameterAnnotationsNative(JNIEnv* env, jobject javaMethod) {
+static jobjectArray Executable_getParameterAnnotationsNative(JNIEnv* env, jobject javaMethod) {
ScopedFastNativeObjectAccess soa(env);
ArtMethod* method = ArtMethod::FromReflectedMethod(soa, javaMethod);
if (method->IsProxyMethod()) {
@@ -77,7 +77,7 @@
}
}
-static jboolean AbstractMethod_isAnnotationPresentNative(JNIEnv* env,
+static jboolean Executable_isAnnotationPresentNative(JNIEnv* env,
jobject javaMethod,
jclass annotationType) {
ScopedFastNativeObjectAccess soa(env);
@@ -91,17 +91,17 @@
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(AbstractMethod, getAnnotationNative,
+ NATIVE_METHOD(Executable, getAnnotationNative,
"!(Ljava/lang/Class;)Ljava/lang/annotation/Annotation;"),
- NATIVE_METHOD(AbstractMethod, getDeclaredAnnotations, "!()[Ljava/lang/annotation/Annotation;"),
- NATIVE_METHOD(AbstractMethod, getParameterAnnotationsNative,
+ NATIVE_METHOD(Executable, getDeclaredAnnotationsNative, "!()[Ljava/lang/annotation/Annotation;"),
+ NATIVE_METHOD(Executable, getParameterAnnotationsNative,
"!()[[Ljava/lang/annotation/Annotation;"),
- NATIVE_METHOD(AbstractMethod, getSignatureAnnotation, "!()[Ljava/lang/String;"),
- NATIVE_METHOD(AbstractMethod, isAnnotationPresentNative, "!(Ljava/lang/Class;)Z"),
+ NATIVE_METHOD(Executable, getSignatureAnnotation, "!()[Ljava/lang/String;"),
+ NATIVE_METHOD(Executable, isAnnotationPresentNative, "!(Ljava/lang/Class;)Z"),
};
-void register_java_lang_reflect_AbstractMethod(JNIEnv* env) {
- REGISTER_NATIVE_METHODS("java/lang/reflect/AbstractMethod");
+void register_java_lang_reflect_Executable(JNIEnv* env) {
+ REGISTER_NATIVE_METHODS("java/lang/reflect/Executable");
}
} // namespace art
diff --git a/runtime/native/java_lang_reflect_AbstractMethod.h b/runtime/native/java_lang_reflect_Executable.h
similarity index 72%
rename from runtime/native/java_lang_reflect_AbstractMethod.h
rename to runtime/native/java_lang_reflect_Executable.h
index 222e5a0..0cfed62 100644
--- a/runtime/native/java_lang_reflect_AbstractMethod.h
+++ b/runtime/native/java_lang_reflect_Executable.h
@@ -14,15 +14,15 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_NATIVE_JAVA_LANG_REFLECT_ABSTRACTMETHOD_H_
-#define ART_RUNTIME_NATIVE_JAVA_LANG_REFLECT_ABSTRACTMETHOD_H_
+#ifndef ART_RUNTIME_NATIVE_JAVA_LANG_REFLECT_EXECUTABLE_H_
+#define ART_RUNTIME_NATIVE_JAVA_LANG_REFLECT_EXECUTABLE_H_
#include <jni.h>
namespace art {
-void register_java_lang_reflect_AbstractMethod(JNIEnv* env);
+void register_java_lang_reflect_Executable(JNIEnv* env);
} // namespace art
-#endif // ART_RUNTIME_NATIVE_JAVA_LANG_REFLECT_ABSTRACTMETHOD_H_
+#endif // ART_RUNTIME_NATIVE_JAVA_LANG_REFLECT_EXECUTABLE_H_
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 67e3fe8..c69e98c 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -24,8 +24,8 @@
#include "dex_file-inl.h"
#include "indirect_reference_table-inl.h"
#include "jni_internal.h"
-#include "mirror/abstract_method.h"
#include "mirror/class-inl.h"
+#include "mirror/executable.h"
#include "mirror/object_array-inl.h"
#include "nth_caller_visitor.h"
#include "scoped_thread_state_change.h"
@@ -578,9 +578,9 @@
return nullptr;
}
- auto* abstract_method = soa.Decode<mirror::AbstractMethod*>(javaMethod);
- const bool accessible = abstract_method->IsAccessible();
- ArtMethod* m = abstract_method->GetArtMethod();
+ auto* executable = soa.Decode<mirror::Executable*>(javaMethod);
+ const bool accessible = executable->IsAccessible();
+ ArtMethod* m = executable->GetArtMethod();
mirror::Class* declaring_class = m->GetDeclaringClass();
if (UNLIKELY(!declaring_class->IsInitialized())) {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index f144b98..15e3b1c 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -108,9 +108,9 @@
#include "native/java_lang_VMClassLoader.h"
#include "native/java_lang_ref_FinalizerReference.h"
#include "native/java_lang_ref_Reference.h"
-#include "native/java_lang_reflect_AbstractMethod.h"
#include "native/java_lang_reflect_Array.h"
#include "native/java_lang_reflect_Constructor.h"
+#include "native/java_lang_reflect_Executable.h"
#include "native/java_lang_reflect_Field.h"
#include "native/java_lang_reflect_Method.h"
#include "native/java_lang_reflect_Parameter.h"
@@ -1378,9 +1378,9 @@
register_java_lang_DexCache(env);
register_java_lang_Object(env);
register_java_lang_ref_FinalizerReference(env);
- register_java_lang_reflect_AbstractMethod(env);
register_java_lang_reflect_Array(env);
register_java_lang_reflect_Constructor(env);
+ register_java_lang_reflect_Executable(env);
register_java_lang_reflect_Field(env);
register_java_lang_reflect_Method(env);
register_java_lang_reflect_Parameter(env);
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index a71578b..9fbf875 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -34,7 +34,9 @@
return (memcmp(version_, kVdexVersion, sizeof(kVdexVersion)) == 0);
}
-VdexFile::Header::Header() {
+VdexFile::Header::Header(uint32_t dex_size, uint32_t verifier_deps_size)
+ : dex_size_(dex_size),
+ verifier_deps_size_(verifier_deps_size) {
memcpy(magic_, kVdexMagic, sizeof(kVdexMagic));
memcpy(version_, kVdexVersion, sizeof(kVdexVersion));
DCHECK(IsMagicValid());
diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h
index 9215e52..6bea153 100644
--- a/runtime/vdex_file.h
+++ b/runtime/vdex_file.h
@@ -42,17 +42,22 @@
public:
struct Header {
public:
- Header();
+ Header(uint32_t dex_size, uint32_t verifier_deps_size);
bool IsMagicValid() const;
bool IsVersionValid() const;
+ uint32_t GetDexSize() const { return dex_size_; }
+ uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; }
+
private:
static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' };
static constexpr uint8_t kVdexVersion[] = { '0', '0', '0', '\0' };
uint8_t magic_[4];
uint8_t version_[4];
+ uint32_t dex_size_;
+ uint32_t verifier_deps_size_;
};
static VdexFile* Open(const std::string& vdex_filename,
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index f1d3189..abd741c 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3284,7 +3284,7 @@
}
break;
// Note: the following instructions encode offsets derived from class linking.
- // As such they use Class*/Field*/AbstractMethod* as these offsets only have
+ // As such they use Class*/Field*/Executable* as these offsets only have
// meaning if the class linking and resolution were successful.
case Instruction::IGET_QUICK:
VerifyQuickFieldAccess<FieldAccessType::kAccGet>(inst, reg_types_.Integer(), true);
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index 5f5fbc8..16c7f77 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -48,8 +48,8 @@
jclass WellKnownClasses::java_lang_NoClassDefFoundError;
jclass WellKnownClasses::java_lang_Object;
jclass WellKnownClasses::java_lang_OutOfMemoryError;
-jclass WellKnownClasses::java_lang_reflect_AbstractMethod;
jclass WellKnownClasses::java_lang_reflect_Constructor;
+jclass WellKnownClasses::java_lang_reflect_Executable;
jclass WellKnownClasses::java_lang_reflect_Field;
jclass WellKnownClasses::java_lang_reflect_Method;
jclass WellKnownClasses::java_lang_reflect_Proxy;
@@ -154,7 +154,7 @@
jfieldID WellKnownClasses::java_lang_Throwable_stackTrace;
jfieldID WellKnownClasses::java_lang_Throwable_stackState;
jfieldID WellKnownClasses::java_lang_Throwable_suppressedExceptions;
-jfieldID WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod;
+jfieldID WellKnownClasses::java_lang_reflect_Executable_artMethod;
jfieldID WellKnownClasses::java_lang_reflect_Proxy_h;
jfieldID WellKnownClasses::java_nio_DirectByteBuffer_capacity;
jfieldID WellKnownClasses::java_nio_DirectByteBuffer_effectiveDirectAddress;
@@ -237,8 +237,8 @@
java_lang_ExceptionInInitializerError = CacheClass(env, "java/lang/ExceptionInInitializerError");
java_lang_IllegalAccessError = CacheClass(env, "java/lang/IllegalAccessError");
java_lang_NoClassDefFoundError = CacheClass(env, "java/lang/NoClassDefFoundError");
- java_lang_reflect_AbstractMethod = CacheClass(env, "java/lang/reflect/AbstractMethod");
java_lang_reflect_Constructor = CacheClass(env, "java/lang/reflect/Constructor");
+ java_lang_reflect_Executable = CacheClass(env, "java/lang/reflect/Executable");
java_lang_reflect_Field = CacheClass(env, "java/lang/reflect/Field");
java_lang_reflect_Method = CacheClass(env, "java/lang/reflect/Method");
java_lang_reflect_Proxy = CacheClass(env, "java/lang/reflect/Proxy");
@@ -362,7 +362,7 @@
java_lang_Throwable_stackTrace = CacheField(env, java_lang_Throwable, false, "stackTrace", "[Ljava/lang/StackTraceElement;");
java_lang_Throwable_stackState = CacheField(env, java_lang_Throwable, false, "backtrace", "Ljava/lang/Object;");
java_lang_Throwable_suppressedExceptions = CacheField(env, java_lang_Throwable, false, "suppressedExceptions", "Ljava/util/List;");
- java_lang_reflect_AbstractMethod_artMethod = CacheField(env, java_lang_reflect_AbstractMethod, false, "artMethod", "J");
+ java_lang_reflect_Executable_artMethod = CacheField(env, java_lang_reflect_Executable, false, "artMethod", "J");
java_lang_reflect_Proxy_h = CacheField(env, java_lang_reflect_Proxy, false, "h", "Ljava/lang/reflect/InvocationHandler;");
java_nio_DirectByteBuffer_capacity = CacheField(env, java_nio_DirectByteBuffer, false, "capacity", "I");
java_nio_DirectByteBuffer_effectiveDirectAddress = CacheField(env, java_nio_DirectByteBuffer, false, "address", "J");
diff --git a/runtime/well_known_classes.h b/runtime/well_known_classes.h
index ce710ff..b4d179c 100644
--- a/runtime/well_known_classes.h
+++ b/runtime/well_known_classes.h
@@ -59,8 +59,8 @@
static jclass java_lang_NoClassDefFoundError;
static jclass java_lang_Object;
static jclass java_lang_OutOfMemoryError;
- static jclass java_lang_reflect_AbstractMethod;
static jclass java_lang_reflect_Constructor;
+ static jclass java_lang_reflect_Executable;
static jclass java_lang_reflect_Field;
static jclass java_lang_reflect_Method;
static jclass java_lang_reflect_Proxy;
@@ -148,7 +148,7 @@
static jfieldID dalvik_system_DexPathList_dexElements;
static jfieldID dalvik_system_DexPathList__Element_dexFile;
static jfieldID dalvik_system_PathClassLoader_pathList;
- static jfieldID java_lang_reflect_AbstractMethod_artMethod;
+ static jfieldID java_lang_reflect_Executable_artMethod;
static jfieldID java_lang_reflect_Proxy_h;
static jfieldID java_lang_Thread_daemon;
static jfieldID java_lang_Thread_group;
diff --git a/test/031-class-attributes/src/ClassAttrs.java b/test/031-class-attributes/src/ClassAttrs.java
index 346e13d..39e69a3 100644
--- a/test/031-class-attributes/src/ClassAttrs.java
+++ b/test/031-class-attributes/src/ClassAttrs.java
@@ -1,9 +1,9 @@
import otherpackage.OtherPackageClass;
import java.io.Serializable;
-import java.lang.reflect.AbstractMethod;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
+import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -223,7 +223,7 @@
try {
Class<?> c = obj.getClass();
if (c == Method.class || c == Constructor.class) {
- c = AbstractMethod.class;
+ c = Executable.class;
}
method = c.getDeclaredMethod("getSignatureAttribute");
method.setAccessible(true);
diff --git a/test/961-default-iface-resolut-generated/build b/test/961-default-iface-resolution-gen/build
similarity index 100%
rename from test/961-default-iface-resolut-generated/build
rename to test/961-default-iface-resolution-gen/build
diff --git a/test/961-default-iface-resolut-generated/expected.txt b/test/961-default-iface-resolution-gen/expected.txt
similarity index 100%
rename from test/961-default-iface-resolut-generated/expected.txt
rename to test/961-default-iface-resolution-gen/expected.txt
diff --git a/test/961-default-iface-resolut-generated/info.txt b/test/961-default-iface-resolution-gen/info.txt
similarity index 100%
rename from test/961-default-iface-resolut-generated/info.txt
rename to test/961-default-iface-resolution-gen/info.txt
diff --git a/test/961-default-iface-resolut-generated/util-src/generate_java.py b/test/961-default-iface-resolution-gen/util-src/generate_java.py
similarity index 100%
rename from test/961-default-iface-resolut-generated/util-src/generate_java.py
rename to test/961-default-iface-resolution-gen/util-src/generate_java.py
diff --git a/test/964-default-iface-init-generated/build b/test/964-default-iface-init-gen/build
similarity index 100%
rename from test/964-default-iface-init-generated/build
rename to test/964-default-iface-init-gen/build
diff --git a/test/964-default-iface-init-generated/expected.txt b/test/964-default-iface-init-gen/expected.txt
similarity index 100%
rename from test/964-default-iface-init-generated/expected.txt
rename to test/964-default-iface-init-gen/expected.txt
diff --git a/test/964-default-iface-init-generated/info.txt b/test/964-default-iface-init-gen/info.txt
similarity index 100%
rename from test/964-default-iface-init-generated/info.txt
rename to test/964-default-iface-init-gen/info.txt
diff --git a/test/964-default-iface-init-generated/src/Displayer.java b/test/964-default-iface-init-gen/src/Displayer.java
similarity index 100%
rename from test/964-default-iface-init-generated/src/Displayer.java
rename to test/964-default-iface-init-gen/src/Displayer.java
diff --git a/test/964-default-iface-init-generated/util-src/generate_java.py b/test/964-default-iface-init-gen/util-src/generate_java.py
similarity index 100%
rename from test/964-default-iface-init-generated/util-src/generate_java.py
rename to test/964-default-iface-init-gen/util-src/generate_java.py
diff --git a/test/968-default-part-compile-generated/build b/test/968-default-partial-compile-gen/build
similarity index 100%
rename from test/968-default-part-compile-generated/build
rename to test/968-default-partial-compile-gen/build
diff --git a/test/968-default-part-compile-generated/expected.txt b/test/968-default-partial-compile-gen/expected.txt
similarity index 100%
rename from test/968-default-part-compile-generated/expected.txt
rename to test/968-default-partial-compile-gen/expected.txt
diff --git a/test/968-default-part-compile-generated/info.txt b/test/968-default-partial-compile-gen/info.txt
similarity index 100%
rename from test/968-default-part-compile-generated/info.txt
rename to test/968-default-partial-compile-gen/info.txt
diff --git a/test/968-default-part-compile-generated/util-src/generate_java.py b/test/968-default-partial-compile-gen/util-src/generate_java.py
similarity index 100%
rename from test/968-default-part-compile-generated/util-src/generate_java.py
rename to test/968-default-partial-compile-gen/util-src/generate_java.py
diff --git a/test/968-default-part-compile-generated/util-src/generate_smali.py b/test/968-default-partial-compile-gen/util-src/generate_smali.py
similarity index 100%
rename from test/968-default-part-compile-generated/util-src/generate_smali.py
rename to test/968-default-partial-compile-gen/util-src/generate_smali.py
diff --git a/test/970-iface-superresolution-generated/build b/test/970-iface-super-resolution-gen/build
similarity index 100%
rename from test/970-iface-superresolution-generated/build
rename to test/970-iface-super-resolution-gen/build
diff --git a/test/970-iface-superresolution-generated/expected.txt b/test/970-iface-super-resolution-gen/expected.txt
similarity index 100%
rename from test/970-iface-superresolution-generated/expected.txt
rename to test/970-iface-super-resolution-gen/expected.txt
diff --git a/test/970-iface-superresolution-generated/info.txt b/test/970-iface-super-resolution-gen/info.txt
similarity index 100%
rename from test/970-iface-superresolution-generated/info.txt
rename to test/970-iface-super-resolution-gen/info.txt
diff --git a/test/970-iface-superresolution-generated/util-src/generate_java.py b/test/970-iface-super-resolution-gen/util-src/generate_java.py
similarity index 100%
rename from test/970-iface-superresolution-generated/util-src/generate_java.py
rename to test/970-iface-super-resolution-gen/util-src/generate_java.py
diff --git a/test/970-iface-superresolution-generated/util-src/generate_smali.py b/test/970-iface-super-resolution-gen/util-src/generate_smali.py
similarity index 100%
rename from test/970-iface-superresolution-generated/util-src/generate_smali.py
rename to test/970-iface-super-resolution-gen/util-src/generate_smali.py
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 559e963..3bcea18 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -278,11 +278,11 @@
# Tests that require python3.
TEST_ART_PYTHON3_DEPENDENCY_RUN_TESTS := \
960-default-smali \
- 961-default-iface-resolut-generated \
- 964-default-iface-init-generated \
- 968-default-part-compile-generated \
+ 961-default-iface-resolution-gen \
+ 964-default-iface-init-gen \
+ 968-default-partial-compile-gen \
969-iface-super \
- 970-iface-superresolution-generated \
+ 970-iface-super-resolution-gen \
971-iface-super
# Check if we have python3 to run our tests.
@@ -362,13 +362,13 @@
# Tests that are broken with GC stress.
# * 137-cfi needs to unwind a second forked process. We're using a primitive sleep to wait till we
# hope the second process got into the expected state. The slowness of gcstress makes this bad.
-# * 961-default-iface-resolut-generated and 964-default-iface-init-generated are very long tests
-# that often will take more than the timeout to run when gcstress is enabled. This is because
-# gcstress slows down allocations significantly which these tests do a lot.
+# * 961-default-iface-resolution-gen and 964-default-iface-init-genare very long tests that often
+# will take more than the timeout to run when gcstress is enabled. This is because gcstress
+# slows down allocations significantly which these tests do a lot.
TEST_ART_BROKEN_GCSTRESS_RUN_TESTS := \
137-cfi \
- 961-default-iface-resolut-generated \
- 964-default-iface-init-generated
+ 961-default-iface-resolution-gen \
+ 964-default-iface-init-gen
ifneq (,$(filter gcstress,$(GC_TYPES)))
ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \
diff --git a/tools/bisection_search/README.md b/tools/bisection_search/README.md
index 64ccb20..d641102 100644
--- a/tools/bisection_search/README.md
+++ b/tools/bisection_search/README.md
@@ -21,12 +21,14 @@
./bisection_search.py -cp classes.dex --expected-output out_int --class Test
-2. Raw-cmd invocation, dalvikvm command is accepted as an argument. The command
- has to start with an executable.
+2. Raw-cmd invocation, dalvikvm command is accepted as an argument.
Extra dalvikvm arguments will be placed on second position in the command
by default. {ARGS} tag can be used to specify a custom position.
+ If used in device mode, the command has to exec a dalvikvm instance. Bisection
+ will fail if pid of the process started by raw-cmd is different than pid of runtime.
+
./bisection_search.py --raw-cmd='run.sh -cp classes.dex Test' --expected-retcode SUCCESS
./bisection_search.py --raw-cmd='/bin/sh art {ARGS} -cp classes.dex Test' --expected-retcode SUCCESS
diff --git a/tools/bisection_search/bisection_search.py b/tools/bisection_search/bisection_search.py
index 0d36aa4..b7f1907 100755
--- a/tools/bisection_search/bisection_search.py
+++ b/tools/bisection_search/bisection_search.py
@@ -34,6 +34,7 @@
from common import FatalError
from common import GetEnvVariableOrError
from common import HostTestEnv
+from common import LogSeverity
from common import RetCode
@@ -57,6 +58,9 @@
# position in the command.
RAW_CMD_RUNTIME_ARGS_TAG = '{ARGS}'
+# Default core image path relative to ANDROID_HOST_OUT.
+DEFAULT_IMAGE_RELATIVE_PATH = '/framework/core.art'
+
class Dex2OatWrapperTestable(object):
"""Class representing a testable compilation.
@@ -104,10 +108,9 @@
print('Testing methods: {0} passes: {1}.'.format(
compiled_methods, passes_to_run))
cmd = self._PrepareCmd(compiled_methods=compiled_methods,
- passes_to_run=passes_to_run,
- verbose_compiler=False)
+ passes_to_run=passes_to_run)
(output, ret_code) = self._test_env.RunCommand(
- cmd, {'ANDROID_LOG_TAGS': '*:e'})
+ cmd, LogSeverity.ERROR)
res = True
if self._expected_retcode:
res = self._expected_retcode == ret_code
@@ -126,8 +129,8 @@
Raises:
FatalError: An error occurred when retrieving methods list.
"""
- cmd = self._PrepareCmd(verbose_compiler=True)
- (output, _) = self._test_env.RunCommand(cmd, {'ANDROID_LOG_TAGS': '*:i'})
+ cmd = self._PrepareCmd()
+ (output, _) = self._test_env.RunCommand(cmd, LogSeverity.INFO)
match_methods = re.findall(r'Building ([^\n]+)\n', output)
if not match_methods:
raise FatalError('Failed to retrieve methods list. '
@@ -146,9 +149,8 @@
Raises:
FatalError: An error occurred when retrieving passes list.
"""
- cmd = self._PrepareCmd(compiled_methods=[compiled_method],
- verbose_compiler=True)
- (output, _) = self._test_env.RunCommand(cmd, {'ANDROID_LOG_TAGS': '*:i'})
+ cmd = self._PrepareCmd(compiled_methods=[compiled_method])
+ (output, _) = self._test_env.RunCommand(cmd, LogSeverity.INFO)
match_passes = re.findall(r'Starting pass: ([^\n]+)\n', output)
if not match_passes:
raise FatalError('Failed to retrieve passes list. '
@@ -168,9 +170,8 @@
self._test_env.WriteLines(self._passes_to_run_path, passes_to_run)
cmd += ['-Xcompiler-option', '--run-passes={0}'.format(
self._passes_to_run_path)]
- if verbose_compiler:
- cmd += ['-Xcompiler-option', '--runtime-arg', '-Xcompiler-option',
- '-verbose:compiler', '-Xcompiler-option', '-j1']
+ cmd += ['-Xcompiler-option', '--runtime-arg', '-Xcompiler-option',
+ '-verbose:compiler', '-Xcompiler-option', '-j1']
cmd += self._base_cmd[self._arguments_position:]
return cmd
@@ -361,8 +362,8 @@
if not args.device:
base_cmd += ['-XXlib:{0}'.format(args.lib)]
if not args.image:
- image_path = '{0}/framework/core-optimizing-pic.art'.format(
- GetEnvVariableOrError('ANDROID_HOST_OUT'))
+ image_path = (GetEnvVariableOrError('ANDROID_HOST_OUT') +
+ DEFAULT_IMAGE_RELATIVE_PATH)
else:
image_path = args.image
base_cmd += ['-Ximage:{0}'.format(image_path)]
diff --git a/tools/bisection_search/common.py b/tools/bisection_search/common.py
index b69b606..3d92ee5 100755
--- a/tools/bisection_search/common.py
+++ b/tools/bisection_search/common.py
@@ -21,6 +21,7 @@
import signal
import shlex
import shutil
+import time
from subprocess import check_call
from subprocess import PIPE
@@ -51,6 +52,48 @@
NOTRUN = 4
+@unique
+class LogSeverity(Enum):
+ VERBOSE = 0
+ DEBUG = 1
+ INFO = 2
+ WARNING = 3
+ ERROR = 4
+ FATAL = 5
+ SILENT = 6
+
+ @property
+ def symbol(self):
+ return self.name[0]
+
+ @classmethod
+ def FromSymbol(cls, s):
+ for log_severity in LogSeverity:
+ if log_severity.symbol == s:
+ return log_severity
+ raise ValueError("{0} is not a valid log severity symbol".format(s))
+
+ def __ge__(self, other):
+ if self.__class__ is other.__class__:
+ return self.value >= other.value
+ return NotImplemented
+
+ def __gt__(self, other):
+ if self.__class__ is other.__class__:
+ return self.value > other.value
+ return NotImplemented
+
+ def __le__(self, other):
+ if self.__class__ is other.__class__:
+ return self.value <= other.value
+ return NotImplemented
+
+ def __lt__(self, other):
+ if self.__class__ is other.__class__:
+ return self.value < other.value
+ return NotImplemented
+
+
def GetEnvVariableOrError(variable_name):
"""Gets value of an environmental variable.
@@ -116,23 +159,17 @@
return (output, stderr_output, retcode)
-def _RunCommandForOutputAndLog(cmd, env, logfile, timeout=60):
- """Runs command and logs its output. Returns the output.
+def _LogCmdOutput(logfile, cmd, output, retcode):
+ """Logs output of a command.
Args:
- cmd: list of strings, command to run.
- env: shell environment to run the command with.
logfile: file handle to logfile.
- timeout: int, timeout in seconds.
-
- Returns:
- tuple (string, string, RetCode) stdout output, stderr output, normalized
- return code.
+ cmd: list of strings, command.
+ output: command output.
+ retcode: RetCode, normalized retcode.
"""
- (output, _, retcode) = RunCommandForOutput(cmd, env, PIPE, STDOUT, timeout)
logfile.write('Command:\n{0}\n{1}\nReturn code: {2}\n'.format(
CommandListToCommandString(cmd), output, retcode))
- return (output, retcode)
def CommandListToCommandString(cmd):
@@ -187,15 +224,14 @@
"""
@abc.abstractmethod
- def RunCommand(self, cmd, env_updates=None):
- """Runs command in environment with updated environmental variables.
+ def RunCommand(self, cmd, log_severity=LogSeverity.ERROR):
+ """Runs command in environment.
Args:
cmd: list of strings, command to run.
- env_updates: dict, string to string, maps names of variables to their
- updated values.
+ log_severity: LogSeverity, minimum severity of logs included in output.
Returns:
- tuple (string, string, int) stdout output, stderr output, return code.
+ tuple (string, int) output, return code.
"""
@abc.abstractproperty
@@ -262,13 +298,17 @@
f.writelines('{0}\n'.format(line) for line in lines)
return
- def RunCommand(self, cmd, env_updates=None):
- if not env_updates:
- env_updates = {}
+ def RunCommand(self, cmd, log_severity=LogSeverity.ERROR):
self._EmptyDexCache()
env = self._shell_env.copy()
- env.update(env_updates)
- return _RunCommandForOutputAndLog(cmd, env, self._logfile, self._timeout)
+ env.update({'ANDROID_LOG_TAGS':'*:' + log_severity.symbol.lower()})
+ (output, err_output, retcode) = RunCommandForOutput(
+ cmd, env, PIPE, PIPE, self._timeout)
+ # We append err_output to output to stay consistent with DeviceTestEnv
+ # implementation.
+ output += err_output
+ _LogCmdOutput(self._logfile, cmd, output, retcode)
+ return (output, retcode)
@property
def logfile(self):
@@ -341,26 +381,63 @@
self._AdbPush(temp_file.name, file_path)
return
- def RunCommand(self, cmd, env_updates=None):
- if not env_updates:
- env_updates = {}
+ def _ExtractPid(self, brief_log_line):
+ """Extracts PID from a single logcat line in brief format."""
+ pid_start_idx = brief_log_line.find('(') + 2
+ if pid_start_idx == -1:
+ return None
+ pid_end_idx = brief_log_line.find(')', pid_start_idx)
+ if pid_end_idx == -1:
+ return None
+ return brief_log_line[pid_start_idx:pid_end_idx]
+
+ def _ExtractSeverity(self, brief_log_line):
+ """Extracts LogSeverity from a single logcat line in brief format."""
+ if not brief_log_line:
+ return None
+ return LogSeverity.FromSymbol(brief_log_line[0])
+
+ def RunCommand(self, cmd, log_severity=LogSeverity.ERROR):
self._EmptyDexCache()
- if 'ANDROID_DATA' not in env_updates:
- env_updates['ANDROID_DATA'] = self._device_env_path
- env_updates_cmd = ' '.join(['{0}={1}'.format(var, val) for var, val
- in env_updates.items()])
- cmd = CommandListToCommandString(cmd)
- adb = 'adb'
+ env_vars_cmd = 'ANDROID_DATA={0} ANDROID_LOG_TAGS=*:i'.format(
+ self._device_env_path)
+ adb_cmd = ['adb']
if self._specific_device:
- adb += ' -s ' + self._specific_device
- cmd = '{0} shell "logcat -c && {1} {2}"'.format(
- adb, env_updates_cmd, cmd)
- (output, retcode) = _RunCommandForOutputAndLog(
- shlex.split(cmd), self._shell_env, self._logfile, self._timeout)
- logcat_cmd = 'adb shell "logcat -d -s -b main dex2oat:* dex2oatd:*"'
- (err_output, _) = _RunCommandForOutputAndLog(
- shlex.split(logcat_cmd), self._shell_env, self._logfile)
- return (output + err_output, retcode)
+ adb_cmd += ['-s', self._specific_device]
+ logcat_cmd = adb_cmd + ['logcat', '-v', 'brief', '-s', '-b', 'main',
+ '-T', '1', 'dex2oat:*', 'dex2oatd:*']
+ logcat_proc = Popen(logcat_cmd, stdout=PIPE, stderr=STDOUT,
+ universal_newlines=True)
+ cmd_str = CommandListToCommandString(cmd)
+ # Print PID of the shell and exec command. We later retrieve this PID and
+ # use it to filter dex2oat logs, keeping those with matching parent PID.
+ device_cmd = ('echo $$ && ' + env_vars_cmd + ' exec ' + cmd_str)
+ cmd = adb_cmd + ['shell', device_cmd]
+ (output, _, retcode) = RunCommandForOutput(cmd, self._shell_env, PIPE,
+ STDOUT, self._timeout)
+ # We need to make sure to only kill logcat once all relevant logs arrive.
+ # Sleep is used for simplicity.
+ time.sleep(0.5)
+ logcat_proc.kill()
+ end_of_first_line = output.find('\n')
+ if end_of_first_line != -1:
+ parent_pid = output[:end_of_first_line]
+ output = output[end_of_first_line + 1:]
+ logcat_output, _ = logcat_proc.communicate()
+ logcat_lines = logcat_output.splitlines(keepends=True)
+ dex2oat_pids = []
+ for line in logcat_lines:
+ # Dex2oat was started by our runtime instance.
+ if 'Running dex2oat (parent PID = ' + parent_pid in line:
+ dex2oat_pids.append(self._ExtractPid(line))
+ break
+ if dex2oat_pids:
+ for line in logcat_lines:
+ if (self._ExtractPid(line) in dex2oat_pids and
+ self._ExtractSeverity(line) >= log_severity):
+ output += line
+ _LogCmdOutput(self._logfile, cmd, output, retcode)
+ return (output, retcode)
@property
def logfile(self):
diff --git a/tools/libcore_failures_concurrent_collector.txt b/tools/libcore_failures_concurrent_collector.txt
index 95f0c2d..0e289a6 100644
--- a/tools/libcore_failures_concurrent_collector.txt
+++ b/tools/libcore_failures_concurrent_collector.txt
@@ -10,11 +10,4 @@
*/
[
-{
- description: "Assertion failing on the concurrent collector configuration.",
- result: EXEC_FAILED,
- names: ["jsr166.LinkedTransferQueueTest#testTransfer2",
- "jsr166.LinkedTransferQueueTest#testWaitingConsumer"],
- bug: 25883050
-}
]