Dex2oat support for multiple oat file and image file outputs.
Multiple changes to dex2oat and the runtime to support a --multi-image
option. This generates a separate oat file and image file output for
each dex file input.
Change-Id: Ie1d6f0b8afa8aed5790065b8c2eb177990c60129
diff --git a/oatdump/Android.mk b/oatdump/Android.mk
index a3ef38d..5c75f20 100644
--- a/oatdump/Android.mk
+++ b/oatdump/Android.mk
@@ -74,14 +74,14 @@
.PHONY: dump-oat-boot-$(TARGET_ARCH)
ifeq ($(ART_BUILD_TARGET_NDEBUG),true)
dump-oat-boot-$(TARGET_ARCH): $(DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME) $(OATDUMP)
- $(OATDUMP) --image=$(DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION) \
+ $(OATDUMP) $(addprefix --image=,$(DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION)) \
--output=$(ART_DUMP_OAT_PATH)/boot.$(TARGET_ARCH).oatdump.txt --instruction-set=$(TARGET_ARCH)
@echo Output in $(ART_DUMP_OAT_PATH)/boot.$(TARGET_ARCH).oatdump.txt
endif
ifdef TARGET_2ND_ARCH
dump-oat-boot-$(TARGET_2ND_ARCH): $(2ND_DEFAULT_DEX_PREOPT_BUILT_IMAGE_FILENAME) $(OATDUMP)
- $(OATDUMP) --image=$(2ND_DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION) \
+ $(OATDUMP) $(addprefix --image=,$(2ND_DEFAULT_DEX_PREOPT_BUILT_IMAGE_LOCATION)) \
--output=$(ART_DUMP_OAT_PATH)/boot.$(TARGET_2ND_ARCH).oatdump.txt --instruction-set=$(TARGET_2ND_ARCH)
@echo Output in $(ART_DUMP_OAT_PATH)/boot.$(TARGET_2ND_ARCH).oatdump.txt
endif
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index bad928e..52c6524 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1492,6 +1492,8 @@
os << "MAGIC: " << image_header_.GetMagic() << "\n\n";
+ os << "IMAGE LOCATION: " << image_space_.GetImageLocation() << "\n\n";
+
os << "IMAGE BEGIN: " << reinterpret_cast<void*>(image_header_.GetImageBegin()) << "\n\n";
os << "IMAGE SIZE: " << image_header_.GetImageSize() << "\n\n";
@@ -1599,9 +1601,8 @@
os << "OBJECTS:\n" << std::flush;
- // Loop through all the image spaces and dump their objects.
+ // Loop through the image space and dump its objects.
gc::Heap* heap = runtime->GetHeap();
- const std::vector<gc::space::ContinuousSpace*>& spaces = heap->GetContinuousSpaces();
Thread* self = Thread::Current();
{
{
@@ -1629,21 +1630,16 @@
}
}
ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
- for (const auto& space : spaces) {
- if (space->IsImageSpace()) {
- auto* image_space = space->AsImageSpace();
- // Dump the normal objects before ArtMethods.
- image_space->GetLiveBitmap()->Walk(ImageDumper::Callback, this);
- indent_os << "\n";
- // TODO: Dump fields.
- // Dump methods after.
- const auto& methods_section = image_header_.GetMethodsSection();
- const size_t pointer_size =
- InstructionSetPointerSize(oat_dumper_->GetOatInstructionSet());
- DumpArtMethodVisitor visitor(this);
- methods_section.VisitPackedArtMethods(&visitor, image_space->Begin(), pointer_size);
- }
- }
+ // Dump the normal objects before ArtMethods.
+ image_space_.GetLiveBitmap()->Walk(ImageDumper::Callback, this);
+ indent_os << "\n";
+ // TODO: Dump fields.
+ // Dump methods after.
+ const auto& methods_section = image_header_.GetMethodsSection();
+ const size_t pointer_size =
+ InstructionSetPointerSize(oat_dumper_->GetOatInstructionSet());
+ DumpArtMethodVisitor visitor(this);
+ methods_section.VisitPackedArtMethods(&visitor, image_space_.Begin(), pointer_size);
// Dump the large objects separately.
heap->GetLargeObjectsSpace()->GetLiveBitmap()->Walk(ImageDumper::Callback, this);
indent_os << "\n";
@@ -2163,6 +2159,9 @@
size_t sum_of_expansion = 0;
size_t sum_of_expansion_squared = 0;
size_t n = method_outlier_size.size();
+ if (n == 0) {
+ return;
+ }
for (size_t i = 0; i < n; i++) {
size_t cur_size = method_outlier_size[i];
sum_of_sizes += cur_size;
@@ -2377,26 +2376,28 @@
DISALLOW_COPY_AND_ASSIGN(ImageDumper);
};
-static int DumpImage(Runtime* runtime, const char* image_location, OatDumperOptions* options,
- std::ostream* os) {
+static int DumpImage(Runtime* runtime, OatDumperOptions* options, std::ostream* os) {
// Dumping the image, no explicit class loader.
ScopedNullHandle<mirror::ClassLoader> null_class_loader;
options->class_loader_ = &null_class_loader;
ScopedObjectAccess soa(Thread::Current());
gc::Heap* heap = runtime->GetHeap();
- gc::space::ImageSpace* image_space = heap->GetBootImageSpace();
- CHECK(image_space != nullptr);
- const ImageHeader& image_header = image_space->GetImageHeader();
- if (!image_header.IsValid()) {
- fprintf(stderr, "Invalid image header %s\n", image_location);
- return EXIT_FAILURE;
+ std::vector<gc::space::ImageSpace*> image_spaces = heap->GetBootImageSpaces();
+ CHECK(!image_spaces.empty());
+ for (gc::space::ImageSpace* image_space : image_spaces) {
+ const ImageHeader& image_header = image_space->GetImageHeader();
+ if (!image_header.IsValid()) {
+ fprintf(stderr, "Invalid image header %s\n", image_space->GetImageLocation().c_str());
+ return EXIT_FAILURE;
+ }
+
+ ImageDumper image_dumper(os, *image_space, image_header, options);
+ if (!image_dumper.Dump()) {
+ return EXIT_FAILURE;
+ }
}
-
- ImageDumper image_dumper(os, *image_space, image_header, options);
-
- bool success = image_dumper.Dump();
- return (success) ? EXIT_SUCCESS : EXIT_FAILURE;
+ return EXIT_SUCCESS;
}
static int DumpOatWithRuntime(Runtime* runtime, OatFile* oat_file, OatDumperOptions* options,
@@ -2689,8 +2690,7 @@
args_->os_) == EXIT_SUCCESS;
}
- return DumpImage(runtime, args_->image_location_, oat_dumper_options_.get(), args_->os_)
- == EXIT_SUCCESS;
+ return DumpImage(runtime, oat_dumper_options_.get(), args_->os_) == EXIT_SUCCESS;
}
std::unique_ptr<OatDumperOptions> oat_dumper_options_;