Simplify instance reference offsets.
Don't encode Object's class. Use trailing rather than leading zeroes to give
offset position.
Change-Id: I1ae74e7a01f63696429644adf81cdf6ee58832fe
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 3fcb188..6df7204 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -278,14 +278,15 @@
}
void Class::SetReferenceInstanceOffsets(uint32_t new_reference_offsets) {
- if (new_reference_offsets != CLASS_WALK_SUPER) {
+ if (kIsDebugBuild && (new_reference_offsets != kClassWalkSuper)) {
// Sanity check that the number of bits set in the reference offset bitmap
// agrees with the number of references
- size_t count = 0;
+ uint32_t count = 0;
for (Class* c = this; c != nullptr; c = c->GetSuperClass()) {
count += c->NumReferenceInstanceFieldsDuringLinking();
}
- CHECK_EQ((size_t)POPCOUNT(new_reference_offsets), count);
+ // +1 for the Class in Object.
+ CHECK_EQ(static_cast<uint32_t>(POPCOUNT(new_reference_offsets)) + 1, count);
}
// Not called within a transaction.
SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, reference_instance_offsets_),
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 0acf695..2d49121 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -28,40 +28,6 @@
#include "primitive.h"
#include "read_barrier_option.h"
-/*
- * A magic value for refOffsets. Ignore the bits and walk the super
- * chain when this is the value.
- * [This is an unlikely "natural" value, since it would be 30 non-ref instance
- * fields followed by 2 ref instance fields.]
- */
-#define CLASS_WALK_SUPER 3U
-#define CLASS_BITS_PER_WORD (sizeof(uint32_t) * 8)
-#define CLASS_OFFSET_ALIGNMENT 4
-#define CLASS_HIGH_BIT (1U << (CLASS_BITS_PER_WORD - 1))
-/*
- * Given an offset, return the bit number which would encode that offset.
- * Local use only.
- */
-#define _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) \
- ((unsigned int)(byteOffset) / \
- CLASS_OFFSET_ALIGNMENT)
-/*
- * Is the given offset too large to be encoded?
- */
-#define CLASS_CAN_ENCODE_OFFSET(byteOffset) \
- (_CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset) < CLASS_BITS_PER_WORD)
-/*
- * Return a single bit, encoding the offset.
- * Undefined if the offset is too large, as defined above.
- */
-#define CLASS_BIT_FROM_OFFSET(byteOffset) \
- (CLASS_HIGH_BIT >> _CLASS_BIT_NUMBER_FROM_OFFSET(byteOffset))
-/*
- * Return an offset, given a bit number as returned from CLZ.
- */
-#define CLASS_OFFSET_FROM_CLZ(rshift) \
- MemberOffset((static_cast<int>(rshift) * CLASS_OFFSET_ALIGNMENT))
-
namespace art {
struct ClassOffsets;
@@ -81,6 +47,12 @@
// C++ mirror of java.lang.Class
class MANAGED Class FINAL : public Object {
public:
+ // A magic value for reference_instance_offsets_. Ignore the bits and walk the super chain when
+ // this is the value.
+ // [This is an unlikely "natural" value, since it would be 30 non-ref instance fields followed by
+ // 2 ref instance fields.]
+ static constexpr uint32_t kClassWalkSuper = 0xC0000000;
+
// Interface method table size. Increasing this value reduces the chance of two interface methods
// colliding in the interface method table but increases the size of classes that implement
// (non-marker) interfaces.
diff --git a/runtime/mirror/object-inl.h b/runtime/mirror/object-inl.h
index 166ea9c..4d5f621 100644
--- a/runtime/mirror/object-inl.h
+++ b/runtime/mirror/object-inl.h
@@ -888,18 +888,18 @@
template<bool kVisitClass, bool kIsStatic, typename Visitor>
inline void Object::VisitFieldsReferences(uint32_t ref_offsets, const Visitor& visitor) {
- if (!kIsStatic && LIKELY(ref_offsets != CLASS_WALK_SUPER)) {
- if (!kVisitClass) {
- // Mask out the class from the reference offsets.
- ref_offsets ^= kWordHighBitMask;
+ if (!kIsStatic && (ref_offsets != mirror::Class::kClassWalkSuper)) {
+ // Instance fields and not the slow-path.
+ if (kVisitClass) {
+ visitor(this, ClassOffset(), kIsStatic);
}
- DCHECK_EQ(ClassOffset().Uint32Value(), 0U);
- // Found a reference offset bitmap. Visit the specified offsets.
+ uint32_t field_offset = mirror::kObjectHeaderSize;
while (ref_offsets != 0) {
- size_t right_shift = CLZ(ref_offsets);
- MemberOffset field_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
- visitor(this, field_offset, kIsStatic);
- ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
+ if ((ref_offsets & 1) != 0) {
+ visitor(this, MemberOffset(field_offset), kIsStatic);
+ }
+ ref_offsets >>= 1;
+ field_offset += sizeof(mirror::HeapReference<mirror::Object>);
}
} else {
// There is no reference offset bitmap. In the non-static case, walk up the class
diff --git a/runtime/mirror/object.h b/runtime/mirror/object.h
index b68aef9..4ed96fc 100644
--- a/runtime/mirror/object.h
+++ b/runtime/mirror/object.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_MIRROR_OBJECT_H_
#define ART_RUNTIME_MIRROR_OBJECT_H_
+#include "globals.h"
#include "object_reference.h"
#include "offsets.h"
#include "verify_object.h"
@@ -60,6 +61,9 @@
// Checks that we don't do field assignments which violate the typing system.
static constexpr bool kCheckFieldAssignments = false;
+// Size of Object.
+static constexpr uint32_t kObjectHeaderSize = kUseBrooksReadBarrier ? 16 : 8;
+
// C++ mirror of java.lang.Object
class MANAGED LOCKABLE Object {
public:
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 7fa664d..1aeba74 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -76,7 +76,8 @@
// Keep constants in sync.
TEST_F(ObjectTest, Constants) {
- EXPECT_EQ(kObjectReferenceSize, sizeof(mirror::HeapReference<mirror::Object>));
+ EXPECT_EQ(kObjectReferenceSize, sizeof(HeapReference<Object>));
+ EXPECT_EQ(kObjectHeaderSize, sizeof(Object));
}
// Keep the assembly code constats in sync.