Initialize array classes in pre-fence visitor.
Rewrite array class initialization to make it easier to
reason about memory visibility. Initialize all members in
the pre-fence visitor for the normal use case. Refactor
initialization of core array classes without boot image to
avoid special-casing in ClassLinker::CreateArrayClass().
Note that the Class::object_size_alloc_fast_path_ field
of primitive classes (instances of which cannot be
allocated) will be kept at numeric_limits<uint32_t>::max().
The boot image before and after is otherwise identical.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: aosp_taimen-userdebug boots.
Test: run-gtests.sh
Test: testrunner.py --target --optimizing
Change-Id: I570e3af011c8d3383ce46c81eb6f2fa60c5a4b0f
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 23df946..422625d 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -236,6 +236,38 @@
}
}
+void Class::SetStatusForPrimitiveOrArray(ClassStatus new_status) {
+ DCHECK(IsPrimitive<kVerifyNone>() || IsArrayClass<kVerifyNone>());
+ DCHECK(!IsErroneous(new_status));
+ DCHECK(!IsErroneous(GetStatus<kVerifyNone>()));
+ DCHECK_GT(new_status, GetStatus<kVerifyNone>());
+
+ if (kBitstringSubtypeCheckEnabled) {
+ LOG(FATAL) << "Unimplemented";
+ }
+ // The ClassStatus is always in the 4 most-significant bits of status_.
+ static_assert(sizeof(status_) == sizeof(uint32_t), "Size of status_ not equal to uint32");
+ uint32_t new_status_value = static_cast<uint32_t>(new_status) << (32 - kClassStatusBitSize);
+ // Use normal store. For primitives and core arrays classes (Object[],
+ // Class[], String[] and primitive arrays), the status is set while the
+ // process is still single threaded. For other arrays classes, it is set
+ // in a pre-fence visitor which initializes all fields and the subsequent
+ // fence together with address dependency shall ensure memory visibility.
+ SetField32</*kTransactionActive=*/ false,
+ /*kCheckTransaction=*/ false,
+ kVerifyNone>(StatusOffset(), new_status_value);
+
+ // Do not update `object_alloc_fast_path_`. Arrays are variable size and
+ // instances of primitive classes cannot be created at all.
+
+ if (kIsDebugBuild && new_status >= ClassStatus::kInitialized) {
+ CHECK(WasVerificationAttempted()) << PrettyClassAndClassLoader();
+ }
+
+ // There can be no waiters to notify as these classes are initialized
+ // before another thread can see them.
+}
+
void Class::SetDexCache(ObjPtr<DexCache> new_dex_cache) {
SetFieldObjectTransaction(OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_), new_dex_cache);
}