summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/image_writer.cc18
-rw-r--r--compiler/oat_writer.cc11
-rw-r--r--dex2oat/dex2oat.cc11
-rw-r--r--oatdump/oatdump.cc102
-rw-r--r--runtime/class_linker.cc2
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc7
-rw-r--r--runtime/gc/space/image_space.cc2
-rw-r--r--runtime/parsed_options.cc6
-rw-r--r--runtime/runtime.cc3
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;