Re-enable parallel verification.
Check that when verifying and initializing a class the lock on the class
is held.
Add logging for slow verification of a method.
Change-Id: Id51f8a108b8d1801d61ee276fab5001ddc5c0044
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 2ee8bd8..a88a2d6 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -274,14 +274,14 @@
SetClassRoot(kJavaLangString, java_lang_String.get());
// Setup the primitive type classes.
- SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass("Z", Primitive::kPrimBoolean));
- SetClassRoot(kPrimitiveByte, CreatePrimitiveClass("B", Primitive::kPrimByte));
- SetClassRoot(kPrimitiveShort, CreatePrimitiveClass("S", Primitive::kPrimShort));
- SetClassRoot(kPrimitiveInt, CreatePrimitiveClass("I", Primitive::kPrimInt));
- SetClassRoot(kPrimitiveLong, CreatePrimitiveClass("J", Primitive::kPrimLong));
- SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass("F", Primitive::kPrimFloat));
- SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass("D", Primitive::kPrimDouble));
- SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass("V", Primitive::kPrimVoid));
+ SetClassRoot(kPrimitiveBoolean, CreatePrimitiveClass(Primitive::kPrimBoolean));
+ SetClassRoot(kPrimitiveByte, CreatePrimitiveClass(Primitive::kPrimByte));
+ SetClassRoot(kPrimitiveShort, CreatePrimitiveClass(Primitive::kPrimShort));
+ SetClassRoot(kPrimitiveInt, CreatePrimitiveClass(Primitive::kPrimInt));
+ SetClassRoot(kPrimitiveLong, CreatePrimitiveClass(Primitive::kPrimLong));
+ SetClassRoot(kPrimitiveFloat, CreatePrimitiveClass(Primitive::kPrimFloat));
+ SetClassRoot(kPrimitiveDouble, CreatePrimitiveClass(Primitive::kPrimDouble));
+ SetClassRoot(kPrimitiveVoid, CreatePrimitiveClass(Primitive::kPrimVoid));
// Create array interface entries to populate once we can load system classes
array_iftable_ = AllocObjectArray<InterfaceEntry>(2);
@@ -327,7 +327,7 @@
// now we can use FindSystemClass
// run char class through InitializePrimitiveClass to finish init
- InitializePrimitiveClass(char_class.get(), "C", Primitive::kPrimChar);
+ InitializePrimitiveClass(char_class.get(), Primitive::kPrimChar);
SetClassRoot(kPrimitiveChar, char_class.get()); // needs descriptor
// Object and String need to be rerun through FindSystemClass to finish init
@@ -1714,16 +1714,14 @@
}
}
-Class* ClassLinker::InitializePrimitiveClass(Class* primitive_class,
- const char* descriptor,
- Primitive::Type type) {
- // TODO: deduce one argument from the other
+Class* ClassLinker::InitializePrimitiveClass(Class* primitive_class, Primitive::Type type) {
CHECK(primitive_class != NULL);
+ ObjectLock lock(primitive_class); // Must hold lock on object when initializing.
primitive_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
primitive_class->SetPrimitiveType(type);
primitive_class->SetStatus(Class::kStatusInitialized);
- Class* existing = InsertClass(descriptor, primitive_class, false);
- CHECK(existing == NULL) << "InitPrimitiveClass(" << descriptor << ") failed";
+ Class* existing = InsertClass(Primitive::Descriptor(type), primitive_class, false);
+ CHECK(existing == NULL) << "InitPrimitiveClass(" << type << ") failed";
return primitive_class;
}
@@ -1803,6 +1801,7 @@
}
new_class->SetComponentType(component_type);
}
+ ObjectLock lock(new_class.get()); // Must hold lock on object when initializing.
DCHECK(new_class->GetComponentType() != NULL);
Class* java_lang_Object = GetClassRoot(kJavaLangObject);
new_class->SetSuperClass(java_lang_Object);
@@ -2272,9 +2271,12 @@
klass->SetStatus(Class::kStatusError);
return NULL;
}
- interfaces_sfield->SetObject(NULL, interfaces);
- throws_sfield->SetObject(NULL, throws);
- klass->SetStatus(Class::kStatusInitialized);
+ {
+ ObjectLock lock(klass.get()); // Must hold lock on object when initializing.
+ interfaces_sfield->SetObject(NULL, interfaces);
+ throws_sfield->SetObject(NULL, throws);
+ klass->SetStatus(Class::kStatusInitialized);
+ }
// sanity checks
if (kIsDebugBuild) {
@@ -2663,10 +2665,8 @@
Class* super_class = klass->GetSuperClass();
if (super_class->GetStatus() != Class::kStatusInitialized) {
CHECK(!super_class->IsInterface());
- Thread* self = Thread::Current();
- klass->MonitorEnter(self);
+ ObjectLock lock(klass); // Must hold lock on object when initializing.
bool super_initialized = InitializeClass(super_class, can_run_clinit, can_init_fields);
- klass->MonitorExit(self);
// TODO: check for a pending exception
if (!super_initialized) {
if (!can_run_clinit) {
diff --git a/src/class_linker.h b/src/class_linker.h
index c21ff71..3cee7f0 100644
--- a/src/class_linker.h
+++ b/src/class_linker.h
@@ -390,13 +390,11 @@
InterfaceEntry* AllocInterfaceEntry(Class* interface)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- Class* CreatePrimitiveClass(const char* descriptor, Primitive::Type type)
+ Class* CreatePrimitiveClass(Primitive::Type type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return InitializePrimitiveClass(AllocClass(sizeof(Class)), descriptor, type);
+ return InitializePrimitiveClass(AllocClass(sizeof(Class)), type);
}
- Class* InitializePrimitiveClass(Class* primitive_class,
- const char* descriptor,
- Primitive::Type type)
+ Class* InitializePrimitiveClass(Class* primitive_class, Primitive::Type type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/src/compiler.cc b/src/compiler.cc
index 69de8ca..b010750 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -481,11 +481,7 @@
TimingLogger timings("compiler");
- // TODO: make the verifier thread-safe and remove this workaround.
- size_t thread_count = thread_count_;
- thread_count_ = 1;
PreCompile(class_loader, dex_files, timings);
- thread_count_ = thread_count;
Compile(class_loader, dex_files);
timings.AddSplit("Compile");
diff --git a/src/object.cc b/src/object.cc
index cde7e04..dcf4ce9 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -612,6 +612,9 @@
CHECK(new_status > GetStatus() || new_status == kStatusError || !Runtime::Current()->IsStarted())
<< PrettyClass(this) << " " << GetStatus() << " -> " << new_status;
CHECK(sizeof(Status) == sizeof(uint32_t)) << PrettyClass(this);
+ if (new_status > kStatusResolved) {
+ CHECK_EQ(GetThinLockId(), Thread::Current()->GetThinLockId()) << PrettyClass(this);
+ }
if (new_status == kStatusError) {
CHECK_NE(GetStatus(), kStatusError) << PrettyClass(this);
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index 813073d..ce5129d 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -281,6 +281,9 @@
MethodVerifier::FailureKind MethodVerifier::VerifyMethod(uint32_t method_idx, const DexFile* dex_file,
DexCache* dex_cache, ClassLoader* class_loader, uint32_t class_def_idx,
const DexFile::CodeItem* code_item, Method* method, uint32_t method_access_flags) {
+ MethodVerifier::FailureKind result = kNoFailure;
+ uint64_t start_ns = NanoTime();
+
MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item, method_idx,
method, method_access_flags);
if (verifier.Verify()) {
@@ -290,7 +293,7 @@
if (verifier.failures_.size() != 0) {
verifier.DumpFailures(LOG(INFO) << "Soft verification failures in "
<< PrettyMethod(method_idx, *dex_file) << "\n");
- return kSoftFailure;
+ result = kSoftFailure;
}
} else {
// Bad method data.
@@ -302,9 +305,14 @@
std::cout << "\n" << verifier.info_messages_.str();
verifier.Dump(std::cout);
}
- return kHardFailure;
+ result = kHardFailure;
}
- return kNoFailure;
+ uint64_t duration_ns = NanoTime() - start_ns;
+ if (duration_ns > MsToNs(100)) {
+ LOG(WARNING) << "Verification of " << PrettyMethod(method_idx, *dex_file)
+ << " took " << PrettyDuration(duration_ns);
+ }
+ return result;
}
void MethodVerifier::VerifyMethodAndDump(Method* method) {