diff options
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/class_linker.cc | 111 | ||||
-rw-r--r-- | runtime/class_linker.h | 8 | ||||
-rw-r--r-- | runtime/native/dalvik_system_DexFile.cc | 4 | ||||
-rw-r--r-- | runtime/oat_file.h | 12 | ||||
-rw-r--r-- | runtime/parsed_options.cc | 14 | ||||
-rw-r--r-- | runtime/parsed_options.h | 1 | ||||
-rw-r--r-- | runtime/runtime.cc | 2 | ||||
-rw-r--r-- | runtime/runtime.h | 5 |
8 files changed, 112 insertions, 45 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index ee6fa66907..d52992c5f2 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -887,12 +887,18 @@ bool ClassLinker::OpenDexFilesFromOat(const char* dex_location, const char* oat_ } } - // Create the oat file. - open_oat_file.reset(CreateOatFileForDexLocation(dex_location, scoped_flock.GetFile()->Fd(), - oat_location, error_msgs)); + if (Runtime::Current()->IsDex2OatEnabled()) { + // Create the oat file. + open_oat_file.reset(CreateOatFileForDexLocation(dex_location, scoped_flock.GetFile()->Fd(), + oat_location, error_msgs)); + } // Failed, bail. if (open_oat_file.get() == nullptr) { + std::string error_msg; + // dex2oat was disabled or crashed. Add the dex file in the list of dex_files to make progress. + DexFile::Open(dex_location, dex_location, &error_msg, dex_files); + error_msgs->push_back(error_msg); return false; } @@ -2016,15 +2022,21 @@ uint32_t ClassLinker::SizeOfClassWithoutEmbeddedTables(const DexFile& dex_file, return mirror::Class::ComputeClassSize(false, 0, num_32, num_64, num_ref); } -OatFile::OatClass ClassLinker::GetOatClass(const DexFile& dex_file, uint16_t class_def_idx) { +bool ClassLinker::FindOatClass(const DexFile& dex_file, + uint16_t class_def_idx, + OatFile::OatClass* oat_class) { + DCHECK(oat_class != nullptr); DCHECK_NE(class_def_idx, DexFile::kDexNoIndex16); const OatFile* oat_file = FindOpenedOatFileForDexFile(dex_file); - CHECK(oat_file != NULL) << dex_file.GetLocation(); + if (oat_file == nullptr) { + return false; + } uint dex_location_checksum = dex_file.GetLocationChecksum(); const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file.GetLocation().c_str(), &dex_location_checksum); CHECK(oat_dex_file != NULL) << dex_file.GetLocation(); - return oat_dex_file->GetOatClass(class_def_idx); + *oat_class = oat_dex_file->GetOatClass(class_def_idx); + return true; } static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, uint16_t class_def_idx, @@ -2061,7 +2073,8 @@ static uint32_t GetOatMethodIndexFromMethodIndex(const DexFile& dex_file, uint16 return 0; } -const OatFile::OatMethod ClassLinker::GetOatMethodFor(mirror::ArtMethod* method) { +bool ClassLinker::FindOatMethodFor(mirror::ArtMethod* method, OatFile::OatMethod* oat_method) { + DCHECK(oat_method != nullptr); // Although we overwrite the trampoline of non-static methods, we may get here via the resolution // method for direct methods (or virtual methods made direct). mirror::Class* declaring_class = method->GetDeclaringClass(); @@ -2088,10 +2101,15 @@ const OatFile::OatMethod ClassLinker::GetOatMethodFor(mirror::ArtMethod* method) GetOatMethodIndexFromMethodIndex(*declaring_class->GetDexCache()->GetDexFile(), method->GetDeclaringClass()->GetDexClassDefIndex(), method->GetDexMethodIndex())); - const OatFile::OatClass oat_class = GetOatClass(*declaring_class->GetDexCache()->GetDexFile(), - declaring_class->GetDexClassDefIndex()); + OatFile::OatClass oat_class; + if (!FindOatClass(*declaring_class->GetDexCache()->GetDexFile(), + declaring_class->GetDexClassDefIndex(), + &oat_class)) { + return false; + } - return oat_class.GetOatMethod(oat_method_index); + *oat_method = oat_class.GetOatMethod(oat_method_index); + return true; } // Special case to get oat code without overwriting a trampoline. @@ -2100,7 +2118,12 @@ const void* ClassLinker::GetQuickOatCodeFor(mirror::ArtMethod* method) { if (method->IsProxyMethod()) { return GetQuickProxyInvokeHandler(); } - const void* result = GetOatMethodFor(method).GetQuickCode(); + OatFile::OatMethod oat_method; + const void* result = nullptr; + if (FindOatMethodFor(method, &oat_method)) { + result = oat_method.GetQuickCode(); + } + if (result == nullptr) { if (method->IsNative()) { // No code and native? Use generic trampoline. @@ -2123,10 +2146,16 @@ const void* ClassLinker::GetPortableOatCodeFor(mirror::ArtMethod* method, if (method->IsProxyMethod()) { return GetPortableProxyInvokeHandler(); } - const OatFile::OatMethod oat_method = GetOatMethodFor(method); - const void* result = oat_method.GetPortableCode(); + OatFile::OatMethod oat_method; + const void* result = nullptr; + const void* quick_code = nullptr; + if (FindOatMethodFor(method, &oat_method)) { + result = oat_method.GetPortableCode(); + quick_code = oat_method.GetQuickCode(); + } + if (result == nullptr) { - if (oat_method.GetQuickCode() == nullptr) { + if (quick_code == nullptr) { // No code? You must mean to go into the interpreter. result = GetPortableToInterpreterBridge(); } else { @@ -2141,14 +2170,20 @@ const void* ClassLinker::GetPortableOatCodeFor(mirror::ArtMethod* method, const void* ClassLinker::GetQuickOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx, uint32_t method_idx) { - const OatFile::OatClass oat_class = GetOatClass(dex_file, class_def_idx); + OatFile::OatClass oat_class; + if (!FindOatClass(dex_file, class_def_idx, &oat_class)) { + return nullptr; + } uint32_t oat_method_idx = GetOatMethodIndexFromMethodIndex(dex_file, class_def_idx, method_idx); return oat_class.GetOatMethod(oat_method_idx).GetQuickCode(); } const void* ClassLinker::GetPortableOatCodeFor(const DexFile& dex_file, uint16_t class_def_idx, uint32_t method_idx) { - const OatFile::OatClass oat_class = GetOatClass(dex_file, class_def_idx); + OatFile::OatClass oat_class; + if (!FindOatClass(dex_file, class_def_idx, &oat_class)) { + return nullptr; + } uint32_t oat_method_idx = GetOatMethodIndexFromMethodIndex(dex_file, class_def_idx, method_idx); return oat_class.GetOatMethod(oat_method_idx).GetPortableCode(); } @@ -2191,7 +2226,6 @@ void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) { const byte* class_data = dex_file.GetClassData(*dex_class_def); // There should always be class data if there were direct methods. CHECK(class_data != nullptr) << PrettyDescriptor(klass); - const OatFile::OatClass oat_class = GetOatClass(dex_file, klass->GetDexClassDefIndex()); ClassDataItemIterator it(dex_file, class_data); // Skip fields while (it.HasNextStaticField()) { @@ -2200,6 +2234,8 @@ void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) { while (it.HasNextInstanceField()) { it.Next(); } + OatFile::OatClass oat_class; + bool has_oat_class = FindOatClass(dex_file, klass->GetDexClassDefIndex(), &oat_class); // Link the code of methods skipped by LinkCode. for (size_t method_index = 0; it.HasNextDirectMethod(); ++method_index, it.Next()) { mirror::ArtMethod* method = klass->GetDirectMethod(method_index); @@ -2207,8 +2243,13 @@ void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) { // Only update static methods. continue; } - const void* portable_code = oat_class.GetOatMethod(method_index).GetPortableCode(); - const void* quick_code = oat_class.GetOatMethod(method_index).GetQuickCode(); + const void* portable_code = nullptr; + const void* quick_code = nullptr; + if (has_oat_class) { + OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index); + portable_code = oat_method.GetPortableCode(); + quick_code = oat_method.GetQuickCode(); + } const bool enter_interpreter = NeedsInterpreter(method, quick_code, portable_code); bool have_portable_code = false; if (enter_interpreter) { @@ -2240,16 +2281,21 @@ void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) { void ClassLinker::LinkCode(Handle<mirror::ArtMethod> method, const OatFile::OatClass* oat_class, const DexFile& dex_file, uint32_t dex_method_index, uint32_t method_index) { + if (Runtime::Current()->IsCompiler()) { + // The following code only applies to a non-compiler runtime. + return; + } // Method shouldn't have already been linked. DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr); DCHECK(method->GetEntryPointFromPortableCompiledCode() == nullptr); - // Every kind of method should at least get an invoke stub from the oat_method. - // non-abstract methods also get their code pointers. - const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index); - oat_method.LinkMethod(method.Get()); + if (oat_class != nullptr) { + // Every kind of method should at least get an invoke stub from the oat_method. + // non-abstract methods also get their code pointers. + const OatFile::OatMethod oat_method = oat_class->GetOatMethod(method_index); + oat_method.LinkMethod(method.Get()); + } // Install entry point from interpreter. - Runtime* runtime = Runtime::Current(); bool enter_interpreter = NeedsInterpreter(method.Get(), method->GetEntryPointFromQuickCompiledCode(), method->GetEntryPointFromPortableCompiledCode()); @@ -2303,6 +2349,7 @@ void ClassLinker::LinkCode(Handle<mirror::ArtMethod> method, const OatFile::OatC } // Allow instrumentation its chance to hijack code. + Runtime* runtime = Runtime::Current(); runtime->GetInstrumentation()->UpdateMethodsCode(method.Get(), method->GetEntryPointFromQuickCompiledCode(), method->GetEntryPointFromPortableCompiledCode(), @@ -2339,8 +2386,10 @@ void ClassLinker::LoadClass(const DexFile& dex_file, return; // no fields or methods - for example a marker interface } - if (Runtime::Current()->IsStarted() && !Runtime::Current()->UseCompileTimeClassPath()) { - const OatFile::OatClass oat_class = GetOatClass(dex_file, klass->GetDexClassDefIndex()); + OatFile::OatClass oat_class; + if (Runtime::Current()->IsStarted() + && !Runtime::Current()->UseCompileTimeClassPath() + && FindOatClass(dex_file, klass->GetDexClassDefIndex(), &oat_class)) { LoadClassMembers(dex_file, class_data, klass, class_loader, &oat_class); } else { LoadClassMembers(dex_file, class_data, klass, class_loader, nullptr); @@ -2423,9 +2472,7 @@ void ClassLinker::LoadClassMembers(const DexFile& dex_file, return; } klass->SetDirectMethod(i, method.Get()); - if (oat_class != nullptr) { - LinkCode(method, oat_class, dex_file, it.GetMemberIndex(), class_def_method_index); - } + LinkCode(method, oat_class, dex_file, it.GetMemberIndex(), class_def_method_index); method->SetMethodIndex(class_def_method_index); class_def_method_index++; } @@ -2438,9 +2485,7 @@ void ClassLinker::LoadClassMembers(const DexFile& dex_file, } klass->SetVirtualMethod(i, method.Get()); DCHECK_EQ(class_def_method_index, it.NumDirectMethods() + i); - if (oat_class != nullptr) { - LinkCode(method, oat_class, dex_file, it.GetMemberIndex(), class_def_method_index); - } + LinkCode(method, oat_class, dex_file, it.GetMemberIndex(), class_def_method_index); class_def_method_index++; } DCHECK(!it.HasNext()); @@ -3221,7 +3266,7 @@ bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file, mirror::Class const OatFile* oat_file = FindOpenedOatFileForDexFile(dex_file); // Make this work with gtests, which do not set up the image properly. // TODO: we should clean up gtests to set up the image path properly. - if (Runtime::Current()->IsCompiler() && (oat_file == NULL)) { + if (Runtime::Current()->IsCompiler() || (oat_file == NULL)) { return false; } diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 8c0904203b..6fc0f0e2f2 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -392,7 +392,7 @@ class ClassLinker { } private: - const OatFile::OatMethod GetOatMethodFor(mirror::ArtMethod* method) + bool FindOatMethodFor(mirror::ArtMethod* method, OatFile::OatMethod* oat_method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); OatFile& GetImageOatFile(gc::space::ImageSpace* space) @@ -461,8 +461,9 @@ class ClassLinker { void FixupStaticTrampolines(mirror::Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - // Finds the associated oat class for a dex_file and descriptor - OatFile::OatClass GetOatClass(const DexFile& dex_file, uint16_t class_def_idx) + // Finds the associated oat class for a dex_file and descriptor. Returns whether the class + // was found, and sets the data in oat_class. + bool FindOatClass(const DexFile& dex_file, uint16_t class_def_idx, OatFile::OatClass* oat_class) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); void RegisterDexFileLocked(const DexFile& dex_file, Handle<mirror::DexCache> dex_cache) @@ -742,6 +743,7 @@ class ClassLinker { friend class ImageWriter; // for GetClassRoots friend class ImageDumper; // for FindOpenedOatFileFromOatLocation friend class ElfPatcher; // for FindOpenedOatFileForDexFile & FindOpenedOatFileFromOatLocation + friend class NoDex2OatTest; // for FindOpenedOatFileForDexFile FRIEND_TEST(ClassLinkerTest, ClassRootDescriptors); FRIEND_TEST(mirror::DexCacheTest, Open); FRIEND_TEST(ExceptionTest, FindExceptionHandler); diff --git a/runtime/native/dalvik_system_DexFile.cc b/runtime/native/dalvik_system_DexFile.cc index c3304e6670..f199c99599 100644 --- a/runtime/native/dalvik_system_DexFile.cc +++ b/runtime/native/dalvik_system_DexFile.cc @@ -114,7 +114,9 @@ static jlong DexFile_openDexFileNative(JNIEnv* env, jclass, jstring javaSourceNa bool success = linker->OpenDexFilesFromOat(sourceName.c_str(), outputName.c_str(), &error_msgs, dex_files.get()); - if (success) { + if (success || !dex_files->empty()) { + // In the case of non-success, we have not found or could not generate the oat file. + // But we may still have found a dex file that we can use. return static_cast<jlong>(reinterpret_cast<uintptr_t>(dex_files.release())); } else { // The vector should be empty after a failed loading attempt. diff --git a/runtime/oat_file.h b/runtime/oat_file.h index 9710a2addd..810eccb2d1 100644 --- a/runtime/oat_file.h +++ b/runtime/oat_file.h @@ -133,6 +133,8 @@ class OatFile { const uint32_t code_offset, const uint32_t gc_map_offset); + OatMethod() {} + private: template<class T> T GetOatPointer(uint32_t offset) const { @@ -166,6 +168,8 @@ class OatFile { // methods are not included. const OatMethod GetOatMethod(uint32_t method_index) const; + OatClass() {} + private: OatClass(const OatFile* oat_file, mirror::Class::Status status, @@ -174,13 +178,13 @@ class OatFile { const uint32_t* bitmap_pointer, const OatMethodOffsets* methods_pointer); - const OatFile* const oat_file_; + const OatFile* oat_file_; - const mirror::Class::Status status_; + mirror::Class::Status status_; - const OatClassType type_; + OatClassType type_; - const uint32_t* const bitmap_; + const uint32_t* bitmap_; const OatMethodOffsets* methods_pointer_; diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index 12f9f33f5f..3ef7a17615 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -223,6 +223,7 @@ bool ParsedOptions::Parse(const RuntimeOptions& options, bool ignore_unrecognize compiler_callbacks_ = nullptr; is_zygote_ = false; must_relocate_ = kDefaultMustRelocate; + dex2oat_enabled_ = true; if (kPoisonHeapReferences) { // kPoisonHeapReferences currently works only with the interpreter only. // TODO: make it work with the compiler. @@ -421,6 +422,10 @@ bool ParsedOptions::Parse(const RuntimeOptions& options, bool ignore_unrecognize must_relocate_ = true; } else if (option == "-Xnorelocate") { must_relocate_ = false; + } else if (option == "-Xnodex2oat") { + dex2oat_enabled_ = false; + } else if (option == "-Xdex2oat") { + dex2oat_enabled_ = true; } else if (option == "-Xint") { interpreter_only_ = true; } else if (StartsWith(option, "-Xgc:")) { @@ -710,7 +715,7 @@ void ParsedOptions::Usage(const char* fmt, ...) { UsageMessage(stream, "The following standard options are supported:\n"); UsageMessage(stream, " -classpath classpath (-cp classpath)\n"); UsageMessage(stream, " -Dproperty=value\n"); - UsageMessage(stream, " -verbose:tag ('gc', 'jni', or 'class')\n"); + UsageMessage(stream, " -verbose:tag ('gc', 'jni', or 'class')\n"); UsageMessage(stream, " -showversion\n"); UsageMessage(stream, " -help\n"); UsageMessage(stream, " -agentlib:jdwp=options\n"); @@ -720,9 +725,9 @@ void ParsedOptions::Usage(const char* fmt, ...) { UsageMessage(stream, " -Xrunjdwp:<options>\n"); UsageMessage(stream, " -Xbootclasspath:bootclasspath\n"); UsageMessage(stream, " -Xcheck:tag (e.g. 'jni')\n"); - UsageMessage(stream, " -XmsN (min heap, must be multiple of 1K, >= 1MB)\n"); - UsageMessage(stream, " -XmxN (max heap, must be multiple of 1K, >= 2MB)\n"); - UsageMessage(stream, " -XssN (stack size)\n"); + UsageMessage(stream, " -XmsN (min heap, must be multiple of 1K, >= 1MB)\n"); + UsageMessage(stream, " -XmxN (max heap, must be multiple of 1K, >= 2MB)\n"); + UsageMessage(stream, " -XssN (stack size)\n"); UsageMessage(stream, " -Xint\n"); UsageMessage(stream, "\n"); @@ -776,6 +781,7 @@ void ParsedOptions::Usage(const char* fmt, ...) { UsageMessage(stream, " -Ximage-compiler-option dex2oat-option\n"); UsageMessage(stream, " -Xpatchoat:filename\n"); UsageMessage(stream, " -X[no]relocate\n"); + UsageMessage(stream, " -X[no]dex2oat (Whether to invoke dex2oat on the application)\n"); UsageMessage(stream, "\n"); UsageMessage(stream, "The following previously supported Dalvik options are ignored:\n"); diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h index c328ca7ef5..aa2c55713e 100644 --- a/runtime/parsed_options.h +++ b/runtime/parsed_options.h @@ -50,6 +50,7 @@ class ParsedOptions { CompilerCallbacks* compiler_callbacks_; bool is_zygote_; bool must_relocate_; + bool dex2oat_enabled_; std::string patchoat_executable_; bool interpreter_only_; bool is_explicit_gc_disabled_; diff --git a/runtime/runtime.cc b/runtime/runtime.cc index d677729b7e..d3957c1e9f 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -101,6 +101,7 @@ Runtime::Runtime() must_relocate_(false), is_concurrent_gc_enabled_(true), is_explicit_gc_disabled_(false), + dex2oat_enabled_(true), default_stack_size_(0), heap_(nullptr), max_spins_before_thin_lock_inflation_(Monitor::kDefaultMaxSpinsBeforeThinLockInflation), @@ -556,6 +557,7 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) must_relocate_ = options->must_relocate_; is_zygote_ = options->is_zygote_; is_explicit_gc_disabled_ = options->is_explicit_gc_disabled_; + dex2oat_enabled_ = options->dex2oat_enabled_; vfprintf_ = options->hook_vfprintf_; exit_ = options->hook_exit_; diff --git a/runtime/runtime.h b/runtime/runtime.h index a85c2e4eda..e76280ae95 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -105,6 +105,10 @@ class Runtime { return must_relocate_; } + bool IsDex2OatEnabled() const { + return dex2oat_enabled_; + } + CompilerCallbacks* GetCompilerCallbacks() { return compiler_callbacks_; } @@ -503,6 +507,7 @@ class Runtime { bool must_relocate_; bool is_concurrent_gc_enabled_; bool is_explicit_gc_disabled_; + bool dex2oat_enabled_; std::string compiler_executable_; std::string patchoat_executable_; |