Clean up after "Load boot image at a random address."

Test: m
Bug: 77856493
Change-Id: I712450603eef6dda0ce9c4b71438d2ec5a8de126
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 8af5d55..e48365b 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -389,7 +389,7 @@
                                                   /*inout*/MemMap* oat_reservation,
                                                   /*out*/std::string* error_msg)
       REQUIRES_SHARED(Locks::mutator_lock_) {
-    TimingLogger logger(__PRETTY_FUNCTION__, true, VLOG_IS_ON(image));
+    TimingLogger logger(__PRETTY_FUNCTION__, /* precise= */ true, VLOG_IS_ON(image));
     std::unique_ptr<ImageSpace> space = Init(image_filename,
                                              image_location,
                                              validate_oat_file,
@@ -1323,7 +1323,7 @@
                       /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
                       /*out*/MemMap* extra_reservation,
                       /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
-    TimingLogger logger(__PRETTY_FUNCTION__, true, VLOG_IS_ON(image));
+    TimingLogger logger(__PRETTY_FUNCTION__, /* precise= */ true, VLOG_IS_ON(image));
     std::string filename = GetSystemImageFilename(image_location_.c_str(), image_isa_);
     std::vector<std::string> locations;
     if (!GetBootClassPathImageLocations(image_location_, filename, &locations, error_msg)) {
@@ -1393,7 +1393,7 @@
       /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces,
       /*out*/MemMap* extra_reservation,
       /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) {
-    TimingLogger logger(__PRETTY_FUNCTION__, true, VLOG_IS_ON(image));
+    TimingLogger logger(__PRETTY_FUNCTION__, /* precise= */ true, VLOG_IS_ON(image));
     DCHECK(DalvikCacheExists());
     std::vector<std::string> locations;
     if (!GetBootClassPathImageLocations(image_location_, cache_filename_, &locations, error_msg)) {
@@ -1597,11 +1597,25 @@
         : diff_(diff) {}
 
     void VisitClass(mirror::Class* klass) REQUIRES_SHARED(Locks::mutator_lock_) {
+      // A mirror::Class object consists of
+      //  - instance fields inherited from j.l.Object,
+      //  - instance fields inherited from j.l.Class,
+      //  - embedded tables (vtable, interface method table),
+      //  - static fields of the class itself.
+      // The reference fields are at the start of each field section (this is how the
+      // ClassLinker orders fields; except when that would create a gap between superclass
+      // fields and the first reference of the subclass due to alignment, it can be filled
+      // with smaller fields - but that's not the case for j.l.Object and j.l.Class).
+
+      DCHECK_ALIGNED(klass, kObjectAlignment);
+      static_assert(IsAligned<kHeapReferenceSize>(kObjectAlignment), "Object alignment check.");
       // First, patch the `klass->klass_`, known to be a reference to the j.l.Class.class.
       // This should be the only reference field in j.l.Object and we assert that below.
       PatchReferenceField</* kMayBeNull */ false>(klass, mirror::Object::ClassOffset());
       // Then patch the reference instance fields described by j.l.Class.class.
-      // Use the sizeof(Object) to determine where these reference fields start.
+      // Use the sizeof(Object) to determine where these reference fields start;
+      // this is the same as `class_class->GetFirstReferenceInstanceFieldOffset()`
+      // after patching but the j.l.Class may not have been patched yet.
       mirror::Class* class_class = klass->GetClass<kVerifyNone, kWithoutReadBarrier>();
       size_t num_reference_instance_fields = class_class->NumReferenceInstanceFields<kVerifyNone>();
       DCHECK_NE(num_reference_instance_fields, 0u);
@@ -1609,8 +1623,10 @@
       MemberOffset instance_field_offset(sizeof(mirror::Object));
       for (size_t i = 0; i != num_reference_instance_fields; ++i) {
         PatchReferenceField(klass, instance_field_offset);
-        instance_field_offset = MemberOffset(
-            instance_field_offset.Uint32Value() + sizeof(mirror::HeapReference<mirror::Object>));
+        static_assert(sizeof(mirror::HeapReference<mirror::Object>) == kHeapReferenceSize,
+                      "Heap reference sizes equality check.");
+        instance_field_offset =
+            MemberOffset(instance_field_offset.Uint32Value() + kHeapReferenceSize);
       }
       // Now that we have patched the `super_class_`, if this is the j.l.Class.class,
       // we can get a reference to j.l.Object.class and assert that it has only one
@@ -1626,8 +1642,10 @@
             klass->GetFirstReferenceStaticFieldOffset<kVerifyNone>(kPointerSize);
         for (size_t i = 0; i != num_reference_static_fields; ++i) {
           PatchReferenceField(klass, static_field_offset);
-          static_field_offset = MemberOffset(
-              static_field_offset.Uint32Value() + sizeof(mirror::HeapReference<mirror::Object>));
+          static_assert(sizeof(mirror::HeapReference<mirror::Object>) == kHeapReferenceSize,
+                        "Heap reference sizes equality check.");
+          static_field_offset =
+              MemberOffset(static_field_offset.Uint32Value() + kHeapReferenceSize);
         }
       }
       // Then patch native pointers.
@@ -1774,7 +1792,7 @@
     PatchObjectVisitor<kPointerSize> patch_object_visitor(diff);
 
     mirror::Class* dcheck_class_class = nullptr;  // Used only for a DCHECK().
-    for (size_t s = 0, size = spaces.size(); s != size; ++s) {
+    for (size_t s = 0u, size = spaces.size(); s != size; ++s) {
       const ImageSpace* space = spaces[s].get();
 
       // First patch the image header. The `diff` is OK for patching 32-bit fields but
@@ -1876,7 +1894,7 @@
       constructor_class = GetClassRoot<mirror::Constructor, kWithoutReadBarrier>(class_roots);
     }
 
-    for (size_t s = 0, size = spaces.size(); s != size; ++s) {
+    for (size_t s = 0u, size = spaces.size(); s != size; ++s) {
       const ImageSpace* space = spaces[s].get();
       const ImageHeader& image_header = space->GetImageHeader();
 
diff --git a/runtime/image-inl.h b/runtime/image-inl.h
index 9fde669..2082064 100644
--- a/runtime/image-inl.h
+++ b/runtime/image-inl.h
@@ -51,9 +51,9 @@
 
 inline void ImageHeader::VisitPackedArtFields(ArtFieldVisitor* visitor, uint8_t* base) const {
   const ImageSection& fields = GetFieldsSection();
-  for (size_t pos = 0; pos < fields.Size(); ) {
+  for (size_t pos = 0u; pos < fields.Size(); ) {
     auto* array = reinterpret_cast<LengthPrefixedArray<ArtField>*>(base + fields.Offset() + pos);
-    for (size_t i = 0; i < array->size(); ++i) {
+    for (size_t i = 0u; i < array->size(); ++i) {
       visitor->Visit(&array->At(i, sizeof(ArtField)));
     }
     pos += array->ComputeSize(array->size());
@@ -66,15 +66,15 @@
   const size_t method_alignment = ArtMethod::Alignment(pointer_size);
   const size_t method_size = ArtMethod::Size(pointer_size);
   const ImageSection& methods = GetMethodsSection();
-  for (size_t pos = 0; pos < methods.Size(); ) {
+  for (size_t pos = 0u; pos < methods.Size(); ) {
     auto* array = reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(base + methods.Offset() + pos);
-    for (size_t i = 0; i < array->size(); ++i) {
+    for (size_t i = 0u; i < array->size(); ++i) {
       visitor->Visit(&array->At(i, method_size, method_alignment));
     }
     pos += array->ComputeSize(array->size(), method_size, method_alignment);
   }
   const ImageSection& runtime_methods = GetRuntimeMethodsSection();
-  for (size_t pos = 0; pos < runtime_methods.Size(); ) {
+  for (size_t pos = 0u; pos < runtime_methods.Size(); ) {
     auto* method = reinterpret_cast<ArtMethod*>(base + runtime_methods.Offset() + pos);
     visitor->Visit(method);
     pos += method_size;