Revert "Initialize classes in runtime app images."
This reverts commit b6a24146c89620fd9ee42b9f83d3118ab7e9ead0.
Reason for revert: DroidMonitor-triggered revert due to bug b/273999229
Bug: 273999229
Change-Id: I00a635f69ac91d33c707487e0e534a721f0ca045
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index bd7ae4c..7848a80 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -382,12 +382,6 @@
ArtField* LookupResolvedField(uint32_t field_idx, ArtMethod* referrer, bool is_static)
REQUIRES_SHARED(Locks::mutator_lock_);
- // Find a field by its field index.
- ArtField* LookupResolvedField(uint32_t field_idx,
- ObjPtr<mirror::DexCache> dex_cache,
- ObjPtr<mirror::ClassLoader> class_loader,
- bool is_static)
- REQUIRES_SHARED(Locks::mutator_lock_);
ArtField* ResolveField(uint32_t field_idx, ArtMethod* referrer, bool is_static)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
@@ -1119,6 +1113,13 @@
REQUIRES(!Locks::classlinker_classes_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
+ // Find a field by its field index.
+ ArtField* LookupResolvedField(uint32_t field_idx,
+ ObjPtr<mirror::DexCache> dex_cache,
+ ObjPtr<mirror::ClassLoader> class_loader,
+ bool is_static)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
void RegisterDexFileLocked(const DexFile& dex_file,
ObjPtr<mirror::DexCache> dex_cache,
ObjPtr<mirror::ClassLoader> class_loader)
diff --git a/runtime/runtime_image.cc b/runtime/runtime_image.cc
index 1eabe82..b8a9c5a 100644
--- a/runtime/runtime_image.cc
+++ b/runtime/runtime_image.cc
@@ -37,7 +37,6 @@
#include "class_loader_context.h"
#include "class_loader_utils.h"
#include "class_root-inl.h"
-#include "dex/class_accessor-inl.h"
#include "gc/space/image_space.h"
#include "image.h"
#include "mirror/object-inl.h"
@@ -232,7 +231,7 @@
// Returns a pointer that can be stored in `objects_`:
// - The pointer itself for boot image objects,
// - The offset in the image for all other objects.
- template <typename T> T* GetOrComputeImageAddress(ObjPtr<T> object)
+ mirror::Object* GetOrComputeImageAddress(ObjPtr<mirror::Object> object)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (object == nullptr || IsInBootImage(object.Ptr())) {
DCHECK(object == nullptr || Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(object));
@@ -260,7 +259,7 @@
} else {
offset = CopyObject(object);
}
- return reinterpret_cast<T*>(image_begin_ + sizeof(ImageHeader) + offset);
+ return reinterpret_cast<mirror::Object*>(image_begin_ + sizeof(ImageHeader) + offset);
}
void CreateImageSections() {
@@ -861,9 +860,7 @@
}
}
- void CopyMethodArrays(ObjPtr<mirror::Class> cls,
- uint32_t class_image_address,
- bool is_class_initialized)
+ void CopyMethodArrays(ObjPtr<mirror::Class> cls, uint32_t class_image_address)
REQUIRES_SHARED(Locks::mutator_lock_) {
size_t number_of_methods = cls->NumMethods();
if (number_of_methods == 0) {
@@ -918,7 +915,7 @@
stub = StubType::kQuickGenericJNITrampoline;
} else if (!cls->IsVerified()) {
stub = StubType::kQuickToInterpreterBridge;
- } else if (!is_class_initialized && method->NeedsClinitCheckBeforeCall()) {
+ } else if (method->NeedsClinitCheckBeforeCall()) {
stub = StubType::kQuickResolutionTrampoline;
} else if (interpreter::IsNterpSupported() && CanMethodUseNterp(method)) {
stub = StubType::kNterpTrampoline;
@@ -1187,7 +1184,7 @@
// and initialized at runtime.
ObjPtr<mirror::Object> ref =
is_static ? nullptr : obj->GetFieldObject<mirror::Object>(offset);
- mirror::Object* address = image_->GetOrComputeImageAddress(ref);
+ mirror::Object* address = image_->GetOrComputeImageAddress(ref.Ptr());
mirror::Object* copy =
reinterpret_cast<mirror::Object*>(image_->objects_.data() + copy_offset_);
copy->GetFieldObjectReferenceAddr<kVerifyNone>(offset)->Assign(address);
@@ -1348,177 +1345,6 @@
return offset;
}
- // Try to initialize `copy`. Note that `cls` may not be initialized.
- // This is called after the image generation logic has visited super classes
- // and super interfaces, so we can just check those directly.
- bool TryInitializeClass(mirror::Class* copy, ObjPtr<mirror::Class> cls, uint32_t class_offset)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- if (!cls->IsVerified()) {
- return false;
- }
- if (cls->IsArrayClass()) {
- return true;
- }
-
- // Check if we have been able to initialize the super class.
- mirror::Class* super = GetOrComputeImageAddress(cls->GetSuperClass());
- if (!super->IsInitialized()) {
- return false;
- }
-
- // We won't initialize class with class initializers.
- if (cls->FindClassInitializer(kRuntimePointerSize) != nullptr) {
- return false;
- }
-
- // For non-interface classes, we require all implemented interfaces to be
- // initialized.
- if (!cls->IsInterface()) {
- for (size_t i = 0; i < cls->NumDirectInterfaces(); i++) {
- mirror::Class* itf = GetOrComputeImageAddress(cls->GetDirectInterface(i));
- if (!itf->IsInitialized()) {
- return false;
- }
- }
- }
-
- // Trivial case: no static fields.
- if (cls->NumStaticFields() == 0u) {
- return true;
- }
-
- // Go over all static fields and try to initialize them.
- EncodedStaticFieldValueIterator it(cls->GetDexFile(), *cls->GetClassDef());
- if (!it.HasNext()) {
- return true;
- }
-
- // Temporary string offsets in case we failed to initialize the class. We
- // will add the offsets at the end of this method if we are successful.
- ArenaVector<AppImageReferenceOffsetInfo> string_offsets(allocator_.Adapter());
- ClassLinker* linker = Runtime::Current()->GetClassLinker();
- ClassAccessor accessor(cls->GetDexFile(), *cls->GetClassDef());
- for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
- if (!it.HasNext()) {
- break;
- }
- ArtField* art_field = linker->LookupResolvedField(field.GetIndex(),
- cls->GetDexCache(),
- cls->GetClassLoader(),
- /* is_static= */ true);
- DCHECK_NE(art_field, nullptr);
- MemberOffset offset(art_field->GetOffset());
- switch (it.GetValueType()) {
- case EncodedArrayValueIterator::ValueType::kBoolean:
- copy->SetFieldBoolean<false>(offset, it.GetJavaValue().z);
- break;
- case EncodedArrayValueIterator::ValueType::kByte:
- copy->SetFieldByte<false>(offset, it.GetJavaValue().b);
- break;
- case EncodedArrayValueIterator::ValueType::kShort:
- copy->SetFieldShort<false>(offset, it.GetJavaValue().s);
- break;
- case EncodedArrayValueIterator::ValueType::kChar:
- copy->SetFieldChar<false>(offset, it.GetJavaValue().c);
- break;
- case EncodedArrayValueIterator::ValueType::kInt:
- copy->SetField32<false>(offset, it.GetJavaValue().i);
- break;
- case EncodedArrayValueIterator::ValueType::kLong:
- copy->SetField64<false>(offset, it.GetJavaValue().j);
- break;
- case EncodedArrayValueIterator::ValueType::kFloat:
- copy->SetField32<false>(offset, it.GetJavaValue().i);
- break;
- case EncodedArrayValueIterator::ValueType::kDouble:
- copy->SetField64<false>(offset, it.GetJavaValue().j);
- break;
- case EncodedArrayValueIterator::ValueType::kNull:
- copy->SetFieldObject<false>(offset, nullptr);
- break;
- case EncodedArrayValueIterator::ValueType::kString: {
- ObjPtr<mirror::String> str =
- linker->LookupString(dex::StringIndex(it.GetJavaValue().i), cls->GetDexCache());
- mirror::String* str_copy = nullptr;
- if (str == nullptr) {
- // String wasn't created yet.
- return false;
- } else if (IsInBootImage(str.Ptr())) {
- str_copy = str.Ptr();
- } else {
- uint32_t hash = static_cast<uint32_t>(str->GetStoredHashCode());
- DCHECK_EQ(hash, static_cast<uint32_t>(str->ComputeHashCode()))
- << "Dex cache strings should be interned";
- auto string_it = intern_table_.FindWithHash(str.Ptr(), hash);
- if (string_it == intern_table_.end()) {
- // The string must be interned.
- uint32_t string_offset = CopyObject(str);
- uint32_t address = image_begin_ + string_offset + sizeof(ImageHeader);
- intern_table_.InsertWithHash(address, hash);
- str_copy = reinterpret_cast<mirror::String*>(address);
- } else {
- str_copy = reinterpret_cast<mirror::String*>(*string_it);
- }
- }
- uint8_t* raw_addr = reinterpret_cast<uint8_t*>(copy) + offset.Int32Value();
- mirror::HeapReference<mirror::Object>* objref_addr =
- reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr);
- objref_addr->Assign</* kIsVolatile= */ false>(str_copy);
- string_offsets.emplace_back(sizeof(ImageHeader) + class_offset, offset.Int32Value());
- break;
- }
- case EncodedArrayValueIterator::ValueType::kType: {
- // Note that it may be that the referenced type hasn't been processed
- // yet by the image generation logic. In this case we bail out for
- // simplicity.
- ObjPtr<mirror::Class> type =
- linker->LookupResolvedType(dex::TypeIndex(it.GetJavaValue().i), cls);
- mirror::Class* type_copy = nullptr;
- if (type == nullptr) {
- // Class wasn't resolved yet.
- return false;
- } else if (IsInBootImage(type.Ptr())) {
- // Make sure the type is in our class table.
- uint32_t hash = type->DescriptorHash();
- class_table_.InsertWithHash(ClassTable::TableSlot(type.Ptr(), hash), hash);
- type_copy = type.Ptr();
- } else if (type->IsArrayClass()) {
- std::string class_name;
- type->GetDescriptor(&class_name);
- auto class_it = array_classes_.find(class_name);
- if (class_it == array_classes_.end()) {
- return false;
- }
- type_copy = reinterpret_cast<mirror::Class*>(
- image_begin_ + sizeof(ImageHeader) + class_it->second);
- } else {
- const dex::ClassDef* class_def = type->GetClassDef();
- DCHECK_NE(class_def, nullptr);
- auto class_it = classes_.find(class_def);
- if (class_it == classes_.end()) {
- return false;
- }
- type_copy = reinterpret_cast<mirror::Class*>(
- image_begin_ + sizeof(ImageHeader) + class_it->second);
- }
- uint8_t* raw_addr = reinterpret_cast<uint8_t*>(copy) + offset.Int32Value();
- mirror::HeapReference<mirror::Object>* objref_addr =
- reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr);
- objref_addr->Assign</* kIsVolatile= */ false>(type_copy);
- break;
- }
- default:
- LOG(FATAL) << "Unreachable";
- }
- it.Next();
- }
- // We have successfully initialized the class, we can now record the string
- // offsets.
- string_reference_offsets_.insert(
- string_reference_offsets_.end(), string_offsets.begin(), string_offsets.end());
- return true;
- }
-
uint32_t CopyClass(ObjPtr<mirror::Class> cls) REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(!cls->IsBootStrapClassLoaded());
uint32_t offset = 0u;
@@ -1562,24 +1388,13 @@
copy->SetAccessFlags(copy->GetAccessFlags() & ~kAccRecursivelyInitialized);
// Clear static field values.
- auto clear_class = [&] () REQUIRES_SHARED(Locks::mutator_lock_) {
- MemberOffset static_offset = cls->GetFirstReferenceStaticFieldOffset(kRuntimePointerSize);
- memset(objects_.data() + offset + static_offset.Uint32Value(),
- 0,
- cls->GetClassSize() - static_offset.Uint32Value());
- };
- clear_class();
-
- bool is_class_initialized = TryInitializeClass(copy, cls, offset);
- if (is_class_initialized) {
- copy->SetStatusInternal(ClassStatus::kVisiblyInitialized);
- } else {
- // If we fail to initialize clear again.
- clear_class();
- }
+ MemberOffset static_offset = cls->GetFirstReferenceStaticFieldOffset(kRuntimePointerSize);
+ memset(objects_.data() + offset + static_offset.Uint32Value(),
+ 0,
+ cls->GetClassSize() - static_offset.Uint32Value());
CopyFieldArrays(cls, class_image_address);
- CopyMethodArrays(cls, class_image_address, is_class_initialized);
+ CopyMethodArrays(cls, class_image_address);
if (cls->ShouldHaveImt()) {
CopyImTable(cls);
}
diff --git a/test/845-data-image/src-art/Main.java b/test/845-data-image/src-art/Main.java
index 1eaa6eb..3c76e88 100644
--- a/test/845-data-image/src-art/Main.java
+++ b/test/845-data-image/src-art/Main.java
@@ -23,15 +23,6 @@
import java.lang.reflect.Method;
import java.util.concurrent.CyclicBarrier;
-class ClassWithStatics {
- public static final String STATIC_STRING = "foo";
- public static final int STATIC_INT = 42;
-}
-
-class ClassWithStaticType {
- public static final Class<?> STATIC_TYPE = Object.class;
-}
-
// Add an interface for testing generating classes and interfaces.
interface Itf {
public int someMethod();
@@ -207,8 +198,6 @@
public static Itf itf = new Main();
public static Itf2 itf2 = new Itf2Impl();
- public static ClassWithStatics statics = new ClassWithStatics();
- public static ClassWithStaticType staticType = new ClassWithStaticType();
public static void runClassTests() {
// Test Class.getName, app images expect all strings to have hash codes.
@@ -240,11 +229,6 @@
assertEquals("int", int.class.getName());
assertEquals("[I", int[].class.getName());
- assertEquals("foo", statics.STATIC_STRING);
- assertEquals(42, statics.STATIC_INT);
-
- assertEquals(Object.class, staticType.STATIC_TYPE);
-
// Call all interface methods to trigger the creation of a imt conflict method.
itf2.defaultMethod1();
itf2.defaultMethod2();