diff options
author | Narayan Kamath <narayan@google.com> | 2014-04-23 20:24:57 +0100 |
---|---|---|
committer | Narayan Kamath <narayan@google.com> | 2014-05-01 11:25:07 +0100 |
commit | 11d9f06a96a6909905c248ed684366190140095c (patch) | |
tree | 27b02ab216b98ba1656d66072fd46c5adec61242 | |
parent | b3016551e5f264264dbb633a1ddf03ac97f9c66c (diff) | |
download | art-11d9f06a96a6909905c248ed684366190140095c.zip art-11d9f06a96a6909905c248ed684366190140095c.tar.gz art-11d9f06a96a6909905c248ed684366190140095c.tar.bz2 |
Use instruction specific dalvik cache dirs.
- All oat & art files are now placed under /data/dalvik-cache/<isa>/.
- GetDalvikCacheOrDie now requires a mandatory subdirectory argument,
and is implicitly rooted under /data/.
- Added helper methods to convert InstructionSet enums into strings
and vice versa.
(cherry picked from commit 2974bc3d8a5d161d449dd66826d668d87bdc3cbe)
Change-Id: Ic7986938e6a7091a2af675ebafec768f7b5fb8cd
-rw-r--r-- | build/Android.gtest.mk | 1 | ||||
-rw-r--r-- | compiler/llvm/llvm_compilation_unit.cc | 2 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 3 | ||||
-rw-r--r-- | runtime/class_linker.cc | 4 | ||||
-rw-r--r-- | runtime/gc/heap.cc | 5 | ||||
-rw-r--r-- | runtime/gc/heap.h | 2 | ||||
-rw-r--r-- | runtime/gc/space/image_space.cc | 8 | ||||
-rw-r--r-- | runtime/gc/space/image_space.h | 8 | ||||
-rw-r--r-- | runtime/instruction_set.cc | 42 | ||||
-rw-r--r-- | runtime/instruction_set.h | 3 | ||||
-rw-r--r-- | runtime/instruction_set_test.cc | 48 | ||||
-rw-r--r-- | runtime/native/dalvik_system_DexFile.cc | 84 | ||||
-rw-r--r-- | runtime/parsed_options.cc | 6 | ||||
-rw-r--r-- | runtime/parsed_options.h | 1 | ||||
-rw-r--r-- | runtime/runtime.cc | 1 | ||||
-rw-r--r-- | runtime/utils.cc | 25 | ||||
-rw-r--r-- | runtime/utils.h | 13 | ||||
-rw-r--r-- | runtime/utils_test.cc | 20 |
18 files changed, 205 insertions, 71 deletions
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk index f25217f..429c523 100644 --- a/build/Android.gtest.mk +++ b/build/Android.gtest.mk @@ -49,6 +49,7 @@ RUNTIME_GTEST_COMMON_SRC_FILES := \ runtime/gtest_test.cc \ runtime/indenter_test.cc \ runtime/indirect_reference_table_test.cc \ + runtime/instruction_set_test.cc \ runtime/intern_table_test.cc \ runtime/leb128_test.cc \ runtime/mem_map_test.cc \ diff --git a/compiler/llvm/llvm_compilation_unit.cc b/compiler/llvm/llvm_compilation_unit.cc index fe60959..78bdb4d 100644 --- a/compiler/llvm/llvm_compilation_unit.cc +++ b/compiler/llvm/llvm_compilation_unit.cc @@ -143,7 +143,7 @@ InstructionSet LlvmCompilationUnit::GetInstructionSet() const { static std::string DumpDirectory() { if (kIsTargetBuild) { - return GetDalvikCacheOrDie(GetAndroidData()); + return GetDalvikCacheOrDie("llvm-dump"); } return "/tmp"; } diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index d3e56da..823b818 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -1101,6 +1101,9 @@ static int dex2oat(int argc, char** argv) { DexFileToMethodInlinerMap method_inliner_map; CompilerCallbacksImpl callbacks(&verification_results, &method_inliner_map); runtime_options.push_back(std::make_pair("compilercallbacks", &callbacks)); + runtime_options.push_back( + std::make_pair("imageinstructionset", + reinterpret_cast<const void*>(GetInstructionSetString(instruction_set)))); Dex2Oat* p_dex2oat; if (!Dex2Oat::Create(&p_dex2oat, diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 583e5e5..c9e3c11 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -919,7 +919,9 @@ const DexFile* ClassLinker::FindDexFileInOatFileFromDexLocation(const char* dex_ } std::string cache_error_msg; - std::string cache_location(GetDalvikCacheFilenameOrDie(dex_location)); + const std::string dalvik_cache(GetDalvikCacheOrDie(GetInstructionSetString(kRuntimeISA))); + std::string cache_location(GetDalvikCacheFilenameOrDie(dex_location, + dalvik_cache.c_str())); dex_file = VerifyAndOpenDexFileFromOatFile(cache_location, dex_location, &cache_error_msg, &open_failed); if (dex_file != nullptr) { diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 4d074f1..50ef7a6 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -89,7 +89,7 @@ static constexpr size_t kNonMovingSpaceCapacity = 64 * MB; Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max_free, double target_utilization, double foreground_heap_growth_multiplier, size_t capacity, - const std::string& image_file_name, + const std::string& image_file_name, const InstructionSet image_instruction_set, CollectorType foreground_collector_type, CollectorType background_collector_type, size_t parallel_gc_threads, size_t conc_gc_threads, bool low_memory_mode, size_t long_pause_log_threshold, size_t long_gc_log_threshold, @@ -186,7 +186,8 @@ Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max // Requested begin for the alloc space, to follow the mapped image and oat files byte* requested_alloc_space_begin = nullptr; if (!image_file_name.empty()) { - space::ImageSpace* image_space = space::ImageSpace::Create(image_file_name.c_str()); + space::ImageSpace* image_space = space::ImageSpace::Create(image_file_name.c_str(), + image_instruction_set); CHECK(image_space != nullptr) << "Failed to create space for " << image_file_name; AddSpace(image_space); // Oat files referenced by image files immediately follow them in memory, ensure alloc space diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index c631372..5533f3d 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h @@ -31,6 +31,7 @@ #include "gc/collector_type.h" #include "globals.h" #include "gtest/gtest.h" +#include "instruction_set.h" #include "jni.h" #include "object_callbacks.h" #include "offsets.h" @@ -140,6 +141,7 @@ class Heap { size_t max_free, double target_utilization, double foreground_heap_growth_multiplier, size_t capacity, const std::string& original_image_file_name, + const InstructionSet image_instruction_set, CollectorType foreground_collector_type, CollectorType background_collector_type, size_t parallel_gc_threads, size_t conc_gc_threads, bool low_memory_mode, size_t long_pause_threshold, size_t long_gc_threshold, diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 91d8820..3de1ba4 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -24,7 +24,6 @@ #include "mirror/object-inl.h" #include "oat_file.h" #include "os.h" -#include "runtime.h" #include "space-inl.h" #include "utils.h" @@ -99,7 +98,8 @@ static bool GenerateImage(const std::string& image_file_name, std::string* error return Exec(arg_vector, error_msg); } -ImageSpace* ImageSpace::Create(const char* original_image_file_name) { +ImageSpace* ImageSpace::Create(const char* original_image_file_name, + const InstructionSet image_isa) { if (OS::FileExists(original_image_file_name)) { // If the /system file exists, it should be up-to-date, don't try to generate std::string error_msg; @@ -112,7 +112,9 @@ ImageSpace* ImageSpace::Create(const char* original_image_file_name) { // If the /system file didn't exist, we need to use one from the dalvik-cache. // If the cache file exists, try to open, but if it fails, regenerate. // If it does not exist, generate. - std::string image_file_name(GetDalvikCacheFilenameOrDie(original_image_file_name)); + const std::string dalvik_cache = GetDalvikCacheOrDie(GetInstructionSetString(image_isa)); + std::string image_file_name(GetDalvikCacheFilenameOrDie(original_image_file_name, + dalvik_cache.c_str())); std::string error_msg; if (OS::FileExists(image_file_name.c_str())) { space::ImageSpace* image_space = ImageSpace::Init(image_file_name.c_str(), true, &error_msg); diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h index f6daf89..1652ec9 100644 --- a/runtime/gc/space/image_space.h +++ b/runtime/gc/space/image_space.h @@ -18,6 +18,7 @@ #define ART_RUNTIME_GC_SPACE_IMAGE_SPACE_H_ #include "gc/accounting/space_bitmap.h" +#include "runtime.h" #include "space.h" namespace art { @@ -34,15 +35,16 @@ class ImageSpace : public MemMapSpace { return kSpaceTypeImageSpace; } - // Create a Space from an image file. Cannot be used for future - // allocation or collected. + // Create a Space from an image file for a specified instruction + // set. Cannot be used for future allocation or collected. // // Create also opens the OatFile associated with the image file so // that it be contiguously allocated with the image before the // creation of the alloc space. The ReleaseOatFile will later be // used to transfer ownership of the OatFile to the ClassLinker when // it is initialized. - static ImageSpace* Create(const char* image) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + static ImageSpace* Create(const char* image, const InstructionSet image_isa) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); // Releases the OatFile from the ImageSpace so it can be transfer to // the caller, presumably the ClassLinker. diff --git a/runtime/instruction_set.cc b/runtime/instruction_set.cc index 73d4279..cbcd2e0 100644 --- a/runtime/instruction_set.cc +++ b/runtime/instruction_set.cc @@ -21,6 +21,48 @@ namespace art { +const char* GetInstructionSetString(const InstructionSet isa) { + switch (isa) { + case kArm: + case kThumb2: + return "arm"; + case kArm64: + return "arm64"; + case kX86: + return "x86"; + case kX86_64: + return "x86_64"; + case kMips: + return "mips"; + case kNone: + return "none"; + default: + LOG(FATAL) << "Unknown ISA " << isa; + return nullptr; + } +} + +InstructionSet GetInstructionSetFromString(const char* isa_str) { + CHECK(isa_str != nullptr); + + if (!strcmp("arm", isa_str)) { + return kArm; + } else if (!strcmp("arm64", isa_str)) { + return kArm64; + } else if (!strcmp("x86", isa_str)) { + return kX86; + } else if (!strcmp("x86_64", isa_str)) { + return kX86_64; + } else if (!strcmp("mips", isa_str)) { + return kMips; + } else if (!strcmp("none", isa_str)) { + return kNone; + } + + LOG(FATAL) << "Unknown ISA " << isa_str; + return kNone; +} + size_t GetInstructionSetPointerSize(InstructionSet isa) { switch (isa) { case kArm: diff --git a/runtime/instruction_set.h b/runtime/instruction_set.h index c746e06..4bc35a7 100644 --- a/runtime/instruction_set.h +++ b/runtime/instruction_set.h @@ -35,6 +35,9 @@ enum InstructionSet { }; std::ostream& operator<<(std::ostream& os, const InstructionSet& rhs); +const char* GetInstructionSetString(const InstructionSet isa); +InstructionSet GetInstructionSetFromString(const char* instruction_set); + size_t GetInstructionSetPointerSize(InstructionSet isa); size_t GetInstructionSetAlignment(InstructionSet isa); bool Is64BitInstructionSet(InstructionSet isa); diff --git a/runtime/instruction_set_test.cc b/runtime/instruction_set_test.cc new file mode 100644 index 0000000..cd6337c --- /dev/null +++ b/runtime/instruction_set_test.cc @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2014 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 "instruction_set.h" + +#include "common_runtime_test.h" + +namespace art { + +class InstructionSetTest : public CommonRuntimeTest {}; + +TEST_F(InstructionSetTest, GetInstructionSetFromString) { + EXPECT_EQ(kArm, GetInstructionSetFromString("arm")); + EXPECT_EQ(kArm64, GetInstructionSetFromString("arm64")); + EXPECT_EQ(kX86, GetInstructionSetFromString("x86")); + EXPECT_EQ(kX86_64, GetInstructionSetFromString("x86_64")); + EXPECT_EQ(kMips, GetInstructionSetFromString("mips")); + EXPECT_EQ(kNone, GetInstructionSetFromString("none")); +} + +TEST_F(InstructionSetTest, GetInstructionSetString) { + EXPECT_STREQ("arm", GetInstructionSetString(kArm)); + EXPECT_STREQ("arm", GetInstructionSetString(kThumb2)); + EXPECT_STREQ("arm64", GetInstructionSetString(kArm64)); + EXPECT_STREQ("x86", GetInstructionSetString(kX86)); + EXPECT_STREQ("x86_64", GetInstructionSetString(kX86_64)); + EXPECT_STREQ("mips", GetInstructionSetString(kMips)); + EXPECT_STREQ("none", GetInstructionSetString(kNone)); +} + +TEST_F(InstructionSetTest, TestRoundTrip) { + EXPECT_EQ(kRuntimeISA, GetInstructionSetFromString(GetInstructionSetString(kRuntimeISA))); +} + +} // namespace art diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index 953d3a6..d9c1309 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -260,16 +260,15 @@ static double GetDoubleProperty(const char* property, double minValue, double ma #endif } -static jboolean DexFile_isDexOptNeededInternal(JNIEnv* env, jclass, jstring javaFilename, - jstring javaPkgname, jboolean defer) { +static jboolean IsDexOptNeededInternal(JNIEnv* env, const char* filename, + const char* pkgname, const char* instruction_set, const jboolean defer) { const bool kVerboseLogging = false; // Spammy logging. const bool kReasonLogging = true; // Logging of reason for returning JNI_TRUE. - ScopedUtfChars filename(env, javaFilename); - if ((filename.c_str() == nullptr) || !OS::FileExists(filename.c_str())) { - LOG(ERROR) << "DexFile_isDexOptNeeded file '" << filename.c_str() << "' does not exist"; + if ((filename == nullptr) || !OS::FileExists(filename)) { + LOG(ERROR) << "DexFile_isDexOptNeeded file '" << filename << "' does not exist"; ScopedLocalRef<jclass> fnfe(env, env->FindClass("java/io/FileNotFoundException")); - const char* message = (filename.c_str() == nullptr) ? "<empty file name>" : filename.c_str(); + const char* message = (filename == nullptr) ? "<empty file name>" : filename; env->ThrowNew(fnfe.get(), message); return JNI_FALSE; } @@ -278,11 +277,14 @@ static jboolean DexFile_isDexOptNeededInternal(JNIEnv* env, jclass, jstring java // fact that code is running at all means that this should be true. Runtime* runtime = Runtime::Current(); ClassLinker* class_linker = runtime->GetClassLinker(); + // TODO: We're assuming that the 64 and 32 bit runtimes have identical + // class paths. isDexOptNeeded will not necessarily be called on a runtime + // that has the same instruction set as the file being dexopted. const std::vector<const DexFile*>& boot_class_path = class_linker->GetBootClassPath(); for (size_t i = 0; i < boot_class_path.size(); i++) { - if (boot_class_path[i]->GetLocation() == filename.c_str()) { + if (boot_class_path[i]->GetLocation() == filename) { if (kVerboseLogging) { - LOG(INFO) << "DexFile_isDexOptNeeded ignoring boot class path file: " << filename.c_str(); + LOG(INFO) << "DexFile_isDexOptNeeded ignoring boot class path file: " << filename; } return JNI_FALSE; } @@ -293,12 +295,11 @@ static jboolean DexFile_isDexOptNeededInternal(JNIEnv* env, jclass, jstring java // If the 'defer' argument is true then this will be retried later. In this case we // need to make sure that the profile file copy is not made so that we will get the // same result second time. - if (javaPkgname != NULL) { - ScopedUtfChars pkgname(env, javaPkgname); - std::string profile_file = GetDalvikCacheOrDie(GetAndroidData()) + std::string("/profiles/") + - pkgname.c_str(); - - std::string profile_cache_dir = GetDalvikCacheOrDie(GetAndroidData()) + "/profile-cache"; + if (pkgname != nullptr) { + const std::string profile_file = GetDalvikCacheOrDie("profiles", false /* create_if_absent */) + + std::string("/") + pkgname; + const std::string profile_cache_dir = GetDalvikCacheOrDie("profile-cache", + false /* create_if_absent */); // Make the profile cache if it doesn't exist. mkdir(profile_cache_dir.c_str(), 0700); @@ -306,7 +307,7 @@ static jboolean DexFile_isDexOptNeededInternal(JNIEnv* env, jclass, jstring java // The previous profile file (a copy of the profile the last time this was run) is // in the dalvik-cache directory because this is owned by system. The profiles // directory is owned by install so system cannot write files in there. - std::string prev_profile_file = profile_cache_dir + std::string("/") + pkgname.c_str(); + std::string prev_profile_file = profile_cache_dir + std::string("/") + pkgname; struct stat profstat, prevstat; int e1 = stat(profile_file.c_str(), &profstat); @@ -377,41 +378,41 @@ static jboolean DexFile_isDexOptNeededInternal(JNIEnv* env, jclass, jstring java } // Check if we have an odex file next to the dex file. - std::string odex_filename(OatFile::DexFilenameToOdexFilename(filename.c_str())); + std::string odex_filename(OatFile::DexFilenameToOdexFilename(filename)); std::string error_msg; UniquePtr<const OatFile> oat_file(OatFile::Open(odex_filename, odex_filename, NULL, false, &error_msg)); if (oat_file.get() == nullptr) { if (kVerboseLogging) { - LOG(INFO) << "DexFile_isDexOptNeeded failed to open oat file '" << filename.c_str() + LOG(INFO) << "DexFile_isDexOptNeeded failed to open oat file '" << filename << "': " << error_msg; } error_msg.clear(); } else { - const art::OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(filename.c_str(), NULL, + const art::OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(filename, NULL, kReasonLogging); if (oat_dex_file != nullptr) { uint32_t location_checksum; // If its not possible to read the classes.dex assume up-to-date as we won't be able to // compile it anyway. - if (!DexFile::GetChecksum(filename.c_str(), &location_checksum, &error_msg)) { + if (!DexFile::GetChecksum(filename, &location_checksum, &error_msg)) { if (kVerboseLogging) { LOG(INFO) << "DexFile_isDexOptNeeded ignoring precompiled stripped file: " - << filename.c_str() << ": " << error_msg; + << filename << ": " << error_msg; } return JNI_FALSE; } - if (ClassLinker::VerifyOatFileChecksums(oat_file.get(), filename.c_str(), location_checksum, + if (ClassLinker::VerifyOatFileChecksums(oat_file.get(), filename, location_checksum, &error_msg)) { if (kVerboseLogging) { LOG(INFO) << "DexFile_isDexOptNeeded precompiled file " << odex_filename - << " has an up-to-date checksum compared to " << filename.c_str(); + << " has an up-to-date checksum compared to " << filename; } return JNI_FALSE; } else { if (kVerboseLogging) { LOG(INFO) << "DexFile_isDexOptNeeded found precompiled file " << odex_filename - << " with an out-of-date checksum compared to " << filename.c_str() + << " with an out-of-date checksum compared to " << filename << ": " << error_msg; } error_msg.clear(); @@ -420,12 +421,14 @@ static jboolean DexFile_isDexOptNeededInternal(JNIEnv* env, jclass, jstring java } // Check if we have an oat file in the cache - std::string cache_location(GetDalvikCacheFilenameOrDie(filename.c_str())); - oat_file.reset(OatFile::Open(cache_location, filename.c_str(), NULL, false, &error_msg)); + const std::string cache_dir(GetDalvikCacheOrDie(instruction_set)); + const std::string cache_location( + GetDalvikCacheFilenameOrDie(filename, cache_dir.c_str())); + oat_file.reset(OatFile::Open(cache_location, filename, NULL, false, &error_msg)); if (oat_file.get() == nullptr) { if (kReasonLogging) { LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location - << " does not exist for " << filename.c_str() << ": " << error_msg; + << " does not exist for " << filename << ": " << error_msg; } return JNI_TRUE; } @@ -458,19 +461,19 @@ static jboolean DexFile_isDexOptNeededInternal(JNIEnv* env, jclass, jstring java } uint32_t location_checksum; - if (!DexFile::GetChecksum(filename.c_str(), &location_checksum, &error_msg)) { + if (!DexFile::GetChecksum(filename, &location_checksum, &error_msg)) { if (kReasonLogging) { - LOG(ERROR) << "DexFile_isDexOptNeeded failed to compute checksum of " << filename.c_str() + LOG(ERROR) << "DexFile_isDexOptNeeded failed to compute checksum of " << filename << " (error " << error_msg << ")"; } return JNI_TRUE; } - if (!ClassLinker::VerifyOatFileChecksums(oat_file.get(), filename.c_str(), location_checksum, + if (!ClassLinker::VerifyOatFileChecksums(oat_file.get(), filename, location_checksum, &error_msg)) { if (kReasonLogging) { LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location - << " has out-of-date checksum compared to " << filename.c_str() + << " has out-of-date checksum compared to " << filename << " (error " << error_msg << ")"; } return JNI_TRUE; @@ -478,15 +481,28 @@ static jboolean DexFile_isDexOptNeededInternal(JNIEnv* env, jclass, jstring java if (kVerboseLogging) { LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location - << " is up-to-date for " << filename.c_str(); + << " is up-to-date for " << filename; } CHECK(error_msg.empty()) << error_msg; return JNI_FALSE; } +static jboolean DexFile_isDexOptNeededInternal(JNIEnv* env, jclass, jstring javaFilename, + jstring javaPkgname, jstring javaInstructionSet, jboolean defer) { + ScopedUtfChars filename(env, javaFilename); + NullableScopedUtfChars pkgname(env, javaPkgname); + ScopedUtfChars instruction_set(env, javaInstructionSet); + + return IsDexOptNeededInternal(env, filename.c_str(), pkgname.c_str(), + instruction_set.c_str(), defer); +} + // public API, NULL pkgname -static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass c, jstring javaFilename) { - return DexFile_isDexOptNeededInternal(env, c, javaFilename, NULL, false); +static jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename) { + const char* instruction_set = GetInstructionSetString(kRuntimeISA); + ScopedUtfChars filename(env, javaFilename); + return IsDexOptNeededInternal(env, filename.c_str(), nullptr /* pkgname */, + instruction_set, false /* defer */); } @@ -495,7 +511,7 @@ static JNINativeMethod gMethods[] = { NATIVE_METHOD(DexFile, defineClassNative, "(Ljava/lang/String;Ljava/lang/ClassLoader;J)Ljava/lang/Class;"), NATIVE_METHOD(DexFile, getClassNameList, "(J)[Ljava/lang/String;"), NATIVE_METHOD(DexFile, isDexOptNeeded, "(Ljava/lang/String;)Z"), - NATIVE_METHOD(DexFile, isDexOptNeededInternal, "(Ljava/lang/String;Ljava/lang/String;Z)Z"), + NATIVE_METHOD(DexFile, isDexOptNeededInternal, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)Z"), NATIVE_METHOD(DexFile, openDexFileNative, "(Ljava/lang/String;Ljava/lang/String;I)J"), }; diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index c0dc94b..9cf8785 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -246,6 +246,7 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni profile_clock_source_ = kDefaultProfilerClockSource; verify_ = true; + image_isa_ = kRuntimeISA; // Default to explicit checks. Switch off with -implicit-checks:. // or setprop dalvik.vm.implicit_checks check1,check2,... @@ -412,6 +413,9 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni } else if (option == "compilercallbacks") { compiler_callbacks_ = reinterpret_cast<CompilerCallbacks*>(const_cast<void*>(options[i].second)); + } else if (option == "imageinstructionset") { + image_isa_ = GetInstructionSetFromString( + reinterpret_cast<const char*>(options[i].second)); } else if (option == "-Xzygote") { is_zygote_ = true; } else if (option == "-Xint") { @@ -673,7 +677,7 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni background_collector_type_ = collector_type_; } return true; -} +} // NOLINT(readability/fn_size) void ParsedOptions::Exit(int status) { hook_exit_(status); diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h index c02eb1d..e0b0fb5 100644 --- a/runtime/parsed_options.h +++ b/runtime/parsed_options.h @@ -85,6 +85,7 @@ class ParsedOptions { bool profile_start_immediately_; ProfilerClockSource profile_clock_source_; bool verify_; + InstructionSet image_isa_; static constexpr uint32_t kExplicitNullCheck = 1; static constexpr uint32_t kExplicitSuspendCheck = 2; diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 6bbfcee..20df78e 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -567,6 +567,7 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { options->foreground_heap_growth_multiplier_, options->heap_maximum_size_, options->image_, + options->image_isa_, options->collector_type_, options->background_collector_type_, options->parallel_gc_threads_, diff --git a/runtime/utils.cc b/runtime/utils.cc index c4d1a78..a0ecb41 100644 --- a/runtime/utils.cc +++ b/runtime/utils.cc @@ -1167,14 +1167,20 @@ const char* GetAndroidData() { return android_data; } -std::string GetDalvikCacheOrDie(const char* android_data) { - std::string dalvik_cache(StringPrintf("%s/dalvik-cache", android_data)); - - if (!OS::DirectoryExists(dalvik_cache.c_str())) { - if (StartsWith(dalvik_cache, "/tmp/")) { - int result = mkdir(dalvik_cache.c_str(), 0700); +std::string GetDalvikCacheOrDie(const char* subdir, const bool create_if_absent) { + CHECK(subdir != nullptr); + const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", GetAndroidData())); + const std::string dalvik_cache = dalvik_cache_root + subdir; + if (create_if_absent && !OS::DirectoryExists(dalvik_cache.c_str())) { + if (StartsWith(dalvik_cache_root, "/tmp/")) { + int result = mkdir(dalvik_cache_root.c_str(), 0700); + if (result != 0) { + PLOG(FATAL) << "Failed to create dalvik-cache directory " << dalvik_cache_root; + return ""; + } + result = mkdir(dalvik_cache.c_str(), 0700); if (result != 0) { - LOG(FATAL) << "Failed to create dalvik-cache directory " << dalvik_cache; + PLOG(FATAL) << "Failed to create dalvik-cache directory " << dalvik_cache; return ""; } } else { @@ -1185,8 +1191,7 @@ std::string GetDalvikCacheOrDie(const char* android_data) { return dalvik_cache; } -std::string GetDalvikCacheFilenameOrDie(const char* location) { - std::string dalvik_cache(GetDalvikCacheOrDie(GetAndroidData())); +std::string GetDalvikCacheFilenameOrDie(const char* location, const char* cache_location) { if (location[0] != '/') { LOG(FATAL) << "Expected path in location to be absolute: "<< location; } @@ -1196,7 +1201,7 @@ std::string GetDalvikCacheFilenameOrDie(const char* location) { cache_file += DexFile::kClassesDex; } std::replace(cache_file.begin(), cache_file.end(), '/', '@'); - return dalvik_cache + "/" + cache_file; + return StringPrintf("%s/%s", cache_location, cache_file.c_str()); } bool IsZipMagic(uint32_t magic) { diff --git a/runtime/utils.h b/runtime/utils.h index 6ab1013..4b2f230 100644 --- a/runtime/utils.h +++ b/runtime/utils.h @@ -394,11 +394,14 @@ const char* GetAndroidRoot(); // Find $ANDROID_DATA, /data, or abort. const char* GetAndroidData(); -// Returns the dalvik-cache location, or dies trying. -std::string GetDalvikCacheOrDie(const char* android_data); - -// Returns the dalvik-cache location for a DexFile or OatFile, or dies trying. -std::string GetDalvikCacheFilenameOrDie(const char* location); +// Returns the dalvik-cache location, or dies trying. subdir will be +// appended to the cache location. +std::string GetDalvikCacheOrDie(const char* subdir, bool create_if_absent = true); + +// Returns the absolute dalvik-cache path for a DexFile or OatFile, or +// dies trying. The path returned will be rooted at cache_location. +std::string GetDalvikCacheFilenameOrDie(const char* file_location, + const char* cache_location); // Check whether the given magic matches a known file type. bool IsZipMagic(uint32_t magic); diff --git a/runtime/utils_test.cc b/runtime/utils_test.cc index 2c1aae8..d425620 100644 --- a/runtime/utils_test.cc +++ b/runtime/utils_test.cc @@ -338,18 +338,16 @@ TEST_F(UtilsTest, EndsWith) { EXPECT_FALSE(EndsWith("oo", "foo")); } -void CheckGetDalvikCacheFilenameOrDie(const char* in, const char* out) { - std::string expected(getenv("ANDROID_DATA")); - expected += "/dalvik-cache/"; - expected += out; - EXPECT_STREQ(expected.c_str(), GetDalvikCacheFilenameOrDie(in).c_str()); -} - TEST_F(UtilsTest, GetDalvikCacheFilenameOrDie) { - CheckGetDalvikCacheFilenameOrDie("/system/app/Foo.apk", "system@app@Foo.apk@classes.dex"); - CheckGetDalvikCacheFilenameOrDie("/data/app/foo-1.apk", "data@app@foo-1.apk@classes.dex"); - CheckGetDalvikCacheFilenameOrDie("/system/framework/core.jar", "system@framework@core.jar@classes.dex"); - CheckGetDalvikCacheFilenameOrDie("/system/framework/boot.art", "system@framework@boot.art"); + EXPECT_STREQ("/foo/system@app@Foo.apk@classes.dex", + GetDalvikCacheFilenameOrDie("/system/app/Foo.apk", "/foo").c_str()); + + EXPECT_STREQ("/foo/data@app@foo-1.apk@classes.dex", + GetDalvikCacheFilenameOrDie("/data/app/foo-1.apk", "/foo").c_str()); + EXPECT_STREQ("/foo/system@framework@core.jar@classes.dex", + GetDalvikCacheFilenameOrDie("/system/framework/core.jar", "/foo").c_str()); + EXPECT_STREQ("/foo/system@framework@boot.art", + GetDalvikCacheFilenameOrDie("/system/framework/boot.art", "/foo").c_str()); } TEST_F(UtilsTest, ExecSuccess) { |