Merge "Stress profile saving for gc-stress tests"
diff --git a/Android.bp b/Android.bp
index ad42d3f..bb92e5f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,7 +1,6 @@
// TODO: These should be handled with transitive static library dependencies
art_static_dependencies = [
// Note: the order is important because of static linking resolution.
- "libdexfile",
"libziparchive",
"libnativehelper",
"libnativebridge",
diff --git a/Android.mk b/Android.mk
index 361ceec..2489308 100644
--- a/Android.mk
+++ b/Android.mk
@@ -79,6 +79,7 @@
include $(art_path)/oatdump/Android.mk
include $(art_path)/tools/Android.mk
include $(art_path)/tools/ahat/Android.mk
+include $(art_path)/tools/amm/Android.mk
include $(art_path)/tools/dexfuzz/Android.mk
include $(art_path)/libart_fake/Android.mk
@@ -486,8 +487,10 @@
$(ART_TARGET_SHARED_LIBRARY_BENCHMARK) \
$(TARGET_CORE_IMG_OUT_BASE).art \
$(TARGET_CORE_IMG_OUT_BASE)-interpreter.art
+ # remove libartd.so and libdexfiled.so from public.libraries.txt because golem builds
+ # won't have it.
sed -i '/libartd.so/d' $(TARGET_OUT)/etc/public.libraries.txt
- # remove libartd.so from public.libraries.txt because golem builds won't have it.
+ sed -i '/libdexfiled.so/d' $(TARGET_OUT)/etc/public.libraries.txt
########################################################################
# Phony target for building what go/lem requires on host.
diff --git a/compiler/Android.bp b/compiler/Android.bp
index 4539659..ba08d79 100644
--- a/compiler/Android.bp
+++ b/compiler/Android.bp
@@ -184,7 +184,6 @@
},
generated_sources: ["art_compiler_operator_srcs"],
shared_libs: [
- "libdexfile",
"libbase",
"libcutils", // for atrace.
"liblzma",
@@ -250,6 +249,7 @@
},
shared_libs: [
"libart",
+ "libdexfile",
],
pgo: {
@@ -295,6 +295,7 @@
},
shared_libs: [
"libartd",
+ "libdexfiled",
],
}
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 3c5a37f..60de722 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -618,14 +618,18 @@
protected:
// Patch info used for recording locations of required linker patches and their targets,
- // i.e. target method, string, type or code identified by their dex file and index.
+ // i.e. target method, string, type or code identified by their dex file and index,
+ // or .data.bimg.rel.ro entries identified by the boot image offset.
template <typename LabelType>
struct PatchInfo {
- PatchInfo(const DexFile& target_dex_file, uint32_t target_index)
- : dex_file(target_dex_file), index(target_index) { }
+ PatchInfo(const DexFile* dex_file, uint32_t off_or_idx)
+ : target_dex_file(dex_file), offset_or_index(off_or_idx), label() { }
- const DexFile& dex_file;
- uint32_t index;
+ // Target dex file or null for .data.bmig.rel.ro patches.
+ const DexFile* target_dex_file;
+ // Either the boot image offset (to write to .data.bmig.rel.ro) or string/type/method index.
+ uint32_t offset_or_index;
+ // Label for the instruction to patch.
LabelType label;
};
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 3fd88e3..60f8f98 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -1395,11 +1395,11 @@
graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
uint64_literals_(std::less<uint64_t>(),
graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
baker_read_barrier_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
jit_string_patches_(StringReferenceValueComparator(),
@@ -4447,11 +4447,11 @@
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative: {
DCHECK(GetCompilerOptions().IsBootImage());
// Add ADRP with its PC-relative method patch.
- vixl::aarch64::Label* adrp_label = NewPcRelativeMethodPatch(invoke->GetTargetMethod());
+ vixl::aarch64::Label* adrp_label = NewBootImageMethodPatch(invoke->GetTargetMethod());
EmitAdrpPlaceholder(adrp_label, XRegisterFrom(temp));
// Add ADD with its PC-relative method patch.
vixl::aarch64::Label* add_label =
- NewPcRelativeMethodPatch(invoke->GetTargetMethod(), adrp_label);
+ NewBootImageMethodPatch(invoke->GetTargetMethod(), adrp_label);
EmitAddPlaceholder(add_label, XRegisterFrom(temp), XRegisterFrom(temp));
break;
}
@@ -4559,51 +4559,47 @@
codegen_->MaybeGenerateMarkingRegisterCheck(/* code */ __LINE__);
}
-vixl::aarch64::Label* CodeGeneratorARM64::NewPcRelativeMethodPatch(
+vixl::aarch64::Label* CodeGeneratorARM64::NewBootImageMethodPatch(
MethodReference target_method,
vixl::aarch64::Label* adrp_label) {
- return NewPcRelativePatch(*target_method.dex_file,
- target_method.index,
- adrp_label,
- &pc_relative_method_patches_);
+ return NewPcRelativePatch(
+ target_method.dex_file, target_method.index, adrp_label, &boot_image_method_patches_);
}
vixl::aarch64::Label* CodeGeneratorARM64::NewMethodBssEntryPatch(
MethodReference target_method,
vixl::aarch64::Label* adrp_label) {
- return NewPcRelativePatch(*target_method.dex_file,
- target_method.index,
- adrp_label,
- &method_bss_entry_patches_);
+ return NewPcRelativePatch(
+ target_method.dex_file, target_method.index, adrp_label, &method_bss_entry_patches_);
}
-vixl::aarch64::Label* CodeGeneratorARM64::NewPcRelativeTypePatch(
+vixl::aarch64::Label* CodeGeneratorARM64::NewBootImageTypePatch(
const DexFile& dex_file,
dex::TypeIndex type_index,
vixl::aarch64::Label* adrp_label) {
- return NewPcRelativePatch(dex_file, type_index.index_, adrp_label, &pc_relative_type_patches_);
+ return NewPcRelativePatch(&dex_file, type_index.index_, adrp_label, &boot_image_type_patches_);
}
vixl::aarch64::Label* CodeGeneratorARM64::NewBssEntryTypePatch(
const DexFile& dex_file,
dex::TypeIndex type_index,
vixl::aarch64::Label* adrp_label) {
- return NewPcRelativePatch(dex_file, type_index.index_, adrp_label, &type_bss_entry_patches_);
+ return NewPcRelativePatch(&dex_file, type_index.index_, adrp_label, &type_bss_entry_patches_);
}
-vixl::aarch64::Label* CodeGeneratorARM64::NewPcRelativeStringPatch(
+vixl::aarch64::Label* CodeGeneratorARM64::NewBootImageStringPatch(
const DexFile& dex_file,
dex::StringIndex string_index,
vixl::aarch64::Label* adrp_label) {
- return
- NewPcRelativePatch(dex_file, string_index.index_, adrp_label, &pc_relative_string_patches_);
+ return NewPcRelativePatch(
+ &dex_file, string_index.index_, adrp_label, &boot_image_string_patches_);
}
vixl::aarch64::Label* CodeGeneratorARM64::NewStringBssEntryPatch(
const DexFile& dex_file,
dex::StringIndex string_index,
vixl::aarch64::Label* adrp_label) {
- return NewPcRelativePatch(dex_file, string_index.index_, adrp_label, &string_bss_entry_patches_);
+ return NewPcRelativePatch(&dex_file, string_index.index_, adrp_label, &string_bss_entry_patches_);
}
vixl::aarch64::Label* CodeGeneratorARM64::NewBakerReadBarrierPatch(uint32_t custom_data) {
@@ -4612,7 +4608,7 @@
}
vixl::aarch64::Label* CodeGeneratorARM64::NewPcRelativePatch(
- const DexFile& dex_file,
+ const DexFile* dex_file,
uint32_t offset_or_index,
vixl::aarch64::Label* adrp_label,
ArenaDeque<PcRelativePatchInfo>* patches) {
@@ -4679,7 +4675,7 @@
ArenaVector<linker::LinkerPatch>* linker_patches) {
for (const PcRelativePatchInfo& info : infos) {
linker_patches->push_back(Factory(info.label.GetLocation(),
- &info.target_dex_file,
+ info.target_dex_file,
info.pc_insn_label->GetLocation(),
info.offset_or_index));
}
@@ -4688,27 +4684,27 @@
void CodeGeneratorARM64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
- pc_relative_method_patches_.size() +
+ boot_image_method_patches_.size() +
method_bss_entry_patches_.size() +
- pc_relative_type_patches_.size() +
+ boot_image_type_patches_.size() +
type_bss_entry_patches_.size() +
- pc_relative_string_patches_.size() +
+ boot_image_string_patches_.size() +
string_bss_entry_patches_.size() +
baker_read_barrier_patches_.size();
linker_patches->reserve(size);
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeMethodPatch>(
- pc_relative_method_patches_, linker_patches);
+ boot_image_method_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>(
- pc_relative_type_patches_, linker_patches);
+ boot_image_type_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>(
- pc_relative_string_patches_, linker_patches);
+ boot_image_string_patches_, linker_patches);
} else {
- DCHECK(pc_relative_method_patches_.empty());
+ DCHECK(boot_image_method_patches_.empty());
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeClassTablePatch>(
- pc_relative_type_patches_, linker_patches);
+ boot_image_type_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringInternTablePatch>(
- pc_relative_string_patches_, linker_patches);
+ boot_image_string_patches_, linker_patches);
}
EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>(
method_bss_entry_patches_, linker_patches);
@@ -4876,11 +4872,11 @@
// Add ADRP with its PC-relative type patch.
const DexFile& dex_file = cls->GetDexFile();
dex::TypeIndex type_index = cls->GetTypeIndex();
- vixl::aarch64::Label* adrp_label = codegen_->NewPcRelativeTypePatch(dex_file, type_index);
+ vixl::aarch64::Label* adrp_label = codegen_->NewBootImageTypePatch(dex_file, type_index);
codegen_->EmitAdrpPlaceholder(adrp_label, out.X());
// Add ADD with its PC-relative type patch.
vixl::aarch64::Label* add_label =
- codegen_->NewPcRelativeTypePatch(dex_file, type_index, adrp_label);
+ codegen_->NewBootImageTypePatch(dex_file, type_index, adrp_label);
codegen_->EmitAddPlaceholder(add_label, out.X(), out.X());
break;
}
@@ -4897,11 +4893,11 @@
// Add ADRP with its PC-relative type patch.
const DexFile& dex_file = cls->GetDexFile();
dex::TypeIndex type_index = cls->GetTypeIndex();
- vixl::aarch64::Label* adrp_label = codegen_->NewPcRelativeTypePatch(dex_file, type_index);
+ vixl::aarch64::Label* adrp_label = codegen_->NewBootImageTypePatch(dex_file, type_index);
codegen_->EmitAdrpPlaceholder(adrp_label, out.X());
// Add LDR with its PC-relative type patch.
vixl::aarch64::Label* ldr_label =
- codegen_->NewPcRelativeTypePatch(dex_file, type_index, adrp_label);
+ codegen_->NewBootImageTypePatch(dex_file, type_index, adrp_label);
codegen_->EmitLdrOffsetPlaceholder(ldr_label, out.W(), out.X());
// Extract the reference from the slot data, i.e. clear the hash bits.
int32_t masked_hash = ClassTable::TableSlot::MaskHash(
@@ -5044,11 +5040,11 @@
// Add ADRP with its PC-relative String patch.
const DexFile& dex_file = load->GetDexFile();
const dex::StringIndex string_index = load->GetStringIndex();
- vixl::aarch64::Label* adrp_label = codegen_->NewPcRelativeStringPatch(dex_file, string_index);
+ vixl::aarch64::Label* adrp_label = codegen_->NewBootImageStringPatch(dex_file, string_index);
codegen_->EmitAdrpPlaceholder(adrp_label, out.X());
// Add ADD with its PC-relative String patch.
vixl::aarch64::Label* add_label =
- codegen_->NewPcRelativeStringPatch(dex_file, string_index, adrp_label);
+ codegen_->NewBootImageStringPatch(dex_file, string_index, adrp_label);
codegen_->EmitAddPlaceholder(add_label, out.X(), out.X());
return;
}
@@ -5064,11 +5060,11 @@
// Add ADRP with its PC-relative String patch.
const DexFile& dex_file = load->GetDexFile();
const dex::StringIndex string_index = load->GetStringIndex();
- vixl::aarch64::Label* adrp_label = codegen_->NewPcRelativeStringPatch(dex_file, string_index);
+ vixl::aarch64::Label* adrp_label = codegen_->NewBootImageStringPatch(dex_file, string_index);
codegen_->EmitAdrpPlaceholder(adrp_label, out.X());
// Add LDR with its PC-relative String patch.
vixl::aarch64::Label* ldr_label =
- codegen_->NewPcRelativeStringPatch(dex_file, string_index, adrp_label);
+ codegen_->NewBootImageStringPatch(dex_file, string_index, adrp_label);
codegen_->EmitLdrOffsetPlaceholder(ldr_label, out.W(), out.X());
return;
}
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index f92c94f..e34f799 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -565,8 +565,8 @@
// to be bound before the instruction. The instruction will be either the
// ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
// to the associated ADRP patch label).
- vixl::aarch64::Label* NewPcRelativeMethodPatch(MethodReference target_method,
- vixl::aarch64::Label* adrp_label = nullptr);
+ vixl::aarch64::Label* NewBootImageMethodPatch(MethodReference target_method,
+ vixl::aarch64::Label* adrp_label = nullptr);
// Add a new .bss entry method patch for an instruction and return
// the label to be bound before the instruction. The instruction will be
@@ -579,9 +579,9 @@
// to be bound before the instruction. The instruction will be either the
// ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
// to the associated ADRP patch label).
- vixl::aarch64::Label* NewPcRelativeTypePatch(const DexFile& dex_file,
- dex::TypeIndex type_index,
- vixl::aarch64::Label* adrp_label = nullptr);
+ vixl::aarch64::Label* NewBootImageTypePatch(const DexFile& dex_file,
+ dex::TypeIndex type_index,
+ vixl::aarch64::Label* adrp_label = nullptr);
// Add a new .bss entry type patch for an instruction and return the label
// to be bound before the instruction. The instruction will be either the
@@ -595,9 +595,9 @@
// to be bound before the instruction. The instruction will be either the
// ADRP (pass `adrp_label = null`) or the ADD (pass `adrp_label` pointing
// to the associated ADRP patch label).
- vixl::aarch64::Label* NewPcRelativeStringPatch(const DexFile& dex_file,
- dex::StringIndex string_index,
- vixl::aarch64::Label* adrp_label = nullptr);
+ vixl::aarch64::Label* NewBootImageStringPatch(const DexFile& dex_file,
+ dex::StringIndex string_index,
+ vixl::aarch64::Label* adrp_label = nullptr);
// Add a new .bss entry string patch for an instruction and return the label
// to be bound before the instruction. The instruction will be either the
@@ -777,17 +777,12 @@
vixl::aarch64::Literal<uint32_t>* DeduplicateUint32Literal(uint32_t value);
vixl::aarch64::Literal<uint64_t>* DeduplicateUint64Literal(uint64_t value);
- // The PcRelativePatchInfo is used for PC-relative addressing of dex cache arrays
- // and boot image strings/types. The only difference is the interpretation of the
- // offset_or_index.
- struct PcRelativePatchInfo {
- PcRelativePatchInfo(const DexFile& dex_file, uint32_t off_or_idx)
- : target_dex_file(dex_file), offset_or_index(off_or_idx), label(), pc_insn_label() { }
+ // The PcRelativePatchInfo is used for PC-relative addressing of methods/strings/types,
+ // whether through .data.bimg.rel.ro, .bss, or directly in the boot image.
+ struct PcRelativePatchInfo : PatchInfo<vixl::aarch64::Label> {
+ PcRelativePatchInfo(const DexFile* dex_file, uint32_t off_or_idx)
+ : PatchInfo<vixl::aarch64::Label>(dex_file, off_or_idx), pc_insn_label() { }
- const DexFile& target_dex_file;
- // Either the dex cache array element offset or the string/type index.
- uint32_t offset_or_index;
- vixl::aarch64::Label label;
vixl::aarch64::Label* pc_insn_label;
};
@@ -798,7 +793,7 @@
uint32_t custom_data;
};
- vixl::aarch64::Label* NewPcRelativePatch(const DexFile& dex_file,
+ vixl::aarch64::Label* NewPcRelativePatch(const DexFile* dex_file,
uint32_t offset_or_index,
vixl::aarch64::Label* adrp_label,
ArenaDeque<PcRelativePatchInfo>* patches);
@@ -826,15 +821,15 @@
// Deduplication map for 64-bit literals, used for non-patchable method address or method code.
Uint64ToLiteralMap uint64_literals_;
// PC-relative method patch info for kBootImageLinkTimePcRelative.
- ArenaDeque<PcRelativePatchInfo> pc_relative_method_patches_;
+ ArenaDeque<PcRelativePatchInfo> boot_image_method_patches_;
// PC-relative method patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
- ArenaDeque<PcRelativePatchInfo> pc_relative_type_patches_;
+ ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_;
// PC-relative String patch info; type depends on configuration (intern table or boot image PIC).
- ArenaDeque<PcRelativePatchInfo> pc_relative_string_patches_;
+ ArenaDeque<PcRelativePatchInfo> boot_image_string_patches_;
// PC-relative String patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> string_bss_entry_patches_;
// Baker read barrier patch info.
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 6d49b32..2f495fc 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -2354,11 +2354,11 @@
isa_features_(isa_features),
uint32_literals_(std::less<uint32_t>(),
graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
baker_read_barrier_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
jit_string_patches_(StringReferenceValueComparator(),
@@ -7131,7 +7131,7 @@
DCHECK(codegen_->GetCompilerOptions().IsBootImage());
DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
- codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
+ codegen_->NewBootImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
codegen_->EmitMovwMovtPlaceholder(labels, out);
break;
}
@@ -7146,7 +7146,7 @@
case HLoadClass::LoadKind::kBootImageClassTable: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
- codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
+ codegen_->NewBootImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
codegen_->EmitMovwMovtPlaceholder(labels, out);
__ Ldr(out, MemOperand(out, /* offset */ 0));
// Extract the reference from the slot data, i.e. clear the hash bits.
@@ -7293,7 +7293,7 @@
case HLoadString::LoadKind::kBootImageLinkTimePcRelative: {
DCHECK(codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex());
+ codegen_->NewBootImageStringPatch(load->GetDexFile(), load->GetStringIndex());
codegen_->EmitMovwMovtPlaceholder(labels, out);
return;
}
@@ -7307,7 +7307,7 @@
case HLoadString::LoadKind::kBootImageInternTable: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex());
+ codegen_->NewBootImageStringPatch(load->GetDexFile(), load->GetStringIndex());
codegen_->EmitMovwMovtPlaceholder(labels, out);
__ Ldr(out, MemOperand(out, /* offset */ 0));
return;
@@ -8893,7 +8893,7 @@
break;
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative: {
DCHECK(GetCompilerOptions().IsBootImage());
- PcRelativePatchInfo* labels = NewPcRelativeMethodPatch(invoke->GetTargetMethod());
+ PcRelativePatchInfo* labels = NewBootImageMethodPatch(invoke->GetTargetMethod());
vixl32::Register temp_reg = RegisterFrom(temp);
EmitMovwMovtPlaceholder(labels, temp_reg);
break;
@@ -8998,42 +8998,40 @@
}
}
-CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewPcRelativeMethodPatch(
+CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewBootImageMethodPatch(
MethodReference target_method) {
- return NewPcRelativePatch(*target_method.dex_file,
- target_method.index,
- &pc_relative_method_patches_);
+ return NewPcRelativePatch(
+ target_method.dex_file, target_method.index, &boot_image_method_patches_);
}
CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewMethodBssEntryPatch(
MethodReference target_method) {
- return NewPcRelativePatch(*target_method.dex_file,
- target_method.index,
- &method_bss_entry_patches_);
+ return NewPcRelativePatch(
+ target_method.dex_file, target_method.index, &method_bss_entry_patches_);
}
-CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewPcRelativeTypePatch(
+CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewBootImageTypePatch(
const DexFile& dex_file, dex::TypeIndex type_index) {
- return NewPcRelativePatch(dex_file, type_index.index_, &pc_relative_type_patches_);
+ return NewPcRelativePatch(&dex_file, type_index.index_, &boot_image_type_patches_);
}
CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewTypeBssEntryPatch(
const DexFile& dex_file, dex::TypeIndex type_index) {
- return NewPcRelativePatch(dex_file, type_index.index_, &type_bss_entry_patches_);
+ return NewPcRelativePatch(&dex_file, type_index.index_, &type_bss_entry_patches_);
}
-CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewPcRelativeStringPatch(
+CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewBootImageStringPatch(
const DexFile& dex_file, dex::StringIndex string_index) {
- return NewPcRelativePatch(dex_file, string_index.index_, &pc_relative_string_patches_);
+ return NewPcRelativePatch(&dex_file, string_index.index_, &boot_image_string_patches_);
}
CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewStringBssEntryPatch(
const DexFile& dex_file, dex::StringIndex string_index) {
- return NewPcRelativePatch(dex_file, string_index.index_, &string_bss_entry_patches_);
+ return NewPcRelativePatch(&dex_file, string_index.index_, &string_bss_entry_patches_);
}
CodeGeneratorARMVIXL::PcRelativePatchInfo* CodeGeneratorARMVIXL::NewPcRelativePatch(
- const DexFile& dex_file, uint32_t offset_or_index, ArenaDeque<PcRelativePatchInfo>* patches) {
+ const DexFile* dex_file, uint32_t offset_or_index, ArenaDeque<PcRelativePatchInfo>* patches) {
patches->emplace_back(dex_file, offset_or_index);
return &patches->back();
}
@@ -9075,45 +9073,45 @@
const ArenaDeque<PcRelativePatchInfo>& infos,
ArenaVector<linker::LinkerPatch>* linker_patches) {
for (const PcRelativePatchInfo& info : infos) {
- const DexFile& dex_file = info.target_dex_file;
+ const DexFile* dex_file = info.target_dex_file;
size_t offset_or_index = info.offset_or_index;
DCHECK(info.add_pc_label.IsBound());
uint32_t add_pc_offset = dchecked_integral_cast<uint32_t>(info.add_pc_label.GetLocation());
// Add MOVW patch.
DCHECK(info.movw_label.IsBound());
uint32_t movw_offset = dchecked_integral_cast<uint32_t>(info.movw_label.GetLocation());
- linker_patches->push_back(Factory(movw_offset, &dex_file, add_pc_offset, offset_or_index));
+ linker_patches->push_back(Factory(movw_offset, dex_file, add_pc_offset, offset_or_index));
// Add MOVT patch.
DCHECK(info.movt_label.IsBound());
uint32_t movt_offset = dchecked_integral_cast<uint32_t>(info.movt_label.GetLocation());
- linker_patches->push_back(Factory(movt_offset, &dex_file, add_pc_offset, offset_or_index));
+ linker_patches->push_back(Factory(movt_offset, dex_file, add_pc_offset, offset_or_index));
}
}
void CodeGeneratorARMVIXL::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
- /* MOVW+MOVT for each entry */ 2u * pc_relative_method_patches_.size() +
+ /* MOVW+MOVT for each entry */ 2u * boot_image_method_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * method_bss_entry_patches_.size() +
- /* MOVW+MOVT for each entry */ 2u * pc_relative_type_patches_.size() +
+ /* MOVW+MOVT for each entry */ 2u * boot_image_type_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * type_bss_entry_patches_.size() +
- /* MOVW+MOVT for each entry */ 2u * pc_relative_string_patches_.size() +
+ /* MOVW+MOVT for each entry */ 2u * boot_image_string_patches_.size() +
/* MOVW+MOVT for each entry */ 2u * string_bss_entry_patches_.size() +
baker_read_barrier_patches_.size();
linker_patches->reserve(size);
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeMethodPatch>(
- pc_relative_method_patches_, linker_patches);
+ boot_image_method_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>(
- pc_relative_type_patches_, linker_patches);
+ boot_image_type_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>(
- pc_relative_string_patches_, linker_patches);
+ boot_image_string_patches_, linker_patches);
} else {
- DCHECK(pc_relative_method_patches_.empty());
+ DCHECK(boot_image_method_patches_.empty());
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeClassTablePatch>(
- pc_relative_type_patches_, linker_patches);
+ boot_image_type_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringInternTablePatch>(
- pc_relative_string_patches_, linker_patches);
+ boot_image_string_patches_, linker_patches);
}
EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>(
method_bss_entry_patches_, linker_patches);
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index 38570bb..bbc715c 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -552,32 +552,34 @@
void MoveFromReturnRegister(Location trg, DataType::Type type) OVERRIDE;
- // The PcRelativePatchInfo is used for PC-relative addressing of dex cache arrays
- // and boot image strings/types. The only difference is the interpretation of the
- // offset_or_index. The PC-relative address is loaded with three instructions,
+ // The PcRelativePatchInfo is used for PC-relative addressing of methods/strings/types,
+ // whether through .data.bimg.rel.ro, .bss, or directly in the boot image.
+ //
+ // The PC-relative address is loaded with three instructions,
// MOVW+MOVT to load the offset to base_reg and then ADD base_reg, PC. The offset
// is calculated from the ADD's effective PC, i.e. PC+4 on Thumb2. Though we
// currently emit these 3 instructions together, instruction scheduling could
// split this sequence apart, so we keep separate labels for each of them.
struct PcRelativePatchInfo {
- PcRelativePatchInfo(const DexFile& dex_file, uint32_t off_or_idx)
+ PcRelativePatchInfo(const DexFile* dex_file, uint32_t off_or_idx)
: target_dex_file(dex_file), offset_or_index(off_or_idx) { }
PcRelativePatchInfo(PcRelativePatchInfo&& other) = default;
- const DexFile& target_dex_file;
- // Either the dex cache array element offset or the string/type index.
+ // Target dex file or null for .data.bmig.rel.ro patches.
+ const DexFile* target_dex_file;
+ // Either the boot image offset (to write to .data.bmig.rel.ro) or string/type/method index.
uint32_t offset_or_index;
vixl::aarch32::Label movw_label;
vixl::aarch32::Label movt_label;
vixl::aarch32::Label add_pc_label;
};
- PcRelativePatchInfo* NewPcRelativeMethodPatch(MethodReference target_method);
+ PcRelativePatchInfo* NewBootImageMethodPatch(MethodReference target_method);
PcRelativePatchInfo* NewMethodBssEntryPatch(MethodReference target_method);
- PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
+ PcRelativePatchInfo* NewBootImageTypePatch(const DexFile& dex_file, dex::TypeIndex type_index);
PcRelativePatchInfo* NewTypeBssEntryPatch(const DexFile& dex_file, dex::TypeIndex type_index);
- PcRelativePatchInfo* NewPcRelativeStringPatch(const DexFile& dex_file,
- dex::StringIndex string_index);
+ PcRelativePatchInfo* NewBootImageStringPatch(const DexFile& dex_file,
+ dex::StringIndex string_index);
PcRelativePatchInfo* NewStringBssEntryPatch(const DexFile& dex_file,
dex::StringIndex string_index);
@@ -774,7 +776,7 @@
};
VIXLUInt32Literal* DeduplicateUint32Literal(uint32_t value, Uint32ToLiteralMap* map);
- PcRelativePatchInfo* NewPcRelativePatch(const DexFile& dex_file,
+ PcRelativePatchInfo* NewPcRelativePatch(const DexFile* dex_file,
uint32_t offset_or_index,
ArenaDeque<PcRelativePatchInfo>* patches);
template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)>
@@ -797,15 +799,15 @@
// Deduplication map for 32-bit literals, used for non-patchable boot image addresses.
Uint32ToLiteralMap uint32_literals_;
// PC-relative method patch info for kBootImageLinkTimePcRelative.
- ArenaDeque<PcRelativePatchInfo> pc_relative_method_patches_;
+ ArenaDeque<PcRelativePatchInfo> boot_image_method_patches_;
// PC-relative method patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
- ArenaDeque<PcRelativePatchInfo> pc_relative_type_patches_;
+ ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_;
// PC-relative String patch info; type depends on configuration (intern table or boot image PIC).
- ArenaDeque<PcRelativePatchInfo> pc_relative_string_patches_;
+ ArenaDeque<PcRelativePatchInfo> boot_image_string_patches_;
// PC-relative String patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> string_bss_entry_patches_;
// Baker read barrier patch info.
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc
index 97604b3..d01b895 100644
--- a/compiler/optimizing/code_generator_mips.cc
+++ b/compiler/optimizing/code_generator_mips.cc
@@ -1017,11 +1017,11 @@
isa_features_(isa_features),
uint32_literals_(std::less<uint32_t>(),
graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
jit_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
jit_class_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
@@ -1583,7 +1583,7 @@
const ArenaDeque<PcRelativePatchInfo>& infos,
ArenaVector<linker::LinkerPatch>* linker_patches) {
for (const PcRelativePatchInfo& info : infos) {
- const DexFile& dex_file = info.target_dex_file;
+ const DexFile* dex_file = info.target_dex_file;
size_t offset_or_index = info.offset_or_index;
DCHECK(info.label.IsBound());
uint32_t literal_offset = __ GetLabelLocation(&info.label);
@@ -1593,33 +1593,33 @@
uint32_t pc_rel_offset = info_high.pc_rel_label.IsBound()
? __ GetLabelLocation(&info_high.pc_rel_label)
: __ GetPcRelBaseLabelLocation();
- linker_patches->push_back(Factory(literal_offset, &dex_file, pc_rel_offset, offset_or_index));
+ linker_patches->push_back(Factory(literal_offset, dex_file, pc_rel_offset, offset_or_index));
}
}
void CodeGeneratorMIPS::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
- pc_relative_method_patches_.size() +
+ boot_image_method_patches_.size() +
method_bss_entry_patches_.size() +
- pc_relative_type_patches_.size() +
+ boot_image_type_patches_.size() +
type_bss_entry_patches_.size() +
- pc_relative_string_patches_.size() +
+ boot_image_string_patches_.size() +
string_bss_entry_patches_.size();
linker_patches->reserve(size);
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeMethodPatch>(
- pc_relative_method_patches_, linker_patches);
+ boot_image_method_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>(
- pc_relative_type_patches_, linker_patches);
+ boot_image_type_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>(
- pc_relative_string_patches_, linker_patches);
+ boot_image_string_patches_, linker_patches);
} else {
- DCHECK(pc_relative_method_patches_.empty());
+ DCHECK(boot_image_method_patches_.empty());
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeClassTablePatch>(
- pc_relative_type_patches_, linker_patches);
+ boot_image_type_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringInternTablePatch>(
- pc_relative_string_patches_, linker_patches);
+ boot_image_string_patches_, linker_patches);
}
EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>(
method_bss_entry_patches_, linker_patches);
@@ -1630,54 +1630,51 @@
DCHECK_EQ(size, linker_patches->size());
}
-CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewPcRelativeMethodPatch(
+CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewBootImageMethodPatch(
MethodReference target_method,
const PcRelativePatchInfo* info_high) {
- return NewPcRelativePatch(*target_method.dex_file,
- target_method.index,
- info_high,
- &pc_relative_method_patches_);
+ return NewPcRelativePatch(
+ target_method.dex_file, target_method.index, info_high, &boot_image_method_patches_);
}
CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewMethodBssEntryPatch(
MethodReference target_method,
const PcRelativePatchInfo* info_high) {
- return NewPcRelativePatch(*target_method.dex_file,
- target_method.index,
- info_high,
- &method_bss_entry_patches_);
+ return NewPcRelativePatch(
+ target_method.dex_file, target_method.index, info_high, &method_bss_entry_patches_);
}
-CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewPcRelativeTypePatch(
+CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewBootImageTypePatch(
const DexFile& dex_file,
dex::TypeIndex type_index,
const PcRelativePatchInfo* info_high) {
- return NewPcRelativePatch(dex_file, type_index.index_, info_high, &pc_relative_type_patches_);
+ return NewPcRelativePatch(&dex_file, type_index.index_, info_high, &boot_image_type_patches_);
}
CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewTypeBssEntryPatch(
const DexFile& dex_file,
dex::TypeIndex type_index,
const PcRelativePatchInfo* info_high) {
- return NewPcRelativePatch(dex_file, type_index.index_, info_high, &type_bss_entry_patches_);
+ return NewPcRelativePatch(&dex_file, type_index.index_, info_high, &type_bss_entry_patches_);
}
-CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewPcRelativeStringPatch(
+CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewBootImageStringPatch(
const DexFile& dex_file,
dex::StringIndex string_index,
const PcRelativePatchInfo* info_high) {
- return NewPcRelativePatch(dex_file, string_index.index_, info_high, &pc_relative_string_patches_);
+ return NewPcRelativePatch(
+ &dex_file, string_index.index_, info_high, &boot_image_string_patches_);
}
CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewStringBssEntryPatch(
const DexFile& dex_file,
dex::StringIndex string_index,
const PcRelativePatchInfo* info_high) {
- return NewPcRelativePatch(dex_file, string_index.index_, info_high, &string_bss_entry_patches_);
+ return NewPcRelativePatch(&dex_file, string_index.index_, info_high, &string_bss_entry_patches_);
}
CodeGeneratorMIPS::PcRelativePatchInfo* CodeGeneratorMIPS::NewPcRelativePatch(
- const DexFile& dex_file,
+ const DexFile* dex_file,
uint32_t offset_or_index,
const PcRelativePatchInfo* info_high,
ArenaDeque<PcRelativePatchInfo>* patches) {
@@ -7828,9 +7825,9 @@
break;
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative: {
DCHECK(GetCompilerOptions().IsBootImage());
- PcRelativePatchInfo* info_high = NewPcRelativeMethodPatch(invoke->GetTargetMethod());
+ PcRelativePatchInfo* info_high = NewBootImageMethodPatch(invoke->GetTargetMethod());
PcRelativePatchInfo* info_low =
- NewPcRelativeMethodPatch(invoke->GetTargetMethod(), info_high);
+ NewBootImageMethodPatch(invoke->GetTargetMethod(), info_high);
Register temp_reg = temp.AsRegister<Register>();
EmitPcRelativeAddressPlaceholderHigh(info_high, TMP, base_reg);
__ Addiu(temp_reg, TMP, /* placeholder */ 0x5678, &info_low->label);
@@ -8046,9 +8043,9 @@
DCHECK(codegen_->GetCompilerOptions().IsBootImage());
DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
CodeGeneratorMIPS::PcRelativePatchInfo* info_high =
- codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
+ codegen_->NewBootImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
CodeGeneratorMIPS::PcRelativePatchInfo* info_low =
- codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex(), info_high);
+ codegen_->NewBootImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex(), info_high);
codegen_->EmitPcRelativeAddressPlaceholderHigh(info_high,
out,
base_or_current_method_reg);
@@ -8072,9 +8069,9 @@
case HLoadClass::LoadKind::kBootImageClassTable: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorMIPS::PcRelativePatchInfo* info_high =
- codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
+ codegen_->NewBootImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
CodeGeneratorMIPS::PcRelativePatchInfo* info_low =
- codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex(), info_high);
+ codegen_->NewBootImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex(), info_high);
codegen_->EmitPcRelativeAddressPlaceholderHigh(info_high,
out,
base_or_current_method_reg);
@@ -8241,9 +8238,9 @@
case HLoadString::LoadKind::kBootImageLinkTimePcRelative: {
DCHECK(codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorMIPS::PcRelativePatchInfo* info_high =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex());
+ codegen_->NewBootImageStringPatch(load->GetDexFile(), load->GetStringIndex());
CodeGeneratorMIPS::PcRelativePatchInfo* info_low =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex(), info_high);
+ codegen_->NewBootImageStringPatch(load->GetDexFile(), load->GetStringIndex(), info_high);
codegen_->EmitPcRelativeAddressPlaceholderHigh(info_high,
out,
base_or_current_method_reg);
@@ -8266,9 +8263,9 @@
case HLoadString::LoadKind::kBootImageInternTable: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorMIPS::PcRelativePatchInfo* info_high =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex());
+ codegen_->NewBootImageStringPatch(load->GetDexFile(), load->GetStringIndex());
CodeGeneratorMIPS::PcRelativePatchInfo* info_low =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex(), info_high);
+ codegen_->NewBootImageStringPatch(load->GetDexFile(), load->GetStringIndex(), info_high);
codegen_->EmitPcRelativeAddressPlaceholderHigh(info_high,
out,
base_or_current_method_reg);
diff --git a/compiler/optimizing/code_generator_mips.h b/compiler/optimizing/code_generator_mips.h
index 32b3e42..d87cfc0 100644
--- a/compiler/optimizing/code_generator_mips.h
+++ b/compiler/optimizing/code_generator_mips.h
@@ -576,8 +576,9 @@
void GenerateImplicitNullCheck(HNullCheck* instruction) OVERRIDE;
void GenerateExplicitNullCheck(HNullCheck* instruction) OVERRIDE;
- // The PcRelativePatchInfo is used for PC-relative addressing of dex cache arrays
- // and boot image strings. The only difference is the interpretation of the offset_or_index.
+ // The PcRelativePatchInfo is used for PC-relative addressing of methods/strings/types,
+ // whether through .data.bimg.rel.ro, .bss, or directly in the boot image.
+ //
// The 16-bit halves of the 32-bit PC-relative offset are patched separately, necessitating
// two patches/infos. There can be more than two patches/infos if the instruction supplying
// the high half is shared with e.g. a slow path, while the low half is supplied by separate
@@ -592,21 +593,14 @@
// ...
// sw r2, low(r1) // patch
// b back
- struct PcRelativePatchInfo {
- PcRelativePatchInfo(const DexFile& dex_file,
+ struct PcRelativePatchInfo : PatchInfo<MipsLabel> {
+ PcRelativePatchInfo(const DexFile* dex_file,
uint32_t off_or_idx,
const PcRelativePatchInfo* info_high)
- : target_dex_file(dex_file),
- offset_or_index(off_or_idx),
- label(),
+ : PatchInfo<MipsLabel>(dex_file, off_or_idx),
pc_rel_label(),
patch_info_high(info_high) { }
- const DexFile& target_dex_file;
- // Either the dex cache array element offset or the string/type index.
- uint32_t offset_or_index;
- // Label for the instruction to patch.
- MipsLabel label;
// Label for the instruction corresponding to PC+0. Not bound or used in low half patches.
// Not bound in high half patches on R2 when using HMipsComputeBaseMethodAddress.
// Bound in high half patches on R2 when using the NAL instruction instead of
@@ -621,19 +615,19 @@
DISALLOW_COPY_AND_ASSIGN(PcRelativePatchInfo);
};
- PcRelativePatchInfo* NewPcRelativeMethodPatch(MethodReference target_method,
- const PcRelativePatchInfo* info_high = nullptr);
+ PcRelativePatchInfo* NewBootImageMethodPatch(MethodReference target_method,
+ const PcRelativePatchInfo* info_high = nullptr);
PcRelativePatchInfo* NewMethodBssEntryPatch(MethodReference target_method,
const PcRelativePatchInfo* info_high = nullptr);
- PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file,
- dex::TypeIndex type_index,
- const PcRelativePatchInfo* info_high = nullptr);
+ PcRelativePatchInfo* NewBootImageTypePatch(const DexFile& dex_file,
+ dex::TypeIndex type_index,
+ const PcRelativePatchInfo* info_high = nullptr);
PcRelativePatchInfo* NewTypeBssEntryPatch(const DexFile& dex_file,
dex::TypeIndex type_index,
const PcRelativePatchInfo* info_high = nullptr);
- PcRelativePatchInfo* NewPcRelativeStringPatch(const DexFile& dex_file,
- dex::StringIndex string_index,
- const PcRelativePatchInfo* info_high = nullptr);
+ PcRelativePatchInfo* NewBootImageStringPatch(const DexFile& dex_file,
+ dex::StringIndex string_index,
+ const PcRelativePatchInfo* info_high = nullptr);
PcRelativePatchInfo* NewStringBssEntryPatch(const DexFile& dex_file,
dex::StringIndex string_index,
const PcRelativePatchInfo* info_high = nullptr);
@@ -675,7 +669,7 @@
using Uint32ToLiteralMap = ArenaSafeMap<uint32_t, Literal*>;
Literal* DeduplicateUint32Literal(uint32_t value, Uint32ToLiteralMap* map);
- PcRelativePatchInfo* NewPcRelativePatch(const DexFile& dex_file,
+ PcRelativePatchInfo* NewPcRelativePatch(const DexFile* dex_file,
uint32_t offset_or_index,
const PcRelativePatchInfo* info_high,
ArenaDeque<PcRelativePatchInfo>* patches);
@@ -696,15 +690,15 @@
// Deduplication map for 32-bit literals, used for non-patchable boot image addresses.
Uint32ToLiteralMap uint32_literals_;
// PC-relative method patch info for kBootImageLinkTimePcRelative.
- ArenaDeque<PcRelativePatchInfo> pc_relative_method_patches_;
+ ArenaDeque<PcRelativePatchInfo> boot_image_method_patches_;
// PC-relative method patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
- ArenaDeque<PcRelativePatchInfo> pc_relative_type_patches_;
+ ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_;
// PC-relative String patch info; type depends on configuration (intern table or boot image PIC).
- ArenaDeque<PcRelativePatchInfo> pc_relative_string_patches_;
+ ArenaDeque<PcRelativePatchInfo> boot_image_string_patches_;
// PC-relative String patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> string_bss_entry_patches_;
diff --git a/compiler/optimizing/code_generator_mips64.cc b/compiler/optimizing/code_generator_mips64.cc
index f1bb5c1..e3529f1 100644
--- a/compiler/optimizing/code_generator_mips64.cc
+++ b/compiler/optimizing/code_generator_mips64.cc
@@ -962,11 +962,11 @@
graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
uint64_literals_(std::less<uint64_t>(),
graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_method_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- pc_relative_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
jit_string_patches_(StringReferenceValueComparator(),
graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
@@ -1499,39 +1499,39 @@
const ArenaDeque<PcRelativePatchInfo>& infos,
ArenaVector<linker::LinkerPatch>* linker_patches) {
for (const PcRelativePatchInfo& info : infos) {
- const DexFile& dex_file = info.target_dex_file;
+ const DexFile* dex_file = info.target_dex_file;
size_t offset_or_index = info.offset_or_index;
DCHECK(info.label.IsBound());
uint32_t literal_offset = __ GetLabelLocation(&info.label);
const PcRelativePatchInfo& info_high = info.patch_info_high ? *info.patch_info_high : info;
uint32_t pc_rel_offset = __ GetLabelLocation(&info_high.label);
- linker_patches->push_back(Factory(literal_offset, &dex_file, pc_rel_offset, offset_or_index));
+ linker_patches->push_back(Factory(literal_offset, dex_file, pc_rel_offset, offset_or_index));
}
}
void CodeGeneratorMIPS64::EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) {
DCHECK(linker_patches->empty());
size_t size =
- pc_relative_method_patches_.size() +
+ boot_image_method_patches_.size() +
method_bss_entry_patches_.size() +
- pc_relative_type_patches_.size() +
+ boot_image_type_patches_.size() +
type_bss_entry_patches_.size() +
- pc_relative_string_patches_.size() +
+ boot_image_string_patches_.size() +
string_bss_entry_patches_.size();
linker_patches->reserve(size);
if (GetCompilerOptions().IsBootImage()) {
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeMethodPatch>(
- pc_relative_method_patches_, linker_patches);
+ boot_image_method_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>(
- pc_relative_type_patches_, linker_patches);
+ boot_image_type_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>(
- pc_relative_string_patches_, linker_patches);
+ boot_image_string_patches_, linker_patches);
} else {
- DCHECK(pc_relative_method_patches_.empty());
+ DCHECK(boot_image_method_patches_.empty());
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeClassTablePatch>(
- pc_relative_type_patches_, linker_patches);
+ boot_image_type_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringInternTablePatch>(
- pc_relative_string_patches_, linker_patches);
+ boot_image_string_patches_, linker_patches);
}
EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>(
method_bss_entry_patches_, linker_patches);
@@ -1542,54 +1542,51 @@
DCHECK_EQ(size, linker_patches->size());
}
-CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewPcRelativeMethodPatch(
+CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewBootImageMethodPatch(
MethodReference target_method,
const PcRelativePatchInfo* info_high) {
- return NewPcRelativePatch(*target_method.dex_file,
- target_method.index,
- info_high,
- &pc_relative_method_patches_);
+ return NewPcRelativePatch(
+ target_method.dex_file, target_method.index, info_high, &boot_image_method_patches_);
}
CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewMethodBssEntryPatch(
MethodReference target_method,
const PcRelativePatchInfo* info_high) {
- return NewPcRelativePatch(*target_method.dex_file,
- target_method.index,
- info_high,
- &method_bss_entry_patches_);
+ return NewPcRelativePatch(
+ target_method.dex_file, target_method.index, info_high, &method_bss_entry_patches_);
}
-CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewPcRelativeTypePatch(
+CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewBootImageTypePatch(
const DexFile& dex_file,
dex::TypeIndex type_index,
const PcRelativePatchInfo* info_high) {
- return NewPcRelativePatch(dex_file, type_index.index_, info_high, &pc_relative_type_patches_);
+ return NewPcRelativePatch(&dex_file, type_index.index_, info_high, &boot_image_type_patches_);
}
CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewTypeBssEntryPatch(
const DexFile& dex_file,
dex::TypeIndex type_index,
const PcRelativePatchInfo* info_high) {
- return NewPcRelativePatch(dex_file, type_index.index_, info_high, &type_bss_entry_patches_);
+ return NewPcRelativePatch(&dex_file, type_index.index_, info_high, &type_bss_entry_patches_);
}
-CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewPcRelativeStringPatch(
+CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewBootImageStringPatch(
const DexFile& dex_file,
dex::StringIndex string_index,
const PcRelativePatchInfo* info_high) {
- return NewPcRelativePatch(dex_file, string_index.index_, info_high, &pc_relative_string_patches_);
+ return NewPcRelativePatch(
+ &dex_file, string_index.index_, info_high, &boot_image_string_patches_);
}
CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewStringBssEntryPatch(
const DexFile& dex_file,
dex::StringIndex string_index,
const PcRelativePatchInfo* info_high) {
- return NewPcRelativePatch(dex_file, string_index.index_, info_high, &string_bss_entry_patches_);
+ return NewPcRelativePatch(&dex_file, string_index.index_, info_high, &string_bss_entry_patches_);
}
CodeGeneratorMIPS64::PcRelativePatchInfo* CodeGeneratorMIPS64::NewPcRelativePatch(
- const DexFile& dex_file,
+ const DexFile* dex_file,
uint32_t offset_or_index,
const PcRelativePatchInfo* info_high,
ArenaDeque<PcRelativePatchInfo>* patches) {
@@ -5917,9 +5914,9 @@
case HInvokeStaticOrDirect::MethodLoadKind::kBootImageLinkTimePcRelative: {
DCHECK(GetCompilerOptions().IsBootImage());
CodeGeneratorMIPS64::PcRelativePatchInfo* info_high =
- NewPcRelativeMethodPatch(invoke->GetTargetMethod());
+ NewBootImageMethodPatch(invoke->GetTargetMethod());
CodeGeneratorMIPS64::PcRelativePatchInfo* info_low =
- NewPcRelativeMethodPatch(invoke->GetTargetMethod(), info_high);
+ NewBootImageMethodPatch(invoke->GetTargetMethod(), info_high);
EmitPcRelativeAddressPlaceholderHigh(info_high, AT, info_low);
__ Daddiu(temp.AsRegister<GpuRegister>(), AT, /* placeholder */ 0x5678);
break;
@@ -6099,9 +6096,9 @@
DCHECK(codegen_->GetCompilerOptions().IsBootImage());
DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
CodeGeneratorMIPS64::PcRelativePatchInfo* info_high =
- codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
+ codegen_->NewBootImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
CodeGeneratorMIPS64::PcRelativePatchInfo* info_low =
- codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex(), info_high);
+ codegen_->NewBootImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex(), info_high);
codegen_->EmitPcRelativeAddressPlaceholderHigh(info_high, AT, info_low);
__ Daddiu(out, AT, /* placeholder */ 0x5678);
break;
@@ -6119,9 +6116,9 @@
case HLoadClass::LoadKind::kBootImageClassTable: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorMIPS64::PcRelativePatchInfo* info_high =
- codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
+ codegen_->NewBootImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex());
CodeGeneratorMIPS64::PcRelativePatchInfo* info_low =
- codegen_->NewPcRelativeTypePatch(cls->GetDexFile(), cls->GetTypeIndex(), info_high);
+ codegen_->NewBootImageTypePatch(cls->GetDexFile(), cls->GetTypeIndex(), info_high);
codegen_->EmitPcRelativeAddressPlaceholderHigh(info_high, AT, info_low);
__ Lwu(out, AT, /* placeholder */ 0x5678);
// Extract the reference from the slot data, i.e. clear the hash bits.
@@ -6235,9 +6232,9 @@
case HLoadString::LoadKind::kBootImageLinkTimePcRelative: {
DCHECK(codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorMIPS64::PcRelativePatchInfo* info_high =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex());
+ codegen_->NewBootImageStringPatch(load->GetDexFile(), load->GetStringIndex());
CodeGeneratorMIPS64::PcRelativePatchInfo* info_low =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex(), info_high);
+ codegen_->NewBootImageStringPatch(load->GetDexFile(), load->GetStringIndex(), info_high);
codegen_->EmitPcRelativeAddressPlaceholderHigh(info_high, AT, info_low);
__ Daddiu(out, AT, /* placeholder */ 0x5678);
return;
@@ -6254,9 +6251,9 @@
case HLoadString::LoadKind::kBootImageInternTable: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorMIPS64::PcRelativePatchInfo* info_high =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex());
+ codegen_->NewBootImageStringPatch(load->GetDexFile(), load->GetStringIndex());
CodeGeneratorMIPS64::PcRelativePatchInfo* info_low =
- codegen_->NewPcRelativeStringPatch(load->GetDexFile(), load->GetStringIndex(), info_high);
+ codegen_->NewBootImageStringPatch(load->GetDexFile(), load->GetStringIndex(), info_high);
codegen_->EmitPcRelativeAddressPlaceholderHigh(info_high, AT, info_low);
__ Lwu(out, AT, /* placeholder */ 0x5678);
return;
diff --git a/compiler/optimizing/code_generator_mips64.h b/compiler/optimizing/code_generator_mips64.h
index d479410..ddeb3eb 100644
--- a/compiler/optimizing/code_generator_mips64.h
+++ b/compiler/optimizing/code_generator_mips64.h
@@ -555,9 +555,9 @@
void GenerateImplicitNullCheck(HNullCheck* instruction) OVERRIDE;
void GenerateExplicitNullCheck(HNullCheck* instruction) OVERRIDE;
- // The PcRelativePatchInfo is used for PC-relative addressing of dex cache arrays,
- // boot image strings and method calls. The only difference is the interpretation of
- // the offset_or_index.
+ // The PcRelativePatchInfo is used for PC-relative addressing of methods/strings/types,
+ // whether through .data.bimg.rel.ro, .bss, or directly in the boot image.
+ //
// The 16-bit halves of the 32-bit PC-relative offset are patched separately, necessitating
// two patches/infos. There can be more than two patches/infos if the instruction supplying
// the high half is shared with e.g. a slow path, while the low half is supplied by separate
@@ -571,20 +571,13 @@
// ...
// sw r2, low(r1) // patch
// bc back
- struct PcRelativePatchInfo {
- PcRelativePatchInfo(const DexFile& dex_file,
+ struct PcRelativePatchInfo : PatchInfo<Mips64Label> {
+ PcRelativePatchInfo(const DexFile* dex_file,
uint32_t off_or_idx,
const PcRelativePatchInfo* info_high)
- : target_dex_file(dex_file),
- offset_or_index(off_or_idx),
- label(),
+ : PatchInfo<Mips64Label>(dex_file, off_or_idx),
patch_info_high(info_high) { }
- const DexFile& target_dex_file;
- // Either the dex cache array element offset or the string/type/method index.
- uint32_t offset_or_index;
- // Label for the instruction to patch.
- Mips64Label label;
// Pointer to the info for the high half patch or nullptr if this is the high half patch info.
const PcRelativePatchInfo* patch_info_high;
@@ -593,19 +586,19 @@
DISALLOW_COPY_AND_ASSIGN(PcRelativePatchInfo);
};
- PcRelativePatchInfo* NewPcRelativeMethodPatch(MethodReference target_method,
- const PcRelativePatchInfo* info_high = nullptr);
+ PcRelativePatchInfo* NewBootImageMethodPatch(MethodReference target_method,
+ const PcRelativePatchInfo* info_high = nullptr);
PcRelativePatchInfo* NewMethodBssEntryPatch(MethodReference target_method,
const PcRelativePatchInfo* info_high = nullptr);
- PcRelativePatchInfo* NewPcRelativeTypePatch(const DexFile& dex_file,
- dex::TypeIndex type_index,
- const PcRelativePatchInfo* info_high = nullptr);
+ PcRelativePatchInfo* NewBootImageTypePatch(const DexFile& dex_file,
+ dex::TypeIndex type_index,
+ const PcRelativePatchInfo* info_high = nullptr);
PcRelativePatchInfo* NewTypeBssEntryPatch(const DexFile& dex_file,
dex::TypeIndex type_index,
const PcRelativePatchInfo* info_high = nullptr);
- PcRelativePatchInfo* NewPcRelativeStringPatch(const DexFile& dex_file,
- dex::StringIndex string_index,
- const PcRelativePatchInfo* info_high = nullptr);
+ PcRelativePatchInfo* NewBootImageStringPatch(const DexFile& dex_file,
+ dex::StringIndex string_index,
+ const PcRelativePatchInfo* info_high = nullptr);
PcRelativePatchInfo* NewStringBssEntryPatch(const DexFile& dex_file,
dex::StringIndex string_index,
const PcRelativePatchInfo* info_high = nullptr);
@@ -639,7 +632,7 @@
Literal* DeduplicateUint32Literal(uint32_t value, Uint32ToLiteralMap* map);
Literal* DeduplicateUint64Literal(uint64_t value);
- PcRelativePatchInfo* NewPcRelativePatch(const DexFile& dex_file,
+ PcRelativePatchInfo* NewPcRelativePatch(const DexFile* dex_file,
uint32_t offset_or_index,
const PcRelativePatchInfo* info_high,
ArenaDeque<PcRelativePatchInfo>* patches);
@@ -663,15 +656,15 @@
// address.
Uint64ToLiteralMap uint64_literals_;
// PC-relative method patch info for kBootImageLinkTimePcRelative.
- ArenaDeque<PcRelativePatchInfo> pc_relative_method_patches_;
+ ArenaDeque<PcRelativePatchInfo> boot_image_method_patches_;
// PC-relative method patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> method_bss_entry_patches_;
// PC-relative type patch info for kBootImageLinkTimePcRelative.
- ArenaDeque<PcRelativePatchInfo> pc_relative_type_patches_;
+ ArenaDeque<PcRelativePatchInfo> boot_image_type_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> type_bss_entry_patches_;
// PC-relative String patch info; type depends on configuration (intern table or boot image PIC).
- ArenaDeque<PcRelativePatchInfo> pc_relative_string_patches_;
+ ArenaDeque<PcRelativePatchInfo> boot_image_string_patches_;
// PC-relative type patch info for kBssEntry.
ArenaDeque<PcRelativePatchInfo> string_bss_entry_patches_;
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 5fede80..6bf0458 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1028,7 +1028,7 @@
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
jit_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
jit_class_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
@@ -4528,7 +4528,7 @@
Register base_reg = GetInvokeStaticOrDirectExtraParameter(invoke,
temp.AsRegister<Register>());
__ leal(temp.AsRegister<Register>(), Address(base_reg, CodeGeneratorX86::kDummy32BitOffset));
- RecordBootMethodPatch(invoke);
+ RecordBootImageMethodPatch(invoke);
break;
}
case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
@@ -4538,10 +4538,7 @@
Register base_reg = GetInvokeStaticOrDirectExtraParameter(invoke,
temp.AsRegister<Register>());
__ movl(temp.AsRegister<Register>(), Address(base_reg, kDummy32BitOffset));
- // Bind a new fixup label at the end of the "movl" insn.
- __ Bind(NewMethodBssEntryPatch(
- invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress(),
- MethodReference(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex())));
+ RecordMethodBssEntryPatch(invoke);
break;
}
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
@@ -4598,56 +4595,55 @@
RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
}
-void CodeGeneratorX86::RecordBootMethodPatch(HInvokeStaticOrDirect* invoke) {
+void CodeGeneratorX86::RecordBootImageMethodPatch(HInvokeStaticOrDirect* invoke) {
DCHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
- HX86ComputeBaseMethodAddress* address =
+ HX86ComputeBaseMethodAddress* method_address =
invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress();
- boot_image_method_patches_.emplace_back(address,
- *invoke->GetTargetMethod().dex_file,
- invoke->GetTargetMethod().index);
+ boot_image_method_patches_.emplace_back(
+ method_address, invoke->GetTargetMethod().dex_file, invoke->GetTargetMethod().index);
__ Bind(&boot_image_method_patches_.back().label);
}
-Label* CodeGeneratorX86::NewMethodBssEntryPatch(
- HX86ComputeBaseMethodAddress* method_address,
- MethodReference target_method) {
+void CodeGeneratorX86::RecordMethodBssEntryPatch(HInvokeStaticOrDirect* invoke) {
+ DCHECK_EQ(invoke->InputCount(), invoke->GetNumberOfArguments() + 1u);
+ HX86ComputeBaseMethodAddress* method_address =
+ invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress();
// Add the patch entry and bind its label at the end of the instruction.
- method_bss_entry_patches_.emplace_back(method_address,
- *target_method.dex_file,
- target_method.index);
- return &method_bss_entry_patches_.back().label;
+ method_bss_entry_patches_.emplace_back(
+ method_address, &GetGraph()->GetDexFile(), invoke->GetDexMethodIndex());
+ __ Bind(&method_bss_entry_patches_.back().label);
}
-void CodeGeneratorX86::RecordBootTypePatch(HLoadClass* load_class) {
- HX86ComputeBaseMethodAddress* address = load_class->InputAt(0)->AsX86ComputeBaseMethodAddress();
- boot_image_type_patches_.emplace_back(address,
- load_class->GetDexFile(),
- load_class->GetTypeIndex().index_);
+void CodeGeneratorX86::RecordBootImageTypePatch(HLoadClass* load_class) {
+ HX86ComputeBaseMethodAddress* method_address =
+ load_class->InputAt(0)->AsX86ComputeBaseMethodAddress();
+ boot_image_type_patches_.emplace_back(
+ method_address, &load_class->GetDexFile(), load_class->GetTypeIndex().index_);
__ Bind(&boot_image_type_patches_.back().label);
}
Label* CodeGeneratorX86::NewTypeBssEntryPatch(HLoadClass* load_class) {
- HX86ComputeBaseMethodAddress* address =
+ HX86ComputeBaseMethodAddress* method_address =
load_class->InputAt(0)->AsX86ComputeBaseMethodAddress();
type_bss_entry_patches_.emplace_back(
- address, load_class->GetDexFile(), load_class->GetTypeIndex().index_);
+ method_address, &load_class->GetDexFile(), load_class->GetTypeIndex().index_);
return &type_bss_entry_patches_.back().label;
}
-void CodeGeneratorX86::RecordBootStringPatch(HLoadString* load_string) {
- HX86ComputeBaseMethodAddress* address = load_string->InputAt(0)->AsX86ComputeBaseMethodAddress();
- string_patches_.emplace_back(address,
- load_string->GetDexFile(),
- load_string->GetStringIndex().index_);
- __ Bind(&string_patches_.back().label);
+void CodeGeneratorX86::RecordBootImageStringPatch(HLoadString* load_string) {
+ HX86ComputeBaseMethodAddress* method_address =
+ load_string->InputAt(0)->AsX86ComputeBaseMethodAddress();
+ boot_image_string_patches_.emplace_back(
+ method_address, &load_string->GetDexFile(), load_string->GetStringIndex().index_);
+ __ Bind(&boot_image_string_patches_.back().label);
}
Label* CodeGeneratorX86::NewStringBssEntryPatch(HLoadString* load_string) {
DCHECK(!GetCompilerOptions().IsBootImage());
- HX86ComputeBaseMethodAddress* address =
+ HX86ComputeBaseMethodAddress* method_address =
load_string->InputAt(0)->AsX86ComputeBaseMethodAddress();
string_bss_entry_patches_.emplace_back(
- address, load_string->GetDexFile(), load_string->GetStringIndex().index_);
+ method_address, &load_string->GetDexFile(), load_string->GetStringIndex().index_);
return &string_bss_entry_patches_.back().label;
}
@@ -4661,8 +4657,10 @@
ArenaVector<linker::LinkerPatch>* linker_patches) {
for (const X86PcRelativePatchInfo& info : infos) {
uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
- linker_patches->push_back(Factory(
- literal_offset, &info.dex_file, GetMethodAddressOffset(info.method_address), info.index));
+ linker_patches->push_back(Factory(literal_offset,
+ info.target_dex_file,
+ GetMethodAddressOffset(info.method_address),
+ info.offset_or_index));
}
}
@@ -4673,7 +4671,7 @@
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
type_bss_entry_patches_.size() +
- string_patches_.size() +
+ boot_image_string_patches_.size() +
string_bss_entry_patches_.size();
linker_patches->reserve(size);
if (GetCompilerOptions().IsBootImage()) {
@@ -4682,13 +4680,13 @@
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>(
boot_image_type_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>(
- string_patches_, linker_patches);
+ boot_image_string_patches_, linker_patches);
} else {
DCHECK(boot_image_method_patches_.empty());
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeClassTablePatch>(
boot_image_type_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringInternTablePatch>(
- string_patches_, linker_patches);
+ boot_image_string_patches_, linker_patches);
}
EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>(
method_bss_entry_patches_, linker_patches);
@@ -6118,7 +6116,7 @@
Handle<mirror::Class> handle) {
ReserveJitClassRoot(TypeReference(&dex_file, type_index), handle);
// Add a patch entry and return the label.
- jit_class_patches_.emplace_back(dex_file, type_index.index_);
+ jit_class_patches_.emplace_back(&dex_file, type_index.index_);
PatchInfo<Label>* info = &jit_class_patches_.back();
return &info->label;
}
@@ -6160,7 +6158,7 @@
DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
Register method_address = locations->InAt(0).AsRegister<Register>();
__ leal(out, Address(method_address, CodeGeneratorX86::kDummy32BitOffset));
- codegen_->RecordBootTypePatch(cls);
+ codegen_->RecordBootImageTypePatch(cls);
break;
}
case HLoadClass::LoadKind::kBootImageAddress: {
@@ -6175,7 +6173,7 @@
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
Register method_address = locations->InAt(0).AsRegister<Register>();
__ movl(out, Address(method_address, CodeGeneratorX86::kDummy32BitOffset));
- codegen_->RecordBootTypePatch(cls);
+ codegen_->RecordBootImageTypePatch(cls);
// Extract the reference from the slot data, i.e. clear the hash bits.
int32_t masked_hash = ClassTable::TableSlot::MaskHash(
ComputeModifiedUtf8Hash(cls->GetDexFile().StringByTypeIdx(cls->GetTypeIndex())));
@@ -6307,7 +6305,7 @@
Handle<mirror::String> handle) {
ReserveJitStringRoot(StringReference(&dex_file, string_index), handle);
// Add a patch entry and return the label.
- jit_string_patches_.emplace_back(dex_file, string_index.index_);
+ jit_string_patches_.emplace_back(&dex_file, string_index.index_);
PatchInfo<Label>* info = &jit_string_patches_.back();
return &info->label;
}
@@ -6324,7 +6322,7 @@
DCHECK(codegen_->GetCompilerOptions().IsBootImage());
Register method_address = locations->InAt(0).AsRegister<Register>();
__ leal(out, Address(method_address, CodeGeneratorX86::kDummy32BitOffset));
- codegen_->RecordBootStringPatch(load);
+ codegen_->RecordBootImageStringPatch(load);
return;
}
case HLoadString::LoadKind::kBootImageAddress: {
@@ -6338,7 +6336,7 @@
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
Register method_address = locations->InAt(0).AsRegister<Register>();
__ movl(out, Address(method_address, CodeGeneratorX86::kDummy32BitOffset));
- codegen_->RecordBootStringPatch(load);
+ codegen_->RecordBootImageStringPatch(load);
return;
}
case HLoadString::LoadKind::kBssEntry: {
@@ -7830,13 +7828,13 @@
void CodeGeneratorX86::EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) {
for (const PatchInfo<Label>& info : jit_string_patches_) {
- StringReference string_reference(&info.dex_file, dex::StringIndex(info.index));
+ StringReference string_reference(info.target_dex_file, dex::StringIndex(info.offset_or_index));
uint64_t index_in_table = GetJitStringRootIndex(string_reference);
PatchJitRootUse(code, roots_data, info, index_in_table);
}
for (const PatchInfo<Label>& info : jit_class_patches_) {
- TypeReference type_reference(&info.dex_file, dex::TypeIndex(info.index));
+ TypeReference type_reference(info.target_dex_file, dex::TypeIndex(info.offset_or_index));
uint64_t index_in_table = GetJitClassRootIndex(type_reference);
PatchJitRootUse(code, roots_data, info, index_in_table);
}
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 0082853..51e5bca 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -414,12 +414,11 @@
void GenerateVirtualCall(
HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
- void RecordBootMethodPatch(HInvokeStaticOrDirect* invoke);
- Label* NewMethodBssEntryPatch(HX86ComputeBaseMethodAddress* method_address,
- MethodReference target_method);
- void RecordBootTypePatch(HLoadClass* load_class);
+ void RecordBootImageMethodPatch(HInvokeStaticOrDirect* invoke);
+ void RecordMethodBssEntryPatch(HInvokeStaticOrDirect* invoke);
+ void RecordBootImageTypePatch(HLoadClass* load_class);
Label* NewTypeBssEntryPatch(HLoadClass* load_class);
- void RecordBootStringPatch(HLoadString* load_string);
+ void RecordBootImageStringPatch(HLoadString* load_string);
Label* NewStringBssEntryPatch(HLoadString* load_string);
Label* NewJitRootStringPatch(const DexFile& dex_file,
dex::StringIndex string_index,
@@ -610,7 +609,7 @@
private:
struct X86PcRelativePatchInfo : PatchInfo<Label> {
X86PcRelativePatchInfo(HX86ComputeBaseMethodAddress* address,
- const DexFile& target_dex_file,
+ const DexFile* target_dex_file,
uint32_t target_index)
: PatchInfo(target_dex_file, target_index),
method_address(address) {}
@@ -641,7 +640,7 @@
// Type patch locations for kBssEntry.
ArenaDeque<X86PcRelativePatchInfo> type_bss_entry_patches_;
// String patch locations; type depends on configuration (intern table or boot image PIC).
- ArenaDeque<X86PcRelativePatchInfo> string_patches_;
+ ArenaDeque<X86PcRelativePatchInfo> boot_image_string_patches_;
// String patch locations for kBssEntry.
ArenaDeque<X86PcRelativePatchInfo> string_bss_entry_patches_;
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index ae35ab5..7be3605 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -993,7 +993,7 @@
DCHECK(GetCompilerOptions().IsBootImage());
__ leal(temp.AsRegister<CpuRegister>(),
Address::Absolute(kDummy32BitOffset, /* no_rip */ false));
- RecordBootMethodPatch(invoke);
+ RecordBootImageMethodPatch(invoke);
break;
case HInvokeStaticOrDirect::MethodLoadKind::kDirectAddress:
Load64BitValue(temp.AsRegister<CpuRegister>(), invoke->GetMethodAddress());
@@ -1001,9 +1001,7 @@
case HInvokeStaticOrDirect::MethodLoadKind::kBssEntry: {
__ movq(temp.AsRegister<CpuRegister>(),
Address::Absolute(kDummy32BitOffset, /* no_rip */ false));
- // Bind a new fixup label at the end of the "movl" insn.
- __ Bind(NewMethodBssEntryPatch(
- MethodReference(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex())));
+ RecordMethodBssEntryPatch(invoke);
break;
}
case HInvokeStaticOrDirect::MethodLoadKind::kRuntimeCall: {
@@ -1061,38 +1059,39 @@
RecordPcInfo(invoke, invoke->GetDexPc(), slow_path);
}
-void CodeGeneratorX86_64::RecordBootMethodPatch(HInvokeStaticOrDirect* invoke) {
- boot_image_method_patches_.emplace_back(*invoke->GetTargetMethod().dex_file,
- invoke->GetTargetMethod().index);
+void CodeGeneratorX86_64::RecordBootImageMethodPatch(HInvokeStaticOrDirect* invoke) {
+ boot_image_method_patches_.emplace_back(
+ invoke->GetTargetMethod().dex_file, invoke->GetTargetMethod().index);
__ Bind(&boot_image_method_patches_.back().label);
}
-Label* CodeGeneratorX86_64::NewMethodBssEntryPatch(MethodReference target_method) {
- // Add a patch entry and return the label.
- method_bss_entry_patches_.emplace_back(*target_method.dex_file, target_method.index);
- return &method_bss_entry_patches_.back().label;
+void CodeGeneratorX86_64::RecordMethodBssEntryPatch(HInvokeStaticOrDirect* invoke) {
+ method_bss_entry_patches_.emplace_back(&GetGraph()->GetDexFile(), invoke->GetDexMethodIndex());
+ __ Bind(&method_bss_entry_patches_.back().label);
}
-void CodeGeneratorX86_64::RecordBootTypePatch(HLoadClass* load_class) {
- boot_image_type_patches_.emplace_back(load_class->GetDexFile(),
- load_class->GetTypeIndex().index_);
+void CodeGeneratorX86_64::RecordBootImageTypePatch(HLoadClass* load_class) {
+ boot_image_type_patches_.emplace_back(
+ &load_class->GetDexFile(), load_class->GetTypeIndex().index_);
__ Bind(&boot_image_type_patches_.back().label);
}
Label* CodeGeneratorX86_64::NewTypeBssEntryPatch(HLoadClass* load_class) {
- type_bss_entry_patches_.emplace_back(load_class->GetDexFile(), load_class->GetTypeIndex().index_);
+ type_bss_entry_patches_.emplace_back(
+ &load_class->GetDexFile(), load_class->GetTypeIndex().index_);
return &type_bss_entry_patches_.back().label;
}
-void CodeGeneratorX86_64::RecordBootStringPatch(HLoadString* load_string) {
- string_patches_.emplace_back(load_string->GetDexFile(), load_string->GetStringIndex().index_);
- __ Bind(&string_patches_.back().label);
+void CodeGeneratorX86_64::RecordBootImageStringPatch(HLoadString* load_string) {
+ boot_image_string_patches_.emplace_back(
+ &load_string->GetDexFile(), load_string->GetStringIndex().index_);
+ __ Bind(&boot_image_string_patches_.back().label);
}
Label* CodeGeneratorX86_64::NewStringBssEntryPatch(HLoadString* load_string) {
DCHECK(!GetCompilerOptions().IsBootImage());
string_bss_entry_patches_.emplace_back(
- load_string->GetDexFile(), load_string->GetStringIndex().index_);
+ &load_string->GetDexFile(), load_string->GetStringIndex().index_);
return &string_bss_entry_patches_.back().label;
}
@@ -1107,7 +1106,7 @@
for (const PatchInfo<Label>& info : infos) {
uint32_t literal_offset = info.label.Position() - kLabelPositionToLiteralOffsetAdjustment;
linker_patches->push_back(
- Factory(literal_offset, &info.dex_file, info.label.Position(), info.index));
+ Factory(literal_offset, info.target_dex_file, info.label.Position(), info.offset_or_index));
}
}
@@ -1118,7 +1117,7 @@
method_bss_entry_patches_.size() +
boot_image_type_patches_.size() +
type_bss_entry_patches_.size() +
- string_patches_.size() +
+ boot_image_string_patches_.size() +
string_bss_entry_patches_.size();
linker_patches->reserve(size);
if (GetCompilerOptions().IsBootImage()) {
@@ -1127,13 +1126,13 @@
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeTypePatch>(
boot_image_type_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::RelativeStringPatch>(
- string_patches_, linker_patches);
+ boot_image_string_patches_, linker_patches);
} else {
DCHECK(boot_image_method_patches_.empty());
EmitPcRelativeLinkerPatches<linker::LinkerPatch::TypeClassTablePatch>(
boot_image_type_patches_, linker_patches);
EmitPcRelativeLinkerPatches<linker::LinkerPatch::StringInternTablePatch>(
- string_patches_, linker_patches);
+ boot_image_string_patches_, linker_patches);
}
EmitPcRelativeLinkerPatches<linker::LinkerPatch::MethodBssEntryPatch>(
method_bss_entry_patches_, linker_patches);
@@ -1231,7 +1230,7 @@
method_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
boot_image_type_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
type_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
- string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
+ boot_image_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
string_bss_entry_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
jit_string_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
jit_class_patches_(graph->GetAllocator()->Adapter(kArenaAllocCodeGenerator)),
@@ -5529,7 +5528,7 @@
Handle<mirror::Class> handle) {
ReserveJitClassRoot(TypeReference(&dex_file, type_index), handle);
// Add a patch entry and return the label.
- jit_class_patches_.emplace_back(dex_file, type_index.index_);
+ jit_class_patches_.emplace_back(&dex_file, type_index.index_);
PatchInfo<Label>* info = &jit_class_patches_.back();
return &info->label;
}
@@ -5570,7 +5569,7 @@
DCHECK(codegen_->GetCompilerOptions().IsBootImage());
DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
__ leal(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
- codegen_->RecordBootTypePatch(cls);
+ codegen_->RecordBootImageTypePatch(cls);
break;
case HLoadClass::LoadKind::kBootImageAddress: {
DCHECK_EQ(read_barrier_option, kWithoutReadBarrier);
@@ -5583,7 +5582,7 @@
case HLoadClass::LoadKind::kBootImageClassTable: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
__ movl(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
- codegen_->RecordBootTypePatch(cls);
+ codegen_->RecordBootImageTypePatch(cls);
// Extract the reference from the slot data, i.e. clear the hash bits.
int32_t masked_hash = ClassTable::TableSlot::MaskHash(
ComputeModifiedUtf8Hash(cls->GetDexFile().StringByTypeIdx(cls->GetTypeIndex())));
@@ -5694,7 +5693,7 @@
Handle<mirror::String> handle) {
ReserveJitStringRoot(StringReference(&dex_file, string_index), handle);
// Add a patch entry and return the label.
- jit_string_patches_.emplace_back(dex_file, string_index.index_);
+ jit_string_patches_.emplace_back(&dex_file, string_index.index_);
PatchInfo<Label>* info = &jit_string_patches_.back();
return &info->label;
}
@@ -5710,7 +5709,7 @@
case HLoadString::LoadKind::kBootImageLinkTimePcRelative: {
DCHECK(codegen_->GetCompilerOptions().IsBootImage());
__ leal(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
- codegen_->RecordBootStringPatch(load);
+ codegen_->RecordBootImageStringPatch(load);
return;
}
case HLoadString::LoadKind::kBootImageAddress: {
@@ -5723,7 +5722,7 @@
case HLoadString::LoadKind::kBootImageInternTable: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
__ movl(out, Address::Absolute(CodeGeneratorX86_64::kDummy32BitOffset, /* no_rip */ false));
- codegen_->RecordBootStringPatch(load);
+ codegen_->RecordBootImageStringPatch(load);
return;
}
case HLoadString::LoadKind::kBssEntry: {
@@ -7160,13 +7159,13 @@
void CodeGeneratorX86_64::EmitJitRootPatches(uint8_t* code, const uint8_t* roots_data) {
for (const PatchInfo<Label>& info : jit_string_patches_) {
- StringReference string_reference(&info.dex_file, dex::StringIndex(info.index));
+ StringReference string_reference(info.target_dex_file, dex::StringIndex(info.offset_or_index));
uint64_t index_in_table = GetJitStringRootIndex(string_reference);
PatchJitRootUse(code, roots_data, info, index_in_table);
}
for (const PatchInfo<Label>& info : jit_class_patches_) {
- TypeReference type_reference(&info.dex_file, dex::TypeIndex(info.index));
+ TypeReference type_reference(info.target_dex_file, dex::TypeIndex(info.offset_or_index));
uint64_t index_in_table = GetJitClassRootIndex(type_reference);
PatchJitRootUse(code, roots_data, info, index_in_table);
}
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index e86123e..1079e94 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -410,11 +410,11 @@
void GenerateVirtualCall(
HInvokeVirtual* invoke, Location temp, SlowPathCode* slow_path = nullptr) OVERRIDE;
- void RecordBootMethodPatch(HInvokeStaticOrDirect* invoke);
- Label* NewMethodBssEntryPatch(MethodReference target_method);
- void RecordBootTypePatch(HLoadClass* load_class);
+ void RecordBootImageMethodPatch(HInvokeStaticOrDirect* invoke);
+ void RecordMethodBssEntryPatch(HInvokeStaticOrDirect* invoke);
+ void RecordBootImageTypePatch(HLoadClass* load_class);
Label* NewTypeBssEntryPatch(HLoadClass* load_class);
- void RecordBootStringPatch(HLoadString* load_string);
+ void RecordBootImageStringPatch(HLoadString* load_string);
Label* NewStringBssEntryPatch(HLoadString* load_string);
Label* NewJitRootStringPatch(const DexFile& dex_file,
dex::StringIndex string_index,
@@ -613,7 +613,7 @@
// Type patch locations for kBssEntry.
ArenaDeque<PatchInfo<Label>> type_bss_entry_patches_;
// String patch locations; type depends on configuration (intern table or boot image PIC).
- ArenaDeque<PatchInfo<Label>> string_patches_;
+ ArenaDeque<PatchInfo<Label>> boot_image_string_patches_;
// String patch locations for kBssEntry.
ArenaDeque<PatchInfo<Label>> string_bss_entry_patches_;
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 43ca2cf..f91d37b 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -4567,7 +4567,7 @@
kFieldClinitCheckRequirementSize>;
// Cached values of the resolved method, to avoid needing the mutator lock.
- MethodReference target_method_;
+ const MethodReference target_method_;
DispatchInfo dispatch_info_;
};
std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::MethodLoadKind rhs);
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp
index ab06ddd..d1272c9 100644
--- a/dex2oat/Android.bp
+++ b/dex2oat/Android.bp
@@ -152,7 +152,7 @@
"libartd-compiler",
"libartd-dexlayout",
"libartd",
- "libdexfile",
+ "libdexfiled",
"libbase",
"liblz4",
"libsigchain",
@@ -185,6 +185,7 @@
"libart-compiler",
"libart-dexlayout",
"libart",
+ "libdexfile",
"libvixl-arm",
"libvixl-arm64",
] + art_static_dependencies,
@@ -216,6 +217,7 @@
"libartd-compiler",
"libartd-dexlayout",
"libartd",
+ "libdexfiled",
"libvixld-arm",
"libvixld-arm64",
] + art_static_dependencies,
@@ -246,6 +248,7 @@
"libbase",
"liblz4",
"libsigchain",
+ "libziparchive",
],
static_libs: [
"libartd-dex2oat",
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 64db7be..b5c5e45 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -456,6 +456,9 @@
UsageError(" --deduplicate-code=true|false: enable|disable code deduplication. Deduplicated");
UsageError(" code will have an arbitrary symbol tagged with [DEDUPED].");
UsageError("");
+ UsageError(" --copying-dex-files=true|false: enable|disable copying the dex files into the");
+ UsageError(" output vdex.");
+ UsageError("");
UsageError(" --compilation-reason=<string>: optional metadata specifying the reason for");
UsageError(" compiling the apk. If specified, the string will be embedded verbatim in");
UsageError(" the key value store of the oat file.");
@@ -1232,6 +1235,7 @@
AssignTrueIfExists(args, M::Host, &is_host_);
AssignTrueIfExists(args, M::AvoidStoringInvocation, &avoid_storing_invocation_);
AssignTrueIfExists(args, M::MultiImage, &multi_image_);
+ AssignIfExists(args, M::CopyDexFiles, ©_dex_files_);
if (args.Exists(M::ForceDeterminism)) {
if (!SupportsDeterministicCompilation()) {
@@ -1425,13 +1429,10 @@
LOG(INFO) << "No " << VdexFile::kVdexNameInDmFile << " file in DexMetadata archive. "
<< "Not doing fast verification.";
} else {
- std::unique_ptr<MemMap> input_file;
- if (zip_entry->IsUncompressed()) {
- input_file.reset(zip_entry->MapDirectlyFromFile(VdexFile::kVdexNameInDmFile, &error_msg));
- } else {
- input_file.reset(zip_entry->ExtractToMemMap(
- kDexMetadata, VdexFile::kVdexNameInDmFile, &error_msg));
- }
+ std::unique_ptr<MemMap> input_file(zip_entry->MapDirectlyOrExtract(
+ VdexFile::kVdexNameInDmFile,
+ kDexMetadata,
+ &error_msg));
if (input_file == nullptr) {
LOG(WARNING) << "Could not open vdex file in DexMetadata archive: " << error_msg;
} else {
@@ -1618,6 +1619,7 @@
key_value_store_.get(),
verify,
update_input_vdex_,
+ copy_dex_files_,
&opened_dex_files_map,
&opened_dex_files)) {
return dex2oat::ReturnCode::kOther;
@@ -2918,6 +2920,9 @@
// Whether the given input vdex is also the output.
bool update_input_vdex_ = false;
+ // By default, copy the dex to the vdex file.
+ bool copy_dex_files_ = true;
+
// The reason for invoking the compiler.
std::string compilation_reason_;
diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc
index 4b6f8a4..1ef100d 100644
--- a/dex2oat/dex2oat_options.cc
+++ b/dex2oat/dex2oat_options.cc
@@ -233,6 +233,11 @@
.IntoKey(M::VeryLargeAppThreshold)
.Define("--force-determinism")
.IntoKey(M::ForceDeterminism)
+ .Define("--copy-dex-files=_")
+ .WithType<bool>()
+ .WithValueMap({{"true", false},
+ {"false", false}})
+ .IntoKey(M::CopyDexFiles)
.Define("--classpath-dir=_")
.WithType<std::string>()
.IntoKey(M::ClasspathDir)
diff --git a/dex2oat/dex2oat_options.def b/dex2oat/dex2oat_options.def
index a1646aa..a9d349b 100644
--- a/dex2oat/dex2oat_options.def
+++ b/dex2oat/dex2oat_options.def
@@ -74,6 +74,7 @@
DEX2OAT_OPTIONS_KEY (Unit, DumpTiming)
DEX2OAT_OPTIONS_KEY (Unit, DumpPasses)
DEX2OAT_OPTIONS_KEY (Unit, DumpStats)
+DEX2OAT_OPTIONS_KEY (bool, CopyDexFiles)
DEX2OAT_OPTIONS_KEY (Unit, AvoidStoringInvocation)
DEX2OAT_OPTIONS_KEY (std::string, SwapFile)
DEX2OAT_OPTIONS_KEY (int, SwapFileFd)
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 4ac8e6a..12cfd24 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -41,6 +41,8 @@
#include "oat.h"
#include "oat_file.h"
#include "utils.h"
+#include "vdex_file.h"
+#include "ziparchive/zip_writer.h"
namespace art {
@@ -1781,4 +1783,90 @@
ASSERT_EQ(nullptr, odex_file->GetCompilationReason());
}
+TEST_F(Dex2oatTest, DontExtract) {
+ std::unique_ptr<const DexFile> dex(OpenTestDexFile("ManyMethods"));
+ std::string error_msg;
+ const std::string out_dir = GetScratchDir();
+ const std::string dex_location = dex->GetLocation();
+ const std::string odex_location = out_dir + "/base.oat";
+ const std::string vdex_location = out_dir + "/base.vdex";
+ GenerateOdexForTest(dex_location,
+ odex_location,
+ CompilerFilter::Filter::kVerify,
+ { "--copy-dex-files=false" },
+ true, // expect_success
+ false, // use_fd
+ [](const OatFile&) {
+ });
+ {
+ // Check the vdex doesn't have dex.
+ std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location.c_str(),
+ /*writable*/ false,
+ /*low_4gb*/ false,
+ /*unquicken*/ false,
+ &error_msg));
+ ASSERT_TRUE(vdex != nullptr);
+ EXPECT_EQ(vdex->GetHeader().GetDexSize(), 0u) << output_;
+ }
+ std::unique_ptr<OatFile> odex_file(OatFile::Open(odex_location.c_str(),
+ odex_location.c_str(),
+ nullptr,
+ nullptr,
+ false,
+ /*low_4gb*/ false,
+ dex_location.c_str(),
+ &error_msg));
+ ASSERT_TRUE(odex_file != nullptr) << dex_location;
+ std::vector<const OatDexFile*> oat_dex_files = odex_file->GetOatDexFiles();
+ ASSERT_EQ(oat_dex_files.size(), 1u);
+ // Verify that the oat file can still open the dex files.
+ for (const OatDexFile* oat_dex : oat_dex_files) {
+ std::unique_ptr<const DexFile> dex_file(oat_dex->OpenDexFile(&error_msg));
+ ASSERT_TRUE(dex_file != nullptr) << error_msg;
+ }
+ // Create a dm file and use it to verify.
+ // Add produced artifacts to a zip file that doesn't contain the classes.dex.
+ ScratchFile dm_file;
+ {
+ std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_location.c_str()));
+ ASSERT_TRUE(vdex_file != nullptr);
+ ASSERT_GT(vdex_file->GetLength(), 0u);
+ FILE* file = fdopen(dm_file.GetFd(), "w+b");
+ ZipWriter writer(file);
+ auto write_all_bytes = [&](File* file) {
+ std::unique_ptr<uint8_t[]> bytes(new uint8_t[file->GetLength()]);
+ ASSERT_TRUE(file->ReadFully(&bytes[0], file->GetLength()));
+ ASSERT_GE(writer.WriteBytes(&bytes[0], file->GetLength()), 0);
+ };
+ // Add vdex to zip.
+ writer.StartEntry(VdexFile::kVdexNameInDmFile, ZipWriter::kCompress);
+ write_all_bytes(vdex_file.get());
+ writer.FinishEntry();
+ writer.Finish();
+ ASSERT_EQ(dm_file.GetFile()->Flush(), 0);
+ }
+
+ // Generate a quickened dex by using the input dm file to verify.
+ GenerateOdexForTest(dex_location,
+ odex_location,
+ CompilerFilter::Filter::kQuicken,
+ { "--dump-timings", "--dm-file=" + dm_file.GetFilename() },
+ true, // expect_success
+ false, // use_fd
+ [](const OatFile& o) {
+ CHECK(o.ContainsDexCode());
+ });
+ if (!kIsTargetBuild) {
+ // The output_ variable is not correctly set for target, TODO: investigate.
+ std::istringstream iss(output_);
+ std::string line;
+ bool found_fast_verify = false;
+ const std::string kFastVerifyString = "Fast Verify";
+ while (std::getline(iss, line) && !found_fast_verify) {
+ found_fast_verify = found_fast_verify || line.find(kFastVerifyString) != std::string::npos;
+ }
+ EXPECT_TRUE(found_fast_verify) << "Expected to find " << kFastVerifyString << "\n" << output_;
+ }
+}
+
} // namespace art
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index 62519fc..303c873 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -276,6 +276,7 @@
&key_value_store,
/* verify */ false, // Dex files may be dex-to-dex-ed, don't verify.
/* update_input_vdex */ false,
+ /* extract_dex_files */ true,
&cur_opened_dex_files_maps,
&cur_opened_dex_files);
ASSERT_TRUE(dex_files_ok);
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 7d8065e..09f9010 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -368,7 +368,7 @@
compiler_driver_(nullptr),
image_writer_(nullptr),
compiling_boot_image_(compiling_boot_image),
- only_contains_uncompressed_zip_entries_(false),
+ extract_dex_files_into_vdex_(true),
dex_files_(nullptr),
vdex_size_(0u),
vdex_dex_files_offset_(0u),
@@ -643,6 +643,7 @@
SafeMap<std::string, std::string>* key_value_store,
bool verify,
bool update_input_vdex,
+ bool copy_dex_files,
/*out*/ std::vector<std::unique_ptr<MemMap>>* opened_dex_files_map,
/*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) {
CHECK(write_state_ == WriteState::kAddingDexFileSources);
@@ -669,7 +670,7 @@
std::unique_ptr<BufferedOutputStream> vdex_out =
std::make_unique<BufferedOutputStream>(std::make_unique<FileOutputStream>(vdex_file));
// Write DEX files into VDEX, mmap and open them.
- if (!WriteDexFiles(vdex_out.get(), vdex_file, update_input_vdex) ||
+ if (!WriteDexFiles(vdex_out.get(), vdex_file, update_input_vdex, copy_dex_files) ||
!OpenDexFiles(vdex_file, verify, &dex_files_map, &dex_files)) {
return false;
}
@@ -2749,7 +2750,7 @@
};
bool OatWriter::WriteQuickeningInfo(OutputStream* vdex_out) {
- if (only_contains_uncompressed_zip_entries_) {
+ if (!extract_dex_files_into_vdex_) {
// Nothing to write. Leave `vdex_size_` untouched and unaligned.
vdex_quickening_info_offset_ = vdex_size_;
size_quickening_info_alignment_ = 0;
@@ -3339,25 +3340,32 @@
return true;
}
-bool OatWriter::WriteDexFiles(OutputStream* out, File* file, bool update_input_vdex) {
+bool OatWriter::WriteDexFiles(OutputStream* out,
+ File* file,
+ bool update_input_vdex,
+ bool copy_dex_files) {
TimingLogger::ScopedTiming split("Write Dex files", timings_);
vdex_dex_files_offset_ = vdex_size_;
- only_contains_uncompressed_zip_entries_ = true;
- for (OatDexFile& oat_dex_file : oat_dex_files_) {
- if (!oat_dex_file.source_.IsZipEntry()) {
- only_contains_uncompressed_zip_entries_ = false;
- break;
- }
- ZipEntry* entry = oat_dex_file.source_.GetZipEntry();
- if (!entry->IsUncompressed() || !entry->IsAlignedToDexHeader()) {
- only_contains_uncompressed_zip_entries_ = false;
- break;
+ extract_dex_files_into_vdex_ = copy_dex_files;
+ // If extraction is enabled, only do it if not all the dex files are aligned and uncompressed.
+ if (extract_dex_files_into_vdex_) {
+ extract_dex_files_into_vdex_ = false;
+ for (OatDexFile& oat_dex_file : oat_dex_files_) {
+ if (!oat_dex_file.source_.IsZipEntry()) {
+ extract_dex_files_into_vdex_ = true;
+ break;
+ }
+ ZipEntry* entry = oat_dex_file.source_.GetZipEntry();
+ if (!entry->IsUncompressed() || !entry->IsAlignedToDexHeader()) {
+ extract_dex_files_into_vdex_ = true;
+ break;
+ }
}
}
- if (!only_contains_uncompressed_zip_entries_) {
+ if (extract_dex_files_into_vdex_) {
// Write dex files.
for (OatDexFile& oat_dex_file : oat_dex_files_) {
if (!WriteDexFile(out, file, &oat_dex_file, update_input_vdex)) {
@@ -3823,13 +3831,13 @@
return true;
}
- if (only_contains_uncompressed_zip_entries_) {
+ if (!extract_dex_files_into_vdex_) {
std::vector<std::unique_ptr<const DexFile>> dex_files;
std::vector<std::unique_ptr<MemMap>> maps;
for (OatDexFile& oat_dex_file : oat_dex_files_) {
std::string error_msg;
- MemMap* map = oat_dex_file.source_.GetZipEntry()->MapDirectlyFromFile(
- oat_dex_file.dex_file_location_data_, &error_msg);
+ MemMap* map = oat_dex_file.source_.GetZipEntry()->MapDirectlyOrExtract(
+ oat_dex_file.dex_file_location_data_, "zipped dex", &error_msg);
if (map == nullptr) {
LOG(ERROR) << error_msg;
return false;
diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h
index 7edb032..6a7e1e4 100644
--- a/dex2oat/linker/oat_writer.h
+++ b/dex2oat/linker/oat_writer.h
@@ -168,6 +168,7 @@
// This is generally the case, and should only be false for tests.
// If `update_input_vdex` is true, then this method won't actually write the dex files,
// and the compiler will just re-use the existing vdex file.
+ // If `copy_dex_files` is true, copy the input dex files into the vdex file.
bool WriteAndOpenDexFiles(File* vdex_file,
OutputStream* oat_rodata,
InstructionSet instruction_set,
@@ -175,6 +176,7 @@
SafeMap<std::string, std::string>* key_value_store,
bool verify,
bool update_input_vdex,
+ bool copy_dex_files,
/*out*/ std::vector<std::unique_ptr<MemMap>>* opened_dex_files_map,
/*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
bool WriteQuickeningInfo(OutputStream* vdex_out);
@@ -283,7 +285,10 @@
// If `update_input_vdex` is true, then this method won't actually write the dex files,
// and the compiler will just re-use the existing vdex file.
- bool WriteDexFiles(OutputStream* out, File* file, bool update_input_vdex);
+ bool WriteDexFiles(OutputStream* out,
+ File* file,
+ bool update_input_vdex,
+ bool copy_dex_files);
bool WriteDexFile(OutputStream* out,
File* file,
OatDexFile* oat_dex_file,
@@ -341,7 +346,7 @@
bool MayHaveCompiledMethods() const;
bool VdexWillContainDexFiles() const {
- return dex_files_ != nullptr && !only_contains_uncompressed_zip_entries_;
+ return dex_files_ != nullptr && extract_dex_files_into_vdex_;
}
// Find the address of the GcRoot<String> in the InternTable for a boot image string.
@@ -375,8 +380,8 @@
const CompilerDriver* compiler_driver_;
ImageWriter* image_writer_;
const bool compiling_boot_image_;
- // Whether the dex files being compiled are all uncompressed in the APK.
- bool only_contains_uncompressed_zip_entries_;
+ // Whether the dex files being compiled are going to be extracted to the vdex.
+ bool extract_dex_files_into_vdex_;
// note OatFile does not take ownership of the DexFiles
const std::vector<const DexFile*>* dex_files_;
diff --git a/dex2oat/linker/oat_writer_test.cc b/dex2oat/linker/oat_writer_test.cc
index cd6ca51..6dd8e19 100644
--- a/dex2oat/linker/oat_writer_test.cc
+++ b/dex2oat/linker/oat_writer_test.cc
@@ -190,15 +190,17 @@
OutputStream* oat_rodata = elf_writer->StartRoData();
std::vector<std::unique_ptr<MemMap>> opened_dex_files_maps;
std::vector<std::unique_ptr<const DexFile>> opened_dex_files;
- if (!oat_writer.WriteAndOpenDexFiles(vdex_file,
- oat_rodata,
- compiler_driver_->GetInstructionSet(),
- compiler_driver_->GetInstructionSetFeatures(),
- &key_value_store,
- verify,
- /* update_input_vdex */ false,
- &opened_dex_files_maps,
- &opened_dex_files)) {
+ if (!oat_writer.WriteAndOpenDexFiles(
+ vdex_file,
+ oat_rodata,
+ compiler_driver_->GetInstructionSet(),
+ compiler_driver_->GetInstructionSetFeatures(),
+ &key_value_store,
+ verify,
+ /* update_input_vdex */ false,
+ compiler_driver_->GetCompilerOptions().GetCompilerFilter(),
+ &opened_dex_files_maps,
+ &opened_dex_files)) {
return false;
}
diff --git a/dexdump/Android.bp b/dexdump/Android.bp
index f6b7a6b..eca0844 100644
--- a/dexdump/Android.bp
+++ b/dexdump/Android.bp
@@ -45,6 +45,7 @@
host_supported: true,
device_supported: false,
static_libs: [
+ "libdexfile",
"libbase",
] + art_static_dependencies,
target: {
diff --git a/dexdump/dexdump.cc b/dexdump/dexdump.cc
index 8778b12..61a1209 100644
--- a/dexdump/dexdump.cc
+++ b/dexdump/dexdump.cc
@@ -34,19 +34,14 @@
#include "dexdump.h"
-#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <iostream>
#include <memory>
#include <sstream>
#include <vector>
+#include "android-base/file.h"
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
@@ -1879,34 +1874,6 @@
}
}
-static bool openAndMapFile(const char* fileName,
- const uint8_t** base,
- size_t* size,
- std::string* error_msg) {
- int fd = open(fileName, O_RDONLY);
- if (fd < 0) {
- *error_msg = "open failed";
- return false;
- }
- struct stat st;
- if (fstat(fd, &st) < 0) {
- *error_msg = "stat failed";
- return false;
- }
- *size = st.st_size;
- if (*size == 0) {
- *error_msg = "size == 0";
- return false;
- }
- void* addr = mmap(nullptr /*addr*/, *size, PROT_READ, MAP_PRIVATE, fd, 0 /*offset*/);
- if (addr == MAP_FAILED) {
- *error_msg = "mmap failed";
- return false;
- }
- *base = reinterpret_cast<const uint8_t*>(addr);
- return true;
-}
-
/*
* Processes a single file (either direct .dex or indirect .zip/.jar/.apk).
*/
@@ -1918,17 +1885,22 @@
// If the file is not a .dex file, the function tries .zip/.jar/.apk files,
// all of which are Zip archives with "classes.dex" inside.
const bool kVerifyChecksum = !gOptions.ignoreBadChecksum;
- const uint8_t* base = nullptr;
- size_t size = 0;
- std::string error_msg;
- if (!openAndMapFile(fileName, &base, &size, &error_msg)) {
- LOG(ERROR) << error_msg;
+ std::string content;
+ // TODO: add an api to android::base to read a std::vector<uint8_t>.
+ if (!android::base::ReadFileToString(fileName, &content)) {
+ LOG(ERROR) << "ReadFileToString failed";
return -1;
}
const DexFileLoader dex_file_loader;
+ std::string error_msg;
std::vector<std::unique_ptr<const DexFile>> dex_files;
- if (!dex_file_loader.OpenAll(
- base, size, fileName, /*verify*/ true, kVerifyChecksum, &error_msg, &dex_files)) {
+ if (!dex_file_loader.OpenAll(reinterpret_cast<const uint8_t*>(content.data()),
+ content.size(),
+ fileName,
+ /*verify*/ true,
+ kVerifyChecksum,
+ &error_msg,
+ &dex_files)) {
// Display returned error message to user. Note that this error behavior
// differs from the error messages shown by the original Dalvik dexdump.
LOG(ERROR) << error_msg;
diff --git a/dexlayout/Android.bp b/dexlayout/Android.bp
index 3ea7f4b..bea61d0 100644
--- a/dexlayout/Android.bp
+++ b/dexlayout/Android.bp
@@ -27,7 +27,6 @@
],
export_include_dirs: ["."],
shared_libs: [
- "libdexfile",
"libbase",
],
static_libs: ["libz"],
@@ -36,7 +35,10 @@
art_cc_library {
name: "libart-dexlayout",
defaults: ["libart-dexlayout-defaults"],
- shared_libs: ["libart"],
+ shared_libs: [
+ "libart",
+ "libdexfile",
+ ],
pgo: {
instrumentation: true,
@@ -51,7 +53,10 @@
"libart-dexlayout-defaults",
"art_debug_defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: [
+ "libartd",
+ "libdexfiled",
+ ],
}
cc_defaults {
diff --git a/dexlist/dexlist.cc b/dexlist/dexlist.cc
index 31a146d..6a50258 100644
--- a/dexlist/dexlist.cc
+++ b/dexlist/dexlist.cc
@@ -23,15 +23,11 @@
* List all methods in all concrete classes in one or more DEX files.
*/
-#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include "dex/code_item_accessors-inl.h"
@@ -170,34 +166,6 @@
}
}
-static bool openAndMapFile(const char* fileName,
- const uint8_t** base,
- size_t* size,
- std::string* error_msg) {
- int fd = open(fileName, O_RDONLY);
- if (fd < 0) {
- *error_msg = "open failed";
- return false;
- }
- struct stat st;
- if (fstat(fd, &st) < 0) {
- *error_msg = "stat failed";
- return false;
- }
- *size = st.st_size;
- if (*size == 0) {
- *error_msg = "size == 0";
- return false;
- }
- void* addr = mmap(nullptr /*addr*/, *size, PROT_READ, MAP_PRIVATE, fd, 0 /*offset*/);
- if (addr == MAP_FAILED) {
- *error_msg = "mmap failed";
- return false;
- }
- *base = reinterpret_cast<const uint8_t*>(addr);
- return true;
-}
-
/*
* Processes a single file (either direct .dex or indirect .zip/.jar/.apk).
*/
@@ -205,17 +173,22 @@
// If the file is not a .dex file, the function tries .zip/.jar/.apk files,
// all of which are Zip archives with "classes.dex" inside.
static constexpr bool kVerifyChecksum = true;
- const uint8_t* base = nullptr;
- size_t size = 0;
- std::string error_msg;
- if (!openAndMapFile(fileName, &base, &size, &error_msg)) {
- LOG(ERROR) << error_msg;
+ std::string content;
+ // TODO: add an api to android::base to read a std::vector<uint8_t>.
+ if (!android::base::ReadFileToString(fileName, &content)) {
+ LOG(ERROR) << "ReadFileToString failed";
return -1;
}
std::vector<std::unique_ptr<const DexFile>> dex_files;
+ std::string error_msg;
const DexFileLoader dex_file_loader;
- if (!dex_file_loader.OpenAll(
- base, size, fileName, /*verify*/ true, kVerifyChecksum, &error_msg, &dex_files)) {
+ if (!dex_file_loader.OpenAll(reinterpret_cast<const uint8_t*>(content.data()),
+ content.size(),
+ fileName,
+ /*verify*/ true,
+ kVerifyChecksum,
+ &error_msg,
+ &dex_files)) {
LOG(ERROR) << error_msg;
return -1;
}
diff --git a/libdexfile/Android.bp b/libdexfile/Android.bp
index bcf2bdb..90c603f 100644
--- a/libdexfile/Android.bp
+++ b/libdexfile/Android.bp
@@ -93,6 +93,14 @@
},
}
+art_cc_library {
+ name: "libdexfiled",
+ defaults: [
+ "art_debug_defaults",
+ "libdexfile_defaults",
+ ],
+}
+
art_cc_test {
name: "art_libdexfile_tests",
defaults: [
diff --git a/libdexfile/dex/base64_test_util.h b/libdexfile/dex/base64_test_util.h
index 683e429..5d73759 100644
--- a/libdexfile/dex/base64_test_util.h
+++ b/libdexfile/dex/base64_test_util.h
@@ -17,13 +17,14 @@
#ifndef ART_LIBDEXFILE_DEX_BASE64_TEST_UTIL_H_
#define ART_LIBDEXFILE_DEX_BASE64_TEST_UTIL_H_
-#include <base/logging.h>
#include <stdint.h>
#include <stdlib.h>
#include <memory>
#include <vector>
+#include <android-base/logging.h>
+
namespace art {
static inline uint8_t* DecodeBase64(const char* src, size_t* dst_size) {
diff --git a/libdexfile/dex/compact_dex_debug_info_test.cc b/libdexfile/dex/compact_dex_debug_info_test.cc
index 3267612..7911a86 100644
--- a/libdexfile/dex/compact_dex_debug_info_test.cc
+++ b/libdexfile/dex/compact_dex_debug_info_test.cc
@@ -16,7 +16,7 @@
#include <vector>
-#include "base/logging.h"
+#include <android-base/logging.h>
#include "dex/compact_dex_debug_info.h"
#include "gtest/gtest.h"
@@ -74,7 +74,7 @@
/*out*/ &table_offset);
EXPECT_LT(sorted_data.size(), data.size());
{
- ScopedLogSeverity sls(LogSeverity::INFO);
+ android::base::ScopedLogSeverity sls(android::base::LogSeverity::INFO);
LOG(INFO) << "raw size " << before_size
<< " table size " << data.size()
<< " sorted table size " << sorted_data.size();
diff --git a/libdexfile/dex/compact_dex_level.h b/libdexfile/dex/compact_dex_level.h
index 2325ac2..599ec4d 100644
--- a/libdexfile/dex/compact_dex_level.h
+++ b/libdexfile/dex/compact_dex_level.h
@@ -19,7 +19,6 @@
#include <string>
-#include "base/macros.h"
#include "dex_file.h"
namespace art {
diff --git a/runtime/dex_cache_resolved_classes.h b/libdexfile/dex/dex_cache_resolved_classes.h
similarity index 93%
rename from runtime/dex_cache_resolved_classes.h
rename to libdexfile/dex/dex_cache_resolved_classes.h
index ca6afc5..4c9acbf 100644
--- a/runtime/dex_cache_resolved_classes.h
+++ b/libdexfile/dex/dex_cache_resolved_classes.h
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef ART_RUNTIME_DEX_CACHE_RESOLVED_CLASSES_H_
-#define ART_RUNTIME_DEX_CACHE_RESOLVED_CLASSES_H_
+#ifndef ART_LIBDEXFILE_DEX_DEX_CACHE_RESOLVED_CLASSES_H_
+#define ART_LIBDEXFILE_DEX_DEX_CACHE_RESOLVED_CLASSES_H_
#include <string>
#include <unordered_set>
@@ -90,4 +90,4 @@
} // namespace art
-#endif // ART_RUNTIME_DEX_CACHE_RESOLVED_CLASSES_H_
+#endif // ART_LIBDEXFILE_DEX_DEX_CACHE_RESOLVED_CLASSES_H_
diff --git a/libdexfile/dex/dex_file-inl.h b/libdexfile/dex/dex_file-inl.h
index b424b50..c86e879 100644
--- a/libdexfile/dex/dex_file-inl.h
+++ b/libdexfile/dex/dex_file-inl.h
@@ -17,7 +17,6 @@
#ifndef ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
#define ART_LIBDEXFILE_DEX_DEX_FILE_INL_H_
-#include "base/bit_utils.h"
#include "base/casts.h"
#include "base/stringpiece.h"
#include "compact_dex_file.h"
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 18eb903..6a704c1 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -45,6 +45,21 @@
static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong");
static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial");
+void DexFile::UnHideAccessFlags(ClassDataItemIterator& class_it) {
+ uint8_t* data = const_cast<uint8_t*>(class_it.DataPointer());
+ uint32_t new_flag = class_it.GetMemberAccessFlags();
+ bool is_method = class_it.IsAtMethod();
+ // Go back 1 uleb to start.
+ data = ReverseSearchUnsignedLeb128(data);
+ if (is_method) {
+ // Methods have another uleb field before the access flags
+ data = ReverseSearchUnsignedLeb128(data);
+ }
+ DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)),
+ new_flag);
+ UpdateUnsignedLeb128(data, new_flag);
+}
+
uint32_t DexFile::CalculateChecksum() const {
return CalculateChecksum(Begin(), Size());
}
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index a38e76c..a62ab62 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -35,6 +35,7 @@
namespace art {
+class ClassDataItemIterator;
class CompactDexFile;
enum InvokeType : uint32_t;
class MemMap;
@@ -1000,6 +1001,9 @@
return container_.get();
}
+ // Changes the dex file pointed to by class_it to not have any hiddenapi flags.
+ static void UnHideAccessFlags(ClassDataItemIterator& class_it);
+
protected:
// First Dex format version supporting default methods.
static const uint32_t kDefaultMethodsVersion = 37;
diff --git a/oatdump/Android.bp b/oatdump/Android.bp
index c93c172..012100d 100644
--- a/oatdump/Android.bp
+++ b/oatdump/Android.bp
@@ -51,7 +51,7 @@
"libartd",
"libartd-compiler",
"libartd-disassembler",
- "libdexfile",
+ "libdexfiled",
"libbase",
],
}
@@ -76,6 +76,7 @@
],
static_libs: [
"libart",
+ "libdexfile",
"libart-compiler",
"libart-disassembler",
"libvixl-arm",
@@ -106,6 +107,7 @@
],
static_libs: [
"libartd",
+ "libdexfiled",
"libartd-compiler",
"libartd-disassembler",
"libvixld-arm",
diff --git a/openjdkjvmti/Android.bp b/openjdkjvmti/Android.bp
index 1500bca..1553b78 100644
--- a/openjdkjvmti/Android.bp
+++ b/openjdkjvmti/Android.bp
@@ -58,7 +58,6 @@
"libopenjdkjvmti_headers",
],
shared_libs: [
- "libdexfile",
"libbase",
],
}
@@ -70,6 +69,7 @@
"libart",
"libart-compiler",
"libart-dexlayout",
+ "libdexfile",
],
}
@@ -83,5 +83,6 @@
"libartd",
"libartd-compiler",
"libartd-dexlayout",
+ "libdexfiled",
],
}
diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc
index 427d87e..90c6449 100644
--- a/openjdkjvmti/fixed_up_dex_file.cc
+++ b/openjdkjvmti/fixed_up_dex_file.cc
@@ -40,6 +40,7 @@
#include "dex/compact_dex_level.h"
#include "dex_to_dex_decompiler.h"
#include "dexlayout.h"
+#include "leb128.h"
#include "oat_file.h"
#include "vdex_file.h"
@@ -50,21 +51,41 @@
dex_file->CalculateChecksum();
}
-static void DoDexUnquicken(const art::DexFile& new_dex_file,
- const art::DexFile& original_dex_file) {
+static void UnhideApis(const art::DexFile& target_dex_file) {
+ for (uint32_t i = 0; i < target_dex_file.NumClassDefs(); ++i) {
+ const uint8_t* class_data = target_dex_file.GetClassData(target_dex_file.GetClassDef(i));
+ if (class_data != nullptr) {
+ for (art::ClassDataItemIterator class_it(target_dex_file, class_data);
+ class_it.HasNext();
+ class_it.Next()) {
+ art::DexFile::UnHideAccessFlags(class_it);
+ }
+ }
+ }
+}
+
+static const art::VdexFile* GetVdex(const art::DexFile& original_dex_file) {
const art::OatDexFile* oat_dex = original_dex_file.GetOatDexFile();
if (oat_dex == nullptr) {
- return;
+ return nullptr;
}
const art::OatFile* oat_file = oat_dex->GetOatFile();
if (oat_file == nullptr) {
- return;
+ return nullptr;
}
- const art::VdexFile* vdex = oat_file->GetVdexFile();
- if (vdex == nullptr) {
- return;
+ return oat_file->GetVdexFile();
+}
+
+static void DoDexUnquicken(const art::DexFile& new_dex_file,
+ const art::DexFile& original_dex_file) {
+ const art::VdexFile* vdex = GetVdex(original_dex_file);
+ if (vdex != nullptr) {
+ vdex->UnquickenDexFile(new_dex_file, original_dex_file, /* decompile_return_instruction */true);
+ } else {
+ // The dex file isn't quickened since it is being used directly. We might still have hiddenapis
+ // so we need to get rid of those.
+ UnhideApis(new_dex_file);
}
- vdex->UnquickenDexFile(new_dex_file, original_dex_file, /* decompile_return_instruction */true);
}
static void DCheckVerifyDexFile(const art::DexFile& dex) {
diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc
index d9cefee..4900f17 100644
--- a/patchoat/patchoat.cc
+++ b/patchoat/patchoat.cc
@@ -357,6 +357,65 @@
return true;
}
+static bool VerifySymlink(const std::string& intended_target, const std::string& link_name) {
+ std::string actual_target;
+ if (!android::base::Readlink(link_name, &actual_target)) {
+ PLOG(ERROR) << "Readlink on " << link_name << " failed.";
+ return false;
+ }
+ return actual_target == intended_target;
+}
+
+static bool VerifyVdexAndOatSymlinks(const std::string& input_image_filename,
+ const std::string& output_image_filename) {
+ return VerifySymlink(ImageHeader::GetVdexLocationFromImageLocation(input_image_filename),
+ ImageHeader::GetVdexLocationFromImageLocation(output_image_filename))
+ && VerifySymlink(ImageHeader::GetOatLocationFromImageLocation(input_image_filename),
+ ImageHeader::GetOatLocationFromImageLocation(output_image_filename));
+}
+
+bool PatchOat::CreateVdexAndOatSymlinks(const std::string& input_image_filename,
+ const std::string& output_image_filename) {
+ std::string input_vdex_filename =
+ ImageHeader::GetVdexLocationFromImageLocation(input_image_filename);
+ std::string input_oat_filename =
+ ImageHeader::GetOatLocationFromImageLocation(input_image_filename);
+
+ std::unique_ptr<File> input_oat_file(OS::OpenFileForReading(input_oat_filename.c_str()));
+ if (input_oat_file.get() == nullptr) {
+ LOG(ERROR) << "Unable to open input oat file at " << input_oat_filename;
+ return false;
+ }
+ std::string error_msg;
+ std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat_file.get(),
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE,
+ &error_msg));
+ if (elf.get() == nullptr) {
+ LOG(ERROR) << "Unable to open oat file " << input_oat_filename << " : " << error_msg;
+ return false;
+ }
+
+ MaybePic is_oat_pic = IsOatPic(elf.get());
+ if (is_oat_pic >= ERROR_FIRST) {
+ // Error logged by IsOatPic
+ return false;
+ } else if (is_oat_pic == NOT_PIC) {
+ LOG(ERROR) << "patchoat cannot be used on non-PIC oat file: " << input_oat_filename;
+ return false;
+ }
+
+ CHECK(is_oat_pic == PIC);
+
+ std::string output_vdex_filename =
+ ImageHeader::GetVdexLocationFromImageLocation(output_image_filename);
+ std::string output_oat_filename =
+ ImageHeader::GetOatLocationFromImageLocation(output_image_filename);
+
+ return SymlinkFile(input_oat_filename, output_oat_filename) &&
+ SymlinkFile(input_vdex_filename, output_vdex_filename);
+}
+
bool PatchOat::Patch(const std::string& image_location,
off_t delta,
const std::string& output_image_directory,
@@ -401,13 +460,11 @@
Thread::Current()->TransitionFromRunnableToSuspended(kNative);
ScopedObjectAccess soa(Thread::Current());
- t.NewTiming("Image Patching setup");
std::vector<gc::space::ImageSpace*> spaces = Runtime::Current()->GetHeap()->GetBootImageSpaces();
- std::map<gc::space::ImageSpace*, std::unique_ptr<File>> space_to_file_map;
std::map<gc::space::ImageSpace*, std::unique_ptr<MemMap>> space_to_memmap_map;
- std::map<gc::space::ImageSpace*, PatchOat> space_to_patchoat_map;
for (size_t i = 0; i < spaces.size(); ++i) {
+ t.NewTiming("Image Patching setup");
gc::space::ImageSpace* space = spaces[i];
std::string input_image_filename = space->GetImageFilename();
std::unique_ptr<File> input_image(OS::OpenFileForReading(input_image_filename.c_str()));
@@ -445,139 +502,76 @@
LOG(ERROR) << "Unable to map image file " << input_image->GetPath() << " : " << error_msg;
return false;
}
- space_to_file_map.emplace(space, std::move(input_image));
+
+
space_to_memmap_map.emplace(space, std::move(image));
- }
-
- // Symlink PIC oat and vdex files and patch the image spaces in memory.
- for (size_t i = 0; i < spaces.size(); ++i) {
- gc::space::ImageSpace* space = spaces[i];
- std::string input_image_filename = space->GetImageFilename();
- std::string input_vdex_filename =
- ImageHeader::GetVdexLocationFromImageLocation(input_image_filename);
- std::string input_oat_filename =
- ImageHeader::GetOatLocationFromImageLocation(input_image_filename);
- std::unique_ptr<File> input_oat_file(OS::OpenFileForReading(input_oat_filename.c_str()));
- if (input_oat_file.get() == nullptr) {
- LOG(ERROR) << "Unable to open input oat file at " << input_oat_filename;
- return false;
- }
- std::string error_msg;
- std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat_file.get(),
- PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg));
- if (elf.get() == nullptr) {
- LOG(ERROR) << "Unable to open oat file " << input_oat_file->GetPath() << " : " << error_msg;
- return false;
- }
-
- if (output_image) {
- MaybePic is_oat_pic = IsOatPic(elf.get());
- if (is_oat_pic >= ERROR_FIRST) {
- // Error logged by IsOatPic
- return false;
- } else if (is_oat_pic == NOT_PIC) {
- LOG(ERROR) << "patchoat cannot be used on non-PIC oat file: " << input_oat_file->GetPath();
- return false;
- } else {
- CHECK(is_oat_pic == PIC);
-
- // Create a symlink.
- std::string converted_image_filename = space->GetImageLocation();
- std::replace(
- converted_image_filename.begin() + 1, converted_image_filename.end(), '/', '@');
- std::string output_image_filename = output_image_directory +
- (android::base::StartsWith(converted_image_filename, "/") ? "" : "/") +
- converted_image_filename;
- std::string output_vdex_filename =
- ImageHeader::GetVdexLocationFromImageLocation(output_image_filename);
- std::string output_oat_filename =
- ImageHeader::GetOatLocationFromImageLocation(output_image_filename);
-
- if (!ReplaceOatFileWithSymlink(input_oat_file->GetPath(),
- output_oat_filename) ||
- !SymlinkFile(input_vdex_filename, output_vdex_filename)) {
- // Errors already logged by above call.
- return false;
- }
- }
- }
-
- PatchOat& p = space_to_patchoat_map.emplace(space,
- PatchOat(
- isa,
- space_to_memmap_map.find(space)->second.get(),
- space->GetLiveBitmap(),
- space->GetMemMap(),
- delta,
- &space_to_memmap_map,
- timings)).first->second;
+ PatchOat p = PatchOat(isa,
+ space_to_memmap_map.at(space).get(),
+ space->GetLiveBitmap(),
+ space->GetMemMap(),
+ delta,
+ &space_to_memmap_map,
+ timings);
t.NewTiming("Patching image");
if (!p.PatchImage(i == 0)) {
LOG(ERROR) << "Failed to patch image file " << input_image_filename;
return false;
}
- }
- if (output_image) {
// Write the patched image spaces.
- for (size_t i = 0; i < spaces.size(); ++i) {
- gc::space::ImageSpace* space = spaces[i];
+ if (output_image) {
+ std::string output_image_filename;
+ if (!GetDalvikCacheFilename(space->GetImageLocation().c_str(),
+ output_image_directory.c_str(),
+ &output_image_filename,
+ &error_msg)) {
+ LOG(ERROR) << "Failed to find relocated image file name: " << error_msg;
+ return false;
+ }
+
+ if (!CreateVdexAndOatSymlinks(input_image_filename, output_image_filename))
+ return false;
t.NewTiming("Writing image");
- std::string converted_image_filename = space->GetImageLocation();
- std::replace(converted_image_filename.begin() + 1, converted_image_filename.end(), '/', '@');
- std::string output_image_filename = output_image_directory +
- (android::base::StartsWith(converted_image_filename, "/") ? "" : "/") +
- converted_image_filename;
std::unique_ptr<File> output_image_file(CreateOrOpen(output_image_filename.c_str()));
if (output_image_file.get() == nullptr) {
LOG(ERROR) << "Failed to open output image file at " << output_image_filename;
return false;
}
- PatchOat& p = space_to_patchoat_map.find(space)->second;
-
bool success = p.WriteImage(output_image_file.get());
success = FinishFile(output_image_file.get(), success);
if (!success) {
return false;
}
}
- }
- if (output_image_relocation) {
- // Write the image relocation information for each space.
- for (size_t i = 0; i < spaces.size(); ++i) {
- gc::space::ImageSpace* space = spaces[i];
-
+ if (output_image_relocation) {
t.NewTiming("Writing image relocation");
std::string original_image_filename(space->GetImageLocation() + ".rel");
std::string image_relocation_filename =
output_image_relocation_directory
+ (android::base::StartsWith(original_image_filename, "/") ? "" : "/")
+ original_image_filename.substr(original_image_filename.find_last_of("/"));
- File& input_image = *space_to_file_map.find(space)->second;
- int64_t input_image_size = input_image.GetLength();
+ int64_t input_image_size = input_image->GetLength();
if (input_image_size < 0) {
LOG(ERROR) << "Error while getting input image size";
return false;
}
- std::string error_msg;
std::unique_ptr<MemMap> original(MemMap::MapFile(input_image_size,
PROT_READ,
MAP_PRIVATE,
- input_image.Fd(),
+ input_image->Fd(),
0,
/*low_4gb*/false,
- input_image.GetPath().c_str(),
+ input_image->GetPath().c_str(),
&error_msg));
if (original.get() == nullptr) {
- LOG(ERROR) << "Unable to map image file " << input_image.GetPath() << " : " << error_msg;
+ LOG(ERROR) << "Unable to map image file " << input_image->GetPath() << " : " << error_msg;
return false;
}
- PatchOat& p = space_to_patchoat_map.find(space)->second;
const MemMap* relocated = p.image_;
if (!WriteRelFile(*original, *relocated, image_relocation_filename, &error_msg)) {
@@ -643,11 +637,10 @@
std::string image_location_dir = android::base::Dirname(image_location);
for (size_t i = 0; i < spaces.size(); ++i) {
gc::space::ImageSpace* space = spaces[i];
- std::string image_filename = space->GetImageLocation();
std::string relocated_image_filename;
std::string error_msg;
- if (!GetDalvikCacheFilename(image_filename.c_str(),
+ if (!GetDalvikCacheFilename(space->GetImageLocation().c_str(),
output_image_directory.c_str(), &relocated_image_filename, &error_msg)) {
LOG(ERROR) << "Failed to find relocated image file name: " << error_msg;
success = false;
@@ -658,7 +651,8 @@
// basename: boot.art
// original: /system/framework/arm64/boot.art
// relocation: /system/framework/arm64/boot.art.rel
- std::string original_image_filename = GetSystemImageFilename(image_filename.c_str(), isa);
+ std::string original_image_filename =
+ GetSystemImageFilename(space->GetImageLocation().c_str(), isa);
if (!CheckImageIdenticalToOriginalExceptForRelocation(
relocated_image_filename, original_image_filename, &error_msg)) {
@@ -666,6 +660,13 @@
success = false;
break;
}
+
+ if (!VerifyVdexAndOatSymlinks(original_image_filename, relocated_image_filename)) {
+ LOG(ERROR) << "Verification of vdex and oat symlinks for "
+ << space->GetImageLocation() << " failed.";
+ success = false;
+ break;
+ }
}
if (!kIsDebugBuild && !(RUNNING_ON_MEMORY_TOOL && kMemoryToolDetectsLeaks)) {
@@ -740,26 +741,6 @@
return is_pic ? PIC : NOT_PIC;
}
-bool PatchOat::ReplaceOatFileWithSymlink(const std::string& input_oat_filename,
- const std::string& output_oat_filename) {
- // Delete the original file, since we won't need it.
- unlink(output_oat_filename.c_str());
-
- // Create a symlink from the old oat to the new oat
- if (symlink(input_oat_filename.c_str(), output_oat_filename.c_str()) < 0) {
- int err = errno;
- LOG(ERROR) << "Failed to create symlink at " << output_oat_filename
- << " error(" << err << "): " << strerror(err);
- return false;
- }
-
- if (kIsDebugBuild) {
- LOG(INFO) << "Created symlink " << output_oat_filename << " -> " << input_oat_filename;
- }
-
- return true;
-}
-
class PatchOat::PatchOatArtFieldVisitor : public ArtFieldVisitor {
public:
explicit PatchOatArtFieldVisitor(PatchOat* patch_oat) : patch_oat_(patch_oat) {}
diff --git a/patchoat/patchoat.h b/patchoat/patchoat.h
index ba59d57..feba523 100644
--- a/patchoat/patchoat.h
+++ b/patchoat/patchoat.h
@@ -91,10 +91,9 @@
// Was the .oat image at oat_in made with --compile-pic ?
static MaybePic IsOatPic(const ElfFile* oat_in);
- // Attempt to replace the file with a symlink
- // Returns false if it fails
- static bool ReplaceOatFileWithSymlink(const std::string& input_oat_filename,
- const std::string& output_oat_filename);
+ static bool CreateVdexAndOatSymlinks(const std::string& input_image_filename,
+ const std::string& output_image_filename);
+
void VisitObject(mirror::Object* obj)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/profman/Android.bp b/profman/Android.bp
index 6592b9d..163be2b 100644
--- a/profman/Android.bp
+++ b/profman/Android.bp
@@ -31,7 +31,6 @@
},
shared_libs: [
- "libdexfile",
"libbase",
],
}
@@ -41,6 +40,7 @@
defaults: ["profman-defaults"],
shared_libs: [
"libart",
+ "libdexfile",
],
}
@@ -52,6 +52,7 @@
],
shared_libs: [
"libartd",
+ "libdexfiled",
],
}
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 110b04f..1ac770f 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -409,7 +409,6 @@
"jni_platform_headers",
],
shared_libs: [
- "libdexfile",
"libnativebridge",
"libnativeloader",
"libbacktrace",
@@ -430,10 +429,7 @@
// ART's macros.h depends on libbase's macros.h.
// Note: runtime_options.h depends on cmdline. But we don't really want to export this
// generically. dex2oat takes care of it itself.
- export_shared_lib_headers: [
- "libbase",
- "libdexfile",
- ],
+ export_shared_lib_headers: ["libbase"],
}
gensrcs {
@@ -490,6 +486,8 @@
strip: {
keep_symbols: true,
},
+ shared_libs: ["libdexfile"],
+ export_shared_lib_headers: ["libdexfile"],
}
art_cc_library {
@@ -498,6 +496,8 @@
"art_debug_defaults",
"libart_defaults",
],
+ shared_libs: ["libdexfiled"],
+ export_shared_lib_headers: ["libdexfiled"],
}
art_cc_library {
diff --git a/runtime/base/stringpiece.cc b/runtime/base/stringpiece.cc
index 672431c..aea4e74 100644
--- a/runtime/base/stringpiece.cc
+++ b/runtime/base/stringpiece.cc
@@ -23,13 +23,6 @@
namespace art {
-#if !defined(NDEBUG)
-char StringPiece::operator[](size_type i) const {
- CHECK_LT(i, length_);
- return ptr_[i];
-}
-#endif
-
void StringPiece::CopyToString(std::string* target) const {
target->assign(ptr_, length_);
}
diff --git a/runtime/base/stringpiece.h b/runtime/base/stringpiece.h
index 46743e9..e7109dc 100644
--- a/runtime/base/stringpiece.h
+++ b/runtime/base/stringpiece.h
@@ -20,6 +20,8 @@
#include <string.h>
#include <string>
+#include <android-base/logging.h>
+
namespace art {
// A string-like object that points to a sized piece of memory.
@@ -84,13 +86,10 @@
length_ = len;
}
-#if defined(NDEBUG)
char operator[](size_type i) const {
+ DCHECK_LT(i, length_);
return ptr_[i];
}
-#else
- char operator[](size_type i) const;
-#endif
void remove_prefix(size_type n) {
ptr_ += n;
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc
index 5549122..05f099f 100644
--- a/runtime/check_jni.cc
+++ b/runtime/check_jni.cc
@@ -46,6 +46,7 @@
#include "well_known_classes.h"
namespace art {
+namespace {
using android::base::StringAppendF;
using android::base::StringPrintf;
@@ -1211,7 +1212,7 @@
// this particular instance of JNIEnv.
if (env != threadEnv) {
// Get the thread owning the JNIEnv that's being used.
- Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->self_;
+ Thread* envThread = reinterpret_cast<JNIEnvExt*>(env)->GetSelf();
AbortF("thread %s using JNIEnv* from thread %s",
ToStr<Thread>(*self).c_str(), ToStr<Thread>(*envThread).c_str());
return false;
@@ -1223,7 +1224,7 @@
case kFlag_CritOkay: // okay to call this method
break;
case kFlag_CritBad: // not okay to call
- if (threadEnv->critical_ > 0) {
+ if (threadEnv->GetCritical() > 0) {
AbortF("thread %s using JNI after critical get",
ToStr<Thread>(*self).c_str());
return false;
@@ -1231,25 +1232,25 @@
break;
case kFlag_CritGet: // this is a "get" call
// Don't check here; we allow nested gets.
- if (threadEnv->critical_ == 0) {
- threadEnv->critical_start_us_ = self->GetCpuMicroTime();
+ if (threadEnv->GetCritical() == 0) {
+ threadEnv->SetCriticalStartUs(self->GetCpuMicroTime());
}
- threadEnv->critical_++;
+ threadEnv->SetCritical(threadEnv->GetCritical() + 1);
break;
case kFlag_CritRelease: // this is a "release" call
- if (threadEnv->critical_ == 0) {
+ if (threadEnv->GetCritical() == 0) {
AbortF("thread %s called too many critical releases",
ToStr<Thread>(*self).c_str());
return false;
- } else if (threadEnv->critical_ == 1) {
+ } else if (threadEnv->GetCritical() == 1) {
// Leaving the critical region, possibly warn about long critical regions.
- uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->critical_start_us_;
+ uint64_t critical_duration_us = self->GetCpuMicroTime() - threadEnv->GetCriticalStartUs();
if (critical_duration_us > kCriticalWarnTimeUs) {
LOG(WARNING) << "JNI critical lock held for "
<< PrettyDuration(UsToNs(critical_duration_us)) << " on " << *self;
}
}
- threadEnv->critical_--;
+ threadEnv->SetCritical(threadEnv->GetCritical() - 1);
break;
default:
LOG(FATAL) << "Bad flags (internal error): " << flags_;
@@ -2621,7 +2622,7 @@
}
static const JNINativeInterface* baseEnv(JNIEnv* env) {
- return reinterpret_cast<JNIEnvExt*>(env)->unchecked_functions_;
+ return reinterpret_cast<JNIEnvExt*>(env)->GetUncheckedFunctions();
}
static jobject NewRef(const char* function_name, JNIEnv* env, jobject obj, IndirectRefKind kind) {
@@ -3847,10 +3848,6 @@
CheckJNI::GetObjectRefType,
};
-const JNINativeInterface* GetCheckJniNativeInterface() {
- return &gCheckNativeInterface;
-}
-
class CheckJII {
public:
static jint DestroyJavaVM(JavaVM* vm) {
@@ -3922,6 +3919,12 @@
CheckJII::AttachCurrentThreadAsDaemon
};
+} // anonymous namespace
+
+const JNINativeInterface* GetCheckJniNativeInterface() {
+ return &gCheckNativeInterface;
+}
+
const JNIInvokeInterface* GetCheckJniInvokeInterface() {
return &gCheckInvokeInterface;
}
diff --git a/runtime/class_linker-inl.h b/runtime/class_linker-inl.h
index cd6e8d5..ae06f8f 100644
--- a/runtime/class_linker-inl.h
+++ b/runtime/class_linker-inl.h
@@ -226,14 +226,7 @@
const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
if (klass != nullptr) {
- if (klass->IsInterface()) {
- resolved = klass->FindInterfaceMethod(dex_cache, method_idx, pointer_size);
- } else {
- resolved = klass->FindClassMethod(dex_cache, method_idx, pointer_size);
- }
- if (resolved != nullptr) {
- dex_cache->SetResolvedMethod(method_idx, resolved, pointer_size);
- }
+ resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx);
}
}
return resolved;
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c4b1bf8..63d47e6 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -7939,6 +7939,39 @@
return oss.str();
}
+ArtMethod* ClassLinker::FindResolvedMethod(ObjPtr<mirror::Class> klass,
+ ObjPtr<mirror::DexCache> dex_cache,
+ ObjPtr<mirror::ClassLoader> class_loader,
+ uint32_t method_idx) {
+ // Search for the method using dex_cache and method_idx. The Class::Find*Method()
+ // functions can optimize the search if the dex_cache is the same as the DexCache
+ // of the class, with fall-back to name and signature search otherwise.
+ ArtMethod* resolved = nullptr;
+ if (klass->IsInterface()) {
+ resolved = klass->FindInterfaceMethod(dex_cache, method_idx, image_pointer_size_);
+ } else {
+ resolved = klass->FindClassMethod(dex_cache, method_idx, image_pointer_size_);
+ }
+ DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr);
+ if (resolved != nullptr) {
+ // In case of jmvti, the dex file gets verified before being registered, so first
+ // check if it's registered before checking class tables.
+ const DexFile& dex_file = *dex_cache->GetDexFile();
+ CHECK(!IsDexFileRegistered(Thread::Current(), dex_file) ||
+ FindClassTable(Thread::Current(), dex_cache) == ClassTableForClassLoader(class_loader))
+ << "DexFile referrer: " << dex_file.GetLocation()
+ << " ClassLoader: " << DescribeLoaders(class_loader, "");
+ // Be a good citizen and update the dex cache to speed subsequent calls.
+ dex_cache->SetResolvedMethod(method_idx, resolved, image_pointer_size_);
+ const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
+ DCHECK(LookupResolvedType(method_id.class_idx_, dex_cache, class_loader) != nullptr)
+ << "Method: " << resolved->PrettyMethod() << ", "
+ << "Class: " << klass->PrettyClass() << " (" << klass->GetStatus() << "), "
+ << "DexFile referrer: " << dex_file.GetLocation();
+ }
+ return resolved;
+}
+
template <ClassLinker::ResolveMode kResolveMode>
ArtMethod* ClassLinker::ResolveMethod(uint32_t method_idx,
Handle<mirror::DexCache> dex_cache,
@@ -7971,6 +8004,7 @@
<< resolved->PrettyMethod() << ";" << resolved
<< "/0x" << std::hex << resolved->GetAccessFlags()
<< " ReferencedClass: " << descriptor
+ << " DexFile referrer: " << dex_file.GetLocation()
<< " ClassLoader: " << DescribeLoaders(class_loader.Get(), descriptor);
}
} else {
@@ -7991,19 +8025,7 @@
}
if (!valid_dex_cache_method) {
- // Search for the method using dex_cache and method_idx. The Class::Find*Method()
- // functions can optimize the search if the dex_cache is the same as the DexCache
- // of the class, with fall-back to name and signature search otherwise.
- if (klass->IsInterface()) {
- resolved = klass->FindInterfaceMethod(dex_cache.Get(), method_idx, pointer_size);
- } else {
- resolved = klass->FindClassMethod(dex_cache.Get(), method_idx, pointer_size);
- }
- DCHECK(resolved == nullptr || resolved->GetDeclaringClassUnchecked() != nullptr);
- if (resolved != nullptr) {
- // Be a good citizen and update the dex cache to speed subsequent calls.
- dex_cache->SetResolvedMethod(method_idx, resolved, pointer_size);
- }
+ resolved = FindResolvedMethod(klass, dex_cache.Get(), class_loader.Get(), method_idx);
}
// Note: We can check for IllegalAccessError only if we have a referrer.
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 16fa1ce..712e3ae 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -27,9 +27,9 @@
#include "base/enums.h"
#include "base/macros.h"
#include "base/mutex.h"
+#include "dex/dex_cache_resolved_classes.h"
#include "dex/dex_file.h"
#include "dex/dex_file_types.h"
-#include "dex_cache_resolved_classes.h"
#include "gc_root.h"
#include "handle.h"
#include "jni.h"
@@ -312,6 +312,13 @@
ObjPtr<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Find a method with the given index from class `klass`, and update the dex cache.
+ ArtMethod* FindResolvedMethod(ObjPtr<mirror::Class> klass,
+ ObjPtr<mirror::DexCache> dex_cache,
+ ObjPtr<mirror::ClassLoader> class_loader,
+ uint32_t method_idx)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// Resolve a method with a given ID from the DexFile associated with the given DexCache
// and ClassLoader, storing the result in DexCache. The ClassLinker and ClassLoader are
// used as in ResolveType. What is unique is the method type argument which is used to
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index 9ef7d42..404c535 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -99,14 +99,13 @@
<< "This must be due to playing wrongly with class loaders";
}
- inlined_method = klass->FindClassMethod(dex_cache, method_index, kRuntimePointerSize);
+ inlined_method = class_linker->FindResolvedMethod(klass, dex_cache, class_loader, method_index);
if (inlined_method == nullptr) {
LOG(FATAL) << "Could not find an inlined method from an .oat file: the class " << descriptor
<< " does not have " << dex_file->GetMethodName(method_id)
<< dex_file->GetMethodSignature(method_id) << " declared. "
<< "This must be due to duplicate classes or playing wrongly with class loaders";
}
- dex_cache->SetResolvedMethod(method_index, inlined_method, kRuntimePointerSize);
return inlined_method;
}
diff --git a/runtime/entrypoints/quick/quick_entrypoints.h b/runtime/entrypoints/quick/quick_entrypoints.h
index 6cd9dc1..795faa8 100644
--- a/runtime/entrypoints/quick/quick_entrypoints.h
+++ b/runtime/entrypoints/quick/quick_entrypoints.h
@@ -38,6 +38,7 @@
class ArtMethod;
template<class MirrorType> class GcRoot;
+template<class MirrorType> class StackReference;
class Thread;
// Pointers to functions that are called by quick compiler generated code via thread-local storage.
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index a8c328f..344e5be 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -649,10 +649,6 @@
REQUIRES_SHARED(Locks::mutator_lock_) {
return QuickArgumentVisitor::GetProxyThisObjectReference(sp)->AsMirrorPtr();
}
-extern "C" StackReference<mirror::Object>* artQuickGetProxyThisObjectReference(ArtMethod** sp)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- return QuickArgumentVisitor::GetProxyThisObjectReference(sp);
-}
// Visits arguments on the stack placing them into the shadow frame.
class BuildQuickShadowFrameVisitor FINAL : public QuickArgumentVisitor {
@@ -953,7 +949,8 @@
std::vector<jvalue> args;
uint32_t shorty_len = 0;
const char* shorty = non_proxy_method->GetShorty(&shorty_len);
- BuildQuickArgumentVisitor local_ref_visitor(sp, false, shorty, shorty_len, &soa, &args);
+ BuildQuickArgumentVisitor local_ref_visitor(
+ sp, /* is_static */ false, shorty, shorty_len, &soa, &args);
local_ref_visitor.VisitArguments();
DCHECK_GT(args.size(), 0U) << proxy_method->PrettyMethod();
@@ -982,6 +979,106 @@
return result.GetJ();
}
+// Visitor returning a reference argument at a given position in a Quick stack frame.
+// NOTE: Only used for testing purposes.
+class GetQuickReferenceArgumentAtVisitor FINAL : public QuickArgumentVisitor {
+ public:
+ GetQuickReferenceArgumentAtVisitor(ArtMethod** sp,
+ const char* shorty,
+ uint32_t shorty_len,
+ size_t arg_pos)
+ : QuickArgumentVisitor(sp, /* is_static */ false, shorty, shorty_len),
+ cur_pos_(0u),
+ arg_pos_(arg_pos),
+ ref_arg_(nullptr) {
+ CHECK_LT(arg_pos, shorty_len) << "Argument position greater than the number arguments";
+ }
+
+ void Visit() REQUIRES_SHARED(Locks::mutator_lock_) OVERRIDE {
+ if (cur_pos_ == arg_pos_) {
+ Primitive::Type type = GetParamPrimitiveType();
+ CHECK_EQ(type, Primitive::kPrimNot) << "Argument at searched position is not a reference";
+ ref_arg_ = reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress());
+ }
+ ++cur_pos_;
+ }
+
+ StackReference<mirror::Object>* GetReferenceArgument() {
+ return ref_arg_;
+ }
+
+ private:
+ // The position of the currently visited argument.
+ size_t cur_pos_;
+ // The position of the searched argument.
+ const size_t arg_pos_;
+ // The reference argument, if found.
+ StackReference<mirror::Object>* ref_arg_;
+
+ DISALLOW_COPY_AND_ASSIGN(GetQuickReferenceArgumentAtVisitor);
+};
+
+// Returning reference argument at position `arg_pos` in Quick stack frame at address `sp`.
+// NOTE: Only used for testing purposes.
+extern "C" StackReference<mirror::Object>* artQuickGetProxyReferenceArgumentAt(size_t arg_pos,
+ ArtMethod** sp)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ ArtMethod* proxy_method = *sp;
+ ArtMethod* non_proxy_method = proxy_method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
+ CHECK(!non_proxy_method->IsStatic())
+ << proxy_method->PrettyMethod() << " " << non_proxy_method->PrettyMethod();
+ uint32_t shorty_len = 0;
+ const char* shorty = non_proxy_method->GetShorty(&shorty_len);
+ GetQuickReferenceArgumentAtVisitor ref_arg_visitor(sp, shorty, shorty_len, arg_pos);
+ ref_arg_visitor.VisitArguments();
+ StackReference<mirror::Object>* ref_arg = ref_arg_visitor.GetReferenceArgument();
+ return ref_arg;
+}
+
+// Visitor returning all the reference arguments in a Quick stack frame.
+class GetQuickReferenceArgumentsVisitor FINAL : public QuickArgumentVisitor {
+ public:
+ GetQuickReferenceArgumentsVisitor(ArtMethod** sp,
+ bool is_static,
+ const char* shorty,
+ uint32_t shorty_len)
+ : QuickArgumentVisitor(sp, is_static, shorty, shorty_len) {}
+
+ void Visit() REQUIRES_SHARED(Locks::mutator_lock_) OVERRIDE {
+ Primitive::Type type = GetParamPrimitiveType();
+ if (type == Primitive::kPrimNot) {
+ StackReference<mirror::Object>* ref_arg =
+ reinterpret_cast<StackReference<mirror::Object>*>(GetParamAddress());
+ ref_args_.push_back(ref_arg);
+ }
+ }
+
+ std::vector<StackReference<mirror::Object>*> GetReferenceArguments() {
+ return ref_args_;
+ }
+
+ private:
+ // The reference arguments.
+ std::vector<StackReference<mirror::Object>*> ref_args_;
+
+ DISALLOW_COPY_AND_ASSIGN(GetQuickReferenceArgumentsVisitor);
+};
+
+// Returning all reference arguments in Quick stack frame at address `sp`.
+std::vector<StackReference<mirror::Object>*> GetProxyReferenceArguments(ArtMethod** sp)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ ArtMethod* proxy_method = *sp;
+ ArtMethod* non_proxy_method = proxy_method->GetInterfaceMethodIfProxy(kRuntimePointerSize);
+ CHECK(!non_proxy_method->IsStatic())
+ << proxy_method->PrettyMethod() << " " << non_proxy_method->PrettyMethod();
+ uint32_t shorty_len = 0;
+ const char* shorty = non_proxy_method->GetShorty(&shorty_len);
+ GetQuickReferenceArgumentsVisitor ref_args_visitor(sp, /* is_static */ false, shorty, shorty_len);
+ ref_args_visitor.VisitArguments();
+ std::vector<StackReference<mirror::Object>*> ref_args = ref_args_visitor.GetReferenceArguments();
+ return ref_args;
+}
+
// Read object references held in arguments from quick frames and place in a JNI local references,
// so they don't get garbage collected.
class RememberForGcArgumentVisitor FINAL : public QuickArgumentVisitor {
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 24cedb0..0ae6dbf 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -269,7 +269,20 @@
}
} else {
CHECK_NE(return_pc, 0U);
- CHECK(!reached_existing_instrumentation_frames_);
+ if (UNLIKELY(reached_existing_instrumentation_frames_)) {
+ std::string thread_name;
+ GetThread()->GetThreadName(thread_name);
+ uint32_t dex_pc = dex::kDexNoIndex;
+ if (last_return_pc_ != 0 &&
+ GetCurrentOatQuickMethodHeader() != nullptr) {
+ dex_pc = GetCurrentOatQuickMethodHeader()->ToDexPc(m, last_return_pc_);
+ }
+ LOG(FATAL) << "While walking " << thread_name << " found existing instrumentation frames."
+ << " method is " << GetMethod()->PrettyMethod()
+ << " return_pc is " << std::hex << return_pc
+ << " dex pc: " << dex_pc;
+ UNREACHABLE();
+ }
InstrumentationStackFrame instrumentation_frame(
m->IsRuntimeMethod() ? nullptr : GetThisObject(),
m,
diff --git a/runtime/java_vm_ext.h b/runtime/java_vm_ext.h
index 8c81c25..ac20afe 100644
--- a/runtime/java_vm_ext.h
+++ b/runtime/java_vm_ext.h
@@ -225,7 +225,7 @@
// Extra checking.
bool check_jni_;
- bool force_copy_;
+ const bool force_copy_;
const bool tracing_enabled_;
// Extra diagnostics.
diff --git a/runtime/jit/profile_compilation_info.cc b/runtime/jit/profile_compilation_info.cc
index dcb4a20..21caa42 100644
--- a/runtime/jit/profile_compilation_info.cc
+++ b/runtime/jit/profile_compilation_info.cc
@@ -1195,22 +1195,10 @@
return kProfileLoadBadData;
}
- std::unique_ptr<MemMap> map;
- if (zip_entry->IsUncompressed()) {
- // Map uncompressed files within zip as file-backed to avoid a dirty copy.
- map.reset(zip_entry->MapDirectlyFromFile(kDexMetadataProfileEntry, error));
- if (map == nullptr) {
- LOG(WARNING) << "Can't mmap profile directly; "
- << "is your ZIP file corrupted? Falling back to extraction.";
- // Try again with Extraction which still has a chance of recovery.
- }
- }
-
- if (map == nullptr) {
- // Default path for compressed ZIP entries, and fallback for stored ZIP entries.
- // TODO(calin) pass along file names to assist with debugging.
- map.reset(zip_entry->ExtractToMemMap("profile file", kDexMetadataProfileEntry, error));
- }
+ // TODO(calin) pass along file names to assist with debugging.
+ std::unique_ptr<MemMap> map(zip_entry->MapDirectlyOrExtract(kDexMetadataProfileEntry,
+ "profile file",
+ error));
if (map != nullptr) {
source->reset(ProfileSource::Create(std::move(map)));
diff --git a/runtime/jit/profile_compilation_info.h b/runtime/jit/profile_compilation_info.h
index 5488a9e..3213c85 100644
--- a/runtime/jit/profile_compilation_info.h
+++ b/runtime/jit/profile_compilation_info.h
@@ -24,7 +24,7 @@
#include "base/arena_containers.h"
#include "base/arena_object.h"
#include "bit_memory_region.h"
-#include "dex_cache_resolved_classes.h"
+#include "dex/dex_cache_resolved_classes.h"
#include "dex/dex_file.h"
#include "dex/dex_file_types.h"
#include "method_reference.h"
diff --git a/runtime/jni_env_ext.h b/runtime/jni_env_ext.h
index 0e8fd03..291ac48 100644
--- a/runtime/jni_env_ext.h
+++ b/runtime/jni_env_ext.h
@@ -96,6 +96,15 @@
}
Thread* GetSelf() const { return self_; }
+ uint32_t GetCritical() const { return critical_; }
+ void SetCritical(uint32_t new_critical) { critical_ = new_critical; }
+ uint64_t GetCriticalStartUs() const { return critical_start_us_; }
+ void SetCriticalStartUs(uint64_t new_critical_start_us) {
+ critical_start_us_ = new_critical_start_us;
+ }
+ const JNINativeInterface* GetUncheckedFunctions() const {
+ return unchecked_functions_;
+ }
JavaVMExt* GetVm() const { return vm_; }
bool IsRuntimeDeleted() const { return runtime_deleted_; }
@@ -190,9 +199,7 @@
// If we are a JNI env for a daemon thread with a deleted runtime.
bool runtime_deleted_;
- friend class CheckJNI;
friend class JNI;
- friend class ScopedCheck;
friend class ScopedJniEnvLocalRefState;
friend class Thread;
ART_FRIEND_TEST(JniInternalTest, JNIEnvExtOffsets);
diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc
index 57a429c..505b745 100644
--- a/runtime/native/dalvik_system_VMRuntime.cc
+++ b/runtime/native/dalvik_system_VMRuntime.cc
@@ -405,18 +405,15 @@
}
const DexFile* dex_file = dex_cache->GetDexFile();
const DexFile::MethodId& method_id = dex_file->GetMethodId(method_idx);
- ObjPtr<mirror::Class> klass = Runtime::Current()->GetClassLinker()->LookupResolvedType(
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+
+ ObjPtr<mirror::Class> klass = class_linker->LookupResolvedType(
method_id.class_idx_, dex_cache, /* class_loader */ nullptr);
if (klass == nullptr) {
return;
}
- ArtMethod* method = klass->IsInterface()
- ? klass->FindInterfaceMethod(dex_cache, method_idx, kRuntimePointerSize)
- : klass->FindClassMethod(dex_cache, method_idx, kRuntimePointerSize);
- if (method == nullptr) {
- return;
- }
- dex_cache->SetResolvedMethod(method_idx, method, kRuntimePointerSize);
+ // Call FindResolvedMethod to populate the dex cache.
+ class_linker->FindResolvedMethod(klass, dex_cache, /* class_loader */ nullptr, method_idx);
}
struct DexCacheStats {
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 12400e2..08e471b 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -277,7 +277,10 @@
jlong token,
jint runtime_flags,
jboolean is_system_server,
+ jboolean is_zygote,
jstring instruction_set) {
+ DCHECK(!(is_system_server && is_zygote));
+
Thread* thread = reinterpret_cast<Thread*>(token);
// Our system thread ID, etc, has changed so reset Thread state.
thread->InitAfterFork();
@@ -346,13 +349,22 @@
}
}
- DCHECK(!is_system_server || !do_hidden_api_checks)
- << "SystemServer should be forked with DISABLE_HIDDEN_API_CHECKS";
+ DCHECK(!(is_system_server && do_hidden_api_checks))
+ << "SystemServer should be forked with ENABLE_HIDDEN_API_CHECKS";
+ DCHECK(!(is_zygote && do_hidden_api_checks))
+ << "Child zygote processes should be forked with ENABLE_HIDDEN_API_CHECKS";
Runtime::Current()->SetHiddenApiChecksEnabled(do_hidden_api_checks);
// Clear the hidden API warning flag, in case it was set.
Runtime::Current()->SetPendingHiddenApiWarning(false);
+ if (is_zygote) {
+ // If creating a child-zygote, do not call into the runtime's post-fork logic.
+ // Doing so would spin up threads for Binder and JDWP. Instead, the Java side
+ // of the child process will call a static main in a class specified by the parent.
+ return;
+ }
+
if (instruction_set != nullptr && !is_system_server) {
ScopedUtfChars isa_string(env, instruction_set);
InstructionSet isa = GetInstructionSetFromString(isa_string.c_str());
@@ -380,7 +392,7 @@
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(ZygoteHooks, nativePreFork, "()J"),
- NATIVE_METHOD(ZygoteHooks, nativePostForkChild, "(JIZLjava/lang/String;)V"),
+ NATIVE_METHOD(ZygoteHooks, nativePostForkChild, "(JIZZLjava/lang/String;)V"),
NATIVE_METHOD(ZygoteHooks, startZygoteNoThreadCreation, "()V"),
NATIVE_METHOD(ZygoteHooks, stopZygoteNoThreadCreation, "()V"),
};
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 2ee7f9d..1de7b20 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -3436,7 +3436,7 @@
return object != nullptr && object->GetLockOwnerThreadId() == GetThreadId();
}
-extern "C" StackReference<mirror::Object>* artQuickGetProxyThisObjectReference(ArtMethod** sp)
+extern std::vector<StackReference<mirror::Object>*> GetProxyReferenceArguments(ArtMethod** sp)
REQUIRES_SHARED(Locks::mutator_lock_);
// RootVisitor parameters are: (const Object* obj, size_t vreg, const StackVisitor* visitor).
@@ -3482,7 +3482,7 @@
}
}
// Mark lock count map required for structured locking checks.
- shadow_frame->GetLockCountData().VisitMonitors(visitor_, -1, this);
+ shadow_frame->GetLockCountData().VisitMonitors(visitor_, /* vreg */ -1, this);
}
private:
@@ -3520,7 +3520,7 @@
}
}
mirror::Object* new_ref = klass.Ptr();
- visitor_(&new_ref, -1, this);
+ visitor_(&new_ref, /* vreg */ -1, this);
if (new_ref != klass) {
method->CASDeclaringClass(klass.Ptr(), new_ref->AsClass());
}
@@ -3583,17 +3583,20 @@
}
}
}
- } else if (!m->IsStatic() && !m->IsRuntimeMethod() && m->IsProxyMethod()) {
- // If this is a non-static proxy method, visit its target (`this` object).
+ } else if (!m->IsRuntimeMethod() && m->IsProxyMethod()) {
+ // If this is a proxy method, visit its reference arguments.
+ DCHECK(!m->IsStatic());
DCHECK(!m->IsNative());
- StackReference<mirror::Object>* ref_addr =
- artQuickGetProxyThisObjectReference(cur_quick_frame);
- mirror::Object* ref = ref_addr->AsMirrorPtr();
- if (ref != nullptr) {
- mirror::Object* new_ref = ref;
- visitor_(&new_ref, -1, this);
- if (ref != new_ref) {
- ref_addr->Assign(new_ref);
+ std::vector<StackReference<mirror::Object>*> ref_addrs =
+ GetProxyReferenceArguments(cur_quick_frame);
+ for (StackReference<mirror::Object>* ref_addr : ref_addrs) {
+ mirror::Object* ref = ref_addr->AsMirrorPtr();
+ if (ref != nullptr) {
+ mirror::Object* new_ref = ref;
+ visitor_(&new_ref, /* vreg */ -1, this);
+ if (ref != new_ref) {
+ ref_addr->Assign(new_ref);
+ }
}
}
}
diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc
index 0829c54..443c35f 100644
--- a/runtime/vdex_file.cc
+++ b/runtime/vdex_file.cc
@@ -263,18 +263,6 @@
UnquickenDexFile(target_dex_file, source_dex_file.Begin(), decompile_return_instruction);
}
-static void UpdateAccessFlags(uint8_t* data, uint32_t new_flag, bool is_method) {
- // Go back 1 uleb to start.
- data = ReverseSearchUnsignedLeb128(data);
- if (is_method) {
- // Methods have another uleb field before the access flags
- data = ReverseSearchUnsignedLeb128(data);
- }
- DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data)),
- new_flag);
- UpdateUnsignedLeb128(data, new_flag);
-}
-
void VdexFile::UnquickenDexFile(const DexFile& target_dex_file,
const uint8_t* source_dex_begin,
bool decompile_return_instruction) const {
@@ -312,14 +300,8 @@
quicken_data,
decompile_return_instruction);
}
- UpdateAccessFlags(const_cast<uint8_t*>(class_it.DataPointer()),
- class_it.GetMemberAccessFlags(),
- /*is_method*/ true);
- } else {
- UpdateAccessFlags(const_cast<uint8_t*>(class_it.DataPointer()),
- class_it.GetMemberAccessFlags(),
- /*is_method*/ false);
}
+ DexFile::UnHideAccessFlags(class_it);
}
}
}
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 3e9dfd1..66e578f 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -3899,21 +3899,13 @@
}
ObjPtr<mirror::Class> klass = klass_type.GetClass();
const RegType& referrer = GetDeclaringClass();
- auto* cl = Runtime::Current()->GetClassLinker();
- auto pointer_size = cl->GetImagePointerSize();
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ PointerSize pointer_size = class_linker->GetImagePointerSize();
ArtMethod* res_method = dex_cache_->GetResolvedMethod(dex_method_idx, pointer_size);
if (res_method == nullptr) {
- // Try to find the method with the appropriate lookup for the klass type (interface or not).
- // If this lookup does not match `method_type`, errors shall be reported below.
- if (klass->IsInterface()) {
- res_method = klass->FindInterfaceMethod(dex_cache_.Get(), dex_method_idx, pointer_size);
- } else {
- res_method = klass->FindClassMethod(dex_cache_.Get(), dex_method_idx, pointer_size);
- }
- if (res_method != nullptr) {
- dex_cache_->SetResolvedMethod(dex_method_idx, res_method, pointer_size);
- }
+ res_method = class_linker->FindResolvedMethod(
+ klass, dex_cache_.Get(), class_loader_.Get(), dex_method_idx);
}
// Record result of method resolution attempt. The klass resolution has recorded whether
diff --git a/runtime/zip_archive.cc b/runtime/zip_archive.cc
index 2caed4b..5b3cab4 100644
--- a/runtime/zip_archive.cc
+++ b/runtime/zip_archive.cc
@@ -193,6 +193,19 @@
return map.release();
}
+MemMap* ZipEntry::MapDirectlyOrExtract(const char* zip_filename,
+ const char* entry_filename,
+ std::string* error_msg) {
+ if (IsUncompressed() && GetFileDescriptor(handle_) >= 0) {
+ MemMap* ret = MapDirectlyFromFile(zip_filename, error_msg);
+ if (ret != nullptr) {
+ return ret;
+ }
+ }
+ // Fall back to extraction for the failure case.
+ return ExtractToMemMap(zip_filename, entry_filename, error_msg);
+}
+
static void SetCloseOnExec(int fd) {
// This dance is more portable than Linux's O_CLOEXEC open(2) flag.
int flags = fcntl(fd, F_GETFD);
diff --git a/runtime/zip_archive.h b/runtime/zip_archive.h
index 70518e1..2ca4aa2 100644
--- a/runtime/zip_archive.h
+++ b/runtime/zip_archive.h
@@ -55,6 +55,10 @@
MemMap* MapDirectlyFromFile(const char* zip_filename, /*out*/std::string* error_msg);
virtual ~ZipEntry();
+ MemMap* MapDirectlyOrExtract(const char* zip_filename,
+ const char* entry_filename,
+ std::string* error_msg);
+
uint32_t GetUncompressedLength();
uint32_t GetCrc32();
diff --git a/test/1945-proxy-method-arguments/expected.txt b/test/1945-proxy-method-arguments/expected.txt
new file mode 100644
index 0000000..1824953
--- /dev/null
+++ b/test/1945-proxy-method-arguments/expected.txt
@@ -0,0 +1,26 @@
+JNI_OnLoad called
+proxy: $Proxy0
+Proxy for interface TestInterface.method0
+ arg0: $Proxy0
+Proxy for interface TestInterface.method1
+ arg0: $Proxy0
+ arg1: java.lang.String "a"
+Proxy for interface TestInterface.method10
+ arg0: $Proxy0
+ arg1: java.lang.String "one"
+ arg2: java.lang.String "two"
+ arg3: java.lang.String "three"
+ arg4: java.lang.String "four"
+ arg5: java.lang.String "five"
+ arg6: java.lang.String "six"
+ arg7: java.lang.String "seven"
+ arg8: java.lang.String "eight"
+ arg9: java.lang.String "nine"
+ arg10: java.lang.String "ten"
+Proxy for interface TestInterface.method10Even
+ arg0: $Proxy0
+ arg2: java.lang.String "two"
+ arg4: java.lang.String "four"
+ arg6: java.lang.String "six"
+ arg8: java.lang.String "eight"
+ arg10: java.lang.String "ten"
diff --git a/test/1945-proxy-method-arguments/get_args.cc b/test/1945-proxy-method-arguments/get_args.cc
new file mode 100644
index 0000000..211ae10
--- /dev/null
+++ b/test/1945-proxy-method-arguments/get_args.cc
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "arch/context.h"
+#include "art_method-inl.h"
+#include "jni.h"
+#include "oat_quick_method_header.h"
+#include "scoped_thread_state_change-inl.h"
+#include "stack.h"
+#include "thread.h"
+
+namespace art {
+
+namespace {
+
+// Visit a proxy method Quick frame at a given depth.
+class GetProxyQuickFrameVisitor FINAL : public StackVisitor {
+ public:
+ GetProxyQuickFrameVisitor(art::Thread* target, art::Context* ctx, size_t frame_depth)
+ REQUIRES_SHARED(art::Locks::mutator_lock_)
+ : art::StackVisitor(target, ctx, art::StackVisitor::StackWalkKind::kIncludeInlinedFrames),
+ cur_depth_(0u),
+ frame_depth_(frame_depth),
+ quick_frame_(nullptr) {}
+
+ bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (GetMethod()->IsRuntimeMethod()) {
+ return true;
+ }
+ if (cur_depth_ == frame_depth_) {
+ // Found frame.
+ ShadowFrame* shadow_frame = GetCurrentShadowFrame();
+ if (shadow_frame != nullptr) {
+ // Nothing to do.
+ } else {
+ VisitQuickFrameAtSearchedDepth();
+ }
+ return false;
+ } else {
+ ++cur_depth_;
+ return true;
+ }
+ }
+
+ void VisitQuickFrameAtSearchedDepth() REQUIRES_SHARED(Locks::mutator_lock_) {
+ quick_frame_ = GetCurrentQuickFrame();
+ CHECK(quick_frame_ != nullptr);
+ ArtMethod* method = *quick_frame_;
+ CHECK(method != nullptr);
+ CHECK(method->IsProxyMethod()) << method->PrettyMethod();
+ }
+
+ // Return the found Quick frame.
+ ArtMethod** GetQuickFrame() {
+ return quick_frame_;
+ }
+
+ private:
+ // The depth of the currently visited frame.
+ size_t cur_depth_;
+ // The depth of the currently searched frame.
+ size_t frame_depth_;
+ // The quick frame, if found.
+ ArtMethod** quick_frame_;
+ // Method name
+
+ DISALLOW_COPY_AND_ASSIGN(GetProxyQuickFrameVisitor);
+};
+
+extern "C" StackReference<mirror::Object>* artQuickGetProxyReferenceArgumentAt(size_t arg_pos,
+ ArtMethod** sp)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+jobject GetProxyReferenceArgument(size_t arg_pos, size_t proxy_method_frame_depth) {
+ Thread* self = Thread::Current();
+ ScopedObjectAccess soa(self);
+ std::unique_ptr<Context> context(Context::Create());
+
+ GetProxyQuickFrameVisitor visitor(self, context.get(), proxy_method_frame_depth);
+ visitor.WalkStack();
+ ArtMethod** quick_frame = visitor.GetQuickFrame();
+ CHECK(quick_frame != nullptr);
+
+ // Find reference argument in frame.
+ StackReference<mirror::Object>* ref_arg =
+ artQuickGetProxyReferenceArgumentAt(arg_pos, quick_frame);
+ CHECK(ref_arg != nullptr);
+ art::ObjPtr<mirror::Object> obj = ref_arg->AsMirrorPtr();
+
+ return obj.IsNull() ? nullptr : soa.AddLocalReference<jobject>(obj);
+}
+
+extern "C" JNIEXPORT jobject JNICALL Java_TestInvocationHandler_getArgument(
+ JNIEnv* env ATTRIBUTE_UNUSED, jobject thiz ATTRIBUTE_UNUSED, int arg_pos, int frame_depth) {
+ return GetProxyReferenceArgument(arg_pos, frame_depth);
+}
+
+} // namespace
+
+} // namespace art
diff --git a/test/1945-proxy-method-arguments/info.txt b/test/1945-proxy-method-arguments/info.txt
new file mode 100644
index 0000000..15ccc44
--- /dev/null
+++ b/test/1945-proxy-method-arguments/info.txt
@@ -0,0 +1,7 @@
+Test checking that reference arguments of proxy methods are visited as
+thread stack roots when visiting Quick frames roots (b/73149739).
+Previously, if the proxy method (direcly or indirectly) executed code
+accessing one of these reference arguments in the proxy method stack
+frame, it could end up with a stale reference, as the corresponding
+object may have been moved by the garbage collector, but the stack
+reference would not have been updated.
diff --git a/test/1945-proxy-method-arguments/src/Main.java b/test/1945-proxy-method-arguments/src/Main.java
new file mode 100644
index 0000000..b04a661
--- /dev/null
+++ b/test/1945-proxy-method-arguments/src/Main.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+interface TestInterface {
+ void method0();
+ void method1(String arg);
+ void method10(String arg1, String arg2, String arg3, String arg4, String arg5,
+ String arg6, String arg7, String arg8, String arg9, String arg10);
+ void method10Even(byte arg1, String arg2, short arg3, String arg4, int arg5,
+ String arg6, long arg7, String arg8, double arg9, String arg10);
+}
+
+class TestInvocationHandler implements InvocationHandler {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) {
+ // Force garbage collection to try to make `proxy` move in memory
+ // (in the case of a moving garbage collector).
+ System.gc();
+
+ System.out.println("Proxy for " + TestInterface.class + "." + method.getName());
+ if (method.getName().equals("method0")) {
+ testMethod0(proxy, args);
+ } else if (method.getName().equals("method1")) {
+ testMethod1(proxy, args);
+ } else if (method.getName().equals("method10")) {
+ testMethod10(proxy, args);
+ } else if (method.getName().equals("method10Even")) {
+ testMethod10Even(proxy, args);
+ }
+ return null;
+ }
+
+ private void testMethod0(Object proxy, Object[] args) {
+ // Get argument 0 (method target) from the proxy method frame ($Proxy0.method0 activation).
+ Object arg0 = getProxyMethodArgument(0);
+ System.out.println(" arg0: " + arg0.getClass().getName());
+ Main.assertEquals(proxy, arg0);
+ }
+
+ private void testMethod1(Object proxy, Object[] args) {
+ // Get argument 0 (method target) from the proxy method frame ($Proxy0.method0 activation).
+ Object arg0 = getProxyMethodArgument(0);
+ System.out.println(" arg0: " + arg0.getClass().getName());
+ Main.assertEquals(proxy, arg0);
+ // Get argument 1 from the proxy method frame ($Proxy0.method1 activation).
+ String arg1 = (String) getProxyMethodArgument(1);
+ System.out.println(" arg1: " + arg1.getClass().getName() + " \"" + arg1 + "\"");
+ Main.assertEquals(args[0], arg1);
+ }
+
+ private void testMethod10(Object proxy, Object[] args) {
+ // Get argument 0 (method target) from the proxy method frame ($Proxy0.method10 activation).
+ Object arg0 = getProxyMethodArgument(0);
+ System.out.println(" arg0: " + arg0.getClass().getName());
+ Main.assertEquals(proxy, arg0);
+ // Get argument `i` from the proxy method frame ($Proxy0.method10 activation).
+ for (int i = 0; i < 10; ++i) {
+ int arg_pos = i + 1;
+ String arg = (String) getProxyMethodArgument(arg_pos);
+ System.out.println(" arg" + arg_pos + ": " + arg.getClass().getName() + " \"" + arg + "\"");
+ Main.assertEquals(args[i], arg);
+ }
+ }
+
+ private void testMethod10Even(Object proxy, Object[] args) {
+ // Get argument 0 (method target) from the proxy method frame ($Proxy0.method10Even
+ // activation).
+ Object arg0 = getProxyMethodArgument(0);
+ System.out.println(" arg0: " + arg0.getClass().getName());
+ Main.assertEquals(proxy, arg0);
+ // Get argument `i` from the proxy method frame ($Proxy0.method10Even activation).
+ for (int i = 1; i < 10; i += 2) {
+ int arg_pos = i + 1;
+ String arg = (String) getProxyMethodArgument(arg_pos);
+ System.out.println(" arg" + arg_pos + ": " + arg.getClass().getName() + " \"" + arg + "\"");
+ Main.assertEquals(args[i], arg);
+ }
+ }
+
+ // Get reference argument at position `arg_pos` in proxy frame.
+ // This method should only be called from one of the
+ // `TestInvocationHandler.testMethod*` methods via `TestInvocationHandler.invoke`.
+ private Object getProxyMethodArgument(int arg_pos) {
+ // Find proxy frame in stack (from a testMethod* method).
+ //
+ // depth method
+ // ----------------------------------------------------------------------
+ // 0 TestInvocationHandler.getArgument (outermost frame)
+ // 1 TestInvocationHandler.getProxyMethodArgument
+ // 2 TestInvocationHandler.testMethod*
+ // 3 TestInvocationHandler.invoke
+ // 4 java.lang.reflect.Proxy.invoke
+ // -> 5 TestInterface.method* (proxy method)
+ // 6 Main.main (innermost frame)
+ //
+ int proxy_method_frame_depth = 5;
+ return getArgument(arg_pos, proxy_method_frame_depth);
+ }
+
+ // Get reference argument at position `arg_pos` in frame at depth `frame_depth`.
+ private native Object getArgument(int arg_pos, int frame_depth);
+}
+
+public class Main {
+ public static void main(String[] args) {
+ System.loadLibrary(args[0]);
+
+ TestInvocationHandler invocationHandler = new TestInvocationHandler();
+ TestInterface proxy = (TestInterface) Proxy.newProxyInstance(
+ Main.class.getClassLoader(),
+ new Class<?>[] { TestInterface.class },
+ invocationHandler);
+ System.out.println("proxy: " + proxy.getClass().getName());
+
+ proxy.method0();
+ proxy.method1("a");
+ proxy.method10("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten");
+ proxy.method10Even((byte) 1, "two", (short) 3, "four", 5, "six", 7L, "eight", 9.0, "ten");
+ }
+
+ public static void assertEquals(Object expected, Object actual) {
+ if (expected != actual) {
+ throw new Error("Expected " + expected + ", got " + actual);
+ }
+ }
+
+ public static void assertEquals(String expected, String actual) {
+ if (expected != actual) {
+ throw new Error("Expected \"" + expected + "\", got \"" + actual + "\"");
+ }
+ }
+}
diff --git a/test/990-method-handle-and-mr/build b/test/807-method-handle-and-mr/build
similarity index 100%
rename from test/990-method-handle-and-mr/build
rename to test/807-method-handle-and-mr/build
diff --git a/test/990-method-handle-and-mr/expected.txt b/test/807-method-handle-and-mr/expected.txt
similarity index 100%
rename from test/990-method-handle-and-mr/expected.txt
rename to test/807-method-handle-and-mr/expected.txt
diff --git a/test/990-method-handle-and-mr/info.txt b/test/807-method-handle-and-mr/info.txt
similarity index 100%
rename from test/990-method-handle-and-mr/info.txt
rename to test/807-method-handle-and-mr/info.txt
diff --git a/test/990-method-handle-and-mr/src/Main.java b/test/807-method-handle-and-mr/src/Main.java
similarity index 100%
rename from test/990-method-handle-and-mr/src/Main.java
rename to test/807-method-handle-and-mr/src/Main.java
diff --git a/test/912-classes/src-art/art/Test912.java b/test/912-classes/src-art/art/Test912.java
index ddfadf3..1a60185 100644
--- a/test/912-classes/src-art/art/Test912.java
+++ b/test/912-classes/src-art/art/Test912.java
@@ -398,6 +398,7 @@
public static double dummy = Math.random(); // So it can't be compile-time initialized.
}
+ @SuppressWarnings("RandomCast")
private static class TestForInitFail {
public static int dummy = ((int)Math.random())/0; // So it throws when initializing.
}
diff --git a/test/983-source-transform-verify/source_transform.cc b/test/983-source-transform-verify/source_transform.cc
index dfefce2..9e65a99 100644
--- a/test/983-source-transform-verify/source_transform.cc
+++ b/test/983-source-transform-verify/source_transform.cc
@@ -14,30 +14,13 @@
* limitations under the License.
*/
-#include <inttypes.h>
+#include "source_transform.h"
-#include <cstdio>
-#include <cstring>
-#include <iostream>
-#include <vector>
+#include "jni.h"
#include "android-base/stringprintf.h"
-#include "jni.h"
#include "jvmti.h"
-
-#include "base/macros.h"
-#include "bytecode_utils.h"
-#include "dex/code_item_accessors-inl.h"
-#include "dex/art_dex_file_loader.h"
-#include "dex/dex_file.h"
-#include "dex/dex_file_loader.h"
-#include "dex/dex_instruction.h"
-#include "jit/jit.h"
-#include "native_stack_dump.h"
-#include "runtime.h"
-#include "scoped_thread_state_change-inl.h"
-#include "thread-current-inl.h"
-#include "thread_list.h"
+#include "scoped_local_ref.h"
// Test infrastructure
#include "jvmti_helper.h"
@@ -48,9 +31,18 @@
constexpr bool kSkipInitialLoad = true;
+static void Println(JNIEnv* env, const char* msg) {
+ ScopedLocalRef<jclass> test_klass(env, env->FindClass("art/Test983"));
+ jmethodID println_method = env->GetStaticMethodID(test_klass.get(),
+ "doPrintln",
+ "(Ljava/lang/String;)V");
+ ScopedLocalRef<jstring> data(env, env->NewStringUTF(msg));
+ env->CallStaticVoidMethod(test_klass.get(), println_method, data.get());
+}
+
// The hook we are using.
void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED,
- JNIEnv* jni_env ATTRIBUTE_UNUSED,
+ JNIEnv* env,
jclass class_being_redefined,
jobject loader ATTRIBUTE_UNUSED,
const char* name,
@@ -60,78 +52,24 @@
jint* new_class_data_len ATTRIBUTE_UNUSED,
unsigned char** new_class_data ATTRIBUTE_UNUSED) {
if (kSkipInitialLoad && class_being_redefined == nullptr) {
- // Something got loaded concurrently. Just ignore it for now.
+ // Something got loaded concurrently. Just ignore it for now. To make sure the test is
+ // repeatable we only care about things that come from RetransformClasses.
return;
}
- std::cout << "Dex file hook for " << name << std::endl;
+ Println(env, android::base::StringPrintf("Dex file hook for %s", name).c_str());
if (IsJVM()) {
return;
}
- // Due to b/72402467 the class_data_len might just be an estimate.
- CHECK_GE(static_cast<size_t>(class_data_len), sizeof(DexFile::Header));
- const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(class_data);
- uint32_t header_file_size = header->file_size_;
- CHECK_LE(static_cast<jint>(header_file_size), class_data_len);
- class_data_len = static_cast<jint>(header_file_size);
-
- const ArtDexFileLoader dex_file_loader;
- std::string error;
- std::unique_ptr<const DexFile> dex(dex_file_loader.Open(class_data,
- class_data_len,
- "fake_location.dex",
- /*location_checksum*/ 0,
- /*oat_dex_file*/ nullptr,
- /*verify*/ true,
- /*verify_checksum*/ true,
- &error));
- if (dex.get() == nullptr) {
- std::cout << "Failed to verify dex file for " << name << " because " << error << std::endl;
- return;
- }
- for (uint32_t i = 0; i < dex->NumClassDefs(); i++) {
- const DexFile::ClassDef& def = dex->GetClassDef(i);
- const uint8_t* data_item = dex->GetClassData(def);
- if (data_item == nullptr) {
- continue;
- }
- for (ClassDataItemIterator it(*dex, data_item); it.HasNext(); it.Next()) {
- if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) {
- continue;
- }
- for (const DexInstructionPcPair& pair :
- art::CodeItemInstructionAccessor(*dex, it.GetMethodCodeItem())) {
- const Instruction& inst = pair.Inst();
- int forbiden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly);
- if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER ||
- (inst.GetVerifyExtraFlags() & forbiden_flags) != 0) {
- std::cout << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex())
- << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : "
- << inst.DumpString(dex.get()) << std::endl;
- continue;
- }
- }
- }
- }
+ VerifyClassData(class_data_len, class_data);
}
// Get all capabilities except those related to retransformation.
-jint OnLoad(JavaVM* vm,
- char* options ATTRIBUTE_UNUSED,
- void* reserved ATTRIBUTE_UNUSED) {
- if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) {
- printf("Unable to get jvmti env!\n");
- return 1;
- }
- SetStandardCapabilities(jvmti_env);
+extern "C" JNIEXPORT void JNICALL Java_art_Test983_setupLoadHook(JNIEnv* env, jclass) {
jvmtiEventCallbacks cb;
memset(&cb, 0, sizeof(cb));
cb.ClassFileLoadHook = CheckDexFileHook;
- if (jvmti_env->SetEventCallbacks(&cb, sizeof(cb)) != JVMTI_ERROR_NONE) {
- printf("Unable to set class file load hook cb!\n");
- return 1;
- }
- return 0;
+ JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventCallbacks(&cb, sizeof(cb)));
}
} // namespace Test983SourceTransformVerify
diff --git a/test/983-source-transform-verify/source_transform.h b/test/983-source-transform-verify/source_transform.h
index db9415a..2206498 100644
--- a/test/983-source-transform-verify/source_transform.h
+++ b/test/983-source-transform-verify/source_transform.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * 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.
@@ -22,7 +22,7 @@
namespace art {
namespace Test983SourceTransformVerify {
-jint OnLoad(JavaVM* vm, char* options, void* reserved);
+void VerifyClassData(jint class_data_len, const unsigned char* class_data);
} // namespace Test983SourceTransformVerify
} // namespace art
diff --git a/test/983-source-transform-verify/source_transform_art.cc b/test/983-source-transform-verify/source_transform_art.cc
new file mode 100644
index 0000000..5353370
--- /dev/null
+++ b/test/983-source-transform-verify/source_transform_art.cc
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "source_transform.h"
+
+#include <inttypes.h>
+
+#include <memory>
+
+#include <android-base/logging.h>
+
+#include "dex/code_item_accessors-inl.h"
+#include "dex/art_dex_file_loader.h"
+#include "dex/dex_file.h"
+#include "dex/dex_file_loader.h"
+#include "dex/dex_instruction.h"
+
+namespace art {
+namespace Test983SourceTransformVerify {
+
+// The hook we are using.
+void VerifyClassData(jint class_data_len, const unsigned char* class_data) {
+ // Due to b/72402467 the class_data_len might just be an estimate.
+ CHECK_GE(static_cast<size_t>(class_data_len), sizeof(DexFile::Header));
+ const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(class_data);
+ uint32_t header_file_size = header->file_size_;
+ CHECK_LE(static_cast<jint>(header_file_size), class_data_len);
+ class_data_len = static_cast<jint>(header_file_size);
+
+ const ArtDexFileLoader dex_file_loader;
+ std::string error;
+ std::unique_ptr<const DexFile> dex(dex_file_loader.Open(class_data,
+ class_data_len,
+ "fake_location.dex",
+ /*location_checksum*/ 0,
+ /*oat_dex_file*/ nullptr,
+ /*verify*/ true,
+ /*verify_checksum*/ true,
+ &error));
+ CHECK(dex.get() != nullptr) << "Failed to verify dex: " << error;
+ for (uint32_t i = 0; i < dex->NumClassDefs(); i++) {
+ const DexFile::ClassDef& def = dex->GetClassDef(i);
+ const uint8_t* data_item = dex->GetClassData(def);
+ if (data_item == nullptr) {
+ continue;
+ }
+ for (ClassDataItemIterator it(*dex, data_item); it.HasNext(); it.Next()) {
+ if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) {
+ continue;
+ }
+ for (const DexInstructionPcPair& pair :
+ art::CodeItemInstructionAccessor(*dex, it.GetMethodCodeItem())) {
+ const Instruction& inst = pair.Inst();
+ int forbidden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly);
+ if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER ||
+ (inst.GetVerifyExtraFlags() & forbidden_flags) != 0) {
+ LOG(FATAL) << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex())
+ << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : "
+ << inst.DumpString(dex.get()) << std::endl;
+ }
+ }
+ }
+ }
+}
+
+} // namespace Test983SourceTransformVerify
+} // namespace art
diff --git a/test/983-source-transform-verify/source_transform_slicer.cc b/test/983-source-transform-verify/source_transform_slicer.cc
new file mode 100644
index 0000000..abf32e7
--- /dev/null
+++ b/test/983-source-transform-verify/source_transform_slicer.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "source_transform.h"
+
+#pragma clang diagnostic push
+// slicer defines its own CHECK. b/65422458
+#pragma push_macro("CHECK")
+#undef CHECK
+
+// Slicer's headers have code that triggers these warnings. b/65298177
+#pragma clang diagnostic ignored "-Wsign-compare"
+#include "reader.h"
+
+#pragma pop_macro("CHECK")
+#pragma clang diagnostic pop
+
+namespace art {
+namespace Test983SourceTransformVerify {
+
+// The hook we are using.
+void VerifyClassData(jint class_data_len, const unsigned char* class_data) {
+ dex::Reader reader(class_data, class_data_len);
+ reader.CreateFullIr(); // This will verify all bytecode.
+}
+
+} // namespace Test983SourceTransformVerify
+} // namespace art
diff --git a/test/983-source-transform-verify/src/art/Test983.java b/test/983-source-transform-verify/src/art/Test983.java
index faae96a..7dc47ab 100644
--- a/test/983-source-transform-verify/src/art/Test983.java
+++ b/test/983-source-transform-verify/src/art/Test983.java
@@ -27,7 +27,15 @@
doTest();
}
+ private native static void setupLoadHook();
+
+ /* called from JNI */
+ public static void doPrintln(String str) {
+ System.out.println(str);
+ }
+
public static void doTest() {
+ setupLoadHook();
Redefinition.enableCommonRetransformation(true);
Redefinition.doCommonClassRetransformation(Transform.class);
Redefinition.doCommonClassRetransformation(Object.class);
diff --git a/test/Android.bp b/test/Android.bp
index 5f39ffe..902f4ed 100644
--- a/test/Android.bp
+++ b/test/Android.bp
@@ -62,7 +62,7 @@
"libvixld-arm",
"libvixld-arm64",
"libart-gtest",
- "libdexfile",
+ "libdexfiled",
"libbase",
"libicuuc",
@@ -114,7 +114,7 @@
shared_libs: [
"libartd",
"libartd-compiler",
- "libdexfile",
+ "libdexfiled",
],
static_libs: [
"libgtest",
@@ -151,7 +151,7 @@
shared_libs: [
"libartd",
"libartd-compiler",
- "libdexfile",
+ "libdexfiled",
"libbase",
"libbacktrace",
],
@@ -238,6 +238,7 @@
"931-agent-thread/agent_thread.cc",
"933-misc-events/misc_events.cc",
"945-obsolete-native/obsolete_native.cc",
+ "983-source-transform-verify/source_transform.cc",
"984-obsolete-invoke/obsolete_invoke.cc",
"986-native-method-bind/native_bind.cc",
"987-agent-bind/agent_bind.cc",
@@ -288,20 +289,22 @@
"909-attach-agent/attach.cc",
"912-classes/classes_art.cc",
"936-search-onload/search_onload.cc",
- "983-source-transform-verify/source_transform.cc",
+ "983-source-transform-verify/source_transform_art.cc",
"1940-ddms-ext/ddm_ext.cc",
"1944-sudden-exit/sudden_exit.cc",
],
shared_libs: [
"libbase",
- "libdexfile",
],
}
art_cc_test_library {
name: "libtiagent",
defaults: ["libtiagent-defaults"],
- shared_libs: ["libart"],
+ shared_libs: [
+ "libart",
+ "libdexfile",
+ ],
}
art_cc_test_library {
@@ -310,24 +313,32 @@
"art_debug_defaults",
"libtiagent-defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: [
+ "libartd",
+ "libdexfiled",
+ ],
}
-art_cc_test_library {
+cc_library_static {
name: "libctstiagent",
defaults: ["libtiagent-base-defaults"],
+ host_supported: false,
+ srcs: [
+ "983-source-transform-verify/source_transform_slicer.cc",
+ ],
whole_static_libs: [
- "libdexfile",
- "libz",
- "libziparchive",
+ "slicer",
+ "libz", // for slicer (using adler32).
],
static_libs: [
"libbase",
- "libcutils",
- "libutils",
],
- shared_libs: [
- "liblog",
+ header_libs: [
+ // This is needed to resolve the base/ header file in libdexfile. Unfortunately there are
+ // many problems with how we export headers that are making doing this the 'right' way
+ // difficult.
+ // TODO: move those headers to art/ rather than under runtime.
+ "libart_runtime_headers",
],
export_include_dirs: ["ti-agent"],
}
@@ -367,11 +378,9 @@
"art_defaults",
],
srcs: [
- "common/runtime_state.cc",
- "common/stack_inspect.cc",
"004-JniTest/jni_test.cc",
- "004-SignalTest/signaltest.cc",
"004-ReferenceMap/stack_walk_refmap_jni.cc",
+ "004-SignalTest/signaltest.cc",
"004-StackWalk/stack_walk_jni.cc",
"004-ThreadStress/thread_stress.cc",
"004-UnsafeTest/unsafe_test.cc",
@@ -388,6 +397,7 @@
"154-gc-loop/heap_interface.cc",
"167-visit-locks/visit_locks.cc",
"169-threadgroup-jni/jni_daemon_thread.cc",
+ "1945-proxy-method-arguments/get_args.cc",
"203-multi-checkpoint/multi_checkpoint.cc",
"305-other-fault-handler/fault_handler.cc",
"454-get-vreg/get_vreg_jni.cc",
@@ -411,9 +421,10 @@
"667-jit-jni-stub/jit_jni_stub_test.cc",
"674-hiddenapi/hiddenapi.cc",
"708-jit-cache-churn/jit.cc",
+ "common/runtime_state.cc",
+ "common/stack_inspect.cc",
],
shared_libs: [
- "libdexfile",
"libbacktrace",
"libbase",
"libnativehelper",
@@ -423,7 +434,10 @@
art_cc_test_library {
name: "libarttest",
defaults: ["libarttest-defaults"],
- shared_libs: ["libart"],
+ shared_libs: [
+ "libart",
+ "libdexfile",
+ ],
}
art_cc_test_library {
@@ -432,7 +446,10 @@
"art_debug_defaults",
"libarttest-defaults",
],
- shared_libs: ["libartd"],
+ shared_libs: [
+ "libartd",
+ "libdexfiled",
+ ],
}
art_cc_test_library {
diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar
index 5200db5..1184ced 100755
--- a/test/etc/run-test-jar
+++ b/test/etc/run-test-jar
@@ -866,7 +866,7 @@
fi
# System libraries needed by libarttestd.so
- PUBLIC_LIBS=libart.so:libartd.so:libc++.so:libbacktrace.so:libdexfile.so:libbase.so:libnativehelper.so
+ PUBLIC_LIBS=libart.so:libartd.so:libc++.so:libbacktrace.so:libdexfile.so:libdexfiled.so:libbase.so:libnativehelper.so
# Create a script with the command. The command can get longer than the longest
# allowed adb command and there is no way to get the exit status from a adb shell
diff --git a/test/knownfailures.json b/test/knownfailures.json
index b483b93..ddf9098 100644
--- a/test/knownfailures.json
+++ b/test/knownfailures.json
@@ -377,12 +377,6 @@
"variant": "jvmti-stress & jit | redefine-stress & jit"
},
{
- "test_patterns": ["674-hiddenapi"],
- "description": ["hiddenapi test is failing with redefine stress cdex"],
- "bug": "http://b/72610009",
- "variant": "redefine-stress & cdex-fast"
- },
- {
"test_patterns": ["616-cha"],
"description": ["The test assumes a boot image exists."],
"bug": "http://b/34193647",
@@ -423,21 +417,13 @@
"variant": "redefine-stress & speed-profile | jvmti-stress & speed-profile"
},
{
- "tests": [
- "714-invoke-custom-lambda-metafactory",
- "950-redefine-intrinsic",
- "951-threaded-obsolete",
- "952-invoke-custom",
- "952-invoke-custom-kinds",
- "953-invoke-polymorphic-compiler",
- "954-invoke-polymorphic-verifier",
- "955-methodhandles-smali",
- "956-methodhandles",
- "957-methodhandle-transforms",
- "958-methodhandle-stackframe",
- "959-invoke-polymorphic-accessors",
- "979-const-method-handle",
- "990-method-handle-and-mr"
+ "test_patterns": [
+ ".*invoke-custom.*",
+ ".*invoke-polymorphic.*",
+ ".*methodhandle.*",
+ ".*method-handle.*",
+ ".*varhandle.*",
+ ".*var-handle.*"
],
"description": [
"Tests that use invoke-polymorphic/invoke-custom which is not yet supported by",
@@ -460,9 +446,22 @@
},
{
"tests": [
+ "132-daemon-locks-shutdown",
+ "607-daemon-stress",
+ "602-deoptimizeable",
+ "121-simple-suspend-check",
+ "083-compiler-regressions"
+ ],
+ "description": ["Tests that have failed on redefine stress for unknown reasons"],
+ "bug": "b/73177368",
+ "variant": "redefine-stress"
+ },
+ {
+ "tests": [
"097-duplicate-method",
"138-duplicate-classes-check2",
"159-app-image-fields",
+ "674-hiddenapi",
"649-vdex-duplicate-method",
"804-class-extends-itself",
"921-hello-failure"
@@ -481,6 +480,7 @@
"626-const-class-linking",
"629-vdex-speed",
"647-jni-get-field-id",
+ "674-hiddenapi",
"944-transform-classloaders"
],
"description": [
@@ -494,7 +494,7 @@
"004-ThreadStress"
],
"description": "The thread stress test just takes too long with field-stress",
- "variant": "jvmti-stress | field-stress | step-stress"
+ "variant": "jvmti-stress | field-stress | step-stress | redefine-stress"
},
{
"tests": [
@@ -653,11 +653,6 @@
"description": ["Test is designed to only check --compiler-filter=speed"]
},
{
- "test_patterns": [".*"],
- "description": ["Tests are timing out for weeks now, disable to fix."],
- "variant": "cdex-fast & redefine-stress"
- },
- {
"tests": "674-HelloWorld-Dm",
"variant": "target",
"description": ["Requires zip, which isn't available on device"]
diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py
index 3d173f5..4329ad4 100755
--- a/test/testrunner/testrunner.py
+++ b/test/testrunner/testrunner.py
@@ -110,6 +110,7 @@
total_test_count = 0
verbose = False
dry_run = False
+ignore_skips = False
build = False
gdb = False
gdb_arg = ''
@@ -710,6 +711,8 @@
return True
if test in env.EXTRA_DISABLED_TESTS:
return True
+ if ignore_skips:
+ return False
variants_list = DISABLED_TEST_CONTAINER.get(test, {})
for variants in variants_list:
variants_present = True
@@ -878,6 +881,7 @@
def parse_option():
global verbose
global dry_run
+ global ignore_skips
global n_thread
global build
global gdb
@@ -897,6 +901,8 @@
parser.add_argument('--dry-run', action='store_true', dest='dry_run')
parser.add_argument("--skip", action="append", dest="skips", default=[],
help="Skip the given test in all circumstances.")
+ parser.add_argument("--no-skips", dest="ignore_skips", action="store_true", default=False,
+ help="Don't skip any run-test configurations listed in knownfailures.json.")
parser.add_argument('--no-build-dependencies',
action='store_false', dest='build',
help="Don't build dependencies under any circumstances. This is the " +
@@ -935,6 +941,7 @@
verbose = True
if options['n_thread']:
n_thread = max(1, options['n_thread'])
+ ignore_skips = options['ignore_skips']
if options['dry_run']:
dry_run = True
verbose = True
diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc
index 9a7352e..bfd165d 100644
--- a/test/ti-agent/common_load.cc
+++ b/test/ti-agent/common_load.cc
@@ -28,7 +28,6 @@
#include "901-hello-ti-agent/basics.h"
#include "909-attach-agent/attach.h"
#include "936-search-onload/search_onload.h"
-#include "983-source-transform-verify/source_transform.h"
#include "1919-vminit-thread-start-timing/vminit.h"
namespace art {
@@ -83,7 +82,6 @@
{ "939-hello-transformation-bcp", common_redefine::OnLoad, nullptr },
{ "941-recursive-obsolete-jit", common_redefine::OnLoad, nullptr },
{ "943-private-recursive-jit", common_redefine::OnLoad, nullptr },
- { "983-source-transform-verify", Test983SourceTransformVerify::OnLoad, nullptr },
{ "1919-vminit-thread-start-timing", Test1919VMInitThreadStart::OnLoad, nullptr },
};
diff --git a/tools/amm/AmmTest/AndroidManifest.xml b/tools/amm/AmmTest/AndroidManifest.xml
new file mode 100644
index 0000000..16529bc
--- /dev/null
+++ b/tools/amm/AmmTest/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.amm.test">
+
+ <application
+ android:label="AmmTest"
+ android:debuggable="true">
+
+ <activity android:name="com.android.amm.test.MainActivity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tools/amm/AmmTest/aahat.png b/tools/amm/AmmTest/aahat.png
new file mode 100644
index 0000000..01b92f4
--- /dev/null
+++ b/tools/amm/AmmTest/aahat.png
Binary files differ
diff --git a/tools/amm/AmmTest/jni/ammtest.c b/tools/amm/AmmTest/jni/ammtest.c
new file mode 100644
index 0000000..9d48475
--- /dev/null
+++ b/tools/amm/AmmTest/jni/ammtest.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+
+// A large uninitialized array gets put in the .bss section:
+char uninit[3 * 4096];
+
+// A large initialized array gets put in the .data section:
+char init[2 * 4096] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.."
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789..";
+
+// A large constant initialized array gets put in the .rodata section:
+const char cinit[1 * 4096] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.."
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789..";
+
+JNIEXPORT jint JNICALL
+Java_com_android_amm_test_SoCodeUse_nGetANumber(JNIEnv* env, jclass cls) {
+ (void) env;
+ (void) cls;
+
+ uninit[4096] = init[123] + cinit[123];
+ return 42;
+}
+
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/BitmapUse.java b/tools/amm/AmmTest/src/com/android/amm/test/BitmapUse.java
new file mode 100644
index 0000000..d8eba2e
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/BitmapUse.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.amm.test;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+
+/**
+ * Exercise loading of a bitmap.
+ */
+class BitmapUse {
+
+ private Bitmap mBitmap;
+
+ public BitmapUse() {
+ ClassLoader loader = BitmapUse.class.getClassLoader();
+ mBitmap = BitmapFactory.decodeStream(loader.getResourceAsStream("aahat.png"), null, null);
+ }
+}
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java b/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java
new file mode 100644
index 0000000..4577f4b
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.amm.test;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.LinearLayout;
+
+public class MainActivity extends Activity {
+
+ private BitmapUse mBitmapUse;
+ private SoCodeUse mSoCodeUse;
+ private TextureViewUse mTextureViewUse;
+ private SurfaceViewUse mSurfaceViewUse;
+ private ThreadedRendererUse mThreadedRendererUse;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mBitmapUse = new BitmapUse();
+ mSoCodeUse = new SoCodeUse();
+
+ LinearLayout ll = new LinearLayout(this);
+ mTextureViewUse = new TextureViewUse(this, ll, 200, 500);
+ mSurfaceViewUse = new SurfaceViewUse(this, ll, 240, 250);
+ setContentView(ll);
+
+ mThreadedRendererUse = new ThreadedRendererUse(this, 122, 152);
+ }
+}
+
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/SoCodeUse.java b/tools/amm/AmmTest/src/com/android/amm/test/SoCodeUse.java
new file mode 100644
index 0000000..9636c0f
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/SoCodeUse.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.amm.test;
+
+class SoCodeUse {
+ private int value;
+
+ public SoCodeUse() {
+ // TODO: Figure out how to cause the native library to be unloaded when
+ // the SoCodeUse instance goes away?
+ System.loadLibrary("ammtestjni");
+ value = nGetANumber();
+ }
+
+ private static native int nGetANumber();
+}
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java b/tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java
new file mode 100644
index 0000000..0c17c77
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.amm.test;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+
+class SurfaceViewUse {
+
+ private SurfaceView mSurfaceView;
+
+ /**
+ * Constructs a SurfaceView object with given dimensions.
+ * The surface view is added to the given ViewGroup object, which should be
+ * included in the main display.
+ */
+ public SurfaceViewUse(Context context, ViewGroup vg, int width, int height) {
+ mSurfaceView = new SurfaceView(context);
+ vg.addView(mSurfaceView, width, height);
+ mSurfaceView.post(new CycleRunnable());
+ }
+
+ // To force as many graphics buffers as will ever be used to actually be
+ // used, we cycle the color of the surface view a handful of times right
+ // when things start up.
+ private class CycleRunnable implements Runnable {
+ private int mCycles = 0;
+ private int mRed = 255;
+ private int mGreen = 0;
+ private int mBlue = 255;
+
+ public void run() {
+ if (mCycles < 10) {
+ mCycles++;
+ updateSurfaceView();
+ mSurfaceView.post(this);
+ }
+ }
+
+ private void updateSurfaceView() {
+ SurfaceHolder holder = mSurfaceView.getHolder();
+ Canvas canvas = holder.lockHardwareCanvas();
+ if (canvas != null) {
+ canvas.drawRGB(mRed, mGreen, mBlue);
+ int tmp = mRed;
+ holder.unlockCanvasAndPost(canvas);
+ mRed = mGreen;
+ mGreen = mBlue;
+ mBlue = tmp;
+ }
+ }
+ }
+}
+
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java b/tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java
new file mode 100644
index 0000000..51ffcd2
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.amm.test;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.view.TextureView;
+import android.view.ViewGroup;
+
+class TextureViewUse {
+
+ private TextureView mTextureView;
+
+ /**
+ * Constructs a TextureView object with given dimensions.
+ * The texture view is added to the given ViewGroup object, which should be
+ * included in the main display.
+ */
+ public TextureViewUse(Context context, ViewGroup vg, int width, int height) {
+ mTextureView = new TextureView(context);
+ vg.addView(mTextureView, width, height);
+ mTextureView.post(new CycleRunnable());
+ }
+
+ // To force as many graphics buffers as will ever be used to actually be
+ // used, we cycle the color of the texture view a handful of times right
+ // when things start up.
+ private class CycleRunnable implements Runnable {
+ private int mCycles = 0;
+ private int mRed = 255;
+ private int mGreen = 255;
+ private int mBlue = 0;
+
+ public void run() {
+ if (mCycles < 10) {
+ mCycles++;
+ updateTextureView();
+ mTextureView.post(this);
+ }
+ }
+
+ private void updateTextureView() {
+ Canvas canvas = mTextureView.lockCanvas();
+ if (canvas != null) {
+ canvas.drawRGB(mRed, mGreen, mBlue);
+ int tmp = mRed;
+ mTextureView.unlockCanvasAndPost(canvas);
+ mRed = mGreen;
+ mGreen = mBlue;
+ mBlue = tmp;
+ }
+ }
+ }
+}
+
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java b/tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java
new file mode 100644
index 0000000..9c25612
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.amm.test;
+
+import android.content.Context;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+class ThreadedRendererUse {
+
+ private TextView mTextView;
+
+ /**
+ * Cause a threaded renderer EGL allocation to be used, with given
+ * dimensions.
+ */
+ public ThreadedRendererUse(Context context, int width, int height) {
+ mTextView = new TextView(context);
+ mTextView.setText("TRU");
+ mTextView.setBackgroundColor(0xffff0000);
+
+ // Adding a view to the WindowManager (as opposed to the app's root view
+ // hierarchy) causes a ThreadedRenderer and EGL allocations under the cover.
+ // We use a TextView here to trigger the use case, but we could use any
+ // other kind of view as well.
+ WindowManager wm = context.getSystemService(WindowManager.class);
+ WindowManager.LayoutParams layout = new WindowManager.LayoutParams();
+ layout.width = width;
+ layout.height = height;
+ wm.addView(mTextView, layout);
+
+ mTextView.post(new CycleRunnable());
+ }
+
+ // To force as many graphics buffers as will ever be used to actually be
+ // used, we cycle the text of the text view a handful of times right
+ // when things start up.
+ private class CycleRunnable implements Runnable {
+ private int mCycles = 0;
+
+ public void run() {
+ if (mCycles < 10) {
+ mCycles++;
+ mTextView.setText("TRU " + mCycles);
+ mTextView.post(this);
+ }
+ }
+ }
+}
+
diff --git a/tools/amm/Android.mk b/tools/amm/Android.mk
new file mode 100644
index 0000000..47030c5
--- /dev/null
+++ b/tools/amm/Android.mk
@@ -0,0 +1,34 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+# --- ammtestjni.so -------------
+include $(CLEAR_VARS)
+LOCAL_MODULE := libammtestjni
+LOCAL_SRC_FILES := $(call all-c-files-under, AmmTest/jni)
+LOCAL_SDK_VERSION := current
+include $(BUILD_SHARED_LIBRARY)
+
+# --- AmmTest.apk --------------
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := AmmTest
+LOCAL_MODULE_TAGS := samples tests
+LOCAL_SRC_FILES := $(call all-java-files-under, AmmTest/src)
+LOCAL_SDK_VERSION := current
+LOCAL_JNI_SHARED_LIBRARIES := libammtestjni
+LOCAL_JAVA_RESOURCE_FILES := $(LOCAL_PATH)/AmmTest/aahat.png
+LOCAL_MANIFEST_FILE := AmmTest/AndroidManifest.xml
+include $(BUILD_PACKAGE)
+
diff --git a/tools/amm/README.md b/tools/amm/README.md
new file mode 100644
index 0000000..17f94a8
--- /dev/null
+++ b/tools/amm/README.md
@@ -0,0 +1,16 @@
+# Actionable Memory Metric
+
+The goal of the actionable memory metric (AMM) is to provide a view of an
+application's memory use that application developers can track, understand,
+and control. AMM can be thought of as a Java heap dump augmented with models
+for non-Java allocations that app developers have some control of.
+
+There are two components of the actionable memory metric:
+1. The value of the metric.
+2. An actionable breakdown of the value of the metric.
+
+The metric is made up of a collection of separate models for different
+categories of memory use. Each model contributes to the value and actionable
+breakdown of the overall metric.
+
+See models/ for a list of models proposed for the actionable memory metric.
diff --git a/tools/amm/models/Bitmap.md b/tools/amm/models/Bitmap.md
new file mode 100644
index 0000000..49a0b9d
--- /dev/null
+++ b/tools/amm/models/Bitmap.md
@@ -0,0 +1,15 @@
+# Bitmap Model
+
+The value of the Bitmap model is the sum of bytes used for native pixel data
+of instances of `android.graphics.Bitmap`. It is calculated by summing for
+each instance `x` of `android.graphics.Bitmap`:
+
+ x.getAllocationByteCount()
+
+The actionable breakdown of the Bitmap model is a breakdown by
+`android.graphics.Bitmap` instance, including width, height, and ideally a
+thumbnail image of each bitmap.
+
+For example, an 800 x 600 bitmap instance using the `ARGB_8888` pixel format
+with native pixel data will be shown as an 800 x 600 bitmap instance taking up
+1875 kB.
diff --git a/tools/amm/models/DexCode.md b/tools/amm/models/DexCode.md
new file mode 100644
index 0000000..a907280
--- /dev/null
+++ b/tools/amm/models/DexCode.md
@@ -0,0 +1,17 @@
+# Dex Code Model
+
+The value of the Dex Code model is the sum of the original uncompressed file
+sizes of all loaded dex files. It is calculated using the best approximation
+of the dex file size available to us on device. On Android O, for example,
+this can be approximated as the virtual size of the corresponding memory
+mapped `.vdex` file read from `/proc/self/maps`. Different Android platform
+versions and scenarios may require different approximations.
+
+The actionable breakdown of the dex code model is a breakdown by
+`dalvik.system.DexFile` instance. Further breakdown of individual dex files
+can be achieved using tools such as dexdump.
+
+For example, for an application `AmmTest.apk` that has a single `classes.dex` file
+that is 500 KB uncompressed, the `DexFile` instance for
+`/data/app/com.android.amm.test-_uHI4CJWpeoztbjN6Tr-Nw==/base.apk` is shown as
+Taking up 500 KB (or the best available approximation thereof).
diff --git a/tools/amm/models/Graphics.md b/tools/amm/models/Graphics.md
new file mode 100644
index 0000000..b327961
--- /dev/null
+++ b/tools/amm/models/Graphics.md
@@ -0,0 +1,22 @@
+# Graphics Models
+
+There are three components to the graphics model, each modeling EGL memory
+use:
+1. For each `android.view.TextureView` instance:
+ 2 * (4 * width * height)
+
+2. For each `android.view.Surface$HwuiContext` instance:
+ 3 * (4 * width * height)
+
+3. For each initialized `android.view.ThreadedRenderer`:
+ 3 * (4 * width * height)
+
+Note: 4 is the number of bytes per pixel. 2 or 3 is the maximum number of
+buffers that may be allocated.
+
+The actionable breakdown is the breakdown by `TextureView`,
+`Surface$HwuiContext` and `ThreadedRenderer` instance, with further details
+about the width and height associated with each instance.
+
+For example, an application with a single 64x256 `TextureView` instance will
+be shown as taking up 128 KB.
diff --git a/tools/amm/models/JavaHeap.md b/tools/amm/models/JavaHeap.md
new file mode 100644
index 0000000..c34c186
--- /dev/null
+++ b/tools/amm/models/JavaHeap.md
@@ -0,0 +1,8 @@
+# Java Heap Model
+
+The value of the Java heap model is the sum of bytes of Java objects allocated
+on the Java heap. It can be calculated using:
+
+ Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()
+
+A Java heap dump is used for an actionable breakdown of the Java heap.
diff --git a/tools/amm/models/SoCode.md b/tools/amm/models/SoCode.md
new file mode 100644
index 0000000..5d3184e
--- /dev/null
+++ b/tools/amm/models/SoCode.md
@@ -0,0 +1,17 @@
+# Shared Native Code Model
+
+The value of the Shared Native Code model is the sum of the virtual memory
+sizes of all loaded `.so` files. It is calculated by reading `/proc/self/maps`.
+
+The actionable breakdown of the shared native code model is a breakdown by
+library name. Unfortunately, due to technical limitations, this does not
+include information about what caused a library to be loaded, whether the
+library was loaded by the app or the platform, the library dependency graph,
+or what is causing a library to remain loaded. Individual `.so` files can be
+further broken down using tools such as `readelf`.
+
+For example, for an application `AmmTest.apk` that includes `libammtestjni.so` as a
+native library that loads 36 KB worth of memory regions, `BaseClassLoader` will
+be shown with library
+`/data/app/com.android.amm.test-_uHI4CJWpeoztbjN6Tr-Nw==/lib/arm64/libammtestjni.so`
+taking up 36 KB.
diff --git a/tools/hiddenapi/Android.bp b/tools/hiddenapi/Android.bp
index f9824f1..af87d31 100644
--- a/tools/hiddenapi/Android.bp
+++ b/tools/hiddenapi/Android.bp
@@ -30,7 +30,6 @@
},
shared_libs: [
- "libdexfile",
"libbase",
],
}
@@ -40,6 +39,7 @@
defaults: ["hiddenapi-defaults"],
shared_libs: [
"libart",
+ "libdexfile",
],
}
@@ -51,6 +51,7 @@
],
shared_libs: [
"libartd",
+ "libdexfiled",
],
}
diff --git a/tools/public.libraries.buildbot.txt b/tools/public.libraries.buildbot.txt
index 734fd1e..de636a8 100644
--- a/tools/public.libraries.buildbot.txt
+++ b/tools/public.libraries.buildbot.txt
@@ -1,6 +1,7 @@
libart.so
libartd.so
libdexfile.so
+libdexfiled.so
libbacktrace.so
libc.so
libc++.so