diff options
author | 2011-10-04 00:56:06 -0700 | |
---|---|---|
committer | 2011-10-04 10:39:42 -0700 | |
commit | 58ae9416e197ae68ed12ed43d87407d4dfb15093 (patch) | |
tree | 9fa93ce844f931155bf4a1d060f091f3285fb205 | |
parent | 4d0207c3ed28bbbb8c583a3c3a37f00d1cd4dedc (diff) |
Simplify command line arguments
Change-Id: I9d6902b0c447fd8fbe5600fd36139791b2ceefb7
-rw-r--r-- | Android.mk | 12 | ||||
-rw-r--r-- | build/Android.oat.mk | 4 | ||||
-rw-r--r-- | build/Android.oattest.mk | 4 | ||||
-rw-r--r-- | oat_process/app_main.cpp | 4 | ||||
-rw-r--r-- | src/class_linker.cc | 154 | ||||
-rw-r--r-- | src/class_linker.h | 29 | ||||
-rw-r--r-- | src/common_test.h | 12 | ||||
-rw-r--r-- | src/dex2oat.cc | 78 | ||||
-rw-r--r-- | src/dex_file.cc | 9 | ||||
-rw-r--r-- | src/dex_file.h | 30 | ||||
-rw-r--r-- | src/heap.cc | 49 | ||||
-rw-r--r-- | src/heap.h | 17 | ||||
-rw-r--r-- | src/image.h | 1 | ||||
-rw-r--r-- | src/image_test.cc | 36 | ||||
-rw-r--r-- | src/image_writer.cc | 21 | ||||
-rw-r--r-- | src/image_writer.h | 6 | ||||
-rw-r--r-- | src/oat_file.cc | 6 | ||||
-rw-r--r-- | src/oat_file.h | 7 | ||||
-rw-r--r-- | src/oat_test.cc | 2 | ||||
-rw-r--r-- | src/oatdump.cc | 115 | ||||
-rw-r--r-- | src/runtime.cc | 176 | ||||
-rw-r--r-- | src/runtime.h | 35 | ||||
-rw-r--r-- | src/runtime_test.cc | 16 | ||||
-rw-r--r-- | src/space.cc | 6 | ||||
-rw-r--r-- | src/space.h | 10 | ||||
-rw-r--r-- | test/003-omnibus-opcodes/build | 4 | ||||
-rw-r--r-- | test/023-many-interfaces/build | 4 | ||||
-rw-r--r-- | test/056-const-string-jumbo/build | 4 | ||||
-rw-r--r-- | test/085-old-style-inner-class/build | 4 | ||||
-rwxr-xr-x | test/etc/default-build | 8 | ||||
-rwxr-xr-x | test/etc/push-and-run-test-jar | 6 |
31 files changed, 341 insertions, 528 deletions
diff --git a/Android.mk b/Android.mk index bd37967c3b..35825e10db 100644 --- a/Android.mk +++ b/Android.mk @@ -113,7 +113,7 @@ test-art-target-run-test: test-art-target-run-test-002 @echo test-art-target-run-test PASSED .PHONY: test-art-target-run-test-002 -test-art-target-run-test-002: +test-art-target-run-test-002: test-art-target-sync art/test/run-test 002 @echo test-art-target-run-test-002 PASSED @@ -134,7 +134,7 @@ $(eval $(call build-art-framework-oat,$(TARGET_OUT_JAVA_LIBRARIES)/am.jar)) test-art-target-oat-process-am: $(TARGET_OUT_JAVA_LIBRARIES)/am.oat test-art-target-sync adb remount adb sync - adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Xbootimage:/system/framework/boot.art -Ximage:/system/framework/am.oat /system/bin com.android.commands.am.Am start http://android.com && touch /sdcard/test-art-target-process-am" + adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Ximage:/system/framework/boot.art -Ximage:/system/framework/am.oat /system/bin com.android.commands.am.Am start http://android.com && touch /sdcard/test-art-target-process-am" $(hide) (adb pull /sdcard/test-art-target-process-am /tmp/ && echo test-art-target-process-am PASSED) || echo test-art-target-process-am FAILED $(hide) rm /tmp/test-art-target-process-am @@ -158,7 +158,7 @@ test-art-target-oat-process-Calculator: $(TARGET_OUT_APPS)/Calculator.oat $(TARG sleep 30; \ fi adb shell kill `adb shell ps | fgrep com.android.calculator2 | sed -e 's/[^ ]* *\([0-9]*\).*/\1/'` - adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Xbootimage:/system/framework/boot.art -Ximage:/system/framework/am.oat /system/bin com.android.commands.am.Am start -a android.intent.action.MAIN -n com.android.calculator2/.Calculator && touch /sdcard/test-art-target-process-Calculator" + adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Ximage:/system/framework/boot.art -Ximage:/system/framework/am.oat /system/bin com.android.commands.am.Am start -a android.intent.action.MAIN -n com.android.calculator2/.Calculator && touch /sdcard/test-art-target-process-Calculator" $(hide) (adb pull /sdcard/test-art-target-process-Calculator /tmp/ && echo test-art-target-process-Calculator PASSED) || echo test-art-target-process-Calculator FAILED $(hide) rm /tmp/test-art-target-process-Calculator @@ -170,17 +170,17 @@ dump-oat: dump-oat-core dump-oat-boot dump-oat-Calculator .PHONY: dump-oat-core dump-oat-core: $(TARGET_CORE_OAT) $(OATDUMP) - $(OATDUMP) $(addprefix --dex-file=,$(TARGET_CORE_DEX)) --oat=$(TARGET_CORE_OAT) --image=$(TARGET_CORE_IMG) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/core.oatdump.txt + $(OATDUMP) --image=$(TARGET_CORE_IMG) --host-prefix=$(PRODUCT_OUT) --output=/tmp/core.oatdump.txt @echo Output in /tmp/core.oatdump.txt .PHONY: dump-oat-boot dump-oat-boot: $(TARGET_BOOT_OAT) $(OATDUMP) - $(OATDUMP) $(addprefix --dex-file=,$(TARGET_BOOT_DEX)) --oat=$(TARGET_BOOT_OAT) --image=$(TARGET_BOOT_IMG) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/boot.oatdump.txt + $(OATDUMP) --image=$(TARGET_BOOT_IMG) --host-prefix=$(PRODUCT_OUT) --output=/tmp/boot.oatdump.txt @echo Output in /tmp/boot.oatdump.txt .PHONY: dump-oat-Calculator dump-oat-Calculator: $(TARGET_OUT_APPS)/Calculator.oat $(TARGET_BOOT_OAT) $(OATDUMP) - $(OATDUMP) --dex-file=$(TARGET_OUT_APPS)/Calculator.apk --oat=$< --image=$(patsubst %.oat,%.art,$<) $(addprefix --boot-dex-file=,$(TARGET_BOOT_DEX)) --boot-oat=$(TARGET_BOOT_OAT) --boot-image=$(TARGET_BOOT_IMG) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/Calculator.oatdump.txt + $(OATDUMP) --image=$(patsubst %.oat,%.art,$<) --boot-image=$(TARGET_BOOT_IMG) --host-prefix=$(PRODUCT_OUT) --output=/tmp/Calculator.oatdump.txt @echo Output in /tmp/Calculator.oatdump.txt diff --git a/build/Android.oat.mk b/build/Android.oat.mk index 52d56216a3..483966742f 100644 --- a/build/Android.oat.mk +++ b/build/Android.oat.mk @@ -50,7 +50,7 @@ $(HOST_CORE_OAT): $(HOST_CORE_DEX) $(DEX2OAT) # TODO: change DEX2OATD to order-only prerequisite when output is stable $(TARGET_CORE_OAT): $(TARGET_CORE_DEX) $(DEX2OAT) @echo "target dex2oat: $@ ($<)" - $(hide) $(DEX2OAT) -Xms32m -Xmx32m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_CORE_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --strip-prefix=$(PRODUCT_OUT) + $(hide) $(DEX2OAT) -Xms32m -Xmx32m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_CORE_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT) ######################################################################## # The full system boot classpath @@ -62,4 +62,4 @@ TARGET_BOOT_IMG := $(TARGET_OUT_JAVA_LIBRARIES)/boot.art # TODO: change DEX2OATD to order-only prerequisite when output is stable $(TARGET_BOOT_OAT): $(TARGET_BOOT_DEX) $(DEX2OAT) @echo "target dex2oat: $@ ($<)" - $(hide) $(DEX2OAT) -Xms256m -Xmx256m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_BOOT_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --strip-prefix=$(PRODUCT_OUT) + $(hide) $(DEX2OAT) -Xms256m -Xmx256m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_BOOT_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT) diff --git a/build/Android.oattest.mk b/build/Android.oattest.mk index ce615b2bf7..b3dee96981 100644 --- a/build/Android.oattest.mk +++ b/build/Android.oattest.mk @@ -40,7 +40,7 @@ define build-art-oat # TODO: change DEX2OATD (and perhaps $(2) boot oat) to order-only prerequisite when output is stable $(patsubst %.apk,%.oat,$(patsubst %.jar,%.oat,$(1))): $(1) $(2) $(DEX2OAT) @echo "target dex2oat: $$@ ($$<)" - $(hide) $(DEX2OAT) -Xms16m -Xmx16m $(addprefix --boot-dex-file=,$(3)) --boot-oat=$(2) --boot-image=$(patsubst %.oat,%.art,$(2)) $(addprefix --dex-file=,$$<) --oat=$$@ --image=$$(patsubst %.oat,%.art,$$@) --strip-prefix=$(PRODUCT_OUT) + $(hide) $(DEX2OAT) -Xms16m -Xmx16m --boot-image=$(patsubst %.oat,%.art,$(2)) $(addprefix --dex-file=,$$<) --oat=$$@ --image=$$(patsubst %.oat,%.art,$$@) --host-prefix=$(PRODUCT_OUT) endef ######################################################################## @@ -64,7 +64,7 @@ define declare-test-test-target test-art-target-oat-$(1): test-art-target-sync adb shell touch /sdcard/test-art-target-oat-$(1) adb shell rm /sdcard/test-art-target-oat-$(1) - adb shell sh -c "oatexecd -Xbootclasspath:/system/framework/core.jar -Xbootoat:/system/framework/core.oat -Xbootimage:/system/framework/core.art -classpath /system/framework/art-test-dex-$(1).jar -Xoat:/system/framework/art-test-dex-$(1).oat -Ximage:/system/framework/art-test-dex-$(1).art $(1) $(2) && touch /sdcard/test-art-target-oat-$(1)" + adb shell sh -c "oatexecd -Ximage:/system/framework/core.art -classpath /system/framework/art-test-dex-$(1).jar -Ximage:/system/framework/art-test-dex-$(1).art $(1) $(2) && touch /sdcard/test-art-target-oat-$(1)" $(hide) (adb pull /sdcard/test-art-target-oat-$(1) /tmp/ && echo test-art-target-oat-$(1) PASSED) || (echo test-art-target-oat-$(1) FAILED && exit 1) $(hide) rm /tmp/test-art-target-oat-$(1) diff --git a/oat_process/app_main.cpp b/oat_process/app_main.cpp index 9ccdf160b4..c5ec8e9483 100644 --- a/oat_process/app_main.cpp +++ b/oat_process/app_main.cpp @@ -212,9 +212,9 @@ int main(int argc, const char* argv[]) // TODO: remove Calculator special case int oatArgc = argc + 2; const char* oatArgv[oatArgc]; - if (strcmp(argv[0], "-Xbootimage:/system/framework/boot.oat") != 0) { + if (strcmp(argv[0], "-Ximage:/system/framework/boot.oat") != 0) { LOG(INFO) << "Adding oat arguments"; - oatArgv[0] = "-Xbootimage:/system/framework/boot.oat"; + oatArgv[0] = "-Ximage:/system/framework/boot.oat"; oatArgv[1] = "-Ximage:/system/app/Calculator.oat"; setenv("CLASSPATH", "/system/app/Calculator.apk", 1); memcpy(oatArgv + (oatArgc - argc), argv, argc * sizeof(*argv)); diff --git a/src/class_linker.cc b/src/class_linker.cc index b4e332d4f6..d3a6ed0a53 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -16,10 +16,12 @@ #include "intern_table.h" #include "logging.h" #include "monitor.h" +#include "oat_file.h" #include "object.h" #include "runtime.h" #include "ScopedLocalRef.h" #include "space.h" +#include "stl_util.h" #include "thread.h" #include "UniquePtr.h" #include "utils.h" @@ -177,17 +179,17 @@ class ObjectLock { DISALLOW_COPY_AND_ASSIGN(ObjectLock); }; -ClassLinker* ClassLinker::Create(const std::vector<const DexFile*>& boot_class_path, - const std::vector<const DexFile*>& class_path, - InternTable* intern_table, bool image) { +ClassLinker* ClassLinker::Create(const std::string& boot_class_path, + InternTable* intern_table) { CHECK_NE(boot_class_path.size(), 0U); UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table)); - if (image) { - class_linker->InitFromImage(boot_class_path, class_path); - } else { - class_linker->Init(boot_class_path, class_path); - } - // TODO: check for failure during initialization + class_linker->Init(boot_class_path); + return class_linker.release(); +} + +ClassLinker* ClassLinker::Create(InternTable* intern_table) { + UniquePtr<ClassLinker> class_linker(new ClassLinker(intern_table)); + class_linker->InitFromImage(); return class_linker.release(); } @@ -201,8 +203,19 @@ ClassLinker::ClassLinker(InternTable* intern_table) CHECK_EQ(arraysize(class_roots_descriptors_), size_t(kClassRootsMax)); } -void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path, - const std::vector<const DexFile*>& class_path) { +void CreateClassPath(const std::string& class_path, + std::vector<const DexFile*>& class_path_vector) { + std::vector<std::string> parsed; + Split(class_path, ':', parsed); + for (size_t i = 0; i < parsed.size(); ++i) { + const DexFile* dex_file = DexFile::Open(parsed[i], Runtime::Current()->GetHostPrefix()); + if (dex_file != NULL) { + class_path_vector.push_back(dex_file); + } + } +} + +void ClassLinker::Init(const std::string& boot_class_path) { const Runtime* runtime = Runtime::Current(); if (runtime->IsVerboseStartup()) { LOG(INFO) << "ClassLinker::InitFrom entering"; @@ -290,16 +303,13 @@ void ClassLinker::Init(const std::vector<const DexFile*>& boot_class_path, // setup boot_class_path_ and register class_path now that we can // use AllocObjectArray to create DexCache instances - for (size_t i = 0; i != boot_class_path.size(); ++i) { - const DexFile* dex_file = boot_class_path[i]; + std::vector<const DexFile*> boot_class_path_vector; + CreateClassPath(boot_class_path, boot_class_path_vector); + for (size_t i = 0; i != boot_class_path_vector.size(); ++i) { + const DexFile* dex_file = boot_class_path_vector[i]; CHECK(dex_file != NULL); AppendToBootClassPath(*dex_file); } - for (size_t i = 0; i != class_path.size(); ++i) { - const DexFile* dex_file = class_path[i]; - CHECK(dex_file != NULL); - RegisterDexFile(*dex_file); - } // Constructor, Field, and Method are necessary so that FindClass can link members Class* java_lang_reflect_Constructor = AllocClass(java_lang_Class, sizeof(MethodClass)); @@ -523,6 +533,36 @@ void ClassLinker::RunRootClinits() { } } +OatFile* ClassLinker::OpenOat(const Space* space) { + const Runtime* runtime = Runtime::Current(); + if (runtime->IsVerboseStartup()) { + LOG(INFO) << "ClassLinker::OpenOat entering"; + } + const ImageHeader& image_header = space->GetImageHeader(); + String* oat_location = image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString(); + std::string oat_filename; + oat_filename += runtime->GetHostPrefix(); + oat_filename += oat_location->ToModifiedUtf8(); + OatFile* oat_file = OatFile::Open(std::string(oat_filename), "", image_header.GetOatBaseAddr()); + if (oat_file == NULL) { + LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image"; + return NULL; + } + uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum(); + uint32_t image_oat_checksum = image_header.GetOatChecksum(); + if (oat_checksum != image_oat_checksum) { + LOG(ERROR) << "Failed to match oat filechecksum " << std::hex << oat_checksum + << " to expected oat checksum " << std::hex << oat_checksum + << " in image"; + return NULL; + } + oat_files_.push_back(oat_file); + if (runtime->IsVerboseStartup()) { + LOG(INFO) << "ClassLinker::OpenOat exiting"; + } + return oat_file; +} + struct ClassLinker::InitFromImageCallbackState { ClassLinker* class_linker; @@ -530,19 +570,47 @@ struct ClassLinker::InitFromImageCallbackState { typedef std::tr1::unordered_map<std::string, ClassRoot> Table; Table descriptor_to_class_root; - - typedef std::tr1::unordered_set<DexCache*, DexCacheHash> Set; - Set dex_caches; }; -void ClassLinker::InitFromImage(const std::vector<const DexFile*>& boot_class_path, - const std::vector<const DexFile*>& class_path) { +void ClassLinker::InitFromImage() { const Runtime* runtime = Runtime::Current(); if (runtime->IsVerboseStartup()) { LOG(INFO) << "ClassLinker::InitFromImage entering"; } CHECK(!init_done_); + const std::vector<Space*>& spaces = Heap::GetSpaces(); + for (size_t i = 0; i < spaces.size(); i++) { + Space* space = spaces[i] ; + if (space->IsImageSpace()) { + OatFile* oat_file = OpenOat(space); + CHECK(oat_file != NULL) << "Failed to open oat file for image"; + Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches); + ObjectArray<DexCache>* dex_caches = dex_caches_object->AsObjectArray<DexCache>(); + + CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(), + static_cast<uint32_t>(dex_caches->GetLength())); + for (int i = 0; i < dex_caches->GetLength(); i++) { + DexCache* dex_cache = dex_caches->Get(i); + const std::string& dex_file_location = dex_cache->GetLocation()->ToModifiedUtf8(); + + std::string dex_filename; + dex_filename += runtime->GetHostPrefix(); + dex_filename += dex_file_location; + const DexFile* dex_file = DexFile::Open(dex_filename, runtime->GetHostPrefix()); + if (dex_file == NULL) { + LOG(FATAL) << "Failed to open dex file " << dex_filename + << " referenced from oat file as " << dex_file_location; + } + + const OatFile::OatDexFile& oat_dex_file = oat_file->GetOatDexFile(dex_file_location); + CHECK_EQ(dex_file->GetHeader().checksum_, oat_dex_file.GetDexFileChecksum()); + + RegisterDexFile(*dex_file, dex_cache); + } + } + } + HeapBitmap* heap_bitmap = Heap::GetLiveBits(); DCHECK(heap_bitmap != NULL); @@ -568,36 +636,6 @@ void ClassLinker::InitFromImage(const std::vector<const DexFile*>& boot_class_pa array_interfaces_ = GetClassRoot(kObjectArrayClass)->GetInterfaces(); DCHECK(array_interfaces_ == GetClassRoot(kBooleanArrayClass)->GetInterfaces()); - // build a map from location to DexCache to match up with DexFile::GetLocation - std::tr1::unordered_map<std::string, DexCache*> location_to_dex_cache; - typedef InitFromImageCallbackState::Set::const_iterator It; // TODO: C++0x auto - for (It it = state.dex_caches.begin(), end = state.dex_caches.end(); it != end; ++it) { - DexCache* dex_cache = *it; - std::string location = dex_cache->GetLocation()->ToModifiedUtf8(); - location_to_dex_cache[location] = dex_cache; - } - CHECK(boot_class_path.size() + class_path.size() == location_to_dex_cache.size()) - << "(" << boot_class_path.size() << " + " << class_path.size() - << " != " << location_to_dex_cache.size() << ")"; - - // reinit boot_class_path with DexFile arguments and found DexCaches - for (size_t i = 0; i != boot_class_path.size(); ++i) { - const DexFile* dex_file = boot_class_path[i]; - CHECK(dex_file != NULL); - DexCache* dex_cache = location_to_dex_cache[dex_file->GetLocation()]; - CHECK(dex_cache != NULL) << dex_file->GetLocation(); - AppendToBootClassPath(*dex_file, dex_cache); - } - - // register class_path with DexFile arguments and found DexCaches - for (size_t i = 0; i != class_path.size(); ++i) { - const DexFile* dex_file = class_path[i]; - CHECK(dex_file != NULL); - DexCache* dex_cache = location_to_dex_cache[dex_file->GetLocation()]; - CHECK(dex_cache != NULL) << dex_file->GetLocation(); - RegisterDexFile(*dex_file, dex_cache); - } - String::SetClass(GetClassRoot(kJavaLangString)); Field::SetClass(GetClassRoot(kJavaLangReflectField)); Method::SetClasses(GetClassRoot(kJavaLangReflectConstructor), GetClassRoot(kJavaLangReflectMethod)); @@ -644,14 +682,6 @@ void ClassLinker::InitFromImageCallback(Object* obj, void* arg) { // restore class to ClassLinker::classes_ table state->class_linker->InsertClass(descriptor, klass); - // note DexCache to match with DexFile later - DexCache* dex_cache = klass->GetDexCache(); - if (dex_cache != NULL) { - state->dex_caches.insert(dex_cache); - } else { - DCHECK(klass->IsArrayClass() || klass->IsPrimitive()); - } - // check if this is a root, if so, register it typedef InitFromImageCallbackState::Table::const_iterator It; // TODO: C++0x auto It it = state->descriptor_to_class_root.find(descriptor); @@ -696,6 +726,8 @@ ClassLinker::~ClassLinker() { ShortArray::ResetArrayClass(); PathClassLoader::ResetClass(); StackTraceElement::ResetClass(); + STLDeleteElements(&boot_class_path_); + STLDeleteElements(&oat_files_); } DexCache* ClassLinker::AllocDexCache(const DexFile& dex_file) { diff --git a/src/class_linker.h b/src/class_linker.h index 3c483a957a..747a6e405c 100644 --- a/src/class_linker.h +++ b/src/class_linker.h @@ -25,6 +25,7 @@ #include "heap.h" #include "macros.h" #include "mutex.h" +#include "oat_file.h" #include "object.h" #include "unordered_map.h" #include "unordered_set.h" @@ -39,10 +40,11 @@ class ObjectLock; class ClassLinker { public: - // Initializes the class linker using DexFiles and an optional an image. - static ClassLinker* Create(const std::vector<const DexFile*>& boot_class_path, - const std::vector<const DexFile*>& class_path, - InternTable* intern_table, bool image); + // Creates the class linker by boot strapping from dex files. + static ClassLinker* Create(const std::string& boot_class_path, InternTable* intern_table); + + // Creates the class linker from one or more images. + static ClassLinker* Create(InternTable* intern_table); ~ClassLinker(); @@ -191,13 +193,12 @@ class ClassLinker { private: ClassLinker(InternTable*); - // Initialize class linker from DexFile instances. - void Init(const std::vector<const DexFile*>& boot_class_path_, - const std::vector<const DexFile*>& class_path_); + // Initialize class linker by bootstraping from dex files + void Init(const std::string& boot_class_path); - // Initialize class linker from pre-initialized image. - void InitFromImage(const std::vector<const DexFile*>& boot_class_path_, - const std::vector<const DexFile*>& class_path_); + // Initialize class linker from one or more images. + void InitFromImage(); + OatFile* OpenOat(const Space* space); static void InitFromImageCallback(Object* obj, void* arg); struct InitFromImageCallbackState; @@ -298,9 +299,16 @@ class ClassLinker { void CreateReferenceOffsets(Class *klass, bool instance, uint32_t reference_offsets); + // For use by ImageWriter to find DexCaches for its roots + const std::vector<DexCache*>& GetDexCaches() { + return dex_caches_; + } + // lock to protect ClassLinker state mutable Mutex lock_; + std::vector<const OatFile*> oat_files_; + std::vector<const DexFile*> boot_class_path_; std::vector<const DexFile*> dex_files_; @@ -389,6 +397,7 @@ class ClassLinker { friend class ObjectTest; FRIEND_TEST(ObjectTest, AllocObjectArray); FRIEND_TEST(ExceptionTest, FindExceptionHandler); + friend class ImageWriter; // for GetDexCaches DISALLOW_COPY_AND_ASSIGN(ClassLinker); }; diff --git a/src/common_test.h b/src/common_test.h index a7c5ea8c09..b321071b83 100644 --- a/src/common_test.h +++ b/src/common_test.h @@ -43,7 +43,7 @@ static inline const DexFile* OpenDexFileBase64(const char* base64, file.reset(); // read dex file - const DexFile* dex_file = DexFile::OpenFile(location, location, ""); + const DexFile* dex_file = DexFile::Open(location, ""); CHECK(dex_file != NULL); return dex_file; } @@ -114,10 +114,12 @@ class CommonTest : public testing::Test { java_lang_dex_file_.reset(GetLibCoreDex()); - boot_class_path_.push_back(java_lang_dex_file_.get()); + std::string boot_class_path; + boot_class_path += "-Xbootclasspath:"; + boot_class_path += GetLibCoreDexFileName(); Runtime::Options options; - options.push_back(std::make_pair("bootclasspath", &boot_class_path_)); + options.push_back(std::make_pair(boot_class_path.c_str(), reinterpret_cast<void*>(NULL))); options.push_back(std::make_pair("-Xcheck:jni", reinterpret_cast<void*>(NULL))); options.push_back(std::make_pair("-Xms64m", reinterpret_cast<void*>(NULL))); options.push_back(std::make_pair("-Xmx64m", reinterpret_cast<void*>(NULL))); @@ -193,7 +195,7 @@ class CommonTest : public testing::Test { const DexFile* GetLibCoreDex() { std::string libcore_dex_file_name = GetLibCoreDexFileName(); - return DexFile::OpenZip(libcore_dex_file_name, ""); + return DexFile::Open(libcore_dex_file_name, ""); } uint32_t FindTypeIdxByDescriptor(const DexFile& dex_file, const StringPiece& descriptor) { @@ -239,7 +241,7 @@ class CommonTest : public testing::Test { filename += "/system/framework/art-test-dex-"; filename += name; filename += ".jar"; - const DexFile* dex_file = DexFile::OpenZip(filename, ""); + const DexFile* dex_file = DexFile::Open(filename, ""); CHECK(dex_file != NULL) << "Failed to open " << filename; return dex_file; } diff --git a/src/dex2oat.cc b/src/dex2oat.cc index 78d36281d8..d34a6810bb 100644 --- a/src/dex2oat.cc +++ b/src/dex2oat.cc @@ -42,25 +42,14 @@ static void usage() { " --boot-image=<file.art>: provide the image file for the boot class path.\n" " Example: --boot-image=/system/framework/boot.art\n" "\n"); - // TODO: remove this by inferring from --boot-image - fprintf(stderr, - " --boot-oat=<file.oat>: provide the oat file for the boot class path.\n" - " Example: --boot-oat=/system/framework/boot.oat\n" - "\n"); - // TODO: remove this by inderring from --boot-image or --boot-oat - fprintf(stderr, - " --boot-dex-file=<dex-file>: specifies a .dex file that is part of the boot\n" - " image specified with --boot. \n" - " Example: --boot-dex-file=/system/framework/core.jar\n" - "\n"); fprintf(stderr, " --method may be used to limit compilation to a subset of methods.\n" " Example: --method=Ljava/lang/Object;<init>()V\n" "\n"); fprintf(stderr, - " --strip-prefix may be used to strip a path prefix from dex file names in the\n" - " the generated image to match the target file system layout.\n" - " Example: --strip-prefix=out/target/product/crespo\n" + " --host-prefix may be used to translate host paths to target paths during\n" + " cross compilation.\n" + " Example: --host-prefix=out/target/product/crespo\n" "\n"); fprintf(stderr, " -Xms<n> may be used to specify an initial heap size for the runtime used to\n" @@ -90,10 +79,8 @@ int dex2oat(int argc, char** argv) { std::string oat_filename; const char* image_filename = NULL; std::string boot_image_option; - std::string boot_oat_option; - std::vector<const char*> boot_dex_filenames; uintptr_t image_base = 0; - std::string strip_location_prefix; + std::string host_prefix; const char* Xms = NULL; const char* Xmx = NULL; @@ -118,17 +105,10 @@ int dex2oat(int argc, char** argv) { } else if (option.starts_with("--boot-image=")) { const char* boot_image_filename = option.substr(strlen("--boot-image=")).data(); boot_image_option.clear(); - boot_image_option += "-Xbootimage:"; + boot_image_option += "-Ximage:"; boot_image_option += boot_image_filename; - } else if (option.starts_with("--boot-oat=")) { - const char* boot_oat_filename = option.substr(strlen("--boot-oat=")).data(); - boot_oat_option.clear(); - boot_oat_option += "-Xbootoat:"; - boot_oat_option += boot_oat_filename; - } else if (option.starts_with("--boot-dex-file=")) { - boot_dex_filenames.push_back(option.substr(strlen("--boot-dex-file=")).data()); - } else if (option.starts_with("--strip-prefix=")) { - strip_location_prefix = option.substr(strlen("--strip-prefix=")).data(); + } else if (option.starts_with("--host-prefix=")) { + host_prefix = option.substr(strlen("--host-prefix=")).data(); } else if (option.starts_with("-Xms")) { Xms = option.data(); } else if (option.starts_with("-Xmx")) { @@ -154,36 +134,25 @@ int dex2oat(int argc, char** argv) { return EXIT_FAILURE; } - if (boot_image_option.empty() != boot_oat_option.empty()) { - fprintf(stderr, "--boot-image and --boat-oat must be specified together or not at all\n"); - return EXIT_FAILURE; - } - if (boot_image_option.empty()) { if (image_base == 0) { fprintf(stderr, "non-zero --base not specified\n"); return EXIT_FAILURE; } - } else { - if (boot_dex_filenames.empty()) { - fprintf(stderr, "no --boot-dex-file values specified with --boot-image\n"); - return EXIT_FAILURE; - } } - std::vector<const DexFile*> dex_files; - DexFile::OpenDexFiles(dex_filenames, dex_files, strip_location_prefix); - - std::vector<const DexFile*> boot_dex_files; - DexFile::OpenDexFiles(boot_dex_filenames, boot_dex_files, strip_location_prefix); - Runtime::Options options; + std::string boot_class_path_string; if (boot_image_option.empty()) { - options.push_back(std::make_pair("bootclasspath", &dex_files)); + boot_class_path_string += "-Xbootclasspath:"; + for (size_t i = 0; i < dex_filenames.size()-1; i++) { + boot_class_path_string += dex_filenames[i]; + boot_class_path_string += ":"; + } + boot_class_path_string += dex_filenames[dex_filenames.size()-1]; + options.push_back(std::make_pair(boot_class_path_string.c_str(), reinterpret_cast<void*>(NULL))); } else { - options.push_back(std::make_pair("bootclasspath", &boot_dex_files)); options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL))); - options.push_back(std::make_pair(boot_oat_option.c_str(), reinterpret_cast<void*>(NULL))); } if (Xms != NULL) { options.push_back(std::make_pair(Xms, reinterpret_cast<void*>(NULL))); @@ -191,6 +160,9 @@ int dex2oat(int argc, char** argv) { if (Xmx != NULL) { options.push_back(std::make_pair(Xmx, reinterpret_cast<void*>(NULL))); } + if (!host_prefix.empty()) { + options.push_back(std::make_pair("host-prefix", host_prefix.c_str())); + } UniquePtr<Runtime> runtime(Runtime::Create(options, false)); if (runtime.get() == NULL) { fprintf(stderr, "could not create runtime\n"); @@ -199,10 +171,12 @@ int dex2oat(int argc, char** argv) { ClassLinker* class_linker = runtime->GetClassLinker(); // If we have an existing boot image, position new space after its oat file - if (!boot_image_option.empty()) { - Space* boot_space = Heap::GetBootSpace(); - CHECK(boot_space != NULL); - byte* oat_limit_addr = boot_space->GetImageHeader().GetOatLimitAddr(); + if (Heap::GetSpaces().size() > 1) { + Space* last_image_space = Heap::GetSpaces()[Heap::GetSpaces().size()-2]; + CHECK(last_image_space != NULL); + CHECK(last_image_space->IsImageSpace()); + CHECK(!Heap::GetSpaces()[Heap::GetSpaces().size()-1]->IsImageSpace()); + byte* oat_limit_addr = last_image_space->GetImageHeader().GetOatLimitAddr(); image_base = RoundUp(reinterpret_cast<uintptr_t>(oat_limit_addr), kPageSize); } @@ -211,6 +185,8 @@ int dex2oat(int argc, char** argv) { if (boot_image_option.empty()) { class_loader = NULL; } else { + std::vector<const DexFile*> dex_files; + DexFile::OpenDexFiles(dex_filenames, dex_files, host_prefix); for (size_t i = 0; i < dex_files.size(); i++) { class_linker->RegisterDexFile(*dex_files[i]); } @@ -279,7 +255,7 @@ int dex2oat(int argc, char** argv) { } ImageWriter image_writer; - if (!image_writer.Write(image_filename, image_base, oat_filename, strip_location_prefix)) { + if (!image_writer.Write(image_filename, image_base, oat_filename, host_prefix)) { fprintf(stderr, "Failed to create image file %s\n", image_filename); return EXIT_FAILURE; } diff --git a/src/dex_file.cc b/src/dex_file.cc index b4cf83793c..474d74213d 100644 --- a/src/dex_file.cc +++ b/src/dex_file.cc @@ -59,8 +59,7 @@ void DexFile::OpenDexFiles(std::vector<const char*>& dex_filenames, const DexFile* DexFile::Open(const std::string& filename, const std::string& strip_location_prefix) { if (filename.size() < 4) { - LOG(WARNING) << "Ignoring short classpath entry '" << filename << "'"; - return NULL; + LOG(WARNING) << "Attempting to open dex file with unknown extension '" << filename << "'"; } std::string suffix(filename.substr(filename.size() - 4)); if (suffix == ".zip" || suffix == ".jar" || suffix == ".apk") { @@ -106,7 +105,7 @@ const DexFile* DexFile::OpenFile(const std::string& filename, } close(fd); byte* dex_file = map->GetAddress(); - return Open(dex_file, length, location.ToString(), map.release()); + return OpenMemory(dex_file, length, location.ToString(), map.release()); } static const char* kClassesDex = "classes.dex"; @@ -349,8 +348,8 @@ const DexFile* DexFile::OpenZip(const std::string& filename, // NOTREACHED } -const DexFile* DexFile::Open(const byte* dex_bytes, size_t length, - const std::string& location, MemMap* mem_map) { +const DexFile* DexFile::OpenMemory(const byte* dex_bytes, size_t length, + const std::string& location, MemMap* mem_map) { UniquePtr<DexFile> dex_file(new DexFile(dex_bytes, length, location, mem_map)); if (!dex_file->Init()) { return NULL; diff --git a/src/dex_file.h b/src/dex_file.h index cb979aee99..45cd33eacb 100644 --- a/src/dex_file.h +++ b/src/dex_file.h @@ -324,19 +324,9 @@ class DexFile { std::vector<const DexFile*>& dex_files, const std::string& strip_location_prefix); - // Opens .dex file, guessing the format based on file extension + // Opens .dex file, guessing the container format based on file extension static const DexFile* Open(const std::string& filename, const std::string& strip_location_prefix); - - // Opens a .dex file from the file system. - static const DexFile* OpenFile(const std::string& filename, - const std::string& original_location, - const std::string& strip_location_prefix); - - // Opens a .jar, .zip, or .apk file from the file system. - static const DexFile* OpenZip(const std::string& filename, - const std::string& strip_location_prefix); - // Closes a .dex file. virtual ~DexFile(); @@ -838,11 +828,21 @@ class DexFile { void ChangePermissions(int prot) const; private: + + // Opens a .dex file + static const DexFile* OpenFile(const std::string& filename, + const std::string& original_location, + const std::string& strip_location_prefix); + + // Opens a dex file from within a .jar, .zip, or .apk file + static const DexFile* OpenZip(const std::string& filename, + const std::string& strip_location_prefix); + // Opens a .dex file at the given address. - static const DexFile* Open(const byte* dex_file, - size_t length, - const std::string& location, - MemMap* mem_map); + static const DexFile* OpenMemory(const byte* dex_file, + size_t length, + const std::string& location, + MemMap* mem_map); DexFile(const byte* addr, size_t length, const std::string& location, MemMap* mem_map) : base_(addr), diff --git a/src/heap.cc b/src/heap.cc index 2051051ab5..92ebbd0cf2 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -2,6 +2,7 @@ #include "heap.h" +#include <limits> #include <vector> #include "UniquePtr.h" @@ -16,8 +17,6 @@ namespace art { std::vector<Space*> Heap::spaces_; -Space* Heap::boot_space_ = NULL; - Space* Heap::alloc_space_ = NULL; size_t Heap::maximum_size_ = 0; @@ -56,29 +55,19 @@ class ScopedHeapLock { }; void Heap::Init(size_t initial_size, size_t maximum_size, - const char* boot_image_file_name, - std::vector<const char*>& image_file_names) { + const std::vector<std::string>& image_file_names) { const Runtime* runtime = Runtime::Current(); if (runtime->IsVerboseStartup()) { LOG(INFO) << "Heap::Init entering"; } - Space* boot_space; - byte* requested_base; - if (boot_image_file_name == NULL) { - boot_space = NULL; - requested_base = NULL; - } else { - boot_space = Space::CreateFromImage(boot_image_file_name); - if (boot_space == NULL) { - LOG(FATAL) << "Failed to create space from " << boot_image_file_name; - } - spaces_.push_back(boot_space); - byte* oat_limit_addr = boot_space->GetImageHeader().GetOatLimitAddr(); - requested_base = reinterpret_cast<byte*>(RoundUp(reinterpret_cast<uintptr_t>(oat_limit_addr), - kPageSize)); - } + // bounds of all spaces for allocating live and mark bitmaps + // there will be at least one space (the alloc space), + // so set to base to max and limit to min to start + byte* base = reinterpret_cast<byte*>(std::numeric_limits<uintptr_t>::max()); + byte* limit = reinterpret_cast<byte*>(std::numeric_limits<uintptr_t>::min()); + byte* requested_base = NULL; std::vector<Space*> image_spaces; for (size_t i = 0; i < image_file_names.size(); i++) { Space* space = Space::CreateFromImage(image_file_names[i]); @@ -88,20 +77,20 @@ void Heap::Init(size_t initial_size, size_t maximum_size, image_spaces.push_back(space); spaces_.push_back(space); byte* oat_limit_addr = space->GetImageHeader().GetOatLimitAddr(); - requested_base = reinterpret_cast<byte*>(RoundUp(reinterpret_cast<uintptr_t>(oat_limit_addr), - kPageSize)); + if (oat_limit_addr > requested_base) { + requested_base = reinterpret_cast<byte*>(RoundUp(reinterpret_cast<uintptr_t>(oat_limit_addr), + kPageSize)); + } + base = std::min(base, space->GetBase()); + limit = std::max(limit, space->GetLimit()); } Space* space = Space::Create(initial_size, maximum_size, requested_base); if (space == NULL) { LOG(FATAL) << "Failed to create alloc space"; } - - if (boot_space == NULL) { - boot_space = space; - } - byte* base = std::min(boot_space->GetBase(), space->GetBase()); - byte* limit = std::max(boot_space->GetLimit(), space->GetLimit()); + base = std::min(base, space->GetBase()); + limit = std::max(limit, space->GetLimit()); DCHECK_LT(base, limit); size_t num_bytes = limit - base; @@ -128,11 +117,7 @@ void Heap::Init(size_t initial_size, size_t maximum_size, // TODO: allocate the card table - // Make objects in boot_space live (after live_bitmap_ is set) - if (boot_image_file_name != NULL) { - boot_space_ = boot_space; - RecordImageAllocations(boot_space); - } + // Make image objects live (after live_bitmap_ is set) for (size_t i = 0; i < image_spaces.size(); i++) { RecordImageAllocations(image_spaces[i]); } diff --git a/src/heap.h b/src/heap.h index b669a869f2..76e33b5515 100644 --- a/src/heap.h +++ b/src/heap.h @@ -41,12 +41,11 @@ class Heap { typedef void (RootVisitor)(const Object* root, void* arg); - // Create a heap with the requested sizes. The optional boot image may - // be NULL, otherwise it is an image filename created by ImageWriter. - // image_file_names specifies application images to load. + // Create a heap with the requested sizes. The possible empty + // image_file_names names specify Spaces to load based on + // ImageWriter output. static void Init(size_t starting_size, size_t maximum_size, - const char* boot_image_file_name, - std::vector<const char*>& image_file_names); + const std::vector<std::string>& image_file_names); static void Destroy(); @@ -105,10 +104,6 @@ class Heap { return spaces_; } - static Space* GetBootSpace() { - return boot_space_; - } - static HeapBitmap* GetLiveBits() { return live_bitmap_; } @@ -199,10 +194,6 @@ class Heap { static std::vector<Space*> spaces_; - // Space loaded from an image - // TODO: remove after intern_addr is removed - static Space* boot_space_; - // default Space for allocations static Space* alloc_space_; diff --git a/src/image.h b/src/image.h index 3d2f5f4d70..4a2efc59fc 100644 --- a/src/image.h +++ b/src/image.h @@ -70,6 +70,7 @@ class PACKED ImageHeader { kAbstractMethodErrorStubArray, kCalleeSaveMethod, kOatLocation, + kDexCaches, kImageRootsMax, }; diff --git a/src/image_test.cc b/src/image_test.cc index 2fd5c34169..903457f165 100644 --- a/src/image_test.cc +++ b/src/image_test.cc @@ -23,8 +23,8 @@ TEST_F(ImageTest, WriteRead) { ImageWriter writer; ScratchFile tmp_image; - const uintptr_t image_base = 0x50000000; - bool success_image = writer.Write(tmp_image.GetFilename(), image_base, + const uintptr_t requested_image_base = 0x60000000; + bool success_image = writer.Write(tmp_image.GetFilename(), requested_image_base, std::string(tmp_oat.GetFilename()), ""); ASSERT_TRUE(success_image); @@ -51,17 +51,10 @@ TEST_F(ImageTest, WriteRead) { UniquePtr<const DexFile> dex(GetLibCoreDex()); ASSERT_TRUE(dex.get() != NULL); - std::vector<const DexFile*> boot_class_path; - boot_class_path.push_back(dex.get()); - Runtime::Options options; - options.push_back(std::make_pair("bootclasspath", &boot_class_path)); - std::string boot_oat("-Xbootoat:"); - boot_oat.append(tmp_oat.GetFilename()); - options.push_back(std::make_pair(boot_oat.c_str(), reinterpret_cast<void*>(NULL))); - std::string boot_image("-Xbootimage:"); - boot_image.append(tmp_image.GetFilename()); - options.push_back(std::make_pair(boot_image.c_str(), reinterpret_cast<void*>(NULL))); + std::string image("-Ximage:"); + image.append(tmp_image.GetFilename()); + options.push_back(std::make_pair(image.c_str(), reinterpret_cast<void*>(NULL))); runtime_.reset(Runtime::Create(options, false)); ASSERT_TRUE(runtime_.get() != NULL); @@ -70,23 +63,20 @@ TEST_F(ImageTest, WriteRead) { ASSERT_TRUE(runtime_->GetJniStubArray() != NULL); ASSERT_EQ(2U, Heap::GetSpaces().size()); - Space* boot_space = Heap::GetBootSpace(); - ASSERT_TRUE(boot_space != NULL); - - // enable to display maps to debug boot_base and boot_limit checking problems below - if (false) { - SignalCatcher::HandleSigQuit(); - } + ASSERT_TRUE(Heap::GetSpaces()[0]->IsImageSpace()); + ASSERT_FALSE(Heap::GetSpaces()[1]->IsImageSpace()); - byte* boot_base = boot_space->GetBase(); - byte* boot_limit = boot_space->GetLimit(); + Space* image_space = Heap::GetSpaces()[0]; + byte* image_base = image_space->GetBase(); + byte* image_limit = image_space->GetLimit(); + CHECK_EQ(requested_image_base, reinterpret_cast<uintptr_t>(image_base)); for (size_t i = 0; i < dex->NumClassDefs(); i++) { const DexFile::ClassDef& class_def = dex->GetClassDef(i); const char* descriptor = dex->GetClassDescriptor(class_def); Class* klass = class_linker_->FindSystemClass(descriptor); EXPECT_TRUE(klass != NULL) << descriptor; - EXPECT_LT(boot_base, reinterpret_cast<byte*>(klass)) << descriptor; - EXPECT_LT(reinterpret_cast<byte*>(klass), boot_limit) << descriptor; + EXPECT_LT(image_base, reinterpret_cast<byte*>(klass)) << descriptor; + EXPECT_LT(reinterpret_cast<byte*>(klass), image_limit) << descriptor; EXPECT_EQ(*klass->GetRawLockWordAddress(), 0); // address should have been removed from monitor } } diff --git a/src/image_writer.cc b/src/image_writer.cc index 37eac2ebe4..2b2ada45f6 100644 --- a/src/image_writer.cc +++ b/src/image_writer.cc @@ -32,6 +32,7 @@ bool ImageWriter::Write(const char* image_filename, uintptr_t image_base, // currently just write the last space, assuming it is the space that was being used for allocation CHECK_GE(spaces.size(), 1U); source_space_ = spaces[spaces.size()-1]; + CHECK(!source_space_->IsImageSpace()); oat_file_.reset(OatFile::Open(oat_filename, strip_location_prefix, NULL)); if (oat_file_.get() == NULL) { @@ -114,10 +115,26 @@ void ImageWriter::CalculateNewObjectOffsetsCallback(Object* obj, void* arg) { } ObjectArray<Object>* ImageWriter::CreateImageRoots() const { - // build a Object[] of the roots needed to restore the runtime Runtime* runtime = Runtime::Current(); ClassLinker* class_linker = runtime->GetClassLinker(); Class* object_array_class = class_linker->FindSystemClass("[Ljava/lang/Object;"); + + // build an Object[] of all the DexCaches used in the source_space_ + const std::vector<DexCache*>& all_dex_caches = class_linker->GetDexCaches(); + std::vector<DexCache*> source_space_dex_caches; + for (size_t i = 0; i < all_dex_caches.size(); i++) { + DexCache* dex_cache = all_dex_caches[i]; + if (InSourceSpace(dex_cache)) { + source_space_dex_caches.push_back(dex_cache); + } + } + ObjectArray<Object>* dex_caches = ObjectArray<Object>::Alloc(object_array_class, + source_space_dex_caches.size()); + for (size_t i = 0; i < source_space_dex_caches.size(); i++) { + dex_caches->Set(i, source_space_dex_caches[i]); + } + + // build an Object[] of the roots needed to restore the runtime ObjectArray<Object>* image_roots = ObjectArray<Object>::Alloc(object_array_class, ImageHeader::kImageRootsMax); image_roots->Set(ImageHeader::kJniStubArray, @@ -128,6 +145,8 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots() const { runtime->GetCalleeSaveMethod()); image_roots->Set(ImageHeader::kOatLocation, String::AllocFromModifiedUtf8(oat_file_->GetLocation().c_str())); + image_roots->Set(ImageHeader::kDexCaches, + dex_caches); for (int i = 0; i < ImageHeader::kImageRootsMax; i++) { CHECK(image_roots->Get(i) != NULL); } diff --git a/src/image_writer.h b/src/image_writer.h index 8c4b308f8e..fda33fecb0 100644 --- a/src/image_writer.h +++ b/src/image_writer.h @@ -62,12 +62,12 @@ class ImageWriter { object->monitor_ = 0; } - bool InSourceSpace(const Object* object) { + bool InSourceSpace(const Object* object) const { DCHECK(source_space_ != NULL); const byte* o = reinterpret_cast<const byte*>(object); return (o >= source_space_->GetBase() && o < source_space_->GetLimit()); } - Object* GetImageAddress(const Object* object) { + Object* GetImageAddress(const Object* object) const { if (object == NULL) { return NULL; } @@ -77,7 +77,7 @@ class ImageWriter { } return reinterpret_cast<Object*>(image_base_ + GetImageOffset(object)); } - Object* GetLocalAddress(const Object* object) { + Object* GetLocalAddress(const Object* object) const { size_t offset = GetImageOffset(object); byte* dst = image_->GetAddress() + offset; return reinterpret_cast<Object*>(dst); diff --git a/src/oat_file.cc b/src/oat_file.cc index 62664941d0..15221a6d07 100644 --- a/src/oat_file.cc +++ b/src/oat_file.cc @@ -123,10 +123,10 @@ const byte* OatFile::GetLimit() const { return mem_map_->GetLimit(); } -const OatFile::OatDexFile& OatFile::GetOatDexFile(const DexFile& dex_file) { - Table::const_iterator it = oat_dex_files_.find(dex_file.GetLocation()); +const OatFile::OatDexFile& OatFile::GetOatDexFile(const std::string& dex_file_location) { + Table::const_iterator it = oat_dex_files_.find(dex_file_location); if (it == oat_dex_files_.end()) { - LOG(FATAL) << "Failed to find OatDexFile for DexFile " << dex_file.GetLocation(); + LOG(FATAL) << "Failed to find OatDexFile for DexFile " << dex_file_location; } return *it->second; } diff --git a/src/oat_file.h b/src/oat_file.h index 2528a6c5a1..6027ddaac2 100644 --- a/src/oat_file.h +++ b/src/oat_file.h @@ -51,6 +51,11 @@ class OatFile { class OatDexFile { public: const OatClass GetOatClass(uint32_t class_def_index) const; + + uint32_t GetDexFileChecksum() const { + return dex_file_checksum_; + } + ~OatDexFile(); private: OatDexFile(const OatFile* oat_file, @@ -67,7 +72,7 @@ class OatFile { DISALLOW_COPY_AND_ASSIGN(OatDexFile); }; - const OatDexFile& GetOatDexFile(const DexFile& dex_file); + const OatDexFile& GetOatDexFile(const std::string& dex_file_location); size_t GetSize() const { return GetLimit() - GetBase(); diff --git a/src/oat_test.cc b/src/oat_test.cc index b1453b35a6..c3d012ea50 100644 --- a/src/oat_test.cc +++ b/src/oat_test.cc @@ -35,7 +35,7 @@ TEST_F(OatTest, WriteRead) { ByteArray* ame_stub_array = runtime->GetAbstractMethodErrorStubArray(); const DexFile& dex_file = *java_lang_dex_file_.get(); - const OatFile::OatDexFile& oat_dex_file = oat_file->GetOatDexFile(dex_file); + const OatFile::OatDexFile& oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation()); for (size_t i = 0; i < dex_file.NumClassDefs(); i++) { const DexFile::ClassDef& class_def = dex_file.GetClassDef(i); const byte* class_data = dex_file.GetClassData(class_def); diff --git a/src/oatdump.cc b/src/oatdump.cc index bec8d10669..e96b25ca9d 100644 --- a/src/oatdump.cc +++ b/src/oatdump.cc @@ -22,43 +22,21 @@ namespace art { static void usage() { fprintf(stderr, "Usage: oatdump [options] ...\n" - " Example: oatdump --dex-file=$ANDROID_PRODUCT_OUT/system/framework/core.jar --oat=$ANDROID_PRODUCT_OUT/system/framework/boot.oat --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art --strip-prefix=$ANDROID_PRODUCT_OUT\n" - " Example: adb shell oatdump --dex-file=/system/framework/core.jar --oat=/system/framework/boot.oat --image=/system/framework/boot.art\n" - "\n"); - // TODO: remove this by inferring from --image or --oat - fprintf(stderr, - " --dex-file=<dex-file>: specifies a .dex file location. At least one .dex\n" - " file must be specified. \n" - " Example: --dex-file=/system/framework/core.jar\n" + " Example: oatdump --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art --host-prefix=$ANDROID_PRODUCT_OUT\n" + " Example: adb shell oatdump --image=/system/framework/boot.art\n" "\n"); fprintf(stderr, " --image=<file.art>: specifies the required input image filename.\n" " Example: --image=/system/framework/boot.art\n" "\n"); - // TODO: remove this by inferring from --image - fprintf(stderr, - " --oat=<file.oat>: specifies the required input oat filename.\n" - " Example: --image=/system/framework/boot.oat\n" - "\n"); fprintf(stderr, " --boot-image=<file.art>: provide the image file for the boot class path.\n" " Example: --boot-image=/system/framework/boot.art\n" "\n"); - // TODO: remove this by inferring from --boot-image fprintf(stderr, - " --boot-oat=<file.oat>: provide the oat file for the boot class path.\n" - " Example: --boot-oat=/system/framework/boot.oat\n" - "\n"); - // TODO: remove this by inderring from --boot-image or --boot-oat - fprintf(stderr, - " --boot-dex-file=<dex-file>: specifies a .dex file that is part of the boot\n" - " image specified with --boot. \n" - " Example: --boot-dex-file=/system/framework/core.jar\n" - "\n"); - fprintf(stderr, - " --strip-prefix may be used to strip a path prefix from dex file names in the\n" - " the generated image to match the target file system layout.\n" - " Example: --strip-prefix=out/target/product/crespo\n" + " --host-prefix may be used to translate host paths to target paths during\n" + " cross compilation.\n" + " Example: --host-prefix=out/target/product/crespo\n" "\n"); fprintf(stderr, " --output=<file> may be used to send the output to a file.\n" @@ -72,6 +50,7 @@ const char* image_roots_descriptions_[] = { "kAbstractMethodErrorStubArray", "kCalleeSaveMethod", "kOatLocation", + "kDexCaches", }; class OatDump { @@ -369,32 +348,20 @@ int oatdump(int argc, char** argv) { usage(); } - std::vector<const char*> dex_filenames; const char* image_filename = NULL; - const char* oat_filename = NULL; const char* boot_image_filename = NULL; - const char* boot_oat_filename = NULL; - std::vector<const char*> boot_dex_filenames; - std::string strip_location_prefix; + std::string host_prefix; std::ostream* os = &std::cout; UniquePtr<std::ofstream> out; for (int i = 0; i < argc; i++) { const StringPiece option(argv[i]); - if (option.starts_with("--dex-file=")) { - dex_filenames.push_back(option.substr(strlen("--dex-file=")).data()); - } else if (option.starts_with("--image=")) { + if (option.starts_with("--image=")) { image_filename = option.substr(strlen("--image=")).data(); - } else if (option.starts_with("--oat=")) { - oat_filename = option.substr(strlen("--oat=")).data(); } else if (option.starts_with("--boot-image=")) { boot_image_filename = option.substr(strlen("--boot-image=")).data(); - } else if (option.starts_with("--boot-oat=")) { - boot_oat_filename = option.substr(strlen("--boot-oat=")).data(); - } else if (option.starts_with("--boot-dex-file=")) { - boot_dex_filenames.push_back(option.substr(strlen("--boot-dex-file=")).data()); - } else if (option.starts_with("--strip-prefix=")) { - strip_location_prefix = option.substr(strlen("--strip-prefix=")).data(); + } else if (option.starts_with("--host-prefix=")) { + host_prefix = option.substr(strlen("--host-prefix=")).data(); } else if (option.starts_with("--output=")) { const char* filename = option.substr(strlen("--output=")).data(); out.reset(new std::ofstream(filename)); @@ -414,69 +381,29 @@ int oatdump(int argc, char** argv) { return EXIT_FAILURE; } - if (oat_filename == NULL) { - fprintf(stderr, "--oat file name not specified\n"); - return EXIT_FAILURE; - } - - if (dex_filenames.empty()) { - fprintf(stderr, "no --dex-file values specified\n"); - return EXIT_FAILURE; - } - - if ((boot_image_filename != NULL) != (boot_oat_filename != NULL)) { - fprintf(stderr, "--boot-image and --boat-oat must be specified together or not at all\n"); - return EXIT_FAILURE; - } - - if (boot_image_filename != NULL && boot_dex_filenames.empty()) { - fprintf(stderr, "no --boot-dex-file values specified with --boot\n"); - return EXIT_FAILURE; - } - - std::vector<const DexFile*> dex_files; - DexFile::OpenDexFiles(dex_filenames, dex_files, strip_location_prefix); - - std::vector<const DexFile*> boot_dex_files; - DexFile::OpenDexFiles(boot_dex_filenames, boot_dex_files, strip_location_prefix); - Runtime::Options options; std::string image_option; std::string oat_option; std::string boot_image_option; std::string boot_oat_option; - if (boot_image_filename == NULL) { - // if we don't have multiple images, pass the main one as the boot to match dex2oat - boot_image_filename = image_filename; - boot_oat_filename = oat_filename; - boot_dex_files = dex_files; - dex_files.clear(); - } else { - image_option += "-Ximage:"; - image_option += image_filename; - oat_option += "-Xoat:"; - oat_option += oat_filename; - options.push_back(std::make_pair("classpath", &dex_files)); - options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL))); - options.push_back(std::make_pair(oat_option.c_str(), reinterpret_cast<void*>(NULL))); + if (boot_image_filename != NULL) { + boot_image_option += "-Ximage:"; + boot_image_option += boot_image_filename; + options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL))); + } + image_option += "-Ximage:"; + image_option += image_filename; + options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL))); + + if (!host_prefix.empty()) { + options.push_back(std::make_pair("host-prefix", host_prefix.c_str())); } - boot_image_option += "-Xbootimage:"; - boot_image_option += boot_image_filename; - boot_oat_option += "-Xbootoat:"; - boot_oat_option += boot_oat_filename; - options.push_back(std::make_pair("bootclasspath", &boot_dex_files)); - options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL))); - options.push_back(std::make_pair(boot_oat_option.c_str(), reinterpret_cast<void*>(NULL))); UniquePtr<Runtime> runtime(Runtime::Create(options, false)); if (runtime.get() == NULL) { fprintf(stderr, "could not create runtime\n"); return EXIT_FAILURE; } - ClassLinker* class_linker = runtime->GetClassLinker(); - for (size_t i = 0; i < dex_files.size(); i++) { - class_linker->RegisterDexFile(*dex_files[i]); - } Space* image_space = Heap::GetSpaces()[Heap::GetSpaces().size()-2]; CHECK(image_space != NULL); diff --git a/src/runtime.cc b/src/runtime.cc index 6cde08227b..a874464aa5 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -16,7 +16,6 @@ #include "oat_file.h" #include "signal_catcher.h" #include "space.h" -#include "stl_util.h" #include "thread.h" #include "thread_list.h" @@ -53,7 +52,6 @@ Runtime::~Runtime() { // Make sure all other non-daemon threads have terminated, and all daemon threads are suspended. delete thread_list_; - STLDeleteElements(&oat_files_); delete class_linker_; Heap::Destroy(); delete intern_table_; @@ -177,22 +175,16 @@ void LoadJniLibrary(JavaVMExt* vm, const char* name) { } } -void CreateClassPath(const std::string& class_path, - std::vector<const DexFile*>& class_path_vector) { - std::vector<std::string> parsed; - Split(class_path, ':', parsed); - for (size_t i = 0; i < parsed.size(); ++i) { - const DexFile* dex_file = DexFile::Open(parsed[i], ""); - if (dex_file != NULL) { - class_path_vector.push_back(dex_file); - } - } -} - Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, bool ignore_unrecognized) { UniquePtr<ParsedOptions> parsed(new ParsedOptions()); - parsed->boot_image_ = NULL; - parsed->boot_oat_ = NULL; + const char* boot_class_path = getenv("BOOTCLASSPATH"); + if (boot_class_path != NULL) { + parsed->boot_class_path_ = getenv("BOOTCLASSPATH"); + } + const char* class_path = getenv("CLASSPATH"); + if (class_path != NULL) { + parsed->class_path_ = getenv("CLASSPATH"); + } #ifdef NDEBUG // -Xcheck:jni is off by default for regular builds... parsed->check_jni_ = false; @@ -211,35 +203,11 @@ Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, b for (size_t i = 0; i < options.size(); ++i) { const StringPiece& option = options[i].first; + if (false) { + LOG(INFO) << "option[" << i << "]=" << option; + } if (option.starts_with("-Xbootclasspath:")) { - parsed->boot_class_path_string_ = option.substr(strlen("-Xbootclasspath:")).data(); - } else if (option == "bootclasspath") { - UNIMPLEMENTED(WARNING) << "what should VMRuntime.getBootClassPath return here?"; - const void* dex_vector = options[i].second; - const std::vector<const DexFile*>* v - = reinterpret_cast<const std::vector<const DexFile*>*>(dex_vector); - if (v == NULL) { - if (ignore_unrecognized) { - continue; - } - // TODO: usage - LOG(FATAL) << "Failed to parse " << option; - return NULL; - } - parsed->boot_class_path_ = *v; - } else if (option == "classpath") { - const void* dex_vector = options[i].second; - const std::vector<const DexFile*>* v - = reinterpret_cast<const std::vector<const DexFile*>*>(dex_vector); - if (v == NULL) { - if (ignore_unrecognized) { - continue; - } - // TODO: usage - LOG(FATAL) << "Failed to parse " << option; - return NULL; - } - parsed->class_path_ = *v; + parsed->boot_class_path_ = option.substr(strlen("-Xbootclasspath:")).data(); } else if (option == "-classpath" || option == "-cp") { // TODO: support -Djava.class.path i++; @@ -249,17 +217,9 @@ Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, b return NULL; } const StringPiece& value = options[i].first; - parsed->class_path_string_ = value.data(); - } else if (option.starts_with("-Xbootimage:")) { - // TODO: remove and just use -Ximage: - parsed->boot_image_ = option.substr(strlen("-Xbootimage:")).data(); - } else if (option.starts_with("-Xbootoat:")) { - // TODO: remove and just use -Xoat: - parsed->boot_oat_ = option.substr(strlen("-Xbootoat:")).data(); + parsed->class_path_ = value.data(); } else if (option.starts_with("-Ximage:")) { parsed->images_.push_back(option.substr(strlen("-Ximage:")).data()); - } else if (option.starts_with("-Xoat:")) { - parsed->oats_.push_back(option.substr(strlen("-Xoat:")).data()); } else if (option.starts_with("-Xcheck:jni")) { parsed->check_jni_ = true; } else if (option.starts_with("-Xms")) { @@ -311,6 +271,8 @@ Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, b parsed->hook_exit_ = reinterpret_cast<void(*)(jint)>(options[i].second); } else if (option == "abort") { parsed->hook_abort_ = reinterpret_cast<void(*)()>(options[i].second); + } else if (option == "host-prefix") { + parsed->host_prefix_ = reinterpret_cast<const char*>(options[i].second); } else { if (!ignore_unrecognized) { // TODO: print usage via vfprintf @@ -321,38 +283,6 @@ Runtime::ParsedOptions* Runtime::ParsedOptions::Create(const Options& options, b } } - // Consider it an error if both bootclasspath and -Xbootclasspath: are supplied. - // TODO: remove bootclasspath and classpath which are mostly just used by tests? - if (!parsed->boot_class_path_.empty() && !parsed->boot_class_path_string_.empty()) { - // TODO: usage - LOG(FATAL) << "bootclasspath and -Xbootclasspath: are mutually exclusive options."; - return NULL; - } - if (!parsed->class_path_.empty() && !parsed->class_path_string_.empty()) { - // TODO: usage - LOG(FATAL) << "bootclasspath and -Xbootclasspath: are mutually exclusive options."; - return NULL; - } - if (parsed->boot_class_path_.empty()) { - if (parsed->boot_class_path_string_ == NULL) { - const char* BOOTCLASSPATH = getenv("BOOTCLASSPATH"); - if (BOOTCLASSPATH != NULL) { - parsed->boot_class_path_string_ = BOOTCLASSPATH; - } - } - CreateClassPath(parsed->boot_class_path_string_, parsed->boot_class_path_); - } - - if (parsed->class_path_.empty()) { - if (parsed->class_path_string_ == NULL) { - const char* CLASSPATH = getenv("CLASSPATH"); - if (CLASSPATH != NULL) { - parsed->class_path_string_ = CLASSPATH; - } - } - CreateClassPath(parsed->class_path_string_, parsed->class_path_); - } - LOG(INFO) << "CheckJNI is " << (parsed->check_jni_ ? "on" : "off"); return parsed.release(); @@ -375,6 +305,9 @@ void Runtime::Start() { if (IsVerboseStartup()) { LOG(INFO) << "Runtime::Start entering"; } + + CHECK(host_prefix_.empty()) << host_prefix_; + InitNativeMethods(); Thread::FinishStartup(); @@ -405,7 +338,7 @@ void Runtime::StartDaemonThreads() { env->CallStaticVoidMethod(c, mid); } -bool Runtime::IsStarted() { +bool Runtime::IsStarted() const { return started_; } @@ -422,8 +355,9 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { LOG(INFO) << "Runtime::Init -verbose:startup enabled"; } - boot_class_path_ = options->boot_class_path_string_; - class_path_ = options->class_path_string_; + host_prefix_ = options->host_prefix_; + boot_class_path_ = options->boot_class_path_; + class_path_ = options->class_path_; properties_ = options->properties_; vfprintf_ = options->hook_vfprintf_; @@ -435,8 +369,7 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { thread_list_ = new ThreadList(options->IsVerbose("thread")); intern_table_ = new InternTable; - Heap::Init(options->heap_initial_size_, options->heap_maximum_size_, - options->boot_image_, options->images_); + Heap::Init(options->heap_initial_size_, options->heap_maximum_size_, options->images_); BlockSignals(); @@ -448,22 +381,10 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { // without creating objects. Thread::Attach(this, "main", false); - class_linker_ = ClassLinker::Create(options->boot_class_path_, - options->class_path_, - intern_table_, - Heap::GetBootSpace() != NULL); - if (Heap::GetBootSpace() != NULL) { - if (!OpenOat(Heap::GetBootSpace(), options->boot_oat_)) { - LOG(ERROR) << "Failed to open boot oat " << options->boot_oat_; - return false; - } - } - for (size_t i = 0; i < options->oats_.size(); i++) { - if (!OpenOat(Heap::GetSpaces()[i+1], options->oats_[i])) { - LOG(ERROR) << "Failed to open oat " << options->oats_[i]; - return false; - } - } + CHECK_GE(Heap::GetSpaces().size(), 1U); + class_linker_ = ((Heap::GetSpaces()[0]->IsImageSpace()) + ? ClassLinker::Create(intern_table_) + : ClassLinker::Create(options->boot_class_path_, intern_table_)); if (IsVerboseStartup()) { LOG(INFO) << "Runtime::Init exiting"; @@ -471,49 +392,6 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { return true; } -bool Runtime::OpenOat(const Space* space, const char* oat) { - if (IsVerboseStartup()) { - LOG(INFO) << "Runtime::OpenOat entering " << oat; - } - // TODO: check in ParsedOptions? - if (space == NULL) { - LOG(ERROR) << "oat specified without image"; - return false; - } - if (oat == NULL) { - LOG(ERROR) << "image specified without oat"; - return false; - } - const ImageHeader& image_header = space->GetImageHeader(); - String* oat_location = image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString(); - std::string oat_filename = oat_location->ToModifiedUtf8(); - if (!StringPiece(oat).ends_with(oat_filename)) { - LOG(ERROR) << "oat file name " << oat - << " does not match value found in image: " << oat_filename; - return false; - } - // TODO: we should be able to just use oat_filename instead of oat - // if we passed the prefix argument to find it on the host during cross compilation. - OatFile* oat_file = OatFile::Open(std::string(oat), "", image_header.GetOatBaseAddr()); - if (oat_file == NULL) { - LOG(ERROR) << "Failed to open oat file " << oat_filename << " referenced from image"; - return false; - } - uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum(); - uint32_t image_oat_checksum = image_header.GetOatChecksum(); - if (oat_checksum != image_oat_checksum) { - LOG(ERROR) << "Failed to match oat filechecksum " << std::hex << oat_checksum - << " to expected oat checksum " << std::hex << oat_checksum - << " in image"; - return false; - } - oat_files_.push_back(oat_file); - if (IsVerboseStartup()) { - LOG(INFO) << "Runtime::OpenOat exiting"; - } - return true; -} - void Runtime::InitNativeMethods() { if (IsVerboseStartup()) { LOG(INFO) << "Runtime::InitNativeMethods entering"; diff --git a/src/runtime.h b/src/runtime.h index bae5643d80..bd2c7a2263 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -30,7 +30,6 @@ class Heap; class InternTable; class JavaVMExt; class Method; -class OatFile; class SignalCatcher; class String; class ThreadList; @@ -45,14 +44,10 @@ class Runtime { // returns null if problem parsing and ignore_unrecognized is false static ParsedOptions* Create(const Options& options, bool ignore_unrecognized); - std::string boot_class_path_string_; - std::vector<const DexFile*> boot_class_path_; - std::string class_path_string_; - std::vector<const DexFile*> class_path_; - const char* boot_image_; - const char* boot_oat_; - std::vector<const char*> images_; - std::vector<const char*> oats_; + std::string boot_class_path_; + std::string class_path_; + std::string host_prefix_; + std::vector<std::string> images_; bool check_jni_; std::string jni_trace_; size_t heap_initial_size_; @@ -79,10 +74,15 @@ class Runtime { return verbose_startup_; } + const std::string& GetHostPrefix() const { + CHECK(!IsStarted()); + return host_prefix_; + } + // Starts a runtime, which may cause threads to be started and code to run. void Start(); - bool IsStarted(); + bool IsStarted() const; static Runtime* Current() { return instance_; @@ -182,13 +182,24 @@ class Runtime { void BlockSignals(); bool Init(const Options& options, bool ignore_unrecognized); - bool OpenOat(const Space* space, const char* boot_oat_); void InitNativeMethods(); void RegisterRuntimeNativeMethods(JNIEnv*); void StartDaemonThreads(); bool verbose_startup_; + // The host prefix is used during cross compilation. It is removed + // from the start of host paths such as: + // $ANDROID_PRODUCT_OUT/system/framework/core.oat + // to produce target paths such as + // /system/framework/core.oat + // Similarly it is prepended to target paths to arrive back at a + // host past. In both cases this is necessary because image and oat + // files embedded expect paths of dependent files (an image points + // to an oat file and an oat files to one or more dex files). These + // files contain the expected target path. + std::string host_prefix_; + std::string boot_class_path_; std::string class_path_; std::vector<std::string> properties_; @@ -202,8 +213,6 @@ class Runtime { ClassLinker* class_linker_; - std::vector<const OatFile*> oat_files_; - SignalCatcher* signal_catcher_; JavaVMExt* java_vm_; diff --git a/src/runtime_test.cc b/src/runtime_test.cc index 66c181b72d..ce03571486 100644 --- a/src/runtime_test.cc +++ b/src/runtime_test.cc @@ -27,7 +27,7 @@ TEST_F(RuntimeTest, ParsedOptions) { options.push_back(std::make_pair(lib_core.c_str(), null)); options.push_back(std::make_pair("-cp", null)); options.push_back(std::make_pair(lib_core.c_str(), null)); - options.push_back(std::make_pair("-Xbootimage:boot_image", null)); + options.push_back(std::make_pair("-Ximage:boot_image", null)); options.push_back(std::make_pair("-Ximage:image_1", null)); options.push_back(std::make_pair("-Ximage:image_2", null)); options.push_back(std::make_pair("-Xcheck:jni", null)); @@ -37,22 +37,24 @@ TEST_F(RuntimeTest, ParsedOptions) { options.push_back(std::make_pair("-Dfoo=bar", null)); options.push_back(std::make_pair("-Dbaz=qux", null)); options.push_back(std::make_pair("-verbose:gc,class,jni", null)); + options.push_back(std::make_pair("host-prefix", "host_prefix")); options.push_back(std::make_pair("vfprintf", test_vfprintf)); options.push_back(std::make_pair("abort", test_abort)); options.push_back(std::make_pair("exit", test_exit)); UniquePtr<Runtime::ParsedOptions> parsed(Runtime::ParsedOptions::Create(options, false)); ASSERT_TRUE(parsed.get() != NULL); - EXPECT_EQ(1U, parsed->boot_class_path_.size()); - EXPECT_EQ(1U, parsed->class_path_.size()); - EXPECT_STREQ("boot_image", parsed->boot_image_); - EXPECT_EQ(2U, parsed->images_.size()); - EXPECT_STREQ("image_1", parsed->images_[0]); - EXPECT_STREQ("image_2", parsed->images_[1]); + EXPECT_EQ(lib_core, parsed->boot_class_path_); + EXPECT_EQ(lib_core, parsed->class_path_); + EXPECT_EQ(3U, parsed->images_.size()); + EXPECT_EQ(std::string("boot_image"), parsed->images_[0]); + EXPECT_EQ(std::string("image_1"), parsed->images_[1]); + EXPECT_EQ(std::string("image_2"), parsed->images_[2]); EXPECT_EQ(true, parsed->check_jni_); EXPECT_EQ(2048U, parsed->heap_initial_size_); EXPECT_EQ(4 * KB, parsed->heap_maximum_size_); EXPECT_EQ(1 * MB, parsed->stack_size_); + EXPECT_EQ("host_prefix", parsed->host_prefix_); EXPECT_TRUE(test_vfprintf == parsed->hook_vfprintf_); EXPECT_TRUE(test_exit == parsed->hook_exit_); EXPECT_TRUE(test_abort == parsed->hook_abort_); diff --git a/src/space.cc b/src/space.cc index 09eb0c9bb9..08d758a108 100644 --- a/src/space.cc +++ b/src/space.cc @@ -24,7 +24,7 @@ Space* Space::Create(size_t initial_size, size_t maximum_size, byte* requested_b } } -Space* Space::CreateFromImage(const char* image_file_name) { +Space* Space::CreateFromImage(const std::string& image_file_name) { CHECK(image_file_name != NULL); UniquePtr<Space> space(new Space()); bool success = space->InitFromImage(image_file_name); @@ -97,13 +97,13 @@ void Space::Init(MemMap* mem_map) { } -bool Space::InitFromImage(const char* image_file_name) { +bool Space::InitFromImage(const std::string& image_file_name) { const Runtime* runtime = Runtime::Current(); if (runtime->IsVerboseStartup()) { LOG(INFO) << "Space::InitFromImage entering" << " image_file_name=" << image_file_name; } - UniquePtr<File> file(OS::OpenFile(image_file_name, false)); + UniquePtr<File> file(OS::OpenFile(image_file_name.c_str(), false)); if (file.get() == NULL) { LOG(WARNING) << "Failed to open " << image_file_name; return false; diff --git a/src/space.h b/src/space.h index 1536c27ae2..1e2a58b3dc 100644 --- a/src/space.h +++ b/src/space.h @@ -23,7 +23,7 @@ class Space { static Space* Create(size_t initial_size, size_t maximum_size, byte* requested_base); // create a Space from an image file. cannot be used for future allocation or collected. - static Space* CreateFromImage(const char* image); + static Space* CreateFromImage(const std::string& image); ~Space(); @@ -51,8 +51,12 @@ class Space { return limit_ - base_; } + bool IsImageSpace() const { + return (image_header_ != NULL); + } + const ImageHeader& GetImageHeader() const { - CHECK(image_header_ != NULL); + CHECK(IsImageSpace()); return *image_header_; } @@ -78,7 +82,7 @@ class Space { void Init(MemMap* map); // Initializes the space from an image file - bool InitFromImage(const char* image_file_name); + bool InitFromImage(const std::string& image_file_name); void* CreateMallocSpace(void* base, size_t initial_size, size_t maximum_size); diff --git a/test/003-omnibus-opcodes/build b/test/003-omnibus-opcodes/build index bbd392f5c4..c3af10c16f 100644 --- a/test/003-omnibus-opcodes/build +++ b/test/003-omnibus-opcodes/build @@ -26,10 +26,8 @@ dx -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex classes zip ${ANDROID_PRODUCT_OUT}/system/framework/test.jar classes.dex dex2oatd -Xms16m -Xmx16m \ - --boot-dex-file=${ANDROID_PRODUCT_OUT}/system/framework/core.jar \ - --boot-oat=${ANDROID_PRODUCT_OUT}/system/framework/core.oat \ --boot-image=${ANDROID_PRODUCT_OUT}/system/framework/core.art \ --dex-file=${ANDROID_PRODUCT_OUT}/system/framework/test.jar \ --oat=${ANDROID_PRODUCT_OUT}/system/framework/test.oat \ --image=${ANDROID_PRODUCT_OUT}/system/framework/test.art \ - --strip-prefix=${ANDROID_PRODUCT_OUT} + --host-prefix=${ANDROID_PRODUCT_OUT} diff --git a/test/023-many-interfaces/build b/test/023-many-interfaces/build index 118e178031..d0f376c2bc 100644 --- a/test/023-many-interfaces/build +++ b/test/023-many-interfaces/build @@ -28,10 +28,8 @@ dx --debug --dex --dump-to=classes.lst --output=classes.dex classes zip ${ANDROID_PRODUCT_OUT}/system/framework/test.jar classes.dex dex2oatd -Xms16m -Xmx16m \ - --boot-dex-file=${ANDROID_PRODUCT_OUT}/system/framework/core.jar \ - --boot-oat=${ANDROID_PRODUCT_OUT}/system/framework/core.oat \ --boot-image=${ANDROID_PRODUCT_OUT}/system/framework/core.art \ --dex-file=${ANDROID_PRODUCT_OUT}/system/framework/test.jar \ --oat=${ANDROID_PRODUCT_OUT}/system/framework/test.oat \ --image=${ANDROID_PRODUCT_OUT}/system/framework/test.art \ - --strip-prefix=${ANDROID_PRODUCT_OUT} + --host-prefix=${ANDROID_PRODUCT_OUT} diff --git a/test/056-const-string-jumbo/build b/test/056-const-string-jumbo/build index c39779b268..a780c1396f 100644 --- a/test/056-const-string-jumbo/build +++ b/test/056-const-string-jumbo/build @@ -47,10 +47,8 @@ dx -JXmx500m --debug --dex --no-optimize --positions=none --no-locals \ zip ${ANDROID_PRODUCT_OUT}/system/framework/test.jar classes.dex dex2oatd -Xms16m -Xmx16m \ - --boot-dex-file=${ANDROID_PRODUCT_OUT}/system/framework/core.jar \ - --boot-oat=${ANDROID_PRODUCT_OUT}/system/framework/core.oat \ --boot-image=${ANDROID_PRODUCT_OUT}/system/framework/core.art \ --dex-file=${ANDROID_PRODUCT_OUT}/system/framework/test.jar \ --oat=${ANDROID_PRODUCT_OUT}/system/framework/test.oat \ --image=${ANDROID_PRODUCT_OUT}/system/framework/test.art \ - --strip-prefix=${ANDROID_PRODUCT_OUT} + --host-prefix=${ANDROID_PRODUCT_OUT} diff --git a/test/085-old-style-inner-class/build b/test/085-old-style-inner-class/build index 5a1b04c916..d3dc15f992 100644 --- a/test/085-old-style-inner-class/build +++ b/test/085-old-style-inner-class/build @@ -29,10 +29,8 @@ dx --debug --dex --dump-to=classes.lst --output=classes.dex \ zip ${ANDROID_PRODUCT_OUT}/system/framework/test.jar classes.dex dex2oatd -Xms16m -Xmx16m \ - --boot-dex-file=${ANDROID_PRODUCT_OUT}/system/framework/core.jar \ - --boot-oat=${ANDROID_PRODUCT_OUT}/system/framework/core.oat \ --boot-image=${ANDROID_PRODUCT_OUT}/system/framework/core.art \ --dex-file=${ANDROID_PRODUCT_OUT}/system/framework/test.jar \ --oat=${ANDROID_PRODUCT_OUT}/system/framework/test.oat \ --image=${ANDROID_PRODUCT_OUT}/system/framework/test.art \ - --strip-prefix=${ANDROID_PRODUCT_OUT} + --host-prefix=${ANDROID_PRODUCT_OUT} diff --git a/test/etc/default-build b/test/etc/default-build index e31e0ead3c..0ef8ba802a 100755 --- a/test/etc/default-build +++ b/test/etc/default-build @@ -29,13 +29,11 @@ dx -JXmx256m --debug --dex --dump-to=classes.lst --output=classes.dex \ zip ${ANDROID_PRODUCT_OUT}/system/framework/test.jar classes.dex dex2oatd -Xms16m -Xmx16m \ - --boot-dex-file=${ANDROID_PRODUCT_OUT}/system/framework/core.jar \ - --boot-oat=${ANDROID_PRODUCT_OUT}/system/framework/core.oat \ --boot-image=${ANDROID_PRODUCT_OUT}/system/framework/core.art \ --dex-file=${ANDROID_PRODUCT_OUT}/system/framework/test.jar \ --oat=${ANDROID_PRODUCT_OUT}/system/framework/test.oat \ --image=${ANDROID_PRODUCT_OUT}/system/framework/test.art \ - --strip-prefix=${ANDROID_PRODUCT_OUT} + --host-prefix=${ANDROID_PRODUCT_OUT} if [ -r src-ex ]; then mkdir classes-ex @@ -51,11 +49,9 @@ if [ -r src-ex ]; then mv classes-1.dex classes.dex dex2oatd -Xms16m -Xmx16m \ - --boot-dex-file=${ANDROID_PRODUCT_OUT}/system/framework/core.jar \ - --boot-oat=${ANDROID_PRODUCT_OUT}/system/framework/core.oat \ --boot-image=${ANDROID_PRODUCT_OUT}/system/framework/core.art \ --dex-file=${ANDROID_PRODUCT_OUT}/system/framework/test-ex.jar \ --oat=${ANDROID_PRODUCT_OUT}/system/framework/test-ex.oat \ --image=${ANDROID_PRODUCT_OUT}/system/framework/test-ex.art \ - --strip-prefix=${ANDROID_PRODUCT_OUT} + --host-prefix=${ANDROID_PRODUCT_OUT} fi diff --git a/test/etc/push-and-run-test-jar b/test/etc/push-and-run-test-jar index fd96b6b735..0d4e3b4555 100755 --- a/test/etc/push-and-run-test-jar +++ b/test/etc/push-and-run-test-jar @@ -135,11 +135,7 @@ if [ "$ZYGOTE" = "y" ]; then adb shell cd /data \; dvz -classpath test.jar Main "$@" else cmdline="cd /data; oatexecd \ - -Xbootclasspath:/system/framework/core.jar \ - -Xbootoat:/system/framework/core.oat \ - -Xbootimage:/system/framework/core.art \ - -classpath /system/framework/test.jar \ - -Xoat:/system/framework/test.oat \ + -Ximage:/system/framework/core.art \ -Ximage:/system/framework/test.art Main" #cmdline="cd /data; dalvikvm $DEX_VERIFY $DEX_OPTIMIZE $DEX_DEBUG \ # $GC_OPTS -cp test.jar -Xint:${INTERP} -ea Main" |