summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2014-04-23 20:24:57 +0100
committerNarayan Kamath <narayan@google.com>2014-05-01 11:25:07 +0100
commit11d9f06a96a6909905c248ed684366190140095c (patch)
tree27b02ab216b98ba1656d66072fd46c5adec61242
parentb3016551e5f264264dbb633a1ddf03ac97f9c66c (diff)
downloadart-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.mk1
-rw-r--r--compiler/llvm/llvm_compilation_unit.cc2
-rw-r--r--dex2oat/dex2oat.cc3
-rw-r--r--runtime/class_linker.cc4
-rw-r--r--runtime/gc/heap.cc5
-rw-r--r--runtime/gc/heap.h2
-rw-r--r--runtime/gc/space/image_space.cc8
-rw-r--r--runtime/gc/space/image_space.h8
-rw-r--r--runtime/instruction_set.cc42
-rw-r--r--runtime/instruction_set.h3
-rw-r--r--runtime/instruction_set_test.cc48
-rw-r--r--runtime/native/dalvik_system_DexFile.cc84
-rw-r--r--runtime/parsed_options.cc6
-rw-r--r--runtime/parsed_options.h1
-rw-r--r--runtime/runtime.cc1
-rw-r--r--runtime/utils.cc25
-rw-r--r--runtime/utils.h13
-rw-r--r--runtime/utils_test.cc20
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) {