From c7993d55b2912532c1b0917e6b0ca43097bed21d Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Wed, 27 Jan 2021 15:20:56 +0000 Subject: Rewrite ClassLinker::LinkFields(). Rewrite field offset assignment to avoid heap allocations in most cases. We do one allocation if there are many fields. Rewrite gap filling to prefer small gaps over big ones. This creates more natural field ordering. For example, class A { byte unalign; } class B extends A { long l; byte a, b, c, d, e, f; } would have previously had offsets 12, 10, 14, 9, 11, 13, 15 for fields a, b, c, d, e, f, respectively. Now these are 9, 10, 11, 12, 13, 14, 15 in line with their lexicographical order. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Test: boots. Bug: 175869411 Change-Id: I558635ac59c959dd85e8a3b015c26a6d90033853 --- runtime/class_linker_test.cc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'runtime/class_linker_test.cc') diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index c677601c0d..c561c4d591 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -485,12 +485,15 @@ struct CheckOffsets { // Classes have a different size due to padding field. Strings are variable length. if (!klass->IsClassClass() && !klass->IsStringClass() && !is_static) { - // Currently only required for AccessibleObject since of the padding fields. The class linker - // says AccessibleObject is 9 bytes but sizeof(AccessibleObject) is 12 bytes due to padding. - // The RoundUp is to get around this case. + // The RoundUp is required for some mirror classes that have a gap at the end, + // such as AccessibleObject, ByteArrayViewVarHandle and ByteBufferViewVarHandle. + // For example, the AccessibleObject has size 9 according to the class linker. + // However, the C++ sizeof(AccessibleObject) is 12 bytes due to alignment, even + // though members in C++ subclasses are actually starting at offset 9. + // + // TODO: We could define a subclass with a `uint8_t` member and check its offset instead. static constexpr size_t kPackAlignment = 4; - size_t expected_size = RoundUp(is_static ? klass->GetClassSize() : klass->GetObjectSize(), - kPackAlignment); + size_t expected_size = RoundUp(klass->GetObjectSize(), kPackAlignment); if (sizeof(T) != expected_size) { LOG(ERROR) << "Class size mismatch:" << " class=" << class_descriptor -- cgit v1.2.3-59-g8ed1b