am 379e2f59: Clean up unnecessary files after build-only. Bug: 9482191
* commit '379e2f5996b38d9f67b9c334c232cb315a5390ad':
Clean up unnecessary files after build-only. Bug: 9482191
diff --git a/compiler/dex/portable/mir_to_gbc.cc b/compiler/dex/portable/mir_to_gbc.cc
index 90cec75..7831cf6 100644
--- a/compiler/dex/portable/mir_to_gbc.cc
+++ b/compiler/dex/portable/mir_to_gbc.cc
@@ -1972,7 +1972,7 @@
::llvm::OwningPtr< ::llvm::tool_output_file> out_file(
new ::llvm::tool_output_file(fname.c_str(), errmsg,
- ::llvm::sys::fs::F_Binary));
+ ::llvm::raw_fd_ostream::F_Binary));
if (!errmsg.empty()) {
LOG(ERROR) << "Failed to create bitcode output file: " << errmsg;
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 7b83e40..bf541c6 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -582,10 +582,11 @@
bool CompilerDriver::IsImageClass(const char* descriptor) const {
DCHECK(descriptor != NULL);
- if (image_classes_.get() == NULL) {
+ if (!IsImage()) {
return true;
+ } else {
+ return image_classes_->find(descriptor) != image_classes_->end();
}
- return image_classes_->find(descriptor) != image_classes_->end();
}
static void ResolveExceptionsForMethod(MethodHelper* mh,
@@ -655,7 +656,7 @@
// Make a list of descriptors for classes to include in the image
void CompilerDriver::LoadImageClasses(base::TimingLogger& timings)
LOCKS_EXCLUDED(Locks::mutator_lock_) {
- if (image_classes_.get() == NULL) {
+ if (!IsImage()) {
return;
}
@@ -669,7 +670,7 @@
SirtRef<mirror::Class> klass(self, class_linker->FindSystemClass(descriptor.c_str()));
if (klass.get() == NULL) {
image_classes_->erase(it++);
- LOG(WARNING) << "Failed to find class " << descriptor;
+ VLOG(compiler) << "Failed to find class " << descriptor;
Thread::Current()->ClearException();
} else {
++it;
@@ -742,21 +743,19 @@
}
void CompilerDriver::UpdateImageClasses(base::TimingLogger& timings) {
- if (image_classes_.get() == NULL) {
- return;
+ if (IsImage()) {
+ timings.NewSplit("UpdateImageClasses");
+
+ // Update image_classes_ with classes for objects created by <clinit> methods.
+ Thread* self = Thread::Current();
+ const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter");
+ gc::Heap* heap = Runtime::Current()->GetHeap();
+ // TODO: Image spaces only?
+ WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
+ heap->FlushAllocStack();
+ heap->GetLiveBitmap()->Walk(FindClinitImageClassesCallback, this);
+ self->EndAssertNoThreadSuspension(old_cause);
}
-
- timings.NewSplit("UpdateImageClasses");
-
- // Update image_classes_ with classes for objects created by <clinit> methods.
- Thread* self = Thread::Current();
- const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter");
- gc::Heap* heap = Runtime::Current()->GetHeap();
- // TODO: Image spaces only?
- WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
- heap->FlushAllocStack();
- heap->GetLiveBitmap()->Walk(FindClinitImageClassesCallback, this);
- self->EndAssertNoThreadSuspension(old_cause);
}
void CompilerDriver::RecordClassStatus(ClassReference ref, CompiledClass* compiled_class) {
@@ -1417,30 +1416,27 @@
// classes found in the boot classpath. Since at runtime we will
// select the class from the boot classpath, do not attempt to resolve
// or compile it now.
-static bool SkipClass(mirror::ClassLoader* class_loader,
- const DexFile& dex_file,
- const DexFile::ClassDef& class_def)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+static bool SkipClass(ClassLinker* class_linker, jobject class_loader, const DexFile& dex_file,
+ const DexFile::ClassDef& class_def) {
if (class_loader == NULL) {
return false;
}
const char* descriptor = dex_file.GetClassDescriptor(class_def);
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- mirror::Class* klass = class_linker->FindClass(descriptor, NULL);
- if (klass == NULL) {
- Thread* self = Thread::Current();
- CHECK(self->IsExceptionPending());
- self->ClearException();
- return false;
- }
- return true;
+ return class_linker->IsInBootClassPath(descriptor);
}
-static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manager, size_t class_def_index)
+static void ResolveClassFieldsAndMethods(const ParallelCompilationManager* manager,
+ size_t class_def_index)
LOCKS_EXCLUDED(Locks::mutator_lock_) {
- ScopedObjectAccess soa(Thread::Current());
- mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader());
+ Thread* self = Thread::Current();
+ jobject jclass_loader = manager->GetClassLoader();
const DexFile& dex_file = *manager->GetDexFile();
+ ClassLinker* class_linker = manager->GetClassLinker();
+
+ // If an instance field is final then we need to have a barrier on the return, static final
+ // fields are assigned within the lock held for class initialization. Conservatively assume
+ // constructor barriers are always required.
+ bool requires_constructor_barrier = true;
// Method and Field are the worst. We can't resolve without either
// context from the code use (to disambiguate virtual vs direct
@@ -1450,72 +1446,89 @@
// definitions, since many of them many never be referenced by
// generated code.
const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
- if (SkipClass(class_loader, dex_file, class_def)) {
- return;
- }
+ if (!SkipClass(class_linker, jclass_loader, dex_file, class_def)) {
+ // Note the class_data pointer advances through the headers,
+ // static fields, instance fields, direct methods, and virtual
+ // methods.
+ const byte* class_data = dex_file.GetClassData(class_def);
+ if (class_data == NULL) {
+ // Empty class such as a marker interface.
+ requires_constructor_barrier = false;
+ } else {
+ ScopedObjectAccess soa(self);
+ mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(jclass_loader);
+ mirror::DexCache* dex_cache = class_linker->FindDexCache(dex_file);
- // Note the class_data pointer advances through the headers,
- // static fields, instance fields, direct methods, and virtual
- // methods.
- const byte* class_data = dex_file.GetClassData(class_def);
- if (class_data == NULL) {
- // empty class such as a marker interface
- return;
- }
- Thread* self = Thread::Current();
- ClassLinker* class_linker = manager->GetClassLinker();
- mirror::DexCache* dex_cache = class_linker->FindDexCache(dex_file);
- ClassDataItemIterator it(dex_file, class_data);
- while (it.HasNextStaticField()) {
- mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
- class_loader, true);
- if (field == NULL) {
- CHECK(self->IsExceptionPending());
- self->ClearException();
- }
- it.Next();
- }
- // If an instance field is final then we need to have a barrier on the return, static final
- // fields are assigned within the lock held for class initialization.
- bool requires_constructor_barrier = false;
- while (it.HasNextInstanceField()) {
- if ((it.GetMemberAccessFlags() & kAccFinal) != 0) {
- requires_constructor_barrier = true;
- }
+ // Resolve the class.
+ mirror::Class* klass = class_linker->ResolveType(dex_file, class_def.class_idx_, dex_cache,
+ class_loader);
- mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(), dex_cache,
- class_loader, false);
- if (field == NULL) {
- CHECK(self->IsExceptionPending());
- self->ClearException();
+ bool resolve_fields_and_methods;
+ if (klass == NULL) {
+ // Class couldn't be resolved, for example, super-class is in a different dex file. Don't
+ // attempt to resolve methods and fields when there is no declaring class.
+ CHECK(soa.Self()->IsExceptionPending());
+ Thread::Current()->ClearException();
+ resolve_fields_and_methods = false;
+ } else {
+ resolve_fields_and_methods = manager->GetCompiler()->IsImage();
+ }
+ ClassDataItemIterator it(dex_file, class_data);
+ while (it.HasNextStaticField()) {
+ if (resolve_fields_and_methods) {
+ mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(),
+ dex_cache, class_loader, true);
+ if (field == NULL) {
+ CHECK(soa.Self()->IsExceptionPending());
+ soa.Self()->ClearException();
+ }
+ }
+ it.Next();
+ }
+ // We require a constructor barrier if there are final instance fields.
+ requires_constructor_barrier = false;
+ while (it.HasNextInstanceField()) {
+ if ((it.GetMemberAccessFlags() & kAccFinal) != 0) {
+ requires_constructor_barrier = true;
+ }
+ if (resolve_fields_and_methods) {
+ mirror::ArtField* field = class_linker->ResolveField(dex_file, it.GetMemberIndex(),
+ dex_cache, class_loader, false);
+ if (field == NULL) {
+ CHECK(soa.Self()->IsExceptionPending());
+ soa.Self()->ClearException();
+ }
+ }
+ it.Next();
+ }
+ if (resolve_fields_and_methods) {
+ while (it.HasNextDirectMethod()) {
+ mirror::ArtMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(),
+ dex_cache, class_loader, NULL,
+ it.GetMethodInvokeType(class_def));
+ if (method == NULL) {
+ CHECK(soa.Self()->IsExceptionPending());
+ soa.Self()->ClearException();
+ }
+ it.Next();
+ }
+ while (it.HasNextVirtualMethod()) {
+ mirror::ArtMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(),
+ dex_cache, class_loader, NULL,
+ it.GetMethodInvokeType(class_def));
+ if (method == NULL) {
+ CHECK(soa.Self()->IsExceptionPending());
+ soa.Self()->ClearException();
+ }
+ it.Next();
+ }
+ DCHECK(!it.HasNext());
+ }
}
- it.Next();
}
if (requires_constructor_barrier) {
- manager->GetCompiler()->AddRequiresConstructorBarrier(soa.Self(), manager->GetDexFile(),
- class_def_index);
+ manager->GetCompiler()->AddRequiresConstructorBarrier(self, &dex_file, class_def_index);
}
- while (it.HasNextDirectMethod()) {
- mirror::ArtMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(),
- dex_cache, class_loader, NULL,
- it.GetMethodInvokeType(class_def));
- if (method == NULL) {
- CHECK(self->IsExceptionPending());
- self->ClearException();
- }
- it.Next();
- }
- while (it.HasNextVirtualMethod()) {
- mirror::ArtMethod* method = class_linker->ResolveMethod(dex_file, it.GetMemberIndex(),
- dex_cache, class_loader, NULL,
- it.GetMethodInvokeType(class_def));
- if (method == NULL) {
- CHECK(self->IsExceptionPending());
- self->ClearException();
- }
- it.Next();
- }
- DCHECK(!it.HasNext());
}
static void ResolveType(const ParallelCompilationManager* manager, size_t type_idx)
@@ -1541,10 +1554,16 @@
// TODO: we could resolve strings here, although the string table is largely filled with class
// and method names.
- timings.NewSplit(strdup(("Resolve " + dex_file.GetLocation() + " Types").c_str()));
ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, thread_pool);
- context.ForAll(0, dex_file.NumTypeIds(), ResolveType, thread_count_);
+ if (IsImage()) {
+ // For images we resolve all types, such as array, whereas for applications just those with
+ // classdefs are resolved by ResolveClassFieldsAndMethods.
+ // TODO: strdup memory leak.
+ timings.NewSplit(strdup(("Resolve " + dex_file.GetLocation() + " Types").c_str()));
+ context.ForAll(0, dex_file.NumTypeIds(), ResolveType, thread_count_);
+ }
+ // TODO: strdup memory leak.
timings.NewSplit(strdup(("Resolve " + dex_file.GetLocation() + " MethodsAndFields").c_str()));
context.ForAll(0, dex_file.NumClassDefs(), ResolveClassFieldsAndMethods, thread_count_);
}
@@ -1567,7 +1586,8 @@
mirror::Class* klass =
manager->GetClassLinker()->FindClass(descriptor,
soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader()));
- if (klass == NULL) { CHECK(soa.Self()->IsExceptionPending());
+ if (klass == NULL) {
+ CHECK(soa.Self()->IsExceptionPending());
soa.Self()->ClearException();
/*
@@ -1587,25 +1607,25 @@
<< PrettyDescriptor(manager->GetDexFile()->GetClassDescriptor(class_def))
<< " because: " << error_msg;
}
- return;
+ } else {
+ CHECK(klass->IsResolved()) << PrettyClass(klass);
+ manager->GetClassLinker()->VerifyClass(klass);
+
+ if (klass->IsErroneous()) {
+ // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
+ CHECK(soa.Self()->IsExceptionPending());
+ soa.Self()->ClearException();
+ }
+
+ CHECK(klass->IsCompileTimeVerified() || klass->IsErroneous())
+ << PrettyDescriptor(klass) << ": state=" << klass->GetStatus();
}
- CHECK(klass->IsResolved()) << PrettyClass(klass);
- manager->GetClassLinker()->VerifyClass(klass);
-
- if (klass->IsErroneous()) {
- // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
- CHECK(soa.Self()->IsExceptionPending());
- soa.Self()->ClearException();
- }
-
-
- CHECK(klass->IsCompileTimeVerified() || klass->IsErroneous())
- << PrettyDescriptor(klass) << ": state=" << klass->GetStatus();
soa.Self()->AssertNoPendingException();
}
void CompilerDriver::VerifyDexFile(jobject class_loader, const DexFile& dex_file,
ThreadPool& thread_pool, base::TimingLogger& timings) {
+ // TODO: strdup memory leak.
timings.NewSplit(strdup(("Verify " + dex_file.GetLocation()).c_str()));
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
ParallelCompilationManager context(class_linker, class_loader, this, &dex_file, thread_pool);
@@ -2033,23 +2053,20 @@
mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader());
const char* descriptor = manager->GetDexFile()->GetClassDescriptor(class_def);
mirror::Class* klass = manager->GetClassLinker()->FindClass(descriptor, class_loader);
- bool compiling_boot = Runtime::Current()->GetHeap()->GetContinuousSpaces().size() == 1;
- bool can_init_static_fields = compiling_boot &&
- manager->GetCompiler()->IsImageClass(descriptor);
if (klass != NULL) {
- // We don't want class initialization occurring on multiple threads due to deadlock problems.
- // For example, a parent class is initialized (holding its lock) that refers to a sub-class
- // in its static/class initializer causing it to try to acquire the sub-class' lock. While
- // on a second thread the sub-class is initialized (holding its lock) after first initializing
- // its parents, whose locks are acquired. This leads to a parent-to-child and a child-to-parent
- // lock ordering and consequent potential deadlock.
- // We need to use an ObjectLock due to potential suspension in the interpreting code. Rather
- // than use a special Object for the purpose we use the Class of java.lang.Class.
- ObjectLock lock1(soa.Self(), klass->GetClass());
- // The lock required to initialize the class.
- ObjectLock lock2(soa.Self(), klass);
// Only try to initialize classes that were successfully verified.
if (klass->IsVerified()) {
+ // We don't want class initialization occurring on multiple threads due to deadlock problems.
+ // For example, a parent class is initialized (holding its lock) that refers to a sub-class
+ // in its static/class initializer causing it to try to acquire the sub-class' lock. While
+ // on a second thread the sub-class is initialized (holding its lock) after first initializing
+ // its parents, whose locks are acquired. This leads to a parent-to-child and a child-to-parent
+ // lock ordering and consequent potential deadlock.
+ // We need to use an ObjectLock due to potential suspension in the interpreting code. Rather
+ // than use a special Object for the purpose we use the Class of java.lang.Class.
+ ObjectLock lock(soa.Self(), klass->GetClass());
+ bool can_init_static_fields = manager->GetCompiler()->IsImage() &&
+ manager->GetCompiler()->IsImageClass(descriptor);
manager->GetClassLinker()->EnsureInitialized(klass, false, can_init_static_fields);
if (soa.Self()->IsExceptionPending()) {
soa.Self()->GetException(NULL)->Dump();
@@ -2070,6 +2087,7 @@
VLOG(compiler) << "Initializing: " << descriptor;
if (StringPiece(descriptor) == "Ljava/lang/Void;") {
// Hand initialize j.l.Void to avoid Dex file operations in un-started runtime.
+ ObjectLock lock(soa.Self(), klass);
mirror::ObjectArray<mirror::ArtField>* fields = klass->GetSFields();
CHECK_EQ(fields->GetLength(), 1);
fields->Get(0)->SetObj(klass, manager->GetClassLinker()->FindPrimitiveClass('V'));
@@ -2103,11 +2121,15 @@
void CompilerDriver::InitializeClasses(jobject jni_class_loader, const DexFile& dex_file,
ThreadPool& thread_pool, base::TimingLogger& timings) {
+ // TODO: strdup memory leak.
timings.NewSplit(strdup(("InitializeNoClinit " + dex_file.GetLocation()).c_str()));
#ifndef NDEBUG
- for (size_t i = 0; i < arraysize(class_initializer_black_list); ++i) {
- const char* descriptor = class_initializer_black_list[i];
- CHECK(IsValidDescriptor(descriptor)) << descriptor;
+ // Sanity check blacklist descriptors.
+ if (IsImage()) {
+ for (size_t i = 0; i < arraysize(class_initializer_black_list); ++i) {
+ const char* descriptor = class_initializer_black_list[i];
+ CHECK(IsValidDescriptor(descriptor)) << descriptor;
+ }
}
#endif
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -2139,12 +2161,9 @@
jobject jclass_loader = manager->GetClassLoader();
const DexFile& dex_file = *manager->GetDexFile();
const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
- {
- ScopedObjectAccess soa(Thread::Current());
- mirror::ClassLoader* class_loader = soa.Decode<mirror::ClassLoader*>(jclass_loader);
- if (SkipClass(class_loader, dex_file, class_def)) {
- return;
- }
+ ClassLinker* class_linker = manager->GetClassLinker();
+ if (SkipClass(class_linker, jclass_loader, dex_file, class_def)) {
+ return;
}
ClassReference ref(&dex_file, class_def_index);
// Skip compiling classes with generic verifier failures since they will still fail at runtime
@@ -2172,6 +2191,7 @@
while (it.HasNextInstanceField()) {
it.Next();
}
+ CompilerDriver* driver = manager->GetCompiler();
// Compile direct methods
int64_t previous_direct_method_idx = -1;
while (it.HasNextDirectMethod()) {
@@ -2183,9 +2203,9 @@
continue;
}
previous_direct_method_idx = method_idx;
- manager->GetCompiler()->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
- it.GetMethodInvokeType(class_def), class_def_index,
- method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level);
+ driver->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
+ it.GetMethodInvokeType(class_def), class_def_index,
+ method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level);
it.Next();
}
// Compile virtual methods
@@ -2199,9 +2219,9 @@
continue;
}
previous_virtual_method_idx = method_idx;
- manager->GetCompiler()->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
- it.GetMethodInvokeType(class_def), class_def_index,
- method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level);
+ driver->CompileMethod(it.GetMethodCodeItem(), it.GetMemberAccessFlags(),
+ it.GetMethodInvokeType(class_def), class_def_index,
+ method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level);
it.Next();
}
DCHECK(!it.HasNext());
@@ -2209,8 +2229,10 @@
void CompilerDriver::CompileDexFile(jobject class_loader, const DexFile& dex_file,
ThreadPool& thread_pool, base::TimingLogger& timings) {
+ // TODO: strdup memory leak.
timings.NewSplit(strdup(("Compile " + dex_file.GetLocation()).c_str()));
- ParallelCompilationManager context(NULL, class_loader, this, &dex_file, thread_pool);
+ ParallelCompilationManager context(Runtime::Current()->GetClassLinker(), class_loader, this,
+ &dex_file, thread_pool);
context.ForAll(0, dex_file.NumClassDefs(), CompilerDriver::CompileClass, thread_count_);
}
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 21a44ea..bcde178 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -110,6 +110,7 @@
return compiler_backend_;
}
+ // Are we compiling and creating an image file?
bool IsImage() const {
return image_;
}
diff --git a/compiler/llvm/llvm_compilation_unit.cc b/compiler/llvm/llvm_compilation_unit.cc
index 139100b..aa439cc 100644
--- a/compiler/llvm/llvm_compilation_unit.cc
+++ b/compiler/llvm/llvm_compilation_unit.cc
@@ -214,6 +214,7 @@
::llvm::TargetOptions target_options;
target_options.FloatABIType = ::llvm::FloatABI::Soft;
target_options.NoFramePointerElim = true;
+ target_options.NoFramePointerElimNonLeaf = true;
target_options.UseSoftFloat = false;
target_options.EnableFastISel = false;
@@ -257,7 +258,7 @@
::llvm::OwningPtr< ::llvm::tool_output_file> out_file(
new ::llvm::tool_output_file(bitcode_filename_.c_str(), errmsg,
- ::llvm::sys::fs::F_Binary));
+ ::llvm::raw_fd_ostream::F_Binary));
if (!errmsg.empty()) {
@@ -277,6 +278,7 @@
// pm_builder.Inliner = ::llvm::createAlwaysInlinerPass();
// pm_builder.Inliner = ::llvm::createPartialInliningPass();
pm_builder.OptLevel = 3;
+ pm_builder.DisableSimplifyLibCalls = 1;
pm_builder.DisableUnitAtATime = 1;
pm_builder.populateFunctionPassManager(fpm);
pm_builder.populateModulePassManager(pm);
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index ceb6bf6..511788b 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -137,6 +137,8 @@
UsageError("");
UsageError(" --host: used with Portable backend to link against host runtime libraries");
UsageError("");
+ UsageError(" --dump-timing: display a breakdown of where time was spent");
+ UsageError("");
UsageError(" --runtime-arg <argument>: used to specify various arguments for the runtime,");
UsageError(" such as initial heap size, maximum heap size, and verbose output.");
UsageError(" Use a separate --runtime-arg switch for each argument.");
@@ -607,7 +609,8 @@
#endif
bool is_host = false;
bool dump_stats = kIsDebugBuild;
- bool dump_timings = kIsDebugBuild;
+ bool dump_timing = false;
+ bool dump_slow_timing = kIsDebugBuild;
bool watch_dog_enabled = !kIsTargetBuild;
@@ -695,6 +698,8 @@
LOG(INFO) << "dex2oat: option[" << i << "]=" << argv[i];
}
runtime_args.push_back(argv[i]);
+ } else if (option == "--dump-timing") {
+ dump_timing = true;
} else {
Usage("unknown argument %s", option.data());
}
@@ -825,6 +830,7 @@
return EXIT_FAILURE;
}
+ timings.StartSplit("dex2oat Setup");
LOG(INFO) << "dex2oat: " << oat_location;
Runtime::Options options;
@@ -926,7 +932,6 @@
}
}
- timings.StartSplit("dex2oat Setup");
UniquePtr<const CompilerDriver> compiler(dex2oat->CreateOatFile(boot_image_option,
host_prefix.get(),
android_root,
@@ -1012,7 +1017,7 @@
}
if (is_host) {
- if (dump_timings && timings.GetTotalNs() > MsToNs(1000)) {
+ if (dump_timing || (dump_slow_timing && timings.GetTotalNs() > MsToNs(1000))) {
LOG(INFO) << Dumpable<base::TimingLogger>(timings);
}
return EXIT_SUCCESS;
@@ -1053,7 +1058,7 @@
timings.EndSplit();
- if (dump_timings && timings.GetTotalNs() > MsToNs(1000)) {
+ if (dump_timing && timings.GetTotalNs() > MsToNs(1000)) {
LOG(INFO) << Dumpable<base::TimingLogger>(timings);
}
return EXIT_SUCCESS;
diff --git a/runtime/base/mutex.h b/runtime/base/mutex.h
index 297a63d..cec06cf 100644
--- a/runtime/base/mutex.h
+++ b/runtime/base/mutex.h
@@ -51,8 +51,8 @@
// Record Log contention information, dumpable via SIGQUIT.
#ifdef ART_USE_FUTEXES
-// To enable lock contention logging, flip this to true.
-const bool kLogLockContentions = false;
+// To disable lock contention logging, flip this to false.
+const bool kLogLockContentions = true;
#else
// Keep this false as lock contention logging is supported only with
// futex.
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d0b8bbd..0110b36 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1290,6 +1290,11 @@
return klass;
}
+bool ClassLinker::IsInBootClassPath(const char* descriptor) {
+ DexFile::ClassPathEntry pair = DexFile::FindInClassPath(descriptor, boot_class_path_);
+ return pair.second != NULL;
+}
+
mirror::Class* ClassLinker::FindSystemClass(const char* descriptor) {
return FindClass(descriptor, NULL);
}
@@ -1320,18 +1325,17 @@
}
} else if (Runtime::Current()->UseCompileTimeClassPath()) {
- // first try the boot class path
- mirror::Class* system_class = FindSystemClass(descriptor);
- if (system_class != NULL) {
+ // First try the boot class path, we check the descriptor first to avoid an unnecessary
+ // throw of a NoClassDefFoundError.
+ if (IsInBootClassPath(descriptor)) {
+ mirror::Class* system_class = FindSystemClass(descriptor);
+ CHECK(system_class != NULL);
return system_class;
}
- CHECK(self->IsExceptionPending());
- self->ClearException();
-
- // next try the compile time class path
+ // Next try the compile time class path.
const std::vector<const DexFile*>* class_path;
{
- ScopedObjectAccessUnchecked soa(Thread::Current());
+ ScopedObjectAccessUnchecked soa(self);
ScopedLocalRef<jobject> jclass_loader(soa.Env(), soa.AddLocalReference<jobject>(class_loader));
class_path = &Runtime::Current()->GetCompileTimeClassPath(jclass_loader.get());
}
@@ -2311,8 +2315,9 @@
mirror::Class::Status oat_file_class_status(mirror::Class::kStatusNotReady);
bool preverified = VerifyClassUsingOatFile(dex_file, klass, oat_file_class_status);
if (oat_file_class_status == mirror::Class::kStatusError) {
- LOG(WARNING) << "Skipping runtime verification of erroneous class " << PrettyDescriptor(klass)
- << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
+ VLOG(class_linker) << "Skipping runtime verification of erroneous class "
+ << PrettyDescriptor(klass) << " in "
+ << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
ThrowVerifyError(klass, "Rejecting class %s because it failed compile-time verification",
PrettyDescriptor(klass).c_str());
klass->SetStatus(mirror::Class::kStatusError);
@@ -2326,7 +2331,7 @@
}
if (preverified || verifier_failure != verifier::MethodVerifier::kHardFailure) {
if (!preverified && verifier_failure != verifier::MethodVerifier::kNoFailure) {
- LOG(WARNING) << "Soft verification failure in class " << PrettyDescriptor(klass)
+ VLOG(class_linker) << "Soft verification failure in class " << PrettyDescriptor(klass)
<< " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
<< " because: " << error_msg;
}
@@ -2696,7 +2701,6 @@
Thread* self = Thread::Current();
- mirror::ArtMethod* clinit = NULL;
{
// see JLS 3rd edition, 12.4.2 "Detailed Initialization Procedure" for the locking protocol
ObjectLock lock(self, klass);
@@ -2721,16 +2725,6 @@
}
}
- clinit = klass->FindDeclaredDirectMethod("<clinit>", "()V");
- if (clinit != NULL && !can_run_clinit) {
- // if the class has a <clinit> but we can't run it during compilation,
- // don't bother going to kStatusInitializing. We return false so that
- // sub-classes don't believe this class is initialized.
- // Opportunistically link non-static methods, TODO: don't initialize and dirty pages
- // in second pass.
- return false;
- }
-
// If the class is kStatusInitializing, either this thread is
// initializing higher up the stack or another thread has beat us
// to initializing and we need to wait. Either way, this
@@ -2775,9 +2769,10 @@
return false;
}
- bool has_static_field_initializers = InitializeStaticFields(klass);
+ bool has_static_field_initializers = InitializeStaticFields(klass, can_init_statics);
- if (clinit != NULL) {
+ mirror::ArtMethod* clinit = klass->FindDeclaredDirectMethod("<clinit>", "()V");
+ if (clinit != NULL && can_run_clinit) {
if (Runtime::Current()->IsStarted()) {
JValue result;
clinit->Invoke(self, NULL, 0, &result, 'V');
@@ -2786,7 +2781,11 @@
}
}
- FixupStaticTrampolines(klass);
+ // Opportunistically set static method trampolines to their destination. Unless initialization
+ // is being hindered at compile time.
+ if (can_init_statics || can_run_clinit || (!has_static_field_initializers && clinit == NULL)) {
+ FixupStaticTrampolines(klass);
+ }
uint64_t t1 = NanoTime();
@@ -2805,15 +2804,15 @@
++thread_stats->class_init_count;
global_stats->class_init_time_ns += (t1 - t0);
thread_stats->class_init_time_ns += (t1 - t0);
- // Set the class as initialized except if we can't initialize static fields and static field
- // initialization is necessary.
- if (!can_init_statics && has_static_field_initializers) {
- klass->SetStatus(mirror::Class::kStatusVerified); // Don't leave class in initializing state.
+ // Set the class as initialized except if failed to initialize static fields.
+ if ((!can_init_statics && has_static_field_initializers) ||
+ (!can_run_clinit && clinit != NULL)) {
+ klass->SetStatus(mirror::Class::kStatusVerified);
success = false;
} else {
klass->SetStatus(mirror::Class::kStatusInitialized);
}
- if (VLOG_IS_ON(class_linker)) {
+ if (success && VLOG_IS_ON(class_linker)) {
ClassHelper kh(klass);
LOG(INFO) << "Initialized class " << kh.GetDescriptor() << " from " << kh.GetLocation();
}
@@ -2986,10 +2985,9 @@
return true;
}
- Thread* self = Thread::Current();
- ScopedThreadStateChange tsc(self, kRunnable);
bool success = InitializeClass(c, can_run_clinit, can_init_fields);
if (!success) {
+ Thread* self = Thread::Current();
CHECK(self->IsExceptionPending() || !can_run_clinit) << PrettyClass(c);
}
return success;
@@ -3005,7 +3003,7 @@
}
}
-bool ClassLinker::InitializeStaticFields(mirror::Class* klass) {
+bool ClassLinker::InitializeStaticFields(mirror::Class* klass, bool can_init_statics) {
size_t num_static_fields = klass->NumStaticFields();
if (num_static_fields == 0) {
return false;
@@ -3022,16 +3020,19 @@
EncodedStaticFieldValueIterator it(dex_file, dex_cache, klass->GetClassLoader(),
this, *dex_class_def);
- if (it.HasNext()) {
- // We reordered the fields, so we need to be able to map the field indexes to the right fields.
- SafeMap<uint32_t, mirror::ArtField*> field_map;
- ConstructFieldMap(dex_file, *dex_class_def, klass, field_map);
- for (size_t i = 0; it.HasNext(); i++, it.Next()) {
- it.ReadValueToField(field_map.Get(i));
+ if (!it.HasNext()) {
+ return false;
+ } else {
+ if (can_init_statics) {
+ // We reordered the fields, so we need to be able to map the field indexes to the right fields.
+ SafeMap<uint32_t, mirror::ArtField*> field_map;
+ ConstructFieldMap(dex_file, *dex_class_def, klass, field_map);
+ for (size_t i = 0; it.HasNext(); i++, it.Next()) {
+ it.ReadValueToField(field_map.Get(i));
+ }
}
return true;
}
- return false;
}
bool ClassLinker::LinkClass(SirtRef<mirror::Class>& klass,
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index d0cc562..624b7ce 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -62,6 +62,8 @@
~ClassLinker();
+ bool IsInBootClassPath(const char* descriptor);
+
// Finds a class by its descriptor, loading it if necessary.
// If class_loader is null, searches boot_class_path_.
mirror::Class* FindClass(const char* descriptor, mirror::ClassLoader* class_loader)
@@ -443,7 +445,7 @@
bool InitializeSuperClass(mirror::Class* klass, bool can_run_clinit, bool can_init_fields)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Initialize static fields, returns true if fields were initialized.
- bool InitializeStaticFields(mirror::Class* klass)
+ bool InitializeStaticFields(mirror::Class* klass, bool can_init_statics)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
bool IsSameDescriptorInDifferentClassContexts(const char* descriptor,