diff options
-rw-r--r-- | compiler/image_writer.cc | 18 | ||||
-rw-r--r-- | compiler/oat_writer.cc | 11 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 11 | ||||
-rw-r--r-- | oatdump/oatdump.cc | 102 | ||||
-rw-r--r-- | runtime/class_linker.cc | 2 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 7 | ||||
-rw-r--r-- | runtime/gc/space/image_space.cc | 2 | ||||
-rw-r--r-- | runtime/parsed_options.cc | 6 | ||||
-rw-r--r-- | runtime/runtime.cc | 3 |
9 files changed, 99 insertions, 63 deletions
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index 69e0950..e3114eb 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -635,15 +635,19 @@ void ImageWriter::FixupMethod(ArtMethod* orig, ArtMethod* copy) { // Use original code if it exists. Otherwise, set the code pointer to the resolution // trampoline. const byte* quick_code = GetOatAddress(orig->GetQuickOatCodeOffset()); - if (quick_code != nullptr) { + if (quick_code != nullptr && + (!orig->IsStatic() || orig->IsConstructor() || orig->GetDeclaringClass()->IsInitialized())) { + // We have code for a non-static or initialized method, just use the code. copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(quick_code); + } else if (quick_code == nullptr && orig->IsNative() && !orig->IsStatic()) { + // Non-static native method missing compiled code, use generic JNI version. + copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_generic_jni_trampoline_offset_)); + } else if (quick_code == nullptr && !orig->IsNative()) { + // We don't have code at all for a non-native method, use the interpreter. + copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_to_interpreter_bridge_offset_)); } else { - if (orig->IsNative() && !orig->IsStatic()) { - // non-static native method missing compiled code, use generic JNI version - copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_generic_jni_trampoline_offset_)); - } else { - copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_resolution_trampoline_offset_)); - } + // We have code for a static method, but need to go through the resolution stub for class initialization. + copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_resolution_trampoline_offset_)); } const byte* portable_code = GetOatAddress(orig->GetPortableOatCodeOffset()); if (portable_code != nullptr) { diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 181240e..186ab38 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -506,15 +506,8 @@ size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index, method->SetCoreSpillMask(core_spill_mask); method->SetFpSpillMask(fp_spill_mask); method->SetOatMappingTableOffset(mapping_table_offset); - // Don't overwrite static method trampoline - if (!method->IsStatic() || method->IsConstructor() || - method->GetDeclaringClass()->IsInitialized()) { - // TODO: record portable code offsets: method->SetPortableOatCodeOffset(portable_code_offset); - method->SetQuickOatCodeOffset(quick_code_offset); - } else { - method->SetEntryPointFromPortableCompiledCode(nullptr); - method->SetEntryPointFromQuickCompiledCode(nullptr); - } + // Portable code offsets are set by ElfWriterMclinker::FixupCompiledCodeOffset after linking. + method->SetQuickOatCodeOffset(quick_code_offset); method->SetOatVmapTableOffset(vmap_table_offset); method->SetOatNativeGcMapOffset(gc_map_offset); } diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 9f6b454..afa8495 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -1166,12 +1166,11 @@ static int dex2oat(int argc, char** argv) { LOG(INFO) << "Wrote input to " << tmp_file_name; } } - - // Ensure opened dex files are writable for dex-to-dex transformations. - for (const auto& dex_file : dex_files) { - if (!dex_file->EnableWrite()) { - PLOG(ERROR) << "Failed to make .dex file writeable '" << dex_file->GetLocation() << "'\n"; - } + } + // Ensure opened dex files are writable for dex-to-dex transformations. + for (const auto& dex_file : dex_files) { + if (!dex_file->EnableWrite()) { + PLOG(ERROR) << "Failed to make .dex file writeable '" << dex_file->GetLocation() << "'\n"; } } diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index bbeb802..841a478 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -126,8 +126,36 @@ class OatDumper { os << "DEX FILE COUNT:\n"; os << oat_header.GetDexFileCount() << "\n\n"; - os << "EXECUTABLE OFFSET:\n"; - os << StringPrintf("0x%08x\n\n", oat_header.GetExecutableOffset()); +#define DUMP_OAT_HEADER_OFFSET(label, offset) \ + os << label " OFFSET:\n"; \ + os << StringPrintf("0x%08x", oat_header.offset()); \ + if (oat_header.offset() != 0) { \ + os << StringPrintf(" (%p)", oat_file_.Begin() + oat_header.offset()); \ + } \ + os << StringPrintf("\n\n"); + + DUMP_OAT_HEADER_OFFSET("EXECUTABLE", GetExecutableOffset); + DUMP_OAT_HEADER_OFFSET("INTERPRETER TO INTERPRETER BRIDGE", + GetInterpreterToInterpreterBridgeOffset); + DUMP_OAT_HEADER_OFFSET("INTERPRETER TO COMPILED CODE BRIDGE", + GetInterpreterToCompiledCodeBridgeOffset); + DUMP_OAT_HEADER_OFFSET("JNI DLSYM LOOKUP", + GetJniDlsymLookupOffset); + DUMP_OAT_HEADER_OFFSET("PORTABLE IMT CONFLICT TRAMPOLINE", + GetPortableImtConflictTrampolineOffset); + DUMP_OAT_HEADER_OFFSET("PORTABLE RESOLUTION TRAMPOLINE", + GetPortableResolutionTrampolineOffset); + DUMP_OAT_HEADER_OFFSET("PORTABLE TO INTERPRETER BRIDGE", + GetPortableToInterpreterBridgeOffset); + DUMP_OAT_HEADER_OFFSET("QUICK GENERIC JNI TRAMPOLINE", + GetQuickGenericJniTrampolineOffset); + DUMP_OAT_HEADER_OFFSET("QUICK IMT CONFLICT TRAMPOLINE", + GetQuickImtConflictTrampolineOffset); + DUMP_OAT_HEADER_OFFSET("QUICK RESOLUTION TRAMPOLINE", + GetQuickResolutionTrampolineOffset); + DUMP_OAT_HEADER_OFFSET("QUICK TO INTERPRETER BRIDGE", + GetQuickToInterpreterBridgeOffset); +#undef DUMP_OAT_HEADER_OFFSET os << "IMAGE FILE LOCATION OAT CHECKSUM:\n"; os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatChecksum()); @@ -214,7 +242,9 @@ class OatDumper { continue; } offsets_.insert(reinterpret_cast<uintptr_t>(&dex_file->GetHeader())); - for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); class_def_index++) { + for (size_t class_def_index = 0; + class_def_index < dex_file->NumClassDefs(); + class_def_index++) { const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(class_def_index)); const byte* class_data = dex_file->GetClassData(class_def); @@ -264,7 +294,9 @@ class OatDumper { os << "NOT FOUND: " << error_msg << "\n\n"; return; } - for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); class_def_index++) { + for (size_t class_def_index = 0; + class_def_index < dex_file->NumClassDefs(); + class_def_index++) { const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); const char* descriptor = dex_file->GetClassDescriptor(class_def); UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file.GetOatClass(class_def_index)); @@ -389,8 +421,9 @@ class OatDumper { SirtRef<mirror::DexCache> dex_cache( soa.Self(), runtime->GetClassLinker()->FindDexCache(dex_file)); SirtRef<mirror::ClassLoader> class_loader(soa.Self(), nullptr); - verifier::MethodVerifier verifier(&dex_file, &dex_cache, &class_loader, &class_def, code_item, - dex_method_idx, nullptr, method_access_flags, true, true); + verifier::MethodVerifier verifier(&dex_file, &dex_cache, &class_loader, &class_def, + code_item, dex_method_idx, nullptr, method_access_flags, + true, true); verifier.Verify(); DumpCode(indent2_os, &verifier, oat_method, code_item); } else { @@ -654,7 +687,8 @@ class OatDumper { uint32_t method_access_flags) { if ((method_access_flags & kAccNative) == 0) { ScopedObjectAccess soa(Thread::Current()); - SirtRef<mirror::DexCache> dex_cache(soa.Self(), Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file)); + SirtRef<mirror::DexCache> dex_cache( + soa.Self(), Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file)); SirtRef<mirror::ClassLoader> class_loader(soa.Self(), nullptr); verifier::MethodVerifier::VerifyMethodAndDump(os, dex_method_idx, dex_file, dex_cache, class_loader, &class_def, code_item, NULL, @@ -701,12 +735,10 @@ class OatDumper { class ImageDumper { public: - explicit ImageDumper(std::ostream* os, const std::string& image_filename, - gc::space::ImageSpace& image_space, + explicit ImageDumper(std::ostream* os, gc::space::ImageSpace& image_space, const ImageHeader& image_header, bool dump_raw_mapping_table, bool dump_raw_gc_map) - : os_(os), image_filename_(image_filename), - image_space_(image_space), image_header_(image_header), + : os_(os), image_space_(image_space), image_header_(image_header), dump_raw_mapping_table_(dump_raw_mapping_table), dump_raw_gc_map_(dump_raw_gc_map) {} @@ -772,7 +804,8 @@ class ImageDumper { os << "\n"; ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); - std::string oat_location = ImageHeader::GetOatLocationFromImageLocation(image_filename_); + std::string image_filename = image_space_.GetImageFilename(); + std::string oat_location = ImageHeader::GetOatLocationFromImageLocation(image_filename); os << "OAT LOCATION: " << oat_location; os << "\n"; std::string error_msg; @@ -836,17 +869,12 @@ class ImageDumper { os_ = saved_os; } os << "STATS:\n" << std::flush; - UniquePtr<File> file(OS::OpenFileForReading(image_filename_.c_str())); + UniquePtr<File> file(OS::OpenFileForReading(image_filename.c_str())); if (file.get() == NULL) { - std::string cache_location(GetDalvikCacheFilenameOrDie(image_filename_.c_str())); - file.reset(OS::OpenFileForReading(cache_location.c_str())); - if (file.get() == NULL) { - LOG(WARNING) << "Failed to find image in " << image_filename_ - << " and " << cache_location; - } + LOG(WARNING) << "Failed to find image in " << image_filename; } if (file.get() != NULL) { - stats_.file_bytes = file->GetLength(); + stats_.file_bytes = file->GetLength(); } size_t header_bytes = sizeof(ImageHeader); stats_.header_bytes = header_bytes; @@ -1027,7 +1055,8 @@ class ImageDumper { indent_os << StringPrintf("%d to %zd: ", i, i + run); i = i + run; } - mirror::Class* value_class = value == NULL ? obj_class->GetComponentType() : value->GetClass(); + mirror::Class* value_class = + (value == NULL) ? obj_class->GetComponentType() : value->GetClass(); PrettyObjectValue(indent_os, value_class, value); } } else if (obj->IsClass()) { @@ -1063,10 +1092,6 @@ class ImageDumper { DCHECK(method->GetNativeGcMap() == NULL) << PrettyMethod(method); DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method); } else { - // TODO: we check there is a GC map here, we may not have a GC map if the code is pointing - // to the quick/portable to interpreter bridge. - CHECK(method->GetNativeGcMap() != NULL) << PrettyMethod(method); - const DexFile::CodeItem* code_item = MethodHelper(method).GetCodeItem(); size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2; state->stats_.dex_instruction_bytes += dex_instruction_bytes; @@ -1363,12 +1388,18 @@ class ImageDumper { "large_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n" "large_method_code_bytes = %8zd (%2.0f%% of oat file bytes)\n\n", oat_file_bytes, - managed_code_bytes, PercentOfOatBytes(managed_code_bytes), - managed_to_native_code_bytes, PercentOfOatBytes(managed_to_native_code_bytes), - native_to_managed_code_bytes, PercentOfOatBytes(native_to_managed_code_bytes), - class_initializer_code_bytes, PercentOfOatBytes(class_initializer_code_bytes), - large_initializer_code_bytes, PercentOfOatBytes(large_initializer_code_bytes), - large_method_code_bytes, PercentOfOatBytes(large_method_code_bytes)) + managed_code_bytes, + PercentOfOatBytes(managed_code_bytes), + managed_to_native_code_bytes, + PercentOfOatBytes(managed_to_native_code_bytes), + native_to_managed_code_bytes, + PercentOfOatBytes(native_to_managed_code_bytes), + class_initializer_code_bytes, + PercentOfOatBytes(class_initializer_code_bytes), + large_initializer_code_bytes, + PercentOfOatBytes(large_initializer_code_bytes), + large_method_code_bytes, + PercentOfOatBytes(large_method_code_bytes)) << "DexFile sizes:\n"; for (const std::pair<std::string, size_t>& oat_dex_file_size : oat_dex_file_sizes) { os << StringPrintf("%s = %zd (%2.0f%% of oat file bytes)\n", @@ -1386,7 +1417,8 @@ class ImageDumper { os << StringPrintf("dex_instruction_bytes = %zd\n", dex_instruction_bytes) << StringPrintf("managed_code_bytes expansion = %.2f (ignoring deduplication %.2f)\n\n", - static_cast<double>(managed_code_bytes) / static_cast<double>(dex_instruction_bytes), + static_cast<double>(managed_code_bytes) / + static_cast<double>(dex_instruction_bytes), static_cast<double>(managed_code_bytes_ignoring_deduplication) / static_cast<double>(dex_instruction_bytes)) << std::flush; @@ -1406,7 +1438,6 @@ class ImageDumper { }; UniquePtr<OatDumper> oat_dumper_; std::ostream* os_; - const std::string image_filename_; gc::space::ImageSpace& image_space_; const ImageHeader& image_header_; bool dump_raw_mapping_table_; @@ -1497,6 +1528,7 @@ static int oatdump(int argc, char** argv) { std::string boot_oat_option; // We are more like a compiler than a run-time. We don't want to execute code. + // TODO: Replace with NoopCompilerCallbacks. struct OatDumpCompilerCallbacks : CompilerCallbacks { virtual bool MethodVerified(verifier::MethodVerifier* /*verifier*/) { return true; } virtual void ClassRejected(ClassReference /*ref*/) { } @@ -1532,8 +1564,8 @@ static int oatdump(int argc, char** argv) { fprintf(stderr, "Invalid image header %s\n", image_filename); return EXIT_FAILURE; } - ImageDumper image_dumper(os, image_filename, *image_space, image_header, - dump_raw_mapping_table, dump_raw_gc_map); + ImageDumper image_dumper(os, *image_space, image_header, + dump_raw_mapping_table, dump_raw_gc_map); image_dumper.Dump(); return EXIT_SUCCESS; } diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index e5ca721..7e43994 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -581,7 +581,7 @@ bool ClassLinker::GenerateOatFile(const char* dex_filename, argv.push_back(oat_fd_option); argv.push_back(oat_location_option); const std::vector<std::string>& compiler_options = Runtime::Current()->GetCompilerOptions(); - for (size_t i = 0; compiler_options.size(); ++i) { + for (size_t i = 0; i < compiler_options.size(); ++i) { argv.push_back(compiler_options[i].c_str()); } diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index ef40be8..63e0d42 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -485,9 +485,11 @@ extern "C" uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Threa ThrowAbstractMethodError(method); return 0; } else { + DCHECK(!method->IsNative()) << PrettyMethod(method); const char* old_cause = self->StartAssertNoThreadSuspension("Building interpreter shadow frame"); MethodHelper mh(method); const DexFile::CodeItem* code_item = mh.GetCodeItem(); + DCHECK(code_item != nullptr) << PrettyMethod(method); uint16_t num_regs = code_item->registers_size_; void* memory = alloca(ShadowFrame::ComputeSize(num_regs)); ShadowFrame* shadow_frame(ShadowFrame::Create(num_regs, NULL, // No last shadow coming from quick. @@ -507,7 +509,7 @@ extern "C" uint64_t artQuickToInterpreterBridge(mirror::ArtMethod* method, Threa // Ensure static method's class is initialized. SirtRef<mirror::Class> sirt_c(self, method->GetDeclaringClass()); if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(sirt_c, true, true)) { - DCHECK(Thread::Current()->IsExceptionPending()); + DCHECK(Thread::Current()->IsExceptionPending()) << PrettyMethod(method); self->PopManagedStackFragment(fragment); return 0; } @@ -766,7 +768,8 @@ extern "C" const void* artQuickResolutionTrampoline(mirror::ArtMethod* called, const void* code = NULL; if (LIKELY(!thread->IsExceptionPending())) { // Incompatible class change should have been handled in resolve method. - CHECK(!called->CheckIncompatibleClassChange(invoke_type)); + CHECK(!called->CheckIncompatibleClassChange(invoke_type)) + << PrettyMethod(called) << " " << invoke_type; if (virtual_or_interface) { // Refine called method based on receiver. CHECK(receiver != nullptr) << invoke_type; diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 98d4eef..8426fab 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -87,7 +87,7 @@ static bool GenerateImage(const std::string& image_file_name, std::string* error } const std::vector<std::string>& compiler_options = Runtime::Current()->GetImageCompilerOptions(); - for (size_t i = 0; compiler_options.size(); ++i) { + for (size_t i = 0; i < compiler_options.size(); ++i) { arg_vector.push_back(compiler_options[i].c_str()); } diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index 765074a..b6f36b6 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -186,10 +186,12 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni profile_clock_source_ = kDefaultProfilerClockSource; for (size_t i = 0; i < options.size(); ++i) { - const std::string option(options[i].first); if (true && options[0].first == "-Xzygote") { - LOG(INFO) << "option[" << i << "]=" << option; + LOG(INFO) << "option[" << i << "]=" << options[i].first; } + } + for (size_t i = 0; i < options.size(); ++i) { + const std::string option(options[i].first); if (StartsWith(option, "-help")) { Usage(nullptr); return false; diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 7546729..de06fb8 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -490,6 +490,9 @@ bool Runtime::Init(const Options& raw_options, bool ignore_unrecognized) { default_stack_size_ = options->stack_size_; stack_trace_file_ = options->stack_trace_file_; + compiler_options_ = options->compiler_options_; + image_compiler_options_ = options->image_compiler_options_; + max_spins_before_thin_lock_inflation_ = options->max_spins_before_thin_lock_inflation_; monitor_list_ = new MonitorList; |