Merge "Clinits may not have the kAccConstructor flag." into dalvik-dev
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 9e67f5a..c37b548 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1865,47 +1865,54 @@
const char* old_cause = self->StartAssertNoThreadSuspension("LoadMethod");
dst->SetDexMethodIndex(dex_method_idx);
dst->SetDeclaringClass(klass.get());
-
- if (method_name == "finalize") {
- // Create the prototype for a signature of "()V"
- const DexFile::StringId* void_string_id = dex_file.FindStringId("V");
- if (void_string_id != NULL) {
- const DexFile::TypeId* void_type_id =
- dex_file.FindTypeId(dex_file.GetIndexForStringId(*void_string_id));
- if (void_type_id != NULL) {
- std::vector<uint16_t> no_args;
- const DexFile::ProtoId* finalizer_proto =
- dex_file.FindProtoId(dex_file.GetIndexForTypeId(*void_type_id), no_args);
- if (finalizer_proto != NULL) {
- // We have the prototype in the dex file
- if (klass->GetClassLoader() != NULL) { // All non-boot finalizer methods are flagged
- klass->SetFinalizable();
- } else {
- ClassHelper kh(klass.get());
- StringPiece klass_descriptor(kh.GetDescriptorAsStringPiece());
- // The Enum class declares a "final" finalize() method to prevent subclasses from
- // introducing a finalizer. We don't want to set the finalizable flag for Enum or its
- // subclasses, so we exclude it here.
- // We also want to avoid setting the flag on Object, where we know that finalize() is
- // empty.
- if (klass_descriptor != "Ljava/lang/Object;" &&
- klass_descriptor != "Ljava/lang/Enum;") {
- klass->SetFinalizable();
- }
- }
- }
- }
- }
- }
dst->SetCodeItemOffset(it.GetMethodCodeItemOffset());
- dst->SetAccessFlags(it.GetMemberAccessFlags());
dst->SetDexCacheStrings(klass->GetDexCache()->GetStrings());
dst->SetDexCacheResolvedMethods(klass->GetDexCache()->GetResolvedMethods());
dst->SetDexCacheResolvedTypes(klass->GetDexCache()->GetResolvedTypes());
dst->SetDexCacheInitializedStaticStorage(klass->GetDexCache()->GetInitializedStaticStorage());
- CHECK(dst->IsArtMethod());
+ uint32_t access_flags = it.GetMemberAccessFlags();
+
+ if (UNLIKELY(method_name == "finalize")) {
+ // Set finalizable flag on declaring class.
+ const DexFile::ProtoId& proto = dex_file.GetProtoId(method_id.proto_idx_);
+ if (dex_file.GetProtoParameters(proto) == NULL) { // No arguments
+ const DexFile::TypeId& return_type = dex_file.GetTypeId(proto.return_type_idx_);
+ if (dex_file.StringDataAsStringPieceByIdx(return_type.descriptor_idx_) == "V") {
+ // Void return type.
+ if (klass->GetClassLoader() != NULL) { // All non-boot finalizer methods are flagged
+ klass->SetFinalizable();
+ } else {
+ ClassHelper kh(klass.get());
+ StringPiece klass_descriptor(kh.GetDescriptorAsStringPiece());
+ // The Enum class declares a "final" finalize() method to prevent subclasses from
+ // introducing a finalizer. We don't want to set the finalizable flag for Enum or its
+ // subclasses, so we exclude it here.
+ // We also want to avoid setting the flag on Object, where we know that finalize() is
+ // empty.
+ if (klass_descriptor != "Ljava/lang/Object;" &&
+ klass_descriptor != "Ljava/lang/Enum;") {
+ klass->SetFinalizable();
+ }
+ }
+ }
+ }
+ } else if (method_name[0] == '<') {
+ // Fix broken access flags for initializers. Bug 11157540.
+ bool is_init = (method_name == "<init>");
+ bool is_clinit = !is_init && (method_name == "<clinit>");
+ if (UNLIKELY(!is_init && !is_clinit)) {
+ LOG(WARNING) << "Unexpected '<' at start of method name " << method_name;
+ } else {
+ if (UNLIKELY((access_flags & kAccConstructor) == 0)) {
+ LOG(WARNING) << method_name << " didn't have expected constructor access flag in class "
+ << PrettyDescriptor(klass.get()) << " in dex file " << dex_file.GetLocation();
+ access_flags |= kAccConstructor;
+ }
+ }
+ }
+ dst->SetAccessFlags(access_flags);
self->EndAssertNoThreadSuspension(old_cause);
return dst;
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index ad9347f..029b73e 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -996,7 +996,7 @@
CHECK(dex_file != NULL);
mirror::Class* klass = class_linker_->FindClass("LStaticsFromCode;", class_loader.get());
- mirror::ArtMethod* clinit = klass->FindDirectMethod("<clinit>", "()V");
+ mirror::ArtMethod* clinit = klass->FindClassInitializer();
mirror::ArtMethod* getS0 = klass->FindDirectMethod("getS0", "()Ljava/lang/Object;");
const DexFile::StringId* string_id = dex_file->FindStringId("LStaticsFromCode;");
ASSERT_TRUE(string_id != NULL);
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index e9e6c5a..c32a661 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -312,7 +312,7 @@
//
// Do not set the DexCache InitializedStaticStorage, since that implies <clinit> has finished
// running.
- if (klass == referring_class && MethodHelper(referrer).IsClassInitializer()) {
+ if (klass == referring_class && referrer->IsConstructor() && referrer->IsStatic()) {
return klass;
}
if (!class_linker->EnsureInitialized(klass, true, true)) {
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index b16c2f7..2b0b1e1 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -500,6 +500,7 @@
if (method->IsConstructor() && method->IsStatic()) {
if (kIsDebugBuild) {
MethodHelper mh(method);
+ CHECK(mh.IsClassInitializer());
CHECK_STREQ(mh.GetName(), "<clinit>");
CHECK_STREQ(mh.GetSignature().ToString().c_str(), "()V");
}
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 1e610f2..4c5f90c 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -270,7 +270,7 @@
Class* klass =
class_linker_->FindClass("LStaticsFromCode;", soa.Decode<ClassLoader*>(class_loader));
- ArtMethod* clinit = klass->FindDirectMethod("<clinit>", "()V");
+ ArtMethod* clinit = klass->FindClassInitializer();
const DexFile::StringId* klass_string_id = dex_file->FindStringId("LStaticsFromCode;");
ASSERT_TRUE(klass_string_id != NULL);
const DexFile::TypeId* klass_type_id = dex_file->FindTypeId(
diff --git a/runtime/object_utils.h b/runtime/object_utils.h
index 692cecc..8062a89 100644
--- a/runtime/object_utils.h
+++ b/runtime/object_utils.h
@@ -592,7 +592,7 @@
}
bool IsClassInitializer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- return IsStatic() && GetNameAsStringPiece() == "<clinit>";
+ return method_->IsConstructor() && IsStatic();
}
size_t NumArgs() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {