xref: /aosp_15_r20/art/runtime/runtime_image.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include "runtime_image.h"
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker #include <lz4.h>
20*795d594fSAndroid Build Coastguard Worker #include <unistd.h>
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "android-base/file.h"
23*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
24*795d594fSAndroid Build Coastguard Worker #include "android-base/strings.h"
25*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set.h"
26*795d594fSAndroid Build Coastguard Worker #include "arch/instruction_set_features.h"
27*795d594fSAndroid Build Coastguard Worker #include "base/arena_allocator.h"
28*795d594fSAndroid Build Coastguard Worker #include "base/arena_containers.h"
29*795d594fSAndroid Build Coastguard Worker #include "base/bit_utils.h"
30*795d594fSAndroid Build Coastguard Worker #include "base/file_utils.h"
31*795d594fSAndroid Build Coastguard Worker #include "base/length_prefixed_array.h"
32*795d594fSAndroid Build Coastguard Worker #include "base/scoped_flock.h"
33*795d594fSAndroid Build Coastguard Worker #include "base/stl_util.h"
34*795d594fSAndroid Build Coastguard Worker #include "base/systrace.h"
35*795d594fSAndroid Build Coastguard Worker #include "base/unix_file/fd_file.h"
36*795d594fSAndroid Build Coastguard Worker #include "base/utils.h"
37*795d594fSAndroid Build Coastguard Worker #include "class_loader_context.h"
38*795d594fSAndroid Build Coastguard Worker #include "class_loader_utils.h"
39*795d594fSAndroid Build Coastguard Worker #include "class_root-inl.h"
40*795d594fSAndroid Build Coastguard Worker #include "dex/class_accessor-inl.h"
41*795d594fSAndroid Build Coastguard Worker #include "gc/space/image_space.h"
42*795d594fSAndroid Build Coastguard Worker #include "mirror/object-inl.h"
43*795d594fSAndroid Build Coastguard Worker #include "mirror/object-refvisitor-inl.h"
44*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-alloc-inl.h"
45*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array-inl.h"
46*795d594fSAndroid Build Coastguard Worker #include "mirror/object_array.h"
47*795d594fSAndroid Build Coastguard Worker #include "mirror/string-inl.h"
48*795d594fSAndroid Build Coastguard Worker #include "nterp_helpers.h"
49*795d594fSAndroid Build Coastguard Worker #include "oat/image.h"
50*795d594fSAndroid Build Coastguard Worker #include "oat/oat.h"
51*795d594fSAndroid Build Coastguard Worker #include "profile/profile_compilation_info.h"
52*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
53*795d594fSAndroid Build Coastguard Worker #include "vdex_file.h"
54*795d594fSAndroid Build Coastguard Worker 
55*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
56*795d594fSAndroid Build Coastguard Worker 
57*795d594fSAndroid Build Coastguard Worker using android::base::StringPrintf;
58*795d594fSAndroid Build Coastguard Worker 
59*795d594fSAndroid Build Coastguard Worker /**
60*795d594fSAndroid Build Coastguard Worker  * The native data structures that we store in the image.
61*795d594fSAndroid Build Coastguard Worker  */
62*795d594fSAndroid Build Coastguard Worker enum class NativeRelocationKind {
63*795d594fSAndroid Build Coastguard Worker   kArtFieldArray,
64*795d594fSAndroid Build Coastguard Worker   kArtMethodArray,
65*795d594fSAndroid Build Coastguard Worker   kArtMethod,
66*795d594fSAndroid Build Coastguard Worker   kImTable,
67*795d594fSAndroid Build Coastguard Worker   // For dex cache arrays which can stay in memory even after startup. Those are
68*795d594fSAndroid Build Coastguard Worker   // dex cache arrays whose size is below a given threshold, defined by
69*795d594fSAndroid Build Coastguard Worker   // DexCache::ShouldAllocateFullArray.
70*795d594fSAndroid Build Coastguard Worker   kFullNativeDexCacheArray,
71*795d594fSAndroid Build Coastguard Worker   // For dex cache arrays which we will want to release after app startup.
72*795d594fSAndroid Build Coastguard Worker   kStartupNativeDexCacheArray,
73*795d594fSAndroid Build Coastguard Worker };
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker /**
76*795d594fSAndroid Build Coastguard Worker  * Helper class to generate an app image at runtime.
77*795d594fSAndroid Build Coastguard Worker  */
78*795d594fSAndroid Build Coastguard Worker class RuntimeImageHelper {
79*795d594fSAndroid Build Coastguard Worker  public:
RuntimeImageHelper(gc::Heap * heap)80*795d594fSAndroid Build Coastguard Worker   explicit RuntimeImageHelper(gc::Heap* heap) :
81*795d594fSAndroid Build Coastguard Worker     allocator_(Runtime::Current()->GetArenaPool()),
82*795d594fSAndroid Build Coastguard Worker     objects_(allocator_.Adapter()),
83*795d594fSAndroid Build Coastguard Worker     art_fields_(allocator_.Adapter()),
84*795d594fSAndroid Build Coastguard Worker     art_methods_(allocator_.Adapter()),
85*795d594fSAndroid Build Coastguard Worker     im_tables_(allocator_.Adapter()),
86*795d594fSAndroid Build Coastguard Worker     metadata_(allocator_.Adapter()),
87*795d594fSAndroid Build Coastguard Worker     dex_cache_arrays_(allocator_.Adapter()),
88*795d594fSAndroid Build Coastguard Worker     string_reference_offsets_(allocator_.Adapter()),
89*795d594fSAndroid Build Coastguard Worker     sections_(ImageHeader::kSectionCount, allocator_.Adapter()),
90*795d594fSAndroid Build Coastguard Worker     object_offsets_(allocator_.Adapter()),
91*795d594fSAndroid Build Coastguard Worker     classes_(allocator_.Adapter()),
92*795d594fSAndroid Build Coastguard Worker     array_classes_(allocator_.Adapter()),
93*795d594fSAndroid Build Coastguard Worker     dex_caches_(allocator_.Adapter()),
94*795d594fSAndroid Build Coastguard Worker     class_hashes_(allocator_.Adapter()),
95*795d594fSAndroid Build Coastguard Worker     native_relocations_(allocator_.Adapter()),
96*795d594fSAndroid Build Coastguard Worker     boot_image_begin_(heap->GetBootImagesStartAddress()),
97*795d594fSAndroid Build Coastguard Worker     boot_image_size_(heap->GetBootImagesSize()),
98*795d594fSAndroid Build Coastguard Worker     image_begin_(boot_image_begin_ + boot_image_size_),
99*795d594fSAndroid Build Coastguard Worker     // Note: image relocation considers the image header in the bitmap.
100*795d594fSAndroid Build Coastguard Worker     object_section_size_(sizeof(ImageHeader)),
101*795d594fSAndroid Build Coastguard Worker     intern_table_(InternStringHash(this), InternStringEquals(this)),
102*795d594fSAndroid Build Coastguard Worker     class_table_(ClassDescriptorHash(this), ClassDescriptorEquals()) {}
103*795d594fSAndroid Build Coastguard Worker 
Generate(std::string * error_msg)104*795d594fSAndroid Build Coastguard Worker   bool Generate(std::string* error_msg) {
105*795d594fSAndroid Build Coastguard Worker     if (!WriteObjects(error_msg)) {
106*795d594fSAndroid Build Coastguard Worker       return false;
107*795d594fSAndroid Build Coastguard Worker     }
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker     // Generate the sections information stored in the header.
110*795d594fSAndroid Build Coastguard Worker     CreateImageSections();
111*795d594fSAndroid Build Coastguard Worker 
112*795d594fSAndroid Build Coastguard Worker     // Now that all sections have been created and we know their offset and
113*795d594fSAndroid Build Coastguard Worker     // size, relocate native pointers inside classes and ImTables.
114*795d594fSAndroid Build Coastguard Worker     RelocateNativePointers();
115*795d594fSAndroid Build Coastguard Worker 
116*795d594fSAndroid Build Coastguard Worker     // Generate the bitmap section, stored kElfSegmentAlignment-aligned after the sections data and
117*795d594fSAndroid Build Coastguard Worker     // of size `object_section_size_` rounded up to kCardSize to match the bitmap size expected by
118*795d594fSAndroid Build Coastguard Worker     // Loader::Init at art::gc::space::ImageSpace.
119*795d594fSAndroid Build Coastguard Worker     size_t sections_end = sections_[ImageHeader::kSectionMetadata].End();
120*795d594fSAndroid Build Coastguard Worker     image_bitmap_ = gc::accounting::ContinuousSpaceBitmap::Create(
121*795d594fSAndroid Build Coastguard Worker         "image bitmap",
122*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<uint8_t*>(image_begin_),
123*795d594fSAndroid Build Coastguard Worker         RoundUp(object_section_size_, gc::accounting::CardTable::kCardSize));
124*795d594fSAndroid Build Coastguard Worker     for (uint32_t offset : object_offsets_) {
125*795d594fSAndroid Build Coastguard Worker       DCHECK(IsAligned<kObjectAlignment>(image_begin_ + sizeof(ImageHeader) + offset));
126*795d594fSAndroid Build Coastguard Worker       image_bitmap_.Set(
127*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<mirror::Object*>(image_begin_ + sizeof(ImageHeader) + offset));
128*795d594fSAndroid Build Coastguard Worker     }
129*795d594fSAndroid Build Coastguard Worker     const size_t bitmap_bytes = image_bitmap_.Size();
130*795d594fSAndroid Build Coastguard Worker     auto* bitmap_section = &sections_[ImageHeader::kSectionImageBitmap];
131*795d594fSAndroid Build Coastguard Worker     // The offset of the bitmap section should be aligned to kElfSegmentAlignment to enable mapping
132*795d594fSAndroid Build Coastguard Worker     // the section from file to memory. However the section size doesn't have to be rounded up as
133*795d594fSAndroid Build Coastguard Worker     // it is located at the end of the file. When mapping file contents to memory, if the last page
134*795d594fSAndroid Build Coastguard Worker     // of the mapping is only partially filled with data, the rest will be zero-filled.
135*795d594fSAndroid Build Coastguard Worker     *bitmap_section = ImageSection(RoundUp(sections_end, kElfSegmentAlignment), bitmap_bytes);
136*795d594fSAndroid Build Coastguard Worker 
137*795d594fSAndroid Build Coastguard Worker     // Compute boot image checksum and boot image components, to be stored in
138*795d594fSAndroid Build Coastguard Worker     // the header.
139*795d594fSAndroid Build Coastguard Worker     gc::Heap* const heap = Runtime::Current()->GetHeap();
140*795d594fSAndroid Build Coastguard Worker     uint32_t boot_image_components = 0u;
141*795d594fSAndroid Build Coastguard Worker     uint32_t boot_image_checksums = 0u;
142*795d594fSAndroid Build Coastguard Worker     const std::vector<gc::space::ImageSpace*>& image_spaces = heap->GetBootImageSpaces();
143*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0u, size = image_spaces.size(); i != size; ) {
144*795d594fSAndroid Build Coastguard Worker       const ImageHeader& header = image_spaces[i]->GetImageHeader();
145*795d594fSAndroid Build Coastguard Worker       boot_image_components += header.GetComponentCount();
146*795d594fSAndroid Build Coastguard Worker       boot_image_checksums ^= header.GetImageChecksum();
147*795d594fSAndroid Build Coastguard Worker       DCHECK_LE(header.GetImageSpaceCount(), size - i);
148*795d594fSAndroid Build Coastguard Worker       i += header.GetImageSpaceCount();
149*795d594fSAndroid Build Coastguard Worker     }
150*795d594fSAndroid Build Coastguard Worker 
151*795d594fSAndroid Build Coastguard Worker     header_ = ImageHeader(
152*795d594fSAndroid Build Coastguard Worker         /* image_reservation_size= */ RoundUp(sections_end, kElfSegmentAlignment),
153*795d594fSAndroid Build Coastguard Worker         /* component_count= */ 1,
154*795d594fSAndroid Build Coastguard Worker         image_begin_,
155*795d594fSAndroid Build Coastguard Worker         sections_end,
156*795d594fSAndroid Build Coastguard Worker         sections_.data(),
157*795d594fSAndroid Build Coastguard Worker         /* image_roots= */ image_begin_ + sizeof(ImageHeader),
158*795d594fSAndroid Build Coastguard Worker         /* oat_checksum= */ 0,
159*795d594fSAndroid Build Coastguard Worker         /* oat_file_begin= */ 0,
160*795d594fSAndroid Build Coastguard Worker         /* oat_data_begin= */ 0,
161*795d594fSAndroid Build Coastguard Worker         /* oat_data_end= */ 0,
162*795d594fSAndroid Build Coastguard Worker         /* oat_file_end= */ 0,
163*795d594fSAndroid Build Coastguard Worker         heap->GetBootImagesStartAddress(),
164*795d594fSAndroid Build Coastguard Worker         heap->GetBootImagesSize(),
165*795d594fSAndroid Build Coastguard Worker         boot_image_components,
166*795d594fSAndroid Build Coastguard Worker         boot_image_checksums,
167*795d594fSAndroid Build Coastguard Worker         kRuntimePointerSize);
168*795d594fSAndroid Build Coastguard Worker 
169*795d594fSAndroid Build Coastguard Worker     // Data size includes everything except the bitmap and the header.
170*795d594fSAndroid Build Coastguard Worker     header_.data_size_ = sections_end - sizeof(ImageHeader);
171*795d594fSAndroid Build Coastguard Worker 
172*795d594fSAndroid Build Coastguard Worker     // Write image methods - needs to happen after creation of the header.
173*795d594fSAndroid Build Coastguard Worker     WriteImageMethods();
174*795d594fSAndroid Build Coastguard Worker 
175*795d594fSAndroid Build Coastguard Worker     return true;
176*795d594fSAndroid Build Coastguard Worker   }
177*795d594fSAndroid Build Coastguard Worker 
FillData(std::vector<uint8_t> & data)178*795d594fSAndroid Build Coastguard Worker   void FillData(std::vector<uint8_t>& data) {
179*795d594fSAndroid Build Coastguard Worker     // Note we don't put the header, we only have it reserved in `data` as
180*795d594fSAndroid Build Coastguard Worker     // Image::WriteData expects the object section to contain the image header.
181*795d594fSAndroid Build Coastguard Worker     auto compute_dest = [&](const ImageSection& section) {
182*795d594fSAndroid Build Coastguard Worker       return data.data() + section.Offset();
183*795d594fSAndroid Build Coastguard Worker     };
184*795d594fSAndroid Build Coastguard Worker 
185*795d594fSAndroid Build Coastguard Worker     auto objects_section = header_.GetImageSection(ImageHeader::kSectionObjects);
186*795d594fSAndroid Build Coastguard Worker     memcpy(compute_dest(objects_section) + sizeof(ImageHeader), objects_.data(), objects_.size());
187*795d594fSAndroid Build Coastguard Worker 
188*795d594fSAndroid Build Coastguard Worker     auto fields_section = header_.GetImageSection(ImageHeader::kSectionArtFields);
189*795d594fSAndroid Build Coastguard Worker     memcpy(compute_dest(fields_section), art_fields_.data(), fields_section.Size());
190*795d594fSAndroid Build Coastguard Worker 
191*795d594fSAndroid Build Coastguard Worker     auto methods_section = header_.GetImageSection(ImageHeader::kSectionArtMethods);
192*795d594fSAndroid Build Coastguard Worker     memcpy(compute_dest(methods_section), art_methods_.data(), methods_section.Size());
193*795d594fSAndroid Build Coastguard Worker 
194*795d594fSAndroid Build Coastguard Worker     auto im_tables_section = header_.GetImageSection(ImageHeader::kSectionImTables);
195*795d594fSAndroid Build Coastguard Worker     memcpy(compute_dest(im_tables_section), im_tables_.data(), im_tables_section.Size());
196*795d594fSAndroid Build Coastguard Worker 
197*795d594fSAndroid Build Coastguard Worker     auto intern_section = header_.GetImageSection(ImageHeader::kSectionInternedStrings);
198*795d594fSAndroid Build Coastguard Worker     intern_table_.WriteToMemory(compute_dest(intern_section));
199*795d594fSAndroid Build Coastguard Worker 
200*795d594fSAndroid Build Coastguard Worker     auto class_table_section = header_.GetImageSection(ImageHeader::kSectionClassTable);
201*795d594fSAndroid Build Coastguard Worker     class_table_.WriteToMemory(compute_dest(class_table_section));
202*795d594fSAndroid Build Coastguard Worker 
203*795d594fSAndroid Build Coastguard Worker     auto string_offsets_section =
204*795d594fSAndroid Build Coastguard Worker         header_.GetImageSection(ImageHeader::kSectionStringReferenceOffsets);
205*795d594fSAndroid Build Coastguard Worker     memcpy(compute_dest(string_offsets_section),
206*795d594fSAndroid Build Coastguard Worker            string_reference_offsets_.data(),
207*795d594fSAndroid Build Coastguard Worker            string_offsets_section.Size());
208*795d594fSAndroid Build Coastguard Worker 
209*795d594fSAndroid Build Coastguard Worker     auto dex_cache_section = header_.GetImageSection(ImageHeader::kSectionDexCacheArrays);
210*795d594fSAndroid Build Coastguard Worker     memcpy(compute_dest(dex_cache_section), dex_cache_arrays_.data(), dex_cache_section.Size());
211*795d594fSAndroid Build Coastguard Worker 
212*795d594fSAndroid Build Coastguard Worker     auto metadata_section = header_.GetImageSection(ImageHeader::kSectionMetadata);
213*795d594fSAndroid Build Coastguard Worker     memcpy(compute_dest(metadata_section), metadata_.data(), metadata_section.Size());
214*795d594fSAndroid Build Coastguard Worker 
215*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(metadata_section.Offset() + metadata_section.Size(), data.size());
216*795d594fSAndroid Build Coastguard Worker   }
217*795d594fSAndroid Build Coastguard Worker 
218*795d594fSAndroid Build Coastguard Worker 
GetHeader()219*795d594fSAndroid Build Coastguard Worker   ImageHeader* GetHeader() {
220*795d594fSAndroid Build Coastguard Worker     return &header_;
221*795d594fSAndroid Build Coastguard Worker   }
222*795d594fSAndroid Build Coastguard Worker 
GetImageBitmap() const223*795d594fSAndroid Build Coastguard Worker   const gc::accounting::ContinuousSpaceBitmap& GetImageBitmap() const {
224*795d594fSAndroid Build Coastguard Worker     return image_bitmap_;
225*795d594fSAndroid Build Coastguard Worker   }
226*795d594fSAndroid Build Coastguard Worker 
GetDexLocation() const227*795d594fSAndroid Build Coastguard Worker   const std::string& GetDexLocation() const {
228*795d594fSAndroid Build Coastguard Worker     return dex_location_;
229*795d594fSAndroid Build Coastguard Worker   }
230*795d594fSAndroid Build Coastguard Worker 
231*795d594fSAndroid Build Coastguard Worker  private:
IsInBootImage(const void * obj) const232*795d594fSAndroid Build Coastguard Worker   bool IsInBootImage(const void* obj) const {
233*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<uintptr_t>(obj) - boot_image_begin_ < boot_image_size_;
234*795d594fSAndroid Build Coastguard Worker   }
235*795d594fSAndroid Build Coastguard Worker 
236*795d594fSAndroid Build Coastguard Worker   // Returns the image contents for `cls`. If `cls` is in the boot image, the
237*795d594fSAndroid Build Coastguard Worker   // method just returns it.
GetClassContent(ObjPtr<mirror::Class> cls)238*795d594fSAndroid Build Coastguard Worker   mirror::Class* GetClassContent(ObjPtr<mirror::Class> cls) REQUIRES_SHARED(Locks::mutator_lock_) {
239*795d594fSAndroid Build Coastguard Worker     if (cls == nullptr || IsInBootImage(cls.Ptr())) {
240*795d594fSAndroid Build Coastguard Worker       return cls.Ptr();
241*795d594fSAndroid Build Coastguard Worker     }
242*795d594fSAndroid Build Coastguard Worker     const dex::ClassDef* class_def = cls->GetClassDef();
243*795d594fSAndroid Build Coastguard Worker     DCHECK(class_def != nullptr) << cls->PrettyClass();
244*795d594fSAndroid Build Coastguard Worker     auto it = classes_.find(class_def);
245*795d594fSAndroid Build Coastguard Worker     DCHECK(it != classes_.end()) << cls->PrettyClass();
246*795d594fSAndroid Build Coastguard Worker     mirror::Class* result = reinterpret_cast<mirror::Class*>(objects_.data() + it->second);
247*795d594fSAndroid Build Coastguard Worker     DCHECK(result->GetClass()->IsClass());
248*795d594fSAndroid Build Coastguard Worker     return result;
249*795d594fSAndroid Build Coastguard Worker   }
250*795d594fSAndroid Build Coastguard Worker 
251*795d594fSAndroid Build Coastguard Worker   // Returns a pointer that can be stored in `objects_`:
252*795d594fSAndroid Build Coastguard Worker   // - The pointer itself for boot image objects,
253*795d594fSAndroid Build Coastguard Worker   // - The offset in the image for all other objects.
GetOrComputeImageAddress(ObjPtr<T> object)254*795d594fSAndroid Build Coastguard Worker   template <typename T> T* GetOrComputeImageAddress(ObjPtr<T> object)
255*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
256*795d594fSAndroid Build Coastguard Worker     if (object == nullptr || IsInBootImage(object.Ptr())) {
257*795d594fSAndroid Build Coastguard Worker       DCHECK(object == nullptr || Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(object));
258*795d594fSAndroid Build Coastguard Worker       return object.Ptr();
259*795d594fSAndroid Build Coastguard Worker     }
260*795d594fSAndroid Build Coastguard Worker 
261*795d594fSAndroid Build Coastguard Worker     if (object->IsClassLoader()) {
262*795d594fSAndroid Build Coastguard Worker       // DexCache and Class point to class loaders. For runtime-generated app
263*795d594fSAndroid Build Coastguard Worker       // images, we don't encode the class loader. It will be set when the
264*795d594fSAndroid Build Coastguard Worker       // runtime is loading the image.
265*795d594fSAndroid Build Coastguard Worker       return nullptr;
266*795d594fSAndroid Build Coastguard Worker     }
267*795d594fSAndroid Build Coastguard Worker 
268*795d594fSAndroid Build Coastguard Worker     if (object->GetClass() == GetClassRoot<mirror::ClassExt>()) {
269*795d594fSAndroid Build Coastguard Worker       // No need to encode `ClassExt`. If needed, it will be reconstructed at
270*795d594fSAndroid Build Coastguard Worker       // runtime.
271*795d594fSAndroid Build Coastguard Worker       return nullptr;
272*795d594fSAndroid Build Coastguard Worker     }
273*795d594fSAndroid Build Coastguard Worker 
274*795d594fSAndroid Build Coastguard Worker     uint32_t offset = 0u;
275*795d594fSAndroid Build Coastguard Worker     if (object->IsClass()) {
276*795d594fSAndroid Build Coastguard Worker       offset = CopyClass(object->AsClass());
277*795d594fSAndroid Build Coastguard Worker     } else if (object->IsDexCache()) {
278*795d594fSAndroid Build Coastguard Worker       offset = CopyDexCache(object->AsDexCache());
279*795d594fSAndroid Build Coastguard Worker     } else {
280*795d594fSAndroid Build Coastguard Worker       offset = CopyObject(object);
281*795d594fSAndroid Build Coastguard Worker     }
282*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<T*>(image_begin_ + sizeof(ImageHeader) + offset);
283*795d594fSAndroid Build Coastguard Worker   }
284*795d594fSAndroid Build Coastguard Worker 
CreateImageSections()285*795d594fSAndroid Build Coastguard Worker   void CreateImageSections() {
286*795d594fSAndroid Build Coastguard Worker     sections_[ImageHeader::kSectionObjects] = ImageSection(0u, object_section_size_);
287*795d594fSAndroid Build Coastguard Worker     sections_[ImageHeader::kSectionArtFields] =
288*795d594fSAndroid Build Coastguard Worker         ImageSection(sections_[ImageHeader::kSectionObjects].End(), art_fields_.size());
289*795d594fSAndroid Build Coastguard Worker 
290*795d594fSAndroid Build Coastguard Worker     // Round up to the alignment for ArtMethod.
291*795d594fSAndroid Build Coastguard Worker     static_assert(IsAligned<sizeof(void*)>(ArtMethod::Size(kRuntimePointerSize)));
292*795d594fSAndroid Build Coastguard Worker     size_t cur_pos = RoundUp(sections_[ImageHeader::kSectionArtFields].End(), sizeof(void*));
293*795d594fSAndroid Build Coastguard Worker     sections_[ImageHeader::kSectionArtMethods] = ImageSection(cur_pos, art_methods_.size());
294*795d594fSAndroid Build Coastguard Worker 
295*795d594fSAndroid Build Coastguard Worker     // Round up to the alignment for ImTables.
296*795d594fSAndroid Build Coastguard Worker     cur_pos = RoundUp(sections_[ImageHeader::kSectionArtMethods].End(), sizeof(void*));
297*795d594fSAndroid Build Coastguard Worker     sections_[ImageHeader::kSectionImTables] = ImageSection(cur_pos, im_tables_.size());
298*795d594fSAndroid Build Coastguard Worker 
299*795d594fSAndroid Build Coastguard Worker     // Round up to the alignment for conflict tables.
300*795d594fSAndroid Build Coastguard Worker     cur_pos = RoundUp(sections_[ImageHeader::kSectionImTables].End(), sizeof(void*));
301*795d594fSAndroid Build Coastguard Worker     sections_[ImageHeader::kSectionIMTConflictTables] = ImageSection(cur_pos, 0u);
302*795d594fSAndroid Build Coastguard Worker 
303*795d594fSAndroid Build Coastguard Worker     sections_[ImageHeader::kSectionRuntimeMethods] =
304*795d594fSAndroid Build Coastguard Worker         ImageSection(sections_[ImageHeader::kSectionIMTConflictTables].End(), 0u);
305*795d594fSAndroid Build Coastguard Worker 
306*795d594fSAndroid Build Coastguard Worker     // Round up to the alignment the string table expects. See HashSet::WriteToMemory.
307*795d594fSAndroid Build Coastguard Worker     cur_pos = RoundUp(sections_[ImageHeader::kSectionRuntimeMethods].End(), sizeof(uint64_t));
308*795d594fSAndroid Build Coastguard Worker 
309*795d594fSAndroid Build Coastguard Worker     size_t intern_table_bytes = intern_table_.WriteToMemory(nullptr);
310*795d594fSAndroid Build Coastguard Worker     sections_[ImageHeader::kSectionInternedStrings] = ImageSection(cur_pos, intern_table_bytes);
311*795d594fSAndroid Build Coastguard Worker 
312*795d594fSAndroid Build Coastguard Worker     // Obtain the new position and round it up to the appropriate alignment.
313*795d594fSAndroid Build Coastguard Worker     cur_pos = RoundUp(sections_[ImageHeader::kSectionInternedStrings].End(), sizeof(uint64_t));
314*795d594fSAndroid Build Coastguard Worker 
315*795d594fSAndroid Build Coastguard Worker     size_t class_table_bytes = class_table_.WriteToMemory(nullptr);
316*795d594fSAndroid Build Coastguard Worker     sections_[ImageHeader::kSectionClassTable] = ImageSection(cur_pos, class_table_bytes);
317*795d594fSAndroid Build Coastguard Worker 
318*795d594fSAndroid Build Coastguard Worker     // Round up to the alignment of the offsets we are going to store.
319*795d594fSAndroid Build Coastguard Worker     cur_pos = RoundUp(sections_[ImageHeader::kSectionClassTable].End(), sizeof(uint32_t));
320*795d594fSAndroid Build Coastguard Worker     sections_[ImageHeader::kSectionStringReferenceOffsets] = ImageSection(
321*795d594fSAndroid Build Coastguard Worker         cur_pos, string_reference_offsets_.size() * sizeof(string_reference_offsets_[0]));
322*795d594fSAndroid Build Coastguard Worker 
323*795d594fSAndroid Build Coastguard Worker     // Round up to the alignment dex caches arrays expects.
324*795d594fSAndroid Build Coastguard Worker     cur_pos =
325*795d594fSAndroid Build Coastguard Worker         RoundUp(sections_[ImageHeader::kSectionStringReferenceOffsets].End(), sizeof(void*));
326*795d594fSAndroid Build Coastguard Worker     sections_[ImageHeader::kSectionDexCacheArrays] =
327*795d594fSAndroid Build Coastguard Worker         ImageSection(cur_pos, dex_cache_arrays_.size());
328*795d594fSAndroid Build Coastguard Worker 
329*795d594fSAndroid Build Coastguard Worker     // Round up to the alignment expected for the metadata, which holds dex
330*795d594fSAndroid Build Coastguard Worker     // cache arrays.
331*795d594fSAndroid Build Coastguard Worker     cur_pos = RoundUp(sections_[ImageHeader::kSectionDexCacheArrays].End(), sizeof(void*));
332*795d594fSAndroid Build Coastguard Worker     sections_[ImageHeader::kSectionMetadata] = ImageSection(cur_pos, metadata_.size());
333*795d594fSAndroid Build Coastguard Worker   }
334*795d594fSAndroid Build Coastguard Worker 
335*795d594fSAndroid Build Coastguard Worker   // Returns the copied mirror Object if in the image, or the object directly if
336*795d594fSAndroid Build Coastguard Worker   // in the boot image. For the copy, this is really its content, it should not
337*795d594fSAndroid Build Coastguard Worker   // be returned as an `ObjPtr` (as it's not a GC object), nor stored anywhere.
FromImageOffsetToRuntimeContent(uint32_t offset)338*795d594fSAndroid Build Coastguard Worker   template<typename T> T* FromImageOffsetToRuntimeContent(uint32_t offset) {
339*795d594fSAndroid Build Coastguard Worker     if (offset == 0u || IsInBootImage(reinterpret_cast<const void*>(offset))) {
340*795d594fSAndroid Build Coastguard Worker       return reinterpret_cast<T*>(offset);
341*795d594fSAndroid Build Coastguard Worker     }
342*795d594fSAndroid Build Coastguard Worker     uint32_t vector_data_offset = FromImageOffsetToVectorOffset(offset);
343*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<T*>(objects_.data() + vector_data_offset);
344*795d594fSAndroid Build Coastguard Worker   }
345*795d594fSAndroid Build Coastguard Worker 
FromImageOffsetToVectorOffset(uint32_t offset) const346*795d594fSAndroid Build Coastguard Worker   uint32_t FromImageOffsetToVectorOffset(uint32_t offset) const {
347*795d594fSAndroid Build Coastguard Worker     DCHECK(!IsInBootImage(reinterpret_cast<const void*>(offset)));
348*795d594fSAndroid Build Coastguard Worker     return offset - sizeof(ImageHeader) - image_begin_;
349*795d594fSAndroid Build Coastguard Worker   }
350*795d594fSAndroid Build Coastguard Worker 
351*795d594fSAndroid Build Coastguard Worker   class InternStringHash {
352*795d594fSAndroid Build Coastguard Worker    public:
InternStringHash(RuntimeImageHelper * helper)353*795d594fSAndroid Build Coastguard Worker     explicit InternStringHash(RuntimeImageHelper* helper) : helper_(helper) {}
354*795d594fSAndroid Build Coastguard Worker 
355*795d594fSAndroid Build Coastguard Worker     // NO_THREAD_SAFETY_ANALYSIS as these helpers get passed to `HashSet`.
operator ()(mirror::String * str) const356*795d594fSAndroid Build Coastguard Worker     size_t operator()(mirror::String* str) const NO_THREAD_SAFETY_ANALYSIS {
357*795d594fSAndroid Build Coastguard Worker       int32_t hash = str->GetStoredHashCode();
358*795d594fSAndroid Build Coastguard Worker       DCHECK_EQ(hash, str->ComputeHashCode());
359*795d594fSAndroid Build Coastguard Worker       // An additional cast to prevent undesired sign extension.
360*795d594fSAndroid Build Coastguard Worker       return static_cast<uint32_t>(hash);
361*795d594fSAndroid Build Coastguard Worker     }
362*795d594fSAndroid Build Coastguard Worker 
operator ()(uint32_t entry) const363*795d594fSAndroid Build Coastguard Worker     size_t operator()(uint32_t entry) const NO_THREAD_SAFETY_ANALYSIS {
364*795d594fSAndroid Build Coastguard Worker       return (*this)(helper_->FromImageOffsetToRuntimeContent<mirror::String>(entry));
365*795d594fSAndroid Build Coastguard Worker     }
366*795d594fSAndroid Build Coastguard Worker 
367*795d594fSAndroid Build Coastguard Worker    private:
368*795d594fSAndroid Build Coastguard Worker     RuntimeImageHelper* helper_;
369*795d594fSAndroid Build Coastguard Worker   };
370*795d594fSAndroid Build Coastguard Worker 
371*795d594fSAndroid Build Coastguard Worker   class InternStringEquals {
372*795d594fSAndroid Build Coastguard Worker    public:
InternStringEquals(RuntimeImageHelper * helper)373*795d594fSAndroid Build Coastguard Worker     explicit InternStringEquals(RuntimeImageHelper* helper) : helper_(helper) {}
374*795d594fSAndroid Build Coastguard Worker 
375*795d594fSAndroid Build Coastguard Worker     // NO_THREAD_SAFETY_ANALYSIS as these helpers get passed to `HashSet`.
operator ()(uint32_t entry,mirror::String * other) const376*795d594fSAndroid Build Coastguard Worker     bool operator()(uint32_t entry, mirror::String* other) const NO_THREAD_SAFETY_ANALYSIS {
377*795d594fSAndroid Build Coastguard Worker       if (kIsDebugBuild) {
378*795d594fSAndroid Build Coastguard Worker         Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
379*795d594fSAndroid Build Coastguard Worker       }
380*795d594fSAndroid Build Coastguard Worker       return other->Equals(helper_->FromImageOffsetToRuntimeContent<mirror::String>(entry));
381*795d594fSAndroid Build Coastguard Worker     }
382*795d594fSAndroid Build Coastguard Worker 
operator ()(uint32_t entry,uint32_t other) const383*795d594fSAndroid Build Coastguard Worker     bool operator()(uint32_t entry, uint32_t other) const NO_THREAD_SAFETY_ANALYSIS {
384*795d594fSAndroid Build Coastguard Worker       return (*this)(entry, helper_->FromImageOffsetToRuntimeContent<mirror::String>(other));
385*795d594fSAndroid Build Coastguard Worker     }
386*795d594fSAndroid Build Coastguard Worker 
387*795d594fSAndroid Build Coastguard Worker    private:
388*795d594fSAndroid Build Coastguard Worker     RuntimeImageHelper* helper_;
389*795d594fSAndroid Build Coastguard Worker   };
390*795d594fSAndroid Build Coastguard Worker 
391*795d594fSAndroid Build Coastguard Worker   using InternTableSet =
392*795d594fSAndroid Build Coastguard Worker         HashSet<uint32_t, DefaultEmptyFn<uint32_t>, InternStringHash, InternStringEquals>;
393*795d594fSAndroid Build Coastguard Worker 
394*795d594fSAndroid Build Coastguard Worker   class ClassDescriptorHash {
395*795d594fSAndroid Build Coastguard Worker    public:
ClassDescriptorHash(RuntimeImageHelper * helper)396*795d594fSAndroid Build Coastguard Worker     explicit ClassDescriptorHash(RuntimeImageHelper* helper) : helper_(helper) {}
397*795d594fSAndroid Build Coastguard Worker 
operator ()(const ClassTable::TableSlot & slot) const398*795d594fSAndroid Build Coastguard Worker     uint32_t operator()(const ClassTable::TableSlot& slot) const NO_THREAD_SAFETY_ANALYSIS {
399*795d594fSAndroid Build Coastguard Worker       uint32_t ptr = slot.NonHashData();
400*795d594fSAndroid Build Coastguard Worker       if (helper_->IsInBootImage(reinterpret_cast32<const void*>(ptr))) {
401*795d594fSAndroid Build Coastguard Worker         return reinterpret_cast32<mirror::Class*>(ptr)->DescriptorHash();
402*795d594fSAndroid Build Coastguard Worker       }
403*795d594fSAndroid Build Coastguard Worker       return helper_->class_hashes_.Get(helper_->FromImageOffsetToVectorOffset(ptr));
404*795d594fSAndroid Build Coastguard Worker     }
405*795d594fSAndroid Build Coastguard Worker 
406*795d594fSAndroid Build Coastguard Worker    private:
407*795d594fSAndroid Build Coastguard Worker     RuntimeImageHelper* helper_;
408*795d594fSAndroid Build Coastguard Worker   };
409*795d594fSAndroid Build Coastguard Worker 
410*795d594fSAndroid Build Coastguard Worker   class ClassDescriptorEquals {
411*795d594fSAndroid Build Coastguard Worker    public:
ClassDescriptorEquals()412*795d594fSAndroid Build Coastguard Worker     ClassDescriptorEquals() {}
413*795d594fSAndroid Build Coastguard Worker 
operator ()(const ClassTable::TableSlot & a,const ClassTable::TableSlot & b) const414*795d594fSAndroid Build Coastguard Worker     bool operator()(const ClassTable::TableSlot& a, const ClassTable::TableSlot& b)
415*795d594fSAndroid Build Coastguard Worker         const NO_THREAD_SAFETY_ANALYSIS {
416*795d594fSAndroid Build Coastguard Worker       // No need to fetch the descriptor: we know the classes we are inserting
417*795d594fSAndroid Build Coastguard Worker       // in the ClassTable are unique.
418*795d594fSAndroid Build Coastguard Worker       return a.Data() == b.Data();
419*795d594fSAndroid Build Coastguard Worker     }
420*795d594fSAndroid Build Coastguard Worker   };
421*795d594fSAndroid Build Coastguard Worker 
422*795d594fSAndroid Build Coastguard Worker   using ClassTableSet = HashSet<ClassTable::TableSlot,
423*795d594fSAndroid Build Coastguard Worker                                 ClassTable::TableSlotEmptyFn,
424*795d594fSAndroid Build Coastguard Worker                                 ClassDescriptorHash,
425*795d594fSAndroid Build Coastguard Worker                                 ClassDescriptorEquals>;
426*795d594fSAndroid Build Coastguard Worker 
427*795d594fSAndroid Build Coastguard Worker   // Helper class to collect classes that we will generate in the image.
428*795d594fSAndroid Build Coastguard Worker   class ClassTableVisitor {
429*795d594fSAndroid Build Coastguard Worker    public:
ClassTableVisitor(Handle<mirror::ClassLoader> loader,VariableSizedHandleScope & handles)430*795d594fSAndroid Build Coastguard Worker     ClassTableVisitor(Handle<mirror::ClassLoader> loader, VariableSizedHandleScope& handles)
431*795d594fSAndroid Build Coastguard Worker         : loader_(loader), handles_(handles) {}
432*795d594fSAndroid Build Coastguard Worker 
operator ()(ObjPtr<mirror::Class> klass)433*795d594fSAndroid Build Coastguard Worker     bool operator()(ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
434*795d594fSAndroid Build Coastguard Worker       // Record app classes and boot classpath classes: app classes will be
435*795d594fSAndroid Build Coastguard Worker       // generated in the image and put in the class table, boot classpath
436*795d594fSAndroid Build Coastguard Worker       // classes will be put in the class table.
437*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::ClassLoader> class_loader = klass->GetClassLoader();
438*795d594fSAndroid Build Coastguard Worker       if (klass->IsResolved() && (class_loader == loader_.Get() || class_loader == nullptr)) {
439*795d594fSAndroid Build Coastguard Worker         handles_.NewHandle(klass);
440*795d594fSAndroid Build Coastguard Worker       }
441*795d594fSAndroid Build Coastguard Worker       return true;
442*795d594fSAndroid Build Coastguard Worker     }
443*795d594fSAndroid Build Coastguard Worker 
444*795d594fSAndroid Build Coastguard Worker    private:
445*795d594fSAndroid Build Coastguard Worker     Handle<mirror::ClassLoader> loader_;
446*795d594fSAndroid Build Coastguard Worker     VariableSizedHandleScope& handles_;
447*795d594fSAndroid Build Coastguard Worker   };
448*795d594fSAndroid Build Coastguard Worker 
449*795d594fSAndroid Build Coastguard Worker   // Helper class visitor to filter out classes we cannot emit.
450*795d594fSAndroid Build Coastguard Worker   class PruneVisitor {
451*795d594fSAndroid Build Coastguard Worker    public:
PruneVisitor(Thread * self,RuntimeImageHelper * helper,const ArenaSet<const DexFile * > & dex_files,ArenaVector<Handle<mirror::Class>> & classes,ArenaAllocator & allocator)452*795d594fSAndroid Build Coastguard Worker     PruneVisitor(Thread* self,
453*795d594fSAndroid Build Coastguard Worker                  RuntimeImageHelper* helper,
454*795d594fSAndroid Build Coastguard Worker                  const ArenaSet<const DexFile*>& dex_files,
455*795d594fSAndroid Build Coastguard Worker                  ArenaVector<Handle<mirror::Class>>& classes,
456*795d594fSAndroid Build Coastguard Worker                  ArenaAllocator& allocator)
457*795d594fSAndroid Build Coastguard Worker         : self_(self),
458*795d594fSAndroid Build Coastguard Worker           helper_(helper),
459*795d594fSAndroid Build Coastguard Worker           dex_files_(dex_files),
460*795d594fSAndroid Build Coastguard Worker           visited_(allocator.Adapter()),
461*795d594fSAndroid Build Coastguard Worker           classes_to_write_(classes) {}
462*795d594fSAndroid Build Coastguard Worker 
CanEmitHelper(Handle<mirror::Class> cls)463*795d594fSAndroid Build Coastguard Worker     bool CanEmitHelper(Handle<mirror::Class> cls) REQUIRES_SHARED(Locks::mutator_lock_) {
464*795d594fSAndroid Build Coastguard Worker       // If the class comes from a dex file which is not part of the primary
465*795d594fSAndroid Build Coastguard Worker       // APK, don't encode it.
466*795d594fSAndroid Build Coastguard Worker       if (!ContainsElement(dex_files_, &cls->GetDexFile())) {
467*795d594fSAndroid Build Coastguard Worker         return false;
468*795d594fSAndroid Build Coastguard Worker       }
469*795d594fSAndroid Build Coastguard Worker 
470*795d594fSAndroid Build Coastguard Worker       // Ensure pointers to classes in `cls` can also be emitted.
471*795d594fSAndroid Build Coastguard Worker       StackHandleScope<1> hs(self_);
472*795d594fSAndroid Build Coastguard Worker       MutableHandle<mirror::Class> other_class = hs.NewHandle(cls->GetSuperClass());
473*795d594fSAndroid Build Coastguard Worker       if (!CanEmit(other_class)) {
474*795d594fSAndroid Build Coastguard Worker         return false;
475*795d594fSAndroid Build Coastguard Worker       }
476*795d594fSAndroid Build Coastguard Worker 
477*795d594fSAndroid Build Coastguard Worker       other_class.Assign(cls->GetComponentType());
478*795d594fSAndroid Build Coastguard Worker       if (!CanEmit(other_class)) {
479*795d594fSAndroid Build Coastguard Worker         return false;
480*795d594fSAndroid Build Coastguard Worker       }
481*795d594fSAndroid Build Coastguard Worker 
482*795d594fSAndroid Build Coastguard Worker       for (size_t i = 0, num_interfaces = cls->NumDirectInterfaces(); i < num_interfaces; ++i) {
483*795d594fSAndroid Build Coastguard Worker         other_class.Assign(cls->GetDirectInterface(i));
484*795d594fSAndroid Build Coastguard Worker         DCHECK(other_class != nullptr);
485*795d594fSAndroid Build Coastguard Worker         if (!CanEmit(other_class)) {
486*795d594fSAndroid Build Coastguard Worker           return false;
487*795d594fSAndroid Build Coastguard Worker         }
488*795d594fSAndroid Build Coastguard Worker       }
489*795d594fSAndroid Build Coastguard Worker       return true;
490*795d594fSAndroid Build Coastguard Worker     }
491*795d594fSAndroid Build Coastguard Worker 
CanEmit(Handle<mirror::Class> cls)492*795d594fSAndroid Build Coastguard Worker     bool CanEmit(Handle<mirror::Class> cls) REQUIRES_SHARED(Locks::mutator_lock_) {
493*795d594fSAndroid Build Coastguard Worker       if (cls == nullptr) {
494*795d594fSAndroid Build Coastguard Worker         return true;
495*795d594fSAndroid Build Coastguard Worker       }
496*795d594fSAndroid Build Coastguard Worker       DCHECK(cls->IsResolved());
497*795d594fSAndroid Build Coastguard Worker       // Only emit classes that are resolved and not erroneous.
498*795d594fSAndroid Build Coastguard Worker       if (cls->IsErroneous()) {
499*795d594fSAndroid Build Coastguard Worker         return false;
500*795d594fSAndroid Build Coastguard Worker       }
501*795d594fSAndroid Build Coastguard Worker 
502*795d594fSAndroid Build Coastguard Worker       // Proxy classes are generated at runtime, so don't emit them.
503*795d594fSAndroid Build Coastguard Worker       if (cls->IsProxyClass()) {
504*795d594fSAndroid Build Coastguard Worker         return false;
505*795d594fSAndroid Build Coastguard Worker       }
506*795d594fSAndroid Build Coastguard Worker 
507*795d594fSAndroid Build Coastguard Worker       // Classes in the boot image can be trivially encoded directly.
508*795d594fSAndroid Build Coastguard Worker       if (helper_->IsInBootImage(cls.Get())) {
509*795d594fSAndroid Build Coastguard Worker         return true;
510*795d594fSAndroid Build Coastguard Worker       }
511*795d594fSAndroid Build Coastguard Worker 
512*795d594fSAndroid Build Coastguard Worker       if (cls->IsBootStrapClassLoaded()) {
513*795d594fSAndroid Build Coastguard Worker         // We cannot encode classes that are part of the boot classpath.
514*795d594fSAndroid Build Coastguard Worker         return false;
515*795d594fSAndroid Build Coastguard Worker       }
516*795d594fSAndroid Build Coastguard Worker 
517*795d594fSAndroid Build Coastguard Worker       DCHECK(!cls->IsPrimitive());
518*795d594fSAndroid Build Coastguard Worker 
519*795d594fSAndroid Build Coastguard Worker       if (cls->IsArrayClass()) {
520*795d594fSAndroid Build Coastguard Worker         if (cls->IsBootStrapClassLoaded()) {
521*795d594fSAndroid Build Coastguard Worker           // For boot classpath arrays, we can only emit them if they are
522*795d594fSAndroid Build Coastguard Worker           // in the boot image already.
523*795d594fSAndroid Build Coastguard Worker           return helper_->IsInBootImage(cls.Get());
524*795d594fSAndroid Build Coastguard Worker         }
525*795d594fSAndroid Build Coastguard Worker         ObjPtr<mirror::Class> temp = cls.Get();
526*795d594fSAndroid Build Coastguard Worker         while ((temp = temp->GetComponentType())->IsArrayClass()) {}
527*795d594fSAndroid Build Coastguard Worker         StackHandleScope<1> hs(self_);
528*795d594fSAndroid Build Coastguard Worker         Handle<mirror::Class> other_class = hs.NewHandle(temp);
529*795d594fSAndroid Build Coastguard Worker         return CanEmit(other_class);
530*795d594fSAndroid Build Coastguard Worker       }
531*795d594fSAndroid Build Coastguard Worker       const dex::ClassDef* class_def = cls->GetClassDef();
532*795d594fSAndroid Build Coastguard Worker       DCHECK_NE(class_def, nullptr);
533*795d594fSAndroid Build Coastguard Worker       auto existing = visited_.find(class_def);
534*795d594fSAndroid Build Coastguard Worker       if (existing != visited_.end()) {
535*795d594fSAndroid Build Coastguard Worker         // Already processed;
536*795d594fSAndroid Build Coastguard Worker         return existing->second == VisitState::kCanEmit;
537*795d594fSAndroid Build Coastguard Worker       }
538*795d594fSAndroid Build Coastguard Worker 
539*795d594fSAndroid Build Coastguard Worker       visited_.Put(class_def, VisitState::kVisiting);
540*795d594fSAndroid Build Coastguard Worker       if (CanEmitHelper(cls)) {
541*795d594fSAndroid Build Coastguard Worker         visited_.Overwrite(class_def, VisitState::kCanEmit);
542*795d594fSAndroid Build Coastguard Worker         return true;
543*795d594fSAndroid Build Coastguard Worker       } else {
544*795d594fSAndroid Build Coastguard Worker         visited_.Overwrite(class_def, VisitState::kCannotEmit);
545*795d594fSAndroid Build Coastguard Worker         return false;
546*795d594fSAndroid Build Coastguard Worker       }
547*795d594fSAndroid Build Coastguard Worker     }
548*795d594fSAndroid Build Coastguard Worker 
Visit(Handle<mirror::Object> obj)549*795d594fSAndroid Build Coastguard Worker     void Visit(Handle<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) {
550*795d594fSAndroid Build Coastguard Worker       MutableHandle<mirror::Class> cls(obj.GetReference());
551*795d594fSAndroid Build Coastguard Worker       if (CanEmit(cls)) {
552*795d594fSAndroid Build Coastguard Worker         if (cls->IsBootStrapClassLoaded()) {
553*795d594fSAndroid Build Coastguard Worker           DCHECK(helper_->IsInBootImage(cls.Get()));
554*795d594fSAndroid Build Coastguard Worker           // Insert the bootclasspath class in the class table.
555*795d594fSAndroid Build Coastguard Worker           uint32_t hash = cls->DescriptorHash();
556*795d594fSAndroid Build Coastguard Worker           helper_->class_table_.InsertWithHash(ClassTable::TableSlot(cls.Get(), hash), hash);
557*795d594fSAndroid Build Coastguard Worker         } else {
558*795d594fSAndroid Build Coastguard Worker           classes_to_write_.push_back(cls);
559*795d594fSAndroid Build Coastguard Worker         }
560*795d594fSAndroid Build Coastguard Worker       }
561*795d594fSAndroid Build Coastguard Worker     }
562*795d594fSAndroid Build Coastguard Worker 
563*795d594fSAndroid Build Coastguard Worker    private:
564*795d594fSAndroid Build Coastguard Worker     enum class VisitState {
565*795d594fSAndroid Build Coastguard Worker       kVisiting,
566*795d594fSAndroid Build Coastguard Worker       kCanEmit,
567*795d594fSAndroid Build Coastguard Worker       kCannotEmit,
568*795d594fSAndroid Build Coastguard Worker     };
569*795d594fSAndroid Build Coastguard Worker 
570*795d594fSAndroid Build Coastguard Worker     Thread* const self_;
571*795d594fSAndroid Build Coastguard Worker     RuntimeImageHelper* const helper_;
572*795d594fSAndroid Build Coastguard Worker     const ArenaSet<const DexFile*>& dex_files_;
573*795d594fSAndroid Build Coastguard Worker     ArenaSafeMap<const dex::ClassDef*, VisitState> visited_;
574*795d594fSAndroid Build Coastguard Worker     ArenaVector<Handle<mirror::Class>>& classes_to_write_;
575*795d594fSAndroid Build Coastguard Worker   };
576*795d594fSAndroid Build Coastguard Worker 
EmitClasses(Thread * self,Handle<mirror::ObjectArray<mirror::Object>> dex_cache_array)577*795d594fSAndroid Build Coastguard Worker   void EmitClasses(Thread* self, Handle<mirror::ObjectArray<mirror::Object>> dex_cache_array)
578*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
579*795d594fSAndroid Build Coastguard Worker     ScopedTrace trace("Emit strings and classes");
580*795d594fSAndroid Build Coastguard Worker     ArenaSet<const DexFile*> dex_files(allocator_.Adapter());
581*795d594fSAndroid Build Coastguard Worker     for (int32_t i = 0; i < dex_cache_array->GetLength(); ++i) {
582*795d594fSAndroid Build Coastguard Worker       dex_files.insert(dex_cache_array->Get(i)->AsDexCache()->GetDexFile());
583*795d594fSAndroid Build Coastguard Worker     }
584*795d594fSAndroid Build Coastguard Worker 
585*795d594fSAndroid Build Coastguard Worker     StackHandleScope<1> hs(self);
586*795d594fSAndroid Build Coastguard Worker     Handle<mirror::ClassLoader> loader = hs.NewHandle(
587*795d594fSAndroid Build Coastguard Worker         dex_cache_array->Get(0)->AsDexCache()->GetClassLoader());
588*795d594fSAndroid Build Coastguard Worker     ClassTable* const class_table = loader->GetClassTable();
589*795d594fSAndroid Build Coastguard Worker     if (class_table == nullptr) {
590*795d594fSAndroid Build Coastguard Worker       return;
591*795d594fSAndroid Build Coastguard Worker     }
592*795d594fSAndroid Build Coastguard Worker 
593*795d594fSAndroid Build Coastguard Worker     VariableSizedHandleScope handles(self);
594*795d594fSAndroid Build Coastguard Worker     {
595*795d594fSAndroid Build Coastguard Worker       ClassTableVisitor class_table_visitor(loader, handles);
596*795d594fSAndroid Build Coastguard Worker       class_table->Visit(class_table_visitor);
597*795d594fSAndroid Build Coastguard Worker     }
598*795d594fSAndroid Build Coastguard Worker 
599*795d594fSAndroid Build Coastguard Worker     ArenaVector<Handle<mirror::Class>> classes_to_write(allocator_.Adapter());
600*795d594fSAndroid Build Coastguard Worker     classes_to_write.reserve(class_table->Size());
601*795d594fSAndroid Build Coastguard Worker     {
602*795d594fSAndroid Build Coastguard Worker       PruneVisitor prune_visitor(self, this, dex_files, classes_to_write, allocator_);
603*795d594fSAndroid Build Coastguard Worker       handles.VisitHandles(prune_visitor);
604*795d594fSAndroid Build Coastguard Worker     }
605*795d594fSAndroid Build Coastguard Worker 
606*795d594fSAndroid Build Coastguard Worker     for (Handle<mirror::Class> cls : classes_to_write) {
607*795d594fSAndroid Build Coastguard Worker       {
608*795d594fSAndroid Build Coastguard Worker         ScopedAssertNoThreadSuspension sants("Writing class");
609*795d594fSAndroid Build Coastguard Worker         CopyClass(cls.Get());
610*795d594fSAndroid Build Coastguard Worker       }
611*795d594fSAndroid Build Coastguard Worker       self->AllowThreadSuspension();
612*795d594fSAndroid Build Coastguard Worker     }
613*795d594fSAndroid Build Coastguard Worker 
614*795d594fSAndroid Build Coastguard Worker     // Relocate the type array entries. We do this now before creating image
615*795d594fSAndroid Build Coastguard Worker     // sections because we may add new boot image classes into our
616*795d594fSAndroid Build Coastguard Worker     // `class_table`_.
617*795d594fSAndroid Build Coastguard Worker     for (auto entry : dex_caches_) {
618*795d594fSAndroid Build Coastguard Worker       const DexFile& dex_file = *entry.first;
619*795d594fSAndroid Build Coastguard Worker       mirror::DexCache* cache = reinterpret_cast<mirror::DexCache*>(&objects_[entry.second]);
620*795d594fSAndroid Build Coastguard Worker       mirror::GcRootArray<mirror::Class>* old_types_array = cache->GetResolvedTypesArray();
621*795d594fSAndroid Build Coastguard Worker       if (HasNativeRelocation(old_types_array)) {
622*795d594fSAndroid Build Coastguard Worker         auto reloc_it = native_relocations_.find(old_types_array);
623*795d594fSAndroid Build Coastguard Worker         DCHECK(reloc_it != native_relocations_.end());
624*795d594fSAndroid Build Coastguard Worker         ArenaVector<uint8_t>& data =
625*795d594fSAndroid Build Coastguard Worker             (reloc_it->second.first == NativeRelocationKind::kFullNativeDexCacheArray)
626*795d594fSAndroid Build Coastguard Worker                 ? dex_cache_arrays_ : metadata_;
627*795d594fSAndroid Build Coastguard Worker         mirror::GcRootArray<mirror::Class>* content_array =
628*795d594fSAndroid Build Coastguard Worker             reinterpret_cast<mirror::GcRootArray<mirror::Class>*>(
629*795d594fSAndroid Build Coastguard Worker                 data.data() + reloc_it->second.second);
630*795d594fSAndroid Build Coastguard Worker         for (uint32_t i = 0; i < dex_file.NumTypeIds(); ++i) {
631*795d594fSAndroid Build Coastguard Worker           ObjPtr<mirror::Class> cls = old_types_array->Get(i);
632*795d594fSAndroid Build Coastguard Worker           if (cls == nullptr) {
633*795d594fSAndroid Build Coastguard Worker             content_array->Set(i, nullptr);
634*795d594fSAndroid Build Coastguard Worker           } else if (IsInBootImage(cls.Ptr())) {
635*795d594fSAndroid Build Coastguard Worker             if (!cls->IsPrimitive()) {
636*795d594fSAndroid Build Coastguard Worker               // The dex cache is concurrently updated by the app. If the class
637*795d594fSAndroid Build Coastguard Worker               // collection logic in `PruneVisitor` did not see this class, insert it now.
638*795d594fSAndroid Build Coastguard Worker               // Note that application class tables do not contain primitive
639*795d594fSAndroid Build Coastguard Worker               // classes.
640*795d594fSAndroid Build Coastguard Worker               uint32_t hash = cls->DescriptorHash();
641*795d594fSAndroid Build Coastguard Worker               class_table_.InsertWithHash(ClassTable::TableSlot(cls.Ptr(), hash), hash);
642*795d594fSAndroid Build Coastguard Worker             }
643*795d594fSAndroid Build Coastguard Worker             content_array->Set(i, cls.Ptr());
644*795d594fSAndroid Build Coastguard Worker           } else if (cls->IsArrayClass()) {
645*795d594fSAndroid Build Coastguard Worker             std::string class_name;
646*795d594fSAndroid Build Coastguard Worker             cls->GetDescriptor(&class_name);
647*795d594fSAndroid Build Coastguard Worker             auto class_it = array_classes_.find(class_name);
648*795d594fSAndroid Build Coastguard Worker             if (class_it == array_classes_.end()) {
649*795d594fSAndroid Build Coastguard Worker               content_array->Set(i, nullptr);
650*795d594fSAndroid Build Coastguard Worker             } else {
651*795d594fSAndroid Build Coastguard Worker               mirror::Class* ptr = reinterpret_cast<mirror::Class*>(
652*795d594fSAndroid Build Coastguard Worker                   image_begin_ + sizeof(ImageHeader) + class_it->second);
653*795d594fSAndroid Build Coastguard Worker               content_array->Set(i, ptr);
654*795d594fSAndroid Build Coastguard Worker             }
655*795d594fSAndroid Build Coastguard Worker           } else {
656*795d594fSAndroid Build Coastguard Worker             DCHECK(!cls->IsPrimitive());
657*795d594fSAndroid Build Coastguard Worker             DCHECK(!cls->IsProxyClass());
658*795d594fSAndroid Build Coastguard Worker             const dex::ClassDef* class_def = cls->GetClassDef();
659*795d594fSAndroid Build Coastguard Worker             DCHECK_NE(class_def, nullptr);
660*795d594fSAndroid Build Coastguard Worker             auto class_it = classes_.find(class_def);
661*795d594fSAndroid Build Coastguard Worker             if (class_it == classes_.end()) {
662*795d594fSAndroid Build Coastguard Worker               content_array->Set(i, nullptr);
663*795d594fSAndroid Build Coastguard Worker             } else {
664*795d594fSAndroid Build Coastguard Worker               mirror::Class* ptr = reinterpret_cast<mirror::Class*>(
665*795d594fSAndroid Build Coastguard Worker                   image_begin_ + sizeof(ImageHeader) + class_it->second);
666*795d594fSAndroid Build Coastguard Worker               content_array->Set(i, ptr);
667*795d594fSAndroid Build Coastguard Worker             }
668*795d594fSAndroid Build Coastguard Worker           }
669*795d594fSAndroid Build Coastguard Worker         }
670*795d594fSAndroid Build Coastguard Worker       }
671*795d594fSAndroid Build Coastguard Worker     }
672*795d594fSAndroid Build Coastguard Worker   }
673*795d594fSAndroid Build Coastguard Worker 
674*795d594fSAndroid Build Coastguard Worker   // Helper visitor returning the location of a native pointer in the image.
675*795d594fSAndroid Build Coastguard Worker   class NativePointerVisitor {
676*795d594fSAndroid Build Coastguard Worker    public:
NativePointerVisitor(RuntimeImageHelper * helper)677*795d594fSAndroid Build Coastguard Worker     explicit NativePointerVisitor(RuntimeImageHelper* helper) : helper_(helper) {}
678*795d594fSAndroid Build Coastguard Worker 
679*795d594fSAndroid Build Coastguard Worker     template <typename T>
operator ()(T * ptr,void ** dest_addr) const680*795d594fSAndroid Build Coastguard Worker     T* operator()(T* ptr, [[maybe_unused]] void** dest_addr) const {
681*795d594fSAndroid Build Coastguard Worker       return helper_->NativeLocationInImage(ptr, /* must_have_relocation= */ true);
682*795d594fSAndroid Build Coastguard Worker     }
683*795d594fSAndroid Build Coastguard Worker 
operator ()(T * ptr,bool must_have_relocation=true) const684*795d594fSAndroid Build Coastguard Worker     template <typename T> T* operator()(T* ptr, bool must_have_relocation = true) const {
685*795d594fSAndroid Build Coastguard Worker       return helper_->NativeLocationInImage(ptr, must_have_relocation);
686*795d594fSAndroid Build Coastguard Worker     }
687*795d594fSAndroid Build Coastguard Worker 
688*795d594fSAndroid Build Coastguard Worker    private:
689*795d594fSAndroid Build Coastguard Worker     RuntimeImageHelper* helper_;
690*795d594fSAndroid Build Coastguard Worker   };
691*795d594fSAndroid Build Coastguard Worker 
NativeLocationInImage(T * ptr,bool must_have_relocation) const692*795d594fSAndroid Build Coastguard Worker   template <typename T> T* NativeLocationInImage(T* ptr, bool must_have_relocation) const {
693*795d594fSAndroid Build Coastguard Worker     if (ptr == nullptr || IsInBootImage(ptr)) {
694*795d594fSAndroid Build Coastguard Worker       return ptr;
695*795d594fSAndroid Build Coastguard Worker     }
696*795d594fSAndroid Build Coastguard Worker 
697*795d594fSAndroid Build Coastguard Worker     auto it = native_relocations_.find(ptr);
698*795d594fSAndroid Build Coastguard Worker     if (it == native_relocations_.end()) {
699*795d594fSAndroid Build Coastguard Worker       DCHECK(!must_have_relocation);
700*795d594fSAndroid Build Coastguard Worker       return nullptr;
701*795d594fSAndroid Build Coastguard Worker     }
702*795d594fSAndroid Build Coastguard Worker     switch (it->second.first) {
703*795d594fSAndroid Build Coastguard Worker       case NativeRelocationKind::kArtMethod:
704*795d594fSAndroid Build Coastguard Worker       case NativeRelocationKind::kArtMethodArray: {
705*795d594fSAndroid Build Coastguard Worker         uint32_t offset = sections_[ImageHeader::kSectionArtMethods].Offset();
706*795d594fSAndroid Build Coastguard Worker         return reinterpret_cast<T*>(image_begin_ + offset + it->second.second);
707*795d594fSAndroid Build Coastguard Worker       }
708*795d594fSAndroid Build Coastguard Worker       case NativeRelocationKind::kArtFieldArray: {
709*795d594fSAndroid Build Coastguard Worker         uint32_t offset = sections_[ImageHeader::kSectionArtFields].Offset();
710*795d594fSAndroid Build Coastguard Worker         return reinterpret_cast<T*>(image_begin_ + offset + it->second.second);
711*795d594fSAndroid Build Coastguard Worker       }
712*795d594fSAndroid Build Coastguard Worker       case NativeRelocationKind::kImTable: {
713*795d594fSAndroid Build Coastguard Worker         uint32_t offset = sections_[ImageHeader::kSectionImTables].Offset();
714*795d594fSAndroid Build Coastguard Worker         return reinterpret_cast<T*>(image_begin_ + offset + it->second.second);
715*795d594fSAndroid Build Coastguard Worker       }
716*795d594fSAndroid Build Coastguard Worker       case NativeRelocationKind::kStartupNativeDexCacheArray: {
717*795d594fSAndroid Build Coastguard Worker         uint32_t offset = sections_[ImageHeader::kSectionMetadata].Offset();
718*795d594fSAndroid Build Coastguard Worker         return reinterpret_cast<T*>(image_begin_ + offset + it->second.second);
719*795d594fSAndroid Build Coastguard Worker       }
720*795d594fSAndroid Build Coastguard Worker       case NativeRelocationKind::kFullNativeDexCacheArray: {
721*795d594fSAndroid Build Coastguard Worker         uint32_t offset = sections_[ImageHeader::kSectionDexCacheArrays].Offset();
722*795d594fSAndroid Build Coastguard Worker         return reinterpret_cast<T*>(image_begin_ + offset + it->second.second);
723*795d594fSAndroid Build Coastguard Worker       }
724*795d594fSAndroid Build Coastguard Worker     }
725*795d594fSAndroid Build Coastguard Worker   }
726*795d594fSAndroid Build Coastguard Worker 
727*795d594fSAndroid Build Coastguard Worker   template <typename Visitor>
RelocateMethodPointerArrays(mirror::Class * klass,const Visitor & visitor)728*795d594fSAndroid Build Coastguard Worker   void RelocateMethodPointerArrays(mirror::Class* klass, const Visitor& visitor)
729*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
730*795d594fSAndroid Build Coastguard Worker     // A bit of magic here: we cast contents from our buffer to mirror::Class,
731*795d594fSAndroid Build Coastguard Worker     // and do pointer comparison between 1) these classes, and 2) boot image objects.
732*795d594fSAndroid Build Coastguard Worker     // Both kinds do not move.
733*795d594fSAndroid Build Coastguard Worker 
734*795d594fSAndroid Build Coastguard Worker     // See if we need to fixup the vtable field.
735*795d594fSAndroid Build Coastguard Worker     mirror::Class* super = FromImageOffsetToRuntimeContent<mirror::Class>(
736*795d594fSAndroid Build Coastguard Worker         reinterpret_cast32<uint32_t>(
737*795d594fSAndroid Build Coastguard Worker             klass->GetSuperClass<kVerifyNone, kWithoutReadBarrier>().Ptr()));
738*795d594fSAndroid Build Coastguard Worker     DCHECK(super != nullptr) << "j.l.Object should never be in an app runtime image";
739*795d594fSAndroid Build Coastguard Worker     mirror::PointerArray* vtable = FromImageOffsetToRuntimeContent<mirror::PointerArray>(
740*795d594fSAndroid Build Coastguard Worker         reinterpret_cast32<uint32_t>(klass->GetVTable<kVerifyNone, kWithoutReadBarrier>().Ptr()));
741*795d594fSAndroid Build Coastguard Worker     mirror::PointerArray* super_vtable = FromImageOffsetToRuntimeContent<mirror::PointerArray>(
742*795d594fSAndroid Build Coastguard Worker         reinterpret_cast32<uint32_t>(super->GetVTable<kVerifyNone, kWithoutReadBarrier>().Ptr()));
743*795d594fSAndroid Build Coastguard Worker     if (vtable != nullptr && vtable != super_vtable) {
744*795d594fSAndroid Build Coastguard Worker       DCHECK(!IsInBootImage(vtable));
745*795d594fSAndroid Build Coastguard Worker       vtable->Fixup(vtable, kRuntimePointerSize, visitor);
746*795d594fSAndroid Build Coastguard Worker     }
747*795d594fSAndroid Build Coastguard Worker 
748*795d594fSAndroid Build Coastguard Worker     // See if we need to fixup entries in the IfTable.
749*795d594fSAndroid Build Coastguard Worker     mirror::IfTable* iftable = FromImageOffsetToRuntimeContent<mirror::IfTable>(
750*795d594fSAndroid Build Coastguard Worker         reinterpret_cast32<uint32_t>(
751*795d594fSAndroid Build Coastguard Worker             klass->GetIfTable<kVerifyNone, kWithoutReadBarrier>().Ptr()));
752*795d594fSAndroid Build Coastguard Worker     mirror::IfTable* super_iftable = FromImageOffsetToRuntimeContent<mirror::IfTable>(
753*795d594fSAndroid Build Coastguard Worker         reinterpret_cast32<uint32_t>(
754*795d594fSAndroid Build Coastguard Worker             super->GetIfTable<kVerifyNone, kWithoutReadBarrier>().Ptr()));
755*795d594fSAndroid Build Coastguard Worker     int32_t iftable_count = iftable->Count();
756*795d594fSAndroid Build Coastguard Worker     int32_t super_iftable_count = super_iftable->Count();
757*795d594fSAndroid Build Coastguard Worker     for (int32_t i = 0; i < iftable_count; ++i) {
758*795d594fSAndroid Build Coastguard Worker       mirror::PointerArray* methods = FromImageOffsetToRuntimeContent<mirror::PointerArray>(
759*795d594fSAndroid Build Coastguard Worker           reinterpret_cast32<uint32_t>(
760*795d594fSAndroid Build Coastguard Worker               iftable->GetMethodArrayOrNull<kVerifyNone, kWithoutReadBarrier>(i).Ptr()));
761*795d594fSAndroid Build Coastguard Worker       mirror::PointerArray* super_methods = (i < super_iftable_count)
762*795d594fSAndroid Build Coastguard Worker           ? FromImageOffsetToRuntimeContent<mirror::PointerArray>(
763*795d594fSAndroid Build Coastguard Worker                 reinterpret_cast32<uint32_t>(
764*795d594fSAndroid Build Coastguard Worker                     super_iftable->GetMethodArrayOrNull<kVerifyNone, kWithoutReadBarrier>(i).Ptr()))
765*795d594fSAndroid Build Coastguard Worker           : nullptr;
766*795d594fSAndroid Build Coastguard Worker       if (methods != super_methods) {
767*795d594fSAndroid Build Coastguard Worker         DCHECK(!IsInBootImage(methods));
768*795d594fSAndroid Build Coastguard Worker         methods->Fixup(methods, kRuntimePointerSize, visitor);
769*795d594fSAndroid Build Coastguard Worker       }
770*795d594fSAndroid Build Coastguard Worker     }
771*795d594fSAndroid Build Coastguard Worker   }
772*795d594fSAndroid Build Coastguard Worker 
773*795d594fSAndroid Build Coastguard Worker   template <typename Visitor, typename T>
RelocateNativeDexCacheArray(mirror::NativeArray<T> * old_method_array,uint32_t num_ids,const Visitor & visitor)774*795d594fSAndroid Build Coastguard Worker   void RelocateNativeDexCacheArray(mirror::NativeArray<T>* old_method_array,
775*795d594fSAndroid Build Coastguard Worker                                    uint32_t num_ids,
776*795d594fSAndroid Build Coastguard Worker                                    const Visitor& visitor)
777*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
778*795d594fSAndroid Build Coastguard Worker     if (old_method_array == nullptr) {
779*795d594fSAndroid Build Coastguard Worker       return;
780*795d594fSAndroid Build Coastguard Worker     }
781*795d594fSAndroid Build Coastguard Worker 
782*795d594fSAndroid Build Coastguard Worker     auto it = native_relocations_.find(old_method_array);
783*795d594fSAndroid Build Coastguard Worker     DCHECK(it != native_relocations_.end());
784*795d594fSAndroid Build Coastguard Worker     ArenaVector<uint8_t>& data =
785*795d594fSAndroid Build Coastguard Worker         (it->second.first == NativeRelocationKind::kFullNativeDexCacheArray)
786*795d594fSAndroid Build Coastguard Worker             ? dex_cache_arrays_ : metadata_;
787*795d594fSAndroid Build Coastguard Worker 
788*795d594fSAndroid Build Coastguard Worker     mirror::NativeArray<T>* content_array =
789*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<mirror::NativeArray<T>*>(data.data() + it->second.second);
790*795d594fSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < num_ids; ++i) {
791*795d594fSAndroid Build Coastguard Worker       // We may not have relocations for some entries, in which case we'll
792*795d594fSAndroid Build Coastguard Worker       // just store null.
793*795d594fSAndroid Build Coastguard Worker       content_array->Set(i, visitor(content_array->Get(i), /* must_have_relocation= */ false));
794*795d594fSAndroid Build Coastguard Worker     }
795*795d594fSAndroid Build Coastguard Worker   }
796*795d594fSAndroid Build Coastguard Worker 
797*795d594fSAndroid Build Coastguard Worker   template <typename Visitor>
RelocateDexCacheArrays(mirror::DexCache * cache,const DexFile & dex_file,const Visitor & visitor)798*795d594fSAndroid Build Coastguard Worker   void RelocateDexCacheArrays(mirror::DexCache* cache,
799*795d594fSAndroid Build Coastguard Worker                               const DexFile& dex_file,
800*795d594fSAndroid Build Coastguard Worker                               const Visitor& visitor)
801*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
802*795d594fSAndroid Build Coastguard Worker     mirror::NativeArray<ArtMethod>* old_method_array = cache->GetResolvedMethodsArray();
803*795d594fSAndroid Build Coastguard Worker     cache->SetResolvedMethodsArray(visitor(old_method_array));
804*795d594fSAndroid Build Coastguard Worker     RelocateNativeDexCacheArray(old_method_array, dex_file.NumMethodIds(), visitor);
805*795d594fSAndroid Build Coastguard Worker 
806*795d594fSAndroid Build Coastguard Worker     mirror::NativeArray<ArtField>* old_field_array = cache->GetResolvedFieldsArray();
807*795d594fSAndroid Build Coastguard Worker     cache->SetResolvedFieldsArray(visitor(old_field_array));
808*795d594fSAndroid Build Coastguard Worker     RelocateNativeDexCacheArray(old_field_array, dex_file.NumFieldIds(), visitor);
809*795d594fSAndroid Build Coastguard Worker 
810*795d594fSAndroid Build Coastguard Worker     mirror::GcRootArray<mirror::String>* old_strings_array = cache->GetStringsArray();
811*795d594fSAndroid Build Coastguard Worker     cache->SetStringsArray(visitor(old_strings_array));
812*795d594fSAndroid Build Coastguard Worker 
813*795d594fSAndroid Build Coastguard Worker     mirror::GcRootArray<mirror::Class>* old_types_array = cache->GetResolvedTypesArray();
814*795d594fSAndroid Build Coastguard Worker     cache->SetResolvedTypesArray(visitor(old_types_array));
815*795d594fSAndroid Build Coastguard Worker   }
816*795d594fSAndroid Build Coastguard Worker 
RelocateNativePointers()817*795d594fSAndroid Build Coastguard Worker   void RelocateNativePointers() {
818*795d594fSAndroid Build Coastguard Worker     ScopedTrace relocate_native_pointers("Relocate native pointers");
819*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(Thread::Current());
820*795d594fSAndroid Build Coastguard Worker     NativePointerVisitor visitor(this);
821*795d594fSAndroid Build Coastguard Worker     for (auto&& entry : classes_) {
822*795d594fSAndroid Build Coastguard Worker       mirror::Class* cls = reinterpret_cast<mirror::Class*>(&objects_[entry.second]);
823*795d594fSAndroid Build Coastguard Worker       cls->FixupNativePointers(cls, kRuntimePointerSize, visitor);
824*795d594fSAndroid Build Coastguard Worker       RelocateMethodPointerArrays(cls, visitor);
825*795d594fSAndroid Build Coastguard Worker     }
826*795d594fSAndroid Build Coastguard Worker     for (auto&& entry : array_classes_) {
827*795d594fSAndroid Build Coastguard Worker       mirror::Class* cls = reinterpret_cast<mirror::Class*>(&objects_[entry.second]);
828*795d594fSAndroid Build Coastguard Worker       cls->FixupNativePointers(cls, kRuntimePointerSize, visitor);
829*795d594fSAndroid Build Coastguard Worker       RelocateMethodPointerArrays(cls, visitor);
830*795d594fSAndroid Build Coastguard Worker     }
831*795d594fSAndroid Build Coastguard Worker     for (auto&& entry : native_relocations_) {
832*795d594fSAndroid Build Coastguard Worker       if (entry.second.first == NativeRelocationKind::kImTable) {
833*795d594fSAndroid Build Coastguard Worker         ImTable* im_table = reinterpret_cast<ImTable*>(im_tables_.data() + entry.second.second);
834*795d594fSAndroid Build Coastguard Worker         RelocateImTable(im_table, visitor);
835*795d594fSAndroid Build Coastguard Worker       }
836*795d594fSAndroid Build Coastguard Worker     }
837*795d594fSAndroid Build Coastguard Worker     for (auto&& entry : dex_caches_) {
838*795d594fSAndroid Build Coastguard Worker       mirror::DexCache* cache = reinterpret_cast<mirror::DexCache*>(&objects_[entry.second]);
839*795d594fSAndroid Build Coastguard Worker       RelocateDexCacheArrays(cache, *entry.first, visitor);
840*795d594fSAndroid Build Coastguard Worker     }
841*795d594fSAndroid Build Coastguard Worker   }
842*795d594fSAndroid Build Coastguard Worker 
RelocateImTable(ImTable * im_table,const NativePointerVisitor & visitor)843*795d594fSAndroid Build Coastguard Worker   void RelocateImTable(ImTable* im_table, const NativePointerVisitor& visitor) {
844*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i < ImTable::kSize; ++i) {
845*795d594fSAndroid Build Coastguard Worker       ArtMethod* method = im_table->Get(i, kRuntimePointerSize);
846*795d594fSAndroid Build Coastguard Worker       ArtMethod* new_method = nullptr;
847*795d594fSAndroid Build Coastguard Worker       if (method->IsRuntimeMethod() && !IsInBootImage(method)) {
848*795d594fSAndroid Build Coastguard Worker         // New IMT conflict method: just use the boot image version.
849*795d594fSAndroid Build Coastguard Worker         // TODO: Consider copying the new IMT conflict method.
850*795d594fSAndroid Build Coastguard Worker         new_method = Runtime::Current()->GetImtConflictMethod();
851*795d594fSAndroid Build Coastguard Worker         DCHECK(IsInBootImage(new_method));
852*795d594fSAndroid Build Coastguard Worker       } else {
853*795d594fSAndroid Build Coastguard Worker         new_method = visitor(method);
854*795d594fSAndroid Build Coastguard Worker       }
855*795d594fSAndroid Build Coastguard Worker       if (method != new_method) {
856*795d594fSAndroid Build Coastguard Worker         im_table->Set(i, new_method, kRuntimePointerSize);
857*795d594fSAndroid Build Coastguard Worker       }
858*795d594fSAndroid Build Coastguard Worker     }
859*795d594fSAndroid Build Coastguard Worker   }
860*795d594fSAndroid Build Coastguard Worker 
CopyFieldArrays(ObjPtr<mirror::Class> cls,uint32_t class_image_address)861*795d594fSAndroid Build Coastguard Worker   void CopyFieldArrays(ObjPtr<mirror::Class> cls, uint32_t class_image_address)
862*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
863*795d594fSAndroid Build Coastguard Worker     LengthPrefixedArray<ArtField>* fields[] = {
864*795d594fSAndroid Build Coastguard Worker         cls->GetSFieldsPtr(), cls->GetIFieldsPtr(),
865*795d594fSAndroid Build Coastguard Worker     };
866*795d594fSAndroid Build Coastguard Worker     for (LengthPrefixedArray<ArtField>* cur_fields : fields) {
867*795d594fSAndroid Build Coastguard Worker       if (cur_fields != nullptr) {
868*795d594fSAndroid Build Coastguard Worker         // Copy the array.
869*795d594fSAndroid Build Coastguard Worker         size_t number_of_fields = cur_fields->size();
870*795d594fSAndroid Build Coastguard Worker         size_t size = LengthPrefixedArray<ArtField>::ComputeSize(number_of_fields);
871*795d594fSAndroid Build Coastguard Worker         size_t offset = art_fields_.size();
872*795d594fSAndroid Build Coastguard Worker         art_fields_.resize(offset + size);
873*795d594fSAndroid Build Coastguard Worker         auto* dest_array =
874*795d594fSAndroid Build Coastguard Worker             reinterpret_cast<LengthPrefixedArray<ArtField>*>(art_fields_.data() + offset);
875*795d594fSAndroid Build Coastguard Worker         memcpy(dest_array, cur_fields, size);
876*795d594fSAndroid Build Coastguard Worker         native_relocations_.Put(cur_fields,
877*795d594fSAndroid Build Coastguard Worker                                 std::make_pair(NativeRelocationKind::kArtFieldArray, offset));
878*795d594fSAndroid Build Coastguard Worker 
879*795d594fSAndroid Build Coastguard Worker         // Update the class pointer of individual fields.
880*795d594fSAndroid Build Coastguard Worker         for (size_t i = 0; i != number_of_fields; ++i) {
881*795d594fSAndroid Build Coastguard Worker           dest_array->At(i).GetDeclaringClassAddressWithoutBarrier()->Assign(
882*795d594fSAndroid Build Coastguard Worker               reinterpret_cast<mirror::Class*>(class_image_address));
883*795d594fSAndroid Build Coastguard Worker         }
884*795d594fSAndroid Build Coastguard Worker       }
885*795d594fSAndroid Build Coastguard Worker     }
886*795d594fSAndroid Build Coastguard Worker   }
887*795d594fSAndroid Build Coastguard Worker 
CopyMethodArrays(ObjPtr<mirror::Class> cls,uint32_t class_image_address,bool is_class_initialized)888*795d594fSAndroid Build Coastguard Worker   void CopyMethodArrays(ObjPtr<mirror::Class> cls,
889*795d594fSAndroid Build Coastguard Worker                         uint32_t class_image_address,
890*795d594fSAndroid Build Coastguard Worker                         bool is_class_initialized)
891*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
892*795d594fSAndroid Build Coastguard Worker     size_t number_of_methods = cls->NumMethods();
893*795d594fSAndroid Build Coastguard Worker     if (number_of_methods == 0) {
894*795d594fSAndroid Build Coastguard Worker       return;
895*795d594fSAndroid Build Coastguard Worker     }
896*795d594fSAndroid Build Coastguard Worker 
897*795d594fSAndroid Build Coastguard Worker     size_t size = LengthPrefixedArray<ArtMethod>::ComputeSize(number_of_methods);
898*795d594fSAndroid Build Coastguard Worker     size_t offset = art_methods_.size();
899*795d594fSAndroid Build Coastguard Worker     art_methods_.resize(offset + size);
900*795d594fSAndroid Build Coastguard Worker     auto* dest_array =
901*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<LengthPrefixedArray<ArtMethod>*>(art_methods_.data() + offset);
902*795d594fSAndroid Build Coastguard Worker     memcpy(dest_array, cls->GetMethodsPtr(), size);
903*795d594fSAndroid Build Coastguard Worker     native_relocations_.Put(cls->GetMethodsPtr(),
904*795d594fSAndroid Build Coastguard Worker                             std::make_pair(NativeRelocationKind::kArtMethodArray, offset));
905*795d594fSAndroid Build Coastguard Worker 
906*795d594fSAndroid Build Coastguard Worker     for (size_t i = 0; i != number_of_methods; ++i) {
907*795d594fSAndroid Build Coastguard Worker       ArtMethod* method = &cls->GetMethodsPtr()->At(i);
908*795d594fSAndroid Build Coastguard Worker       ArtMethod* copy = &dest_array->At(i);
909*795d594fSAndroid Build Coastguard Worker 
910*795d594fSAndroid Build Coastguard Worker       // Update the class pointer.
911*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::Class> declaring_class = method->GetDeclaringClass();
912*795d594fSAndroid Build Coastguard Worker       if (declaring_class == cls) {
913*795d594fSAndroid Build Coastguard Worker         copy->GetDeclaringClassAddressWithoutBarrier()->Assign(
914*795d594fSAndroid Build Coastguard Worker             reinterpret_cast<mirror::Class*>(class_image_address));
915*795d594fSAndroid Build Coastguard Worker       } else {
916*795d594fSAndroid Build Coastguard Worker         DCHECK(method->IsCopied());
917*795d594fSAndroid Build Coastguard Worker         if (!IsInBootImage(declaring_class.Ptr())) {
918*795d594fSAndroid Build Coastguard Worker           DCHECK(classes_.find(declaring_class->GetClassDef()) != classes_.end());
919*795d594fSAndroid Build Coastguard Worker           copy->GetDeclaringClassAddressWithoutBarrier()->Assign(
920*795d594fSAndroid Build Coastguard Worker               reinterpret_cast<mirror::Class*>(
921*795d594fSAndroid Build Coastguard Worker                   image_begin_ +
922*795d594fSAndroid Build Coastguard Worker                   sizeof(ImageHeader) +
923*795d594fSAndroid Build Coastguard Worker                   classes_.Get(declaring_class->GetClassDef())));
924*795d594fSAndroid Build Coastguard Worker         }
925*795d594fSAndroid Build Coastguard Worker       }
926*795d594fSAndroid Build Coastguard Worker 
927*795d594fSAndroid Build Coastguard Worker       // Record the native relocation of the method.
928*795d594fSAndroid Build Coastguard Worker       uintptr_t copy_offset =
929*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<uintptr_t>(copy) - reinterpret_cast<uintptr_t>(art_methods_.data());
930*795d594fSAndroid Build Coastguard Worker       native_relocations_.Put(method,
931*795d594fSAndroid Build Coastguard Worker                               std::make_pair(NativeRelocationKind::kArtMethod, copy_offset));
932*795d594fSAndroid Build Coastguard Worker 
933*795d594fSAndroid Build Coastguard Worker       // Ignore the single-implementation info for abstract method.
934*795d594fSAndroid Build Coastguard Worker       if (method->IsAbstract()) {
935*795d594fSAndroid Build Coastguard Worker         copy->SetHasSingleImplementation(false);
936*795d594fSAndroid Build Coastguard Worker         copy->SetSingleImplementation(nullptr, kRuntimePointerSize);
937*795d594fSAndroid Build Coastguard Worker       }
938*795d594fSAndroid Build Coastguard Worker 
939*795d594fSAndroid Build Coastguard Worker       // Set the entrypoint and data pointer of the method.
940*795d594fSAndroid Build Coastguard Worker       StubType stub;
941*795d594fSAndroid Build Coastguard Worker       if (method->IsNative()) {
942*795d594fSAndroid Build Coastguard Worker         stub = StubType::kQuickGenericJNITrampoline;
943*795d594fSAndroid Build Coastguard Worker       } else if (!cls->IsVerified()) {
944*795d594fSAndroid Build Coastguard Worker         stub = StubType::kQuickToInterpreterBridge;
945*795d594fSAndroid Build Coastguard Worker       } else if (!is_class_initialized && method->NeedsClinitCheckBeforeCall()) {
946*795d594fSAndroid Build Coastguard Worker         stub = StubType::kQuickResolutionTrampoline;
947*795d594fSAndroid Build Coastguard Worker       } else if (interpreter::IsNterpSupported() && CanMethodUseNterp(method)) {
948*795d594fSAndroid Build Coastguard Worker         stub = StubType::kNterpTrampoline;
949*795d594fSAndroid Build Coastguard Worker       } else {
950*795d594fSAndroid Build Coastguard Worker         stub = StubType::kQuickToInterpreterBridge;
951*795d594fSAndroid Build Coastguard Worker       }
952*795d594fSAndroid Build Coastguard Worker       const std::vector<gc::space::ImageSpace*>& image_spaces =
953*795d594fSAndroid Build Coastguard Worker           Runtime::Current()->GetHeap()->GetBootImageSpaces();
954*795d594fSAndroid Build Coastguard Worker       DCHECK(!image_spaces.empty());
955*795d594fSAndroid Build Coastguard Worker       const OatFile* oat_file = image_spaces[0]->GetOatFile();
956*795d594fSAndroid Build Coastguard Worker       DCHECK(oat_file != nullptr);
957*795d594fSAndroid Build Coastguard Worker       const OatHeader& header = oat_file->GetOatHeader();
958*795d594fSAndroid Build Coastguard Worker       const void* entrypoint = header.GetOatAddress(stub);
959*795d594fSAndroid Build Coastguard Worker       if (method->IsNative() && (is_class_initialized || !method->NeedsClinitCheckBeforeCall())) {
960*795d594fSAndroid Build Coastguard Worker         // Use boot JNI stub if found.
961*795d594fSAndroid Build Coastguard Worker         ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
962*795d594fSAndroid Build Coastguard Worker         const void* boot_jni_stub = class_linker->FindBootJniStub(method);
963*795d594fSAndroid Build Coastguard Worker         if (boot_jni_stub != nullptr) {
964*795d594fSAndroid Build Coastguard Worker           entrypoint = boot_jni_stub;
965*795d594fSAndroid Build Coastguard Worker         }
966*795d594fSAndroid Build Coastguard Worker       }
967*795d594fSAndroid Build Coastguard Worker       copy->SetEntryPointFromQuickCompiledCode(entrypoint);
968*795d594fSAndroid Build Coastguard Worker 
969*795d594fSAndroid Build Coastguard Worker       if (method->IsNative()) {
970*795d594fSAndroid Build Coastguard Worker         StubType stub_type = method->IsCriticalNative()
971*795d594fSAndroid Build Coastguard Worker             ? StubType::kJNIDlsymLookupCriticalTrampoline
972*795d594fSAndroid Build Coastguard Worker             : StubType::kJNIDlsymLookupTrampoline;
973*795d594fSAndroid Build Coastguard Worker         copy->SetEntryPointFromJni(header.GetOatAddress(stub_type));
974*795d594fSAndroid Build Coastguard Worker       } else if (method->HasCodeItem()) {
975*795d594fSAndroid Build Coastguard Worker         const uint8_t* code_item = reinterpret_cast<const uint8_t*>(method->GetCodeItem());
976*795d594fSAndroid Build Coastguard Worker         DCHECK_GE(code_item, method->GetDexFile()->DataBegin());
977*795d594fSAndroid Build Coastguard Worker         uint32_t code_item_offset = dchecked_integral_cast<uint32_t>(
978*795d594fSAndroid Build Coastguard Worker             code_item - method->GetDexFile()->DataBegin());;
979*795d594fSAndroid Build Coastguard Worker         copy->SetDataPtrSize(
980*795d594fSAndroid Build Coastguard Worker             reinterpret_cast<const void*>(code_item_offset), kRuntimePointerSize);
981*795d594fSAndroid Build Coastguard Worker       }
982*795d594fSAndroid Build Coastguard Worker     }
983*795d594fSAndroid Build Coastguard Worker   }
984*795d594fSAndroid Build Coastguard Worker 
CopyImTable(ObjPtr<mirror::Class> cls)985*795d594fSAndroid Build Coastguard Worker   void CopyImTable(ObjPtr<mirror::Class> cls) REQUIRES_SHARED(Locks::mutator_lock_) {
986*795d594fSAndroid Build Coastguard Worker     ImTable* table = cls->GetImt(kRuntimePointerSize);
987*795d594fSAndroid Build Coastguard Worker 
988*795d594fSAndroid Build Coastguard Worker     // If the table is null or shared and/or already emitted, we can skip.
989*795d594fSAndroid Build Coastguard Worker     if (table == nullptr || IsInBootImage(table) || HasNativeRelocation(table)) {
990*795d594fSAndroid Build Coastguard Worker       return;
991*795d594fSAndroid Build Coastguard Worker     }
992*795d594fSAndroid Build Coastguard Worker     const size_t size = ImTable::SizeInBytes(kRuntimePointerSize);
993*795d594fSAndroid Build Coastguard Worker     size_t offset = im_tables_.size();
994*795d594fSAndroid Build Coastguard Worker     im_tables_.resize(offset + size);
995*795d594fSAndroid Build Coastguard Worker     uint8_t* dest = im_tables_.data() + offset;
996*795d594fSAndroid Build Coastguard Worker     memcpy(dest, table, size);
997*795d594fSAndroid Build Coastguard Worker     native_relocations_.Put(table, std::make_pair(NativeRelocationKind::kImTable, offset));
998*795d594fSAndroid Build Coastguard Worker   }
999*795d594fSAndroid Build Coastguard Worker 
HasNativeRelocation(void * ptr) const1000*795d594fSAndroid Build Coastguard Worker   bool HasNativeRelocation(void* ptr) const {
1001*795d594fSAndroid Build Coastguard Worker     return native_relocations_.find(ptr) != native_relocations_.end();
1002*795d594fSAndroid Build Coastguard Worker   }
1003*795d594fSAndroid Build Coastguard Worker 
1004*795d594fSAndroid Build Coastguard Worker 
LoadClassesFromReferenceProfile(Thread * self,const dchecked_vector<Handle<mirror::DexCache>> & dex_caches)1005*795d594fSAndroid Build Coastguard Worker   static void LoadClassesFromReferenceProfile(
1006*795d594fSAndroid Build Coastguard Worker       Thread* self,
1007*795d594fSAndroid Build Coastguard Worker       const dchecked_vector<Handle<mirror::DexCache>>& dex_caches)
1008*795d594fSAndroid Build Coastguard Worker           REQUIRES_SHARED(Locks::mutator_lock_) {
1009*795d594fSAndroid Build Coastguard Worker     AppInfo* app_info = Runtime::Current()->GetAppInfo();
1010*795d594fSAndroid Build Coastguard Worker     std::string profile_file = app_info->GetPrimaryApkReferenceProfile();
1011*795d594fSAndroid Build Coastguard Worker 
1012*795d594fSAndroid Build Coastguard Worker     if (profile_file.empty()) {
1013*795d594fSAndroid Build Coastguard Worker       return;
1014*795d594fSAndroid Build Coastguard Worker     }
1015*795d594fSAndroid Build Coastguard Worker 
1016*795d594fSAndroid Build Coastguard Worker     // Lock the file, it could be concurrently updated by the system. Don't block
1017*795d594fSAndroid Build Coastguard Worker     // as this is app startup sensitive.
1018*795d594fSAndroid Build Coastguard Worker     std::string error;
1019*795d594fSAndroid Build Coastguard Worker     ScopedFlock profile =
1020*795d594fSAndroid Build Coastguard Worker         LockedFile::Open(profile_file.c_str(), O_RDONLY, /*block=*/false, &error);
1021*795d594fSAndroid Build Coastguard Worker 
1022*795d594fSAndroid Build Coastguard Worker     if (profile == nullptr) {
1023*795d594fSAndroid Build Coastguard Worker       LOG(DEBUG) << "Couldn't lock the profile file " << profile_file << ": " << error;
1024*795d594fSAndroid Build Coastguard Worker       return;
1025*795d594fSAndroid Build Coastguard Worker     }
1026*795d594fSAndroid Build Coastguard Worker 
1027*795d594fSAndroid Build Coastguard Worker     ProfileCompilationInfo profile_info(/* for_boot_image= */ false);
1028*795d594fSAndroid Build Coastguard Worker 
1029*795d594fSAndroid Build Coastguard Worker     if (!profile_info.Load(profile->Fd())) {
1030*795d594fSAndroid Build Coastguard Worker       LOG(DEBUG) << "Could not load profile file";
1031*795d594fSAndroid Build Coastguard Worker       return;
1032*795d594fSAndroid Build Coastguard Worker     }
1033*795d594fSAndroid Build Coastguard Worker 
1034*795d594fSAndroid Build Coastguard Worker     StackHandleScope<1> hs(self);
1035*795d594fSAndroid Build Coastguard Worker     Handle<mirror::ClassLoader> class_loader =
1036*795d594fSAndroid Build Coastguard Worker         hs.NewHandle<mirror::ClassLoader>(dex_caches[0]->GetClassLoader());
1037*795d594fSAndroid Build Coastguard Worker     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1038*795d594fSAndroid Build Coastguard Worker     ScopedTrace loading_classes("Loading classes from profile");
1039*795d594fSAndroid Build Coastguard Worker     for (auto dex_cache : dex_caches) {
1040*795d594fSAndroid Build Coastguard Worker       const DexFile* dex_file = dex_cache->GetDexFile();
1041*795d594fSAndroid Build Coastguard Worker       const ArenaSet<dex::TypeIndex>* class_types = profile_info.GetClasses(*dex_file);
1042*795d594fSAndroid Build Coastguard Worker       if (class_types == nullptr) {
1043*795d594fSAndroid Build Coastguard Worker         // This means the profile file did not reference the dex file, which is the case
1044*795d594fSAndroid Build Coastguard Worker         // if there's no classes and methods of that dex file in the profile.
1045*795d594fSAndroid Build Coastguard Worker         continue;
1046*795d594fSAndroid Build Coastguard Worker       }
1047*795d594fSAndroid Build Coastguard Worker 
1048*795d594fSAndroid Build Coastguard Worker       for (dex::TypeIndex idx : *class_types) {
1049*795d594fSAndroid Build Coastguard Worker         // The index is greater or equal to NumTypeIds if the type is an extra
1050*795d594fSAndroid Build Coastguard Worker         // descriptor, not referenced by the dex file.
1051*795d594fSAndroid Build Coastguard Worker         if (idx.index_ < dex_file->NumTypeIds()) {
1052*795d594fSAndroid Build Coastguard Worker           ObjPtr<mirror::Class> klass = class_linker->ResolveType(idx, dex_cache, class_loader);
1053*795d594fSAndroid Build Coastguard Worker           if (klass == nullptr) {
1054*795d594fSAndroid Build Coastguard Worker             self->ClearException();
1055*795d594fSAndroid Build Coastguard Worker             LOG(DEBUG) << "Failed to preload " << dex_file->PrettyType(idx);
1056*795d594fSAndroid Build Coastguard Worker             continue;
1057*795d594fSAndroid Build Coastguard Worker           }
1058*795d594fSAndroid Build Coastguard Worker         }
1059*795d594fSAndroid Build Coastguard Worker       }
1060*795d594fSAndroid Build Coastguard Worker     }
1061*795d594fSAndroid Build Coastguard Worker   }
1062*795d594fSAndroid Build Coastguard Worker 
WriteObjects(std::string * error_msg)1063*795d594fSAndroid Build Coastguard Worker   bool WriteObjects(std::string* error_msg) {
1064*795d594fSAndroid Build Coastguard Worker     ScopedTrace write_objects("Writing objects");
1065*795d594fSAndroid Build Coastguard Worker     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1066*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(Thread::Current());
1067*795d594fSAndroid Build Coastguard Worker     VariableSizedHandleScope handles(soa.Self());
1068*795d594fSAndroid Build Coastguard Worker 
1069*795d594fSAndroid Build Coastguard Worker     Handle<mirror::Class> object_array_class = handles.NewHandle(
1070*795d594fSAndroid Build Coastguard Worker         GetClassRoot<mirror::ObjectArray<mirror::Object>>(class_linker));
1071*795d594fSAndroid Build Coastguard Worker 
1072*795d594fSAndroid Build Coastguard Worker     Handle<mirror::ObjectArray<mirror::Object>> image_roots = handles.NewHandle(
1073*795d594fSAndroid Build Coastguard Worker         mirror::ObjectArray<mirror::Object>::Alloc(
1074*795d594fSAndroid Build Coastguard Worker             soa.Self(), object_array_class.Get(), ImageHeader::kImageRootsMax));
1075*795d594fSAndroid Build Coastguard Worker 
1076*795d594fSAndroid Build Coastguard Worker     if (image_roots == nullptr) {
1077*795d594fSAndroid Build Coastguard Worker       DCHECK(soa.Self()->IsExceptionPending());
1078*795d594fSAndroid Build Coastguard Worker       soa.Self()->ClearException();
1079*795d594fSAndroid Build Coastguard Worker       *error_msg = "Out of memory when trying to generate a runtime app image";
1080*795d594fSAndroid Build Coastguard Worker       return false;
1081*795d594fSAndroid Build Coastguard Worker     }
1082*795d594fSAndroid Build Coastguard Worker 
1083*795d594fSAndroid Build Coastguard Worker     // Find the dex files that will be used for generating the app image.
1084*795d594fSAndroid Build Coastguard Worker     dchecked_vector<Handle<mirror::DexCache>> dex_caches;
1085*795d594fSAndroid Build Coastguard Worker     FindDexCaches(soa.Self(), dex_caches, handles);
1086*795d594fSAndroid Build Coastguard Worker 
1087*795d594fSAndroid Build Coastguard Worker     if (dex_caches.size() == 0) {
1088*795d594fSAndroid Build Coastguard Worker       *error_msg = "Did not find dex caches to generate an app image";
1089*795d594fSAndroid Build Coastguard Worker       return false;
1090*795d594fSAndroid Build Coastguard Worker     }
1091*795d594fSAndroid Build Coastguard Worker     const OatDexFile* oat_dex_file = dex_caches[0]->GetDexFile()->GetOatDexFile();
1092*795d594fSAndroid Build Coastguard Worker     VdexFile* vdex_file = oat_dex_file->GetOatFile()->GetVdexFile();
1093*795d594fSAndroid Build Coastguard Worker     // The first entry in `dex_caches` contains the location of the primary APK.
1094*795d594fSAndroid Build Coastguard Worker     dex_location_ = oat_dex_file->GetDexFileLocation();
1095*795d594fSAndroid Build Coastguard Worker 
1096*795d594fSAndroid Build Coastguard Worker     size_t number_of_dex_files = vdex_file->GetNumberOfDexFiles();
1097*795d594fSAndroid Build Coastguard Worker     if (number_of_dex_files != dex_caches.size()) {
1098*795d594fSAndroid Build Coastguard Worker       // This means some dex files haven't been executed. For simplicity, just
1099*795d594fSAndroid Build Coastguard Worker       // register them and recollect dex caches.
1100*795d594fSAndroid Build Coastguard Worker       Handle<mirror::ClassLoader> loader = handles.NewHandle(dex_caches[0]->GetClassLoader());
1101*795d594fSAndroid Build Coastguard Worker       VisitClassLoaderDexFiles(soa.Self(), loader, [&](const art::DexFile* dex_file)
1102*795d594fSAndroid Build Coastguard Worker           REQUIRES_SHARED(Locks::mutator_lock_) {
1103*795d594fSAndroid Build Coastguard Worker         class_linker->RegisterDexFile(*dex_file, dex_caches[0]->GetClassLoader());
1104*795d594fSAndroid Build Coastguard Worker         return true;  // Continue with other dex files.
1105*795d594fSAndroid Build Coastguard Worker       });
1106*795d594fSAndroid Build Coastguard Worker       dex_caches.clear();
1107*795d594fSAndroid Build Coastguard Worker       FindDexCaches(soa.Self(), dex_caches, handles);
1108*795d594fSAndroid Build Coastguard Worker       if (number_of_dex_files != dex_caches.size()) {
1109*795d594fSAndroid Build Coastguard Worker         *error_msg = "Number of dex caches does not match number of dex files in the primary APK";
1110*795d594fSAndroid Build Coastguard Worker         return false;
1111*795d594fSAndroid Build Coastguard Worker       }
1112*795d594fSAndroid Build Coastguard Worker     }
1113*795d594fSAndroid Build Coastguard Worker 
1114*795d594fSAndroid Build Coastguard Worker     // If classes referenced in the reference profile are not loaded, preload
1115*795d594fSAndroid Build Coastguard Worker     // them. This makes sure we generate a good runtime app image, even if this
1116*795d594fSAndroid Build Coastguard Worker     // current app run did not load all startup classes.
1117*795d594fSAndroid Build Coastguard Worker     LoadClassesFromReferenceProfile(soa.Self(), dex_caches);
1118*795d594fSAndroid Build Coastguard Worker 
1119*795d594fSAndroid Build Coastguard Worker     // We store the checksums of the dex files used at runtime. These can be
1120*795d594fSAndroid Build Coastguard Worker     // different compared to the vdex checksums due to compact dex.
1121*795d594fSAndroid Build Coastguard Worker     std::vector<uint32_t> checksums(number_of_dex_files);
1122*795d594fSAndroid Build Coastguard Worker     uint32_t checksum_index = 0;
1123*795d594fSAndroid Build Coastguard Worker     for (const OatDexFile* current_oat_dex_file : oat_dex_file->GetOatFile()->GetOatDexFiles()) {
1124*795d594fSAndroid Build Coastguard Worker       const DexFile::Header* header =
1125*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<const DexFile::Header*>(current_oat_dex_file->GetDexFilePointer());
1126*795d594fSAndroid Build Coastguard Worker       checksums[checksum_index++] = header->checksum_;
1127*795d594fSAndroid Build Coastguard Worker     }
1128*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(checksum_index, number_of_dex_files);
1129*795d594fSAndroid Build Coastguard Worker 
1130*795d594fSAndroid Build Coastguard Worker     // Create the fake OatHeader to store the dependencies of the image.
1131*795d594fSAndroid Build Coastguard Worker     SafeMap<std::string, std::string> key_value_store;
1132*795d594fSAndroid Build Coastguard Worker     Runtime* runtime = Runtime::Current();
1133*795d594fSAndroid Build Coastguard Worker     key_value_store.Put(OatHeader::kApexVersionsKey, runtime->GetApexVersions());
1134*795d594fSAndroid Build Coastguard Worker     key_value_store.Put(OatHeader::kBootClassPathKey,
1135*795d594fSAndroid Build Coastguard Worker                         android::base::Join(runtime->GetBootClassPathLocations(), ':'));
1136*795d594fSAndroid Build Coastguard Worker     key_value_store.Put(OatHeader::kBootClassPathChecksumsKey,
1137*795d594fSAndroid Build Coastguard Worker                         runtime->GetBootClassPathChecksums());
1138*795d594fSAndroid Build Coastguard Worker     key_value_store.Put(OatHeader::kClassPathKey,
1139*795d594fSAndroid Build Coastguard Worker                         oat_dex_file->GetOatFile()->GetClassLoaderContext());
1140*795d594fSAndroid Build Coastguard Worker     key_value_store.Put(OatHeader::kConcurrentCopying,
1141*795d594fSAndroid Build Coastguard Worker                         gUseReadBarrier ? OatHeader::kTrueValue : OatHeader::kFalseValue);
1142*795d594fSAndroid Build Coastguard Worker 
1143*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<const InstructionSetFeatures> isa_features =
1144*795d594fSAndroid Build Coastguard Worker         InstructionSetFeatures::FromCppDefines();
1145*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<OatHeader> oat_header(
1146*795d594fSAndroid Build Coastguard Worker         OatHeader::Create(kRuntimeQuickCodeISA,
1147*795d594fSAndroid Build Coastguard Worker                           isa_features.get(),
1148*795d594fSAndroid Build Coastguard Worker                           number_of_dex_files,
1149*795d594fSAndroid Build Coastguard Worker                           &key_value_store));
1150*795d594fSAndroid Build Coastguard Worker 
1151*795d594fSAndroid Build Coastguard Worker     // Create the byte array containing the oat header and dex checksums.
1152*795d594fSAndroid Build Coastguard Worker     uint32_t checksums_size = checksums.size() * sizeof(uint32_t);
1153*795d594fSAndroid Build Coastguard Worker     Handle<mirror::ByteArray> header_data = handles.NewHandle(
1154*795d594fSAndroid Build Coastguard Worker         mirror::ByteArray::Alloc(soa.Self(), oat_header->GetHeaderSize() + checksums_size));
1155*795d594fSAndroid Build Coastguard Worker 
1156*795d594fSAndroid Build Coastguard Worker     if (header_data == nullptr) {
1157*795d594fSAndroid Build Coastguard Worker       DCHECK(soa.Self()->IsExceptionPending());
1158*795d594fSAndroid Build Coastguard Worker       soa.Self()->ClearException();
1159*795d594fSAndroid Build Coastguard Worker       *error_msg = "Out of memory when trying to generate a runtime app image";
1160*795d594fSAndroid Build Coastguard Worker       return false;
1161*795d594fSAndroid Build Coastguard Worker     }
1162*795d594fSAndroid Build Coastguard Worker 
1163*795d594fSAndroid Build Coastguard Worker     memcpy(header_data->GetData(), oat_header.get(), oat_header->GetHeaderSize());
1164*795d594fSAndroid Build Coastguard Worker     memcpy(header_data->GetData() + oat_header->GetHeaderSize(), checksums.data(), checksums_size);
1165*795d594fSAndroid Build Coastguard Worker 
1166*795d594fSAndroid Build Coastguard Worker     // Create and populate the dex caches aray.
1167*795d594fSAndroid Build Coastguard Worker     Handle<mirror::ObjectArray<mirror::Object>> dex_cache_array = handles.NewHandle(
1168*795d594fSAndroid Build Coastguard Worker         mirror::ObjectArray<mirror::Object>::Alloc(
1169*795d594fSAndroid Build Coastguard Worker             soa.Self(), object_array_class.Get(), dex_caches.size()));
1170*795d594fSAndroid Build Coastguard Worker 
1171*795d594fSAndroid Build Coastguard Worker     if (dex_cache_array == nullptr) {
1172*795d594fSAndroid Build Coastguard Worker       DCHECK(soa.Self()->IsExceptionPending());
1173*795d594fSAndroid Build Coastguard Worker       soa.Self()->ClearException();
1174*795d594fSAndroid Build Coastguard Worker       *error_msg = "Out of memory when trying to generate a runtime app image";
1175*795d594fSAndroid Build Coastguard Worker       return false;
1176*795d594fSAndroid Build Coastguard Worker     }
1177*795d594fSAndroid Build Coastguard Worker 
1178*795d594fSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < dex_caches.size(); ++i) {
1179*795d594fSAndroid Build Coastguard Worker       dex_cache_array->Set(i, dex_caches[i].Get());
1180*795d594fSAndroid Build Coastguard Worker     }
1181*795d594fSAndroid Build Coastguard Worker 
1182*795d594fSAndroid Build Coastguard Worker     image_roots->Set(ImageHeader::kDexCaches, dex_cache_array.Get());
1183*795d594fSAndroid Build Coastguard Worker     image_roots->Set(ImageHeader::kClassRoots, class_linker->GetClassRoots());
1184*795d594fSAndroid Build Coastguard Worker     image_roots->Set(ImageHeader::kAppImageOatHeader, header_data.Get());
1185*795d594fSAndroid Build Coastguard Worker 
1186*795d594fSAndroid Build Coastguard Worker     {
1187*795d594fSAndroid Build Coastguard Worker       // Now that we have created all objects needed for the `image_roots`, copy
1188*795d594fSAndroid Build Coastguard Worker       // it into the buffer. Note that this will recursively copy all objects
1189*795d594fSAndroid Build Coastguard Worker       // contained in `image_roots`. That's acceptable as we don't have cycles,
1190*795d594fSAndroid Build Coastguard Worker       // nor a deep graph.
1191*795d594fSAndroid Build Coastguard Worker       ScopedAssertNoThreadSuspension sants("Writing runtime app image");
1192*795d594fSAndroid Build Coastguard Worker       CopyObject(image_roots.Get());
1193*795d594fSAndroid Build Coastguard Worker     }
1194*795d594fSAndroid Build Coastguard Worker 
1195*795d594fSAndroid Build Coastguard Worker     // Emit classes defined in the app class loader (which will also indirectly
1196*795d594fSAndroid Build Coastguard Worker     // emit dex caches and their arrays).
1197*795d594fSAndroid Build Coastguard Worker     EmitClasses(soa.Self(), dex_cache_array);
1198*795d594fSAndroid Build Coastguard Worker 
1199*795d594fSAndroid Build Coastguard Worker     return true;
1200*795d594fSAndroid Build Coastguard Worker   }
1201*795d594fSAndroid Build Coastguard Worker 
1202*795d594fSAndroid Build Coastguard Worker   class FixupVisitor {
1203*795d594fSAndroid Build Coastguard Worker    public:
FixupVisitor(RuntimeImageHelper * image,size_t copy_offset)1204*795d594fSAndroid Build Coastguard Worker     FixupVisitor(RuntimeImageHelper* image, size_t copy_offset)
1205*795d594fSAndroid Build Coastguard Worker         : image_(image), copy_offset_(copy_offset) {}
1206*795d594fSAndroid Build Coastguard Worker 
1207*795d594fSAndroid Build Coastguard Worker     // We do not visit native roots. These are handled with other logic.
VisitRootIfNonNull(mirror::CompressedReference<mirror::Object> * root) const1208*795d594fSAndroid Build Coastguard Worker     void VisitRootIfNonNull(
1209*795d594fSAndroid Build Coastguard Worker         [[maybe_unused]] mirror::CompressedReference<mirror::Object>* root) const {
1210*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "UNREACHABLE";
1211*795d594fSAndroid Build Coastguard Worker     }
VisitRoot(mirror::CompressedReference<mirror::Object> * root) const1212*795d594fSAndroid Build Coastguard Worker     void VisitRoot([[maybe_unused]] mirror::CompressedReference<mirror::Object>* root) const {
1213*795d594fSAndroid Build Coastguard Worker       LOG(FATAL) << "UNREACHABLE";
1214*795d594fSAndroid Build Coastguard Worker     }
1215*795d594fSAndroid Build Coastguard Worker 
operator ()(ObjPtr<mirror::Object> obj,MemberOffset offset,bool is_static) const1216*795d594fSAndroid Build Coastguard Worker     void operator()(ObjPtr<mirror::Object> obj,
1217*795d594fSAndroid Build Coastguard Worker                     MemberOffset offset,
1218*795d594fSAndroid Build Coastguard Worker                     bool is_static) const
1219*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::mutator_lock_) {
1220*795d594fSAndroid Build Coastguard Worker       // We don't copy static fields, they are being handled when we try to
1221*795d594fSAndroid Build Coastguard Worker       // initialize the class.
1222*795d594fSAndroid Build Coastguard Worker       ObjPtr<mirror::Object> ref =
1223*795d594fSAndroid Build Coastguard Worker           is_static ? nullptr : obj->GetFieldObject<mirror::Object>(offset);
1224*795d594fSAndroid Build Coastguard Worker       mirror::Object* address = image_->GetOrComputeImageAddress(ref);
1225*795d594fSAndroid Build Coastguard Worker       mirror::Object* copy =
1226*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<mirror::Object*>(image_->objects_.data() + copy_offset_);
1227*795d594fSAndroid Build Coastguard Worker       copy->GetFieldObjectReferenceAddr<kVerifyNone>(offset)->Assign(address);
1228*795d594fSAndroid Build Coastguard Worker     }
1229*795d594fSAndroid Build Coastguard Worker 
1230*795d594fSAndroid Build Coastguard Worker     // java.lang.ref.Reference visitor.
operator ()(ObjPtr<mirror::Class> klass,ObjPtr<mirror::Reference> ref) const1231*795d594fSAndroid Build Coastguard Worker     void operator()([[maybe_unused]] ObjPtr<mirror::Class> klass,
1232*795d594fSAndroid Build Coastguard Worker                     ObjPtr<mirror::Reference> ref) const REQUIRES_SHARED(Locks::mutator_lock_) {
1233*795d594fSAndroid Build Coastguard Worker       operator()(ref, mirror::Reference::ReferentOffset(), /* is_static */ false);
1234*795d594fSAndroid Build Coastguard Worker     }
1235*795d594fSAndroid Build Coastguard Worker 
1236*795d594fSAndroid Build Coastguard Worker    private:
1237*795d594fSAndroid Build Coastguard Worker     RuntimeImageHelper* image_;
1238*795d594fSAndroid Build Coastguard Worker     size_t copy_offset_;
1239*795d594fSAndroid Build Coastguard Worker   };
1240*795d594fSAndroid Build Coastguard Worker 
1241*795d594fSAndroid Build Coastguard Worker   template <typename T>
CopyNativeDexCacheArray(uint32_t num_entries,uint32_t max_entries,mirror::NativeArray<T> * array)1242*795d594fSAndroid Build Coastguard Worker   void CopyNativeDexCacheArray(uint32_t num_entries,
1243*795d594fSAndroid Build Coastguard Worker                                uint32_t max_entries,
1244*795d594fSAndroid Build Coastguard Worker                                mirror::NativeArray<T>* array) {
1245*795d594fSAndroid Build Coastguard Worker     if (array == nullptr) {
1246*795d594fSAndroid Build Coastguard Worker       return;
1247*795d594fSAndroid Build Coastguard Worker     }
1248*795d594fSAndroid Build Coastguard Worker 
1249*795d594fSAndroid Build Coastguard Worker     bool only_startup = !mirror::DexCache::ShouldAllocateFullArray(num_entries, max_entries);
1250*795d594fSAndroid Build Coastguard Worker     ArenaVector<uint8_t>& data = only_startup ? metadata_ : dex_cache_arrays_;
1251*795d594fSAndroid Build Coastguard Worker     NativeRelocationKind relocation_kind = only_startup
1252*795d594fSAndroid Build Coastguard Worker         ? NativeRelocationKind::kStartupNativeDexCacheArray
1253*795d594fSAndroid Build Coastguard Worker         : NativeRelocationKind::kFullNativeDexCacheArray;
1254*795d594fSAndroid Build Coastguard Worker 
1255*795d594fSAndroid Build Coastguard Worker     size_t size = num_entries * sizeof(void*);
1256*795d594fSAndroid Build Coastguard Worker     // We need to reserve space to store `num_entries` because ImageSpace doesn't have
1257*795d594fSAndroid Build Coastguard Worker     // access to the dex files when relocating dex caches.
1258*795d594fSAndroid Build Coastguard Worker     size_t offset = RoundUp(data.size(), sizeof(void*)) + sizeof(uintptr_t);
1259*795d594fSAndroid Build Coastguard Worker     data.resize(RoundUp(data.size(), sizeof(void*)) + sizeof(uintptr_t) + size);
1260*795d594fSAndroid Build Coastguard Worker     reinterpret_cast<uintptr_t*>(data.data() + offset)[-1] = num_entries;
1261*795d594fSAndroid Build Coastguard Worker 
1262*795d594fSAndroid Build Coastguard Worker     // Copy each entry individually. We cannot use memcpy, as the entries may be
1263*795d594fSAndroid Build Coastguard Worker     // updated concurrently by other mutator threads.
1264*795d594fSAndroid Build Coastguard Worker     mirror::NativeArray<T>* copy = reinterpret_cast<mirror::NativeArray<T>*>(data.data() + offset);
1265*795d594fSAndroid Build Coastguard Worker     for (uint32_t i = 0; i < num_entries; ++i) {
1266*795d594fSAndroid Build Coastguard Worker       copy->Set(i, array->Get(i));
1267*795d594fSAndroid Build Coastguard Worker     }
1268*795d594fSAndroid Build Coastguard Worker     native_relocations_.Put(array, std::make_pair(relocation_kind, offset));
1269*795d594fSAndroid Build Coastguard Worker   }
1270*795d594fSAndroid Build Coastguard Worker 
1271*795d594fSAndroid Build Coastguard Worker   template <typename T>
CreateGcRootDexCacheArray(uint32_t num_entries,uint32_t max_entries,mirror::GcRootArray<T> * array)1272*795d594fSAndroid Build Coastguard Worker   mirror::GcRootArray<T>* CreateGcRootDexCacheArray(uint32_t num_entries,
1273*795d594fSAndroid Build Coastguard Worker                                                     uint32_t max_entries,
1274*795d594fSAndroid Build Coastguard Worker                                                     mirror::GcRootArray<T>* array) {
1275*795d594fSAndroid Build Coastguard Worker     if (array == nullptr) {
1276*795d594fSAndroid Build Coastguard Worker       return nullptr;
1277*795d594fSAndroid Build Coastguard Worker     }
1278*795d594fSAndroid Build Coastguard Worker     bool only_startup = !mirror::DexCache::ShouldAllocateFullArray(num_entries, max_entries);
1279*795d594fSAndroid Build Coastguard Worker     ArenaVector<uint8_t>& data = only_startup ? metadata_ : dex_cache_arrays_;
1280*795d594fSAndroid Build Coastguard Worker     NativeRelocationKind relocation_kind = only_startup
1281*795d594fSAndroid Build Coastguard Worker         ? NativeRelocationKind::kStartupNativeDexCacheArray
1282*795d594fSAndroid Build Coastguard Worker         : NativeRelocationKind::kFullNativeDexCacheArray;
1283*795d594fSAndroid Build Coastguard Worker     size_t size = num_entries * sizeof(GcRoot<T>);
1284*795d594fSAndroid Build Coastguard Worker     // We need to reserve space to store `num_entries` because ImageSpace doesn't have
1285*795d594fSAndroid Build Coastguard Worker     // access to the dex files when relocating dex caches.
1286*795d594fSAndroid Build Coastguard Worker     static_assert(sizeof(GcRoot<T>) == sizeof(uint32_t));
1287*795d594fSAndroid Build Coastguard Worker     size_t offset = data.size() + sizeof(uint32_t);
1288*795d594fSAndroid Build Coastguard Worker     data.resize(data.size() + sizeof(uint32_t) + size);
1289*795d594fSAndroid Build Coastguard Worker     reinterpret_cast<uint32_t*>(data.data() + offset)[-1] = num_entries;
1290*795d594fSAndroid Build Coastguard Worker     native_relocations_.Put(array, std::make_pair(relocation_kind, offset));
1291*795d594fSAndroid Build Coastguard Worker 
1292*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast<mirror::GcRootArray<T>*>(data.data() + offset);
1293*795d594fSAndroid Build Coastguard Worker   }
EmitDexCacheArrays()1294*795d594fSAndroid Build Coastguard Worker   static bool EmitDexCacheArrays() {
1295*795d594fSAndroid Build Coastguard Worker     // We need to treat dex cache arrays specially in an image for userfaultfd.
1296*795d594fSAndroid Build Coastguard Worker     // Disable for now. See b/270936884.
1297*795d594fSAndroid Build Coastguard Worker     return !gUseUserfaultfd;
1298*795d594fSAndroid Build Coastguard Worker   }
1299*795d594fSAndroid Build Coastguard Worker 
CopyDexCache(ObjPtr<mirror::DexCache> cache)1300*795d594fSAndroid Build Coastguard Worker   uint32_t CopyDexCache(ObjPtr<mirror::DexCache> cache) REQUIRES_SHARED(Locks::mutator_lock_) {
1301*795d594fSAndroid Build Coastguard Worker     auto it = dex_caches_.find(cache->GetDexFile());
1302*795d594fSAndroid Build Coastguard Worker     if (it != dex_caches_.end()) {
1303*795d594fSAndroid Build Coastguard Worker       return it->second;
1304*795d594fSAndroid Build Coastguard Worker     }
1305*795d594fSAndroid Build Coastguard Worker     uint32_t offset = CopyObject(cache);
1306*795d594fSAndroid Build Coastguard Worker     dex_caches_.Put(cache->GetDexFile(), offset);
1307*795d594fSAndroid Build Coastguard Worker     // For dex caches, clear pointers to data that will be set at runtime.
1308*795d594fSAndroid Build Coastguard Worker     mirror::Object* copy = reinterpret_cast<mirror::Object*>(objects_.data() + offset);
1309*795d594fSAndroid Build Coastguard Worker     reinterpret_cast<mirror::DexCache*>(copy)->ResetNativeArrays();
1310*795d594fSAndroid Build Coastguard Worker     reinterpret_cast<mirror::DexCache*>(copy)->SetDexFile(nullptr);
1311*795d594fSAndroid Build Coastguard Worker 
1312*795d594fSAndroid Build Coastguard Worker     if (!EmitDexCacheArrays()) {
1313*795d594fSAndroid Build Coastguard Worker       return offset;
1314*795d594fSAndroid Build Coastguard Worker     }
1315*795d594fSAndroid Build Coastguard Worker 
1316*795d594fSAndroid Build Coastguard Worker     // Copy the ArtMethod array.
1317*795d594fSAndroid Build Coastguard Worker     mirror::NativeArray<ArtMethod>* resolved_methods = cache->GetResolvedMethodsArray();
1318*795d594fSAndroid Build Coastguard Worker     CopyNativeDexCacheArray(cache->GetDexFile()->NumMethodIds(),
1319*795d594fSAndroid Build Coastguard Worker                             mirror::DexCache::kDexCacheMethodCacheSize,
1320*795d594fSAndroid Build Coastguard Worker                             resolved_methods);
1321*795d594fSAndroid Build Coastguard Worker     // Store the array pointer in the dex cache, which will be relocated at the end.
1322*795d594fSAndroid Build Coastguard Worker     reinterpret_cast<mirror::DexCache*>(copy)->SetResolvedMethodsArray(resolved_methods);
1323*795d594fSAndroid Build Coastguard Worker 
1324*795d594fSAndroid Build Coastguard Worker     // Copy the ArtField array.
1325*795d594fSAndroid Build Coastguard Worker     mirror::NativeArray<ArtField>* resolved_fields = cache->GetResolvedFieldsArray();
1326*795d594fSAndroid Build Coastguard Worker     CopyNativeDexCacheArray(cache->GetDexFile()->NumFieldIds(),
1327*795d594fSAndroid Build Coastguard Worker                             mirror::DexCache::kDexCacheFieldCacheSize,
1328*795d594fSAndroid Build Coastguard Worker                             resolved_fields);
1329*795d594fSAndroid Build Coastguard Worker     // Store the array pointer in the dex cache, which will be relocated at the end.
1330*795d594fSAndroid Build Coastguard Worker     reinterpret_cast<mirror::DexCache*>(copy)->SetResolvedFieldsArray(resolved_fields);
1331*795d594fSAndroid Build Coastguard Worker 
1332*795d594fSAndroid Build Coastguard Worker     // Copy the type array.
1333*795d594fSAndroid Build Coastguard Worker     mirror::GcRootArray<mirror::Class>* resolved_types = cache->GetResolvedTypesArray();
1334*795d594fSAndroid Build Coastguard Worker     CreateGcRootDexCacheArray(cache->GetDexFile()->NumTypeIds(),
1335*795d594fSAndroid Build Coastguard Worker                               mirror::DexCache::kDexCacheTypeCacheSize,
1336*795d594fSAndroid Build Coastguard Worker                               resolved_types);
1337*795d594fSAndroid Build Coastguard Worker     // Store the array pointer in the dex cache, which will be relocated at the end.
1338*795d594fSAndroid Build Coastguard Worker     reinterpret_cast<mirror::DexCache*>(copy)->SetResolvedTypesArray(resolved_types);
1339*795d594fSAndroid Build Coastguard Worker 
1340*795d594fSAndroid Build Coastguard Worker     // Copy the string array.
1341*795d594fSAndroid Build Coastguard Worker     mirror::GcRootArray<mirror::String>* strings = cache->GetStringsArray();
1342*795d594fSAndroid Build Coastguard Worker     // Note: `new_strings` points to temporary data, and is only valid here.
1343*795d594fSAndroid Build Coastguard Worker     mirror::GcRootArray<mirror::String>* new_strings =
1344*795d594fSAndroid Build Coastguard Worker         CreateGcRootDexCacheArray(cache->GetDexFile()->NumStringIds(),
1345*795d594fSAndroid Build Coastguard Worker                                   mirror::DexCache::kDexCacheStringCacheSize,
1346*795d594fSAndroid Build Coastguard Worker                                   strings);
1347*795d594fSAndroid Build Coastguard Worker     // Store the array pointer in the dex cache, which will be relocated at the end.
1348*795d594fSAndroid Build Coastguard Worker     reinterpret_cast<mirror::DexCache*>(copy)->SetStringsArray(strings);
1349*795d594fSAndroid Build Coastguard Worker 
1350*795d594fSAndroid Build Coastguard Worker     // The code below copies new objects, so invalidate the address we have for
1351*795d594fSAndroid Build Coastguard Worker     // `copy`.
1352*795d594fSAndroid Build Coastguard Worker     copy = nullptr;
1353*795d594fSAndroid Build Coastguard Worker     if (strings != nullptr) {
1354*795d594fSAndroid Build Coastguard Worker       for (uint32_t i = 0; i < cache->GetDexFile()->NumStringIds(); ++i) {
1355*795d594fSAndroid Build Coastguard Worker         ObjPtr<mirror::String> str = strings->Get(i);
1356*795d594fSAndroid Build Coastguard Worker         if (str == nullptr || IsInBootImage(str.Ptr())) {
1357*795d594fSAndroid Build Coastguard Worker           new_strings->Set(i, str.Ptr());
1358*795d594fSAndroid Build Coastguard Worker         } else {
1359*795d594fSAndroid Build Coastguard Worker           uint32_t hash = static_cast<uint32_t>(str->GetStoredHashCode());
1360*795d594fSAndroid Build Coastguard Worker           DCHECK_EQ(hash, static_cast<uint32_t>(str->ComputeHashCode()))
1361*795d594fSAndroid Build Coastguard Worker               << "Dex cache strings should be interned";
1362*795d594fSAndroid Build Coastguard Worker           auto it2 = intern_table_.FindWithHash(str.Ptr(), hash);
1363*795d594fSAndroid Build Coastguard Worker           if (it2 == intern_table_.end()) {
1364*795d594fSAndroid Build Coastguard Worker             uint32_t string_offset = CopyObject(str);
1365*795d594fSAndroid Build Coastguard Worker             uint32_t address = image_begin_ + string_offset + sizeof(ImageHeader);
1366*795d594fSAndroid Build Coastguard Worker             intern_table_.InsertWithHash(address, hash);
1367*795d594fSAndroid Build Coastguard Worker             new_strings->Set(i, reinterpret_cast<mirror::String*>(address));
1368*795d594fSAndroid Build Coastguard Worker           } else {
1369*795d594fSAndroid Build Coastguard Worker             new_strings->Set(i, reinterpret_cast<mirror::String*>(*it2));
1370*795d594fSAndroid Build Coastguard Worker           }
1371*795d594fSAndroid Build Coastguard Worker           // To not confuse string references from the dex cache object and
1372*795d594fSAndroid Build Coastguard Worker           // string references from the array, we put an offset bigger than the
1373*795d594fSAndroid Build Coastguard Worker           // size of a DexCache object. ClassLinker::VisitInternedStringReferences
1374*795d594fSAndroid Build Coastguard Worker           // knows how to decode this offset.
1375*795d594fSAndroid Build Coastguard Worker           string_reference_offsets_.emplace_back(
1376*795d594fSAndroid Build Coastguard Worker               sizeof(ImageHeader) + offset, sizeof(mirror::DexCache) + i);
1377*795d594fSAndroid Build Coastguard Worker         }
1378*795d594fSAndroid Build Coastguard Worker       }
1379*795d594fSAndroid Build Coastguard Worker     }
1380*795d594fSAndroid Build Coastguard Worker 
1381*795d594fSAndroid Build Coastguard Worker     return offset;
1382*795d594fSAndroid Build Coastguard Worker   }
1383*795d594fSAndroid Build Coastguard Worker 
IsInitialized(mirror::Class * cls)1384*795d594fSAndroid Build Coastguard Worker   bool IsInitialized(mirror::Class* cls) REQUIRES_SHARED(Locks::mutator_lock_) {
1385*795d594fSAndroid Build Coastguard Worker     if (IsInBootImage(cls)) {
1386*795d594fSAndroid Build Coastguard Worker       const OatDexFile* oat_dex_file = cls->GetDexFile().GetOatDexFile();
1387*795d594fSAndroid Build Coastguard Worker       DCHECK(oat_dex_file != nullptr) << "We should always have an .oat file for a boot image";
1388*795d594fSAndroid Build Coastguard Worker       uint16_t class_def_index = cls->GetDexClassDefIndex();
1389*795d594fSAndroid Build Coastguard Worker       ClassStatus oat_file_class_status = oat_dex_file->GetOatClass(class_def_index).GetStatus();
1390*795d594fSAndroid Build Coastguard Worker       return oat_file_class_status == ClassStatus::kVisiblyInitialized;
1391*795d594fSAndroid Build Coastguard Worker     } else {
1392*795d594fSAndroid Build Coastguard Worker       return cls->IsVisiblyInitialized<kVerifyNone>();
1393*795d594fSAndroid Build Coastguard Worker     }
1394*795d594fSAndroid Build Coastguard Worker   }
1395*795d594fSAndroid Build Coastguard Worker   // Try to initialize `copy`. Note that `cls` may not be initialized.
1396*795d594fSAndroid Build Coastguard Worker   // This is called after the image generation logic has visited super classes
1397*795d594fSAndroid Build Coastguard Worker   // and super interfaces, so we can just check those directly.
TryInitializeClass(mirror::Class * copy,ObjPtr<mirror::Class> cls,uint32_t class_offset)1398*795d594fSAndroid Build Coastguard Worker   bool TryInitializeClass(mirror::Class* copy, ObjPtr<mirror::Class> cls, uint32_t class_offset)
1399*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
1400*795d594fSAndroid Build Coastguard Worker     if (!cls->IsVerified()) {
1401*795d594fSAndroid Build Coastguard Worker       return false;
1402*795d594fSAndroid Build Coastguard Worker     }
1403*795d594fSAndroid Build Coastguard Worker     if (cls->IsArrayClass()) {
1404*795d594fSAndroid Build Coastguard Worker       return true;
1405*795d594fSAndroid Build Coastguard Worker     }
1406*795d594fSAndroid Build Coastguard Worker 
1407*795d594fSAndroid Build Coastguard Worker     // Check if we have been able to initialize the super class.
1408*795d594fSAndroid Build Coastguard Worker     mirror::Class* super = GetClassContent(cls->GetSuperClass());
1409*795d594fSAndroid Build Coastguard Worker     DCHECK(super != nullptr)
1410*795d594fSAndroid Build Coastguard Worker         << "App image classes should always have a super class: " << cls->PrettyClass();
1411*795d594fSAndroid Build Coastguard Worker     if (!IsInitialized(super)) {
1412*795d594fSAndroid Build Coastguard Worker       return false;
1413*795d594fSAndroid Build Coastguard Worker     }
1414*795d594fSAndroid Build Coastguard Worker 
1415*795d594fSAndroid Build Coastguard Worker     // We won't initialize class with class initializers.
1416*795d594fSAndroid Build Coastguard Worker     if (cls->FindClassInitializer(kRuntimePointerSize) != nullptr) {
1417*795d594fSAndroid Build Coastguard Worker       return false;
1418*795d594fSAndroid Build Coastguard Worker     }
1419*795d594fSAndroid Build Coastguard Worker 
1420*795d594fSAndroid Build Coastguard Worker     // For non-interface classes, we require all implemented interfaces to be
1421*795d594fSAndroid Build Coastguard Worker     // initialized.
1422*795d594fSAndroid Build Coastguard Worker     if (!cls->IsInterface()) {
1423*795d594fSAndroid Build Coastguard Worker       for (size_t i = 0; i < cls->NumDirectInterfaces(); i++) {
1424*795d594fSAndroid Build Coastguard Worker         mirror::Class* itf = GetClassContent(cls->GetDirectInterface(i));
1425*795d594fSAndroid Build Coastguard Worker         if (!IsInitialized(itf)) {
1426*795d594fSAndroid Build Coastguard Worker           return false;
1427*795d594fSAndroid Build Coastguard Worker         }
1428*795d594fSAndroid Build Coastguard Worker       }
1429*795d594fSAndroid Build Coastguard Worker     }
1430*795d594fSAndroid Build Coastguard Worker 
1431*795d594fSAndroid Build Coastguard Worker     // Trivial case: no static fields.
1432*795d594fSAndroid Build Coastguard Worker     if (cls->NumStaticFields() == 0u) {
1433*795d594fSAndroid Build Coastguard Worker       return true;
1434*795d594fSAndroid Build Coastguard Worker     }
1435*795d594fSAndroid Build Coastguard Worker 
1436*795d594fSAndroid Build Coastguard Worker     // Go over all static fields and try to initialize them.
1437*795d594fSAndroid Build Coastguard Worker     EncodedStaticFieldValueIterator it(cls->GetDexFile(), *cls->GetClassDef());
1438*795d594fSAndroid Build Coastguard Worker     if (!it.HasNext()) {
1439*795d594fSAndroid Build Coastguard Worker       return true;
1440*795d594fSAndroid Build Coastguard Worker     }
1441*795d594fSAndroid Build Coastguard Worker 
1442*795d594fSAndroid Build Coastguard Worker     // Temporary string offsets in case we failed to initialize the class. We
1443*795d594fSAndroid Build Coastguard Worker     // will add the offsets at the end of this method if we are successful.
1444*795d594fSAndroid Build Coastguard Worker     ArenaVector<AppImageReferenceOffsetInfo> string_offsets(allocator_.Adapter());
1445*795d594fSAndroid Build Coastguard Worker     ClassLinker* linker = Runtime::Current()->GetClassLinker();
1446*795d594fSAndroid Build Coastguard Worker     ClassAccessor accessor(cls->GetDexFile(), *cls->GetClassDef());
1447*795d594fSAndroid Build Coastguard Worker     for (const ClassAccessor::Field& field : accessor.GetStaticFields()) {
1448*795d594fSAndroid Build Coastguard Worker       if (!it.HasNext()) {
1449*795d594fSAndroid Build Coastguard Worker         break;
1450*795d594fSAndroid Build Coastguard Worker       }
1451*795d594fSAndroid Build Coastguard Worker       ArtField* art_field = linker->LookupResolvedField(field.GetIndex(),
1452*795d594fSAndroid Build Coastguard Worker                                                         cls->GetDexCache(),
1453*795d594fSAndroid Build Coastguard Worker                                                         cls->GetClassLoader(),
1454*795d594fSAndroid Build Coastguard Worker                                                         /* is_static= */ true);
1455*795d594fSAndroid Build Coastguard Worker       DCHECK_NE(art_field, nullptr);
1456*795d594fSAndroid Build Coastguard Worker       MemberOffset offset(art_field->GetOffset());
1457*795d594fSAndroid Build Coastguard Worker       switch (it.GetValueType()) {
1458*795d594fSAndroid Build Coastguard Worker         case EncodedArrayValueIterator::ValueType::kBoolean:
1459*795d594fSAndroid Build Coastguard Worker           copy->SetFieldBoolean<false>(offset, it.GetJavaValue().z);
1460*795d594fSAndroid Build Coastguard Worker           break;
1461*795d594fSAndroid Build Coastguard Worker         case EncodedArrayValueIterator::ValueType::kByte:
1462*795d594fSAndroid Build Coastguard Worker           copy->SetFieldByte<false>(offset, it.GetJavaValue().b);
1463*795d594fSAndroid Build Coastguard Worker           break;
1464*795d594fSAndroid Build Coastguard Worker         case EncodedArrayValueIterator::ValueType::kShort:
1465*795d594fSAndroid Build Coastguard Worker           copy->SetFieldShort<false>(offset, it.GetJavaValue().s);
1466*795d594fSAndroid Build Coastguard Worker           break;
1467*795d594fSAndroid Build Coastguard Worker         case EncodedArrayValueIterator::ValueType::kChar:
1468*795d594fSAndroid Build Coastguard Worker           copy->SetFieldChar<false>(offset, it.GetJavaValue().c);
1469*795d594fSAndroid Build Coastguard Worker           break;
1470*795d594fSAndroid Build Coastguard Worker         case EncodedArrayValueIterator::ValueType::kInt:
1471*795d594fSAndroid Build Coastguard Worker           copy->SetField32<false>(offset, it.GetJavaValue().i);
1472*795d594fSAndroid Build Coastguard Worker           break;
1473*795d594fSAndroid Build Coastguard Worker         case EncodedArrayValueIterator::ValueType::kLong:
1474*795d594fSAndroid Build Coastguard Worker           copy->SetField64<false>(offset, it.GetJavaValue().j);
1475*795d594fSAndroid Build Coastguard Worker           break;
1476*795d594fSAndroid Build Coastguard Worker         case EncodedArrayValueIterator::ValueType::kFloat:
1477*795d594fSAndroid Build Coastguard Worker           copy->SetField32<false>(offset, it.GetJavaValue().i);
1478*795d594fSAndroid Build Coastguard Worker           break;
1479*795d594fSAndroid Build Coastguard Worker         case EncodedArrayValueIterator::ValueType::kDouble:
1480*795d594fSAndroid Build Coastguard Worker           copy->SetField64<false>(offset, it.GetJavaValue().j);
1481*795d594fSAndroid Build Coastguard Worker           break;
1482*795d594fSAndroid Build Coastguard Worker         case EncodedArrayValueIterator::ValueType::kNull:
1483*795d594fSAndroid Build Coastguard Worker           copy->SetFieldObject<false>(offset, nullptr);
1484*795d594fSAndroid Build Coastguard Worker           break;
1485*795d594fSAndroid Build Coastguard Worker         case EncodedArrayValueIterator::ValueType::kString: {
1486*795d594fSAndroid Build Coastguard Worker           ObjPtr<mirror::String> str =
1487*795d594fSAndroid Build Coastguard Worker               linker->LookupString(dex::StringIndex(it.GetJavaValue().i), cls->GetDexCache());
1488*795d594fSAndroid Build Coastguard Worker           mirror::String* str_copy = nullptr;
1489*795d594fSAndroid Build Coastguard Worker           if (str == nullptr) {
1490*795d594fSAndroid Build Coastguard Worker             // String wasn't created yet.
1491*795d594fSAndroid Build Coastguard Worker             return false;
1492*795d594fSAndroid Build Coastguard Worker           } else if (IsInBootImage(str.Ptr())) {
1493*795d594fSAndroid Build Coastguard Worker             str_copy = str.Ptr();
1494*795d594fSAndroid Build Coastguard Worker           } else {
1495*795d594fSAndroid Build Coastguard Worker             uint32_t hash = static_cast<uint32_t>(str->GetStoredHashCode());
1496*795d594fSAndroid Build Coastguard Worker             DCHECK_EQ(hash, static_cast<uint32_t>(str->ComputeHashCode()))
1497*795d594fSAndroid Build Coastguard Worker                 << "Dex cache strings should be interned";
1498*795d594fSAndroid Build Coastguard Worker             auto string_it = intern_table_.FindWithHash(str.Ptr(), hash);
1499*795d594fSAndroid Build Coastguard Worker             if (string_it == intern_table_.end()) {
1500*795d594fSAndroid Build Coastguard Worker               // The string must be interned.
1501*795d594fSAndroid Build Coastguard Worker               uint32_t string_offset = CopyObject(str);
1502*795d594fSAndroid Build Coastguard Worker               // Reload the class copy after having copied the string.
1503*795d594fSAndroid Build Coastguard Worker               copy = reinterpret_cast<mirror::Class*>(objects_.data() + class_offset);
1504*795d594fSAndroid Build Coastguard Worker               uint32_t address = image_begin_ + string_offset + sizeof(ImageHeader);
1505*795d594fSAndroid Build Coastguard Worker               intern_table_.InsertWithHash(address, hash);
1506*795d594fSAndroid Build Coastguard Worker               str_copy = reinterpret_cast<mirror::String*>(address);
1507*795d594fSAndroid Build Coastguard Worker             } else {
1508*795d594fSAndroid Build Coastguard Worker               str_copy = reinterpret_cast<mirror::String*>(*string_it);
1509*795d594fSAndroid Build Coastguard Worker             }
1510*795d594fSAndroid Build Coastguard Worker             string_offsets.emplace_back(sizeof(ImageHeader) + class_offset, offset.Int32Value());
1511*795d594fSAndroid Build Coastguard Worker           }
1512*795d594fSAndroid Build Coastguard Worker           uint8_t* raw_addr = reinterpret_cast<uint8_t*>(copy) + offset.Int32Value();
1513*795d594fSAndroid Build Coastguard Worker           mirror::HeapReference<mirror::Object>* objref_addr =
1514*795d594fSAndroid Build Coastguard Worker               reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr);
1515*795d594fSAndroid Build Coastguard Worker           objref_addr->Assign</* kIsVolatile= */ false>(str_copy);
1516*795d594fSAndroid Build Coastguard Worker           break;
1517*795d594fSAndroid Build Coastguard Worker         }
1518*795d594fSAndroid Build Coastguard Worker         case EncodedArrayValueIterator::ValueType::kType: {
1519*795d594fSAndroid Build Coastguard Worker           // Note that it may be that the referenced type hasn't been processed
1520*795d594fSAndroid Build Coastguard Worker           // yet by the image generation logic. In this case we bail out for
1521*795d594fSAndroid Build Coastguard Worker           // simplicity.
1522*795d594fSAndroid Build Coastguard Worker           ObjPtr<mirror::Class> type =
1523*795d594fSAndroid Build Coastguard Worker               linker->LookupResolvedType(dex::TypeIndex(it.GetJavaValue().i), cls);
1524*795d594fSAndroid Build Coastguard Worker           mirror::Class* type_copy = nullptr;
1525*795d594fSAndroid Build Coastguard Worker           if (type == nullptr) {
1526*795d594fSAndroid Build Coastguard Worker             // Class wasn't resolved yet.
1527*795d594fSAndroid Build Coastguard Worker             return false;
1528*795d594fSAndroid Build Coastguard Worker           } else if (IsInBootImage(type.Ptr())) {
1529*795d594fSAndroid Build Coastguard Worker             // Make sure the type is in our class table.
1530*795d594fSAndroid Build Coastguard Worker             uint32_t hash = type->DescriptorHash();
1531*795d594fSAndroid Build Coastguard Worker             class_table_.InsertWithHash(ClassTable::TableSlot(type.Ptr(), hash), hash);
1532*795d594fSAndroid Build Coastguard Worker             type_copy = type.Ptr();
1533*795d594fSAndroid Build Coastguard Worker           } else if (type->IsArrayClass()) {
1534*795d594fSAndroid Build Coastguard Worker             std::string class_name;
1535*795d594fSAndroid Build Coastguard Worker             type->GetDescriptor(&class_name);
1536*795d594fSAndroid Build Coastguard Worker             auto class_it = array_classes_.find(class_name);
1537*795d594fSAndroid Build Coastguard Worker             if (class_it == array_classes_.end()) {
1538*795d594fSAndroid Build Coastguard Worker               return false;
1539*795d594fSAndroid Build Coastguard Worker             }
1540*795d594fSAndroid Build Coastguard Worker             type_copy = reinterpret_cast<mirror::Class*>(
1541*795d594fSAndroid Build Coastguard Worker                 image_begin_ + sizeof(ImageHeader) + class_it->second);
1542*795d594fSAndroid Build Coastguard Worker           } else {
1543*795d594fSAndroid Build Coastguard Worker             const dex::ClassDef* class_def = type->GetClassDef();
1544*795d594fSAndroid Build Coastguard Worker             DCHECK_NE(class_def, nullptr);
1545*795d594fSAndroid Build Coastguard Worker             auto class_it = classes_.find(class_def);
1546*795d594fSAndroid Build Coastguard Worker             if (class_it == classes_.end()) {
1547*795d594fSAndroid Build Coastguard Worker               return false;
1548*795d594fSAndroid Build Coastguard Worker             }
1549*795d594fSAndroid Build Coastguard Worker             type_copy = reinterpret_cast<mirror::Class*>(
1550*795d594fSAndroid Build Coastguard Worker                 image_begin_ + sizeof(ImageHeader) + class_it->second);
1551*795d594fSAndroid Build Coastguard Worker           }
1552*795d594fSAndroid Build Coastguard Worker           uint8_t* raw_addr = reinterpret_cast<uint8_t*>(copy) + offset.Int32Value();
1553*795d594fSAndroid Build Coastguard Worker           mirror::HeapReference<mirror::Object>* objref_addr =
1554*795d594fSAndroid Build Coastguard Worker               reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_addr);
1555*795d594fSAndroid Build Coastguard Worker           objref_addr->Assign</* kIsVolatile= */ false>(type_copy);
1556*795d594fSAndroid Build Coastguard Worker           break;
1557*795d594fSAndroid Build Coastguard Worker         }
1558*795d594fSAndroid Build Coastguard Worker         default:
1559*795d594fSAndroid Build Coastguard Worker           LOG(FATAL) << "Unreachable";
1560*795d594fSAndroid Build Coastguard Worker       }
1561*795d594fSAndroid Build Coastguard Worker       it.Next();
1562*795d594fSAndroid Build Coastguard Worker     }
1563*795d594fSAndroid Build Coastguard Worker     // We have successfully initialized the class, we can now record the string
1564*795d594fSAndroid Build Coastguard Worker     // offsets.
1565*795d594fSAndroid Build Coastguard Worker     string_reference_offsets_.insert(
1566*795d594fSAndroid Build Coastguard Worker         string_reference_offsets_.end(), string_offsets.begin(), string_offsets.end());
1567*795d594fSAndroid Build Coastguard Worker     return true;
1568*795d594fSAndroid Build Coastguard Worker   }
1569*795d594fSAndroid Build Coastguard Worker 
CopyClass(ObjPtr<mirror::Class> cls)1570*795d594fSAndroid Build Coastguard Worker   uint32_t CopyClass(ObjPtr<mirror::Class> cls) REQUIRES_SHARED(Locks::mutator_lock_) {
1571*795d594fSAndroid Build Coastguard Worker     DCHECK(!cls->IsBootStrapClassLoaded());
1572*795d594fSAndroid Build Coastguard Worker     uint32_t offset = 0u;
1573*795d594fSAndroid Build Coastguard Worker     if (cls->IsArrayClass()) {
1574*795d594fSAndroid Build Coastguard Worker       std::string class_name;
1575*795d594fSAndroid Build Coastguard Worker       cls->GetDescriptor(&class_name);
1576*795d594fSAndroid Build Coastguard Worker       auto it = array_classes_.find(class_name);
1577*795d594fSAndroid Build Coastguard Worker       if (it != array_classes_.end()) {
1578*795d594fSAndroid Build Coastguard Worker         return it->second;
1579*795d594fSAndroid Build Coastguard Worker       }
1580*795d594fSAndroid Build Coastguard Worker       offset = CopyObject(cls);
1581*795d594fSAndroid Build Coastguard Worker       array_classes_.Put(class_name, offset);
1582*795d594fSAndroid Build Coastguard Worker     } else {
1583*795d594fSAndroid Build Coastguard Worker       const dex::ClassDef* class_def = cls->GetClassDef();
1584*795d594fSAndroid Build Coastguard Worker       auto it = classes_.find(class_def);
1585*795d594fSAndroid Build Coastguard Worker       if (it != classes_.end()) {
1586*795d594fSAndroid Build Coastguard Worker         return it->second;
1587*795d594fSAndroid Build Coastguard Worker       }
1588*795d594fSAndroid Build Coastguard Worker       offset = CopyObject(cls);
1589*795d594fSAndroid Build Coastguard Worker       classes_.Put(class_def, offset);
1590*795d594fSAndroid Build Coastguard Worker     }
1591*795d594fSAndroid Build Coastguard Worker 
1592*795d594fSAndroid Build Coastguard Worker     uint32_t hash = cls->DescriptorHash();
1593*795d594fSAndroid Build Coastguard Worker     // Save the hash, the `HashSet` implementation requires to find it.
1594*795d594fSAndroid Build Coastguard Worker     class_hashes_.Put(offset, hash);
1595*795d594fSAndroid Build Coastguard Worker     uint32_t class_image_address = image_begin_ + sizeof(ImageHeader) + offset;
1596*795d594fSAndroid Build Coastguard Worker     bool inserted =
1597*795d594fSAndroid Build Coastguard Worker         class_table_.InsertWithHash(ClassTable::TableSlot(class_image_address, hash), hash).second;
1598*795d594fSAndroid Build Coastguard Worker     DCHECK(inserted) << "Class " << cls->PrettyDescriptor()
1599*795d594fSAndroid Build Coastguard Worker                      << " (" << cls.Ptr() << ") already inserted";
1600*795d594fSAndroid Build Coastguard Worker 
1601*795d594fSAndroid Build Coastguard Worker     // Clear internal state.
1602*795d594fSAndroid Build Coastguard Worker     mirror::Class* copy = reinterpret_cast<mirror::Class*>(objects_.data() + offset);
1603*795d594fSAndroid Build Coastguard Worker     copy->SetClinitThreadId(static_cast<pid_t>(0u));
1604*795d594fSAndroid Build Coastguard Worker     if (cls->IsArrayClass()) {
1605*795d594fSAndroid Build Coastguard Worker       DCHECK(copy->IsVisiblyInitialized());
1606*795d594fSAndroid Build Coastguard Worker     } else {
1607*795d594fSAndroid Build Coastguard Worker       copy->SetStatusInternal(cls->IsVerified() ? ClassStatus::kVerified : ClassStatus::kResolved);
1608*795d594fSAndroid Build Coastguard Worker     }
1609*795d594fSAndroid Build Coastguard Worker 
1610*795d594fSAndroid Build Coastguard Worker     // Clear static field values.
1611*795d594fSAndroid Build Coastguard Worker     auto clear_class = [&] () REQUIRES_SHARED(Locks::mutator_lock_) {
1612*795d594fSAndroid Build Coastguard Worker       MemberOffset static_offset = cls->GetFirstReferenceStaticFieldOffset(kRuntimePointerSize);
1613*795d594fSAndroid Build Coastguard Worker       uint32_t ref_offsets = cls->GetReferenceInstanceOffsets();
1614*795d594fSAndroid Build Coastguard Worker       size_t size = cls->GetClassSize() - static_offset.Uint32Value();
1615*795d594fSAndroid Build Coastguard Worker       // Adjust for overflow instance-offset bitmap, which is after the static
1616*795d594fSAndroid Build Coastguard Worker       // fields.
1617*795d594fSAndroid Build Coastguard Worker       if ((ref_offsets & mirror::Class::kVisitReferencesSlowpathMask) != 0) {
1618*795d594fSAndroid Build Coastguard Worker         ref_offsets &= ~mirror::Class::kVisitReferencesSlowpathMask;
1619*795d594fSAndroid Build Coastguard Worker         size -= ref_offsets * sizeof(uint32_t);
1620*795d594fSAndroid Build Coastguard Worker       }
1621*795d594fSAndroid Build Coastguard Worker       memset(objects_.data() + offset + static_offset.Uint32Value(), 0, size);
1622*795d594fSAndroid Build Coastguard Worker     };
1623*795d594fSAndroid Build Coastguard Worker     clear_class();
1624*795d594fSAndroid Build Coastguard Worker 
1625*795d594fSAndroid Build Coastguard Worker     bool is_class_initialized = TryInitializeClass(copy, cls, offset);
1626*795d594fSAndroid Build Coastguard Worker     // Reload the copy, it may have moved after `TryInitializeClass`.
1627*795d594fSAndroid Build Coastguard Worker     copy = reinterpret_cast<mirror::Class*>(objects_.data() + offset);
1628*795d594fSAndroid Build Coastguard Worker     if (is_class_initialized) {
1629*795d594fSAndroid Build Coastguard Worker       copy->SetStatusInternal(ClassStatus::kVisiblyInitialized);
1630*795d594fSAndroid Build Coastguard Worker       if (!cls->IsArrayClass() && !cls->IsFinalizable()) {
1631*795d594fSAndroid Build Coastguard Worker         copy->SetObjectSizeAllocFastPath(RoundUp(cls->GetObjectSize(), kObjectAlignment));
1632*795d594fSAndroid Build Coastguard Worker       }
1633*795d594fSAndroid Build Coastguard Worker       if (cls->IsInterface()) {
1634*795d594fSAndroid Build Coastguard Worker         copy->SetAccessFlags(copy->GetAccessFlags() | kAccRecursivelyInitialized);
1635*795d594fSAndroid Build Coastguard Worker       }
1636*795d594fSAndroid Build Coastguard Worker     } else {
1637*795d594fSAndroid Build Coastguard Worker       // If we fail to initialize, remove initialization related flags and
1638*795d594fSAndroid Build Coastguard Worker       // clear again.
1639*795d594fSAndroid Build Coastguard Worker       copy->SetObjectSizeAllocFastPath(std::numeric_limits<uint32_t>::max());
1640*795d594fSAndroid Build Coastguard Worker       copy->SetAccessFlags(copy->GetAccessFlags() & ~kAccRecursivelyInitialized);
1641*795d594fSAndroid Build Coastguard Worker       clear_class();
1642*795d594fSAndroid Build Coastguard Worker     }
1643*795d594fSAndroid Build Coastguard Worker 
1644*795d594fSAndroid Build Coastguard Worker     CopyFieldArrays(cls, class_image_address);
1645*795d594fSAndroid Build Coastguard Worker     CopyMethodArrays(cls, class_image_address, is_class_initialized);
1646*795d594fSAndroid Build Coastguard Worker     if (cls->ShouldHaveImt()) {
1647*795d594fSAndroid Build Coastguard Worker       CopyImTable(cls);
1648*795d594fSAndroid Build Coastguard Worker     }
1649*795d594fSAndroid Build Coastguard Worker 
1650*795d594fSAndroid Build Coastguard Worker     return offset;
1651*795d594fSAndroid Build Coastguard Worker   }
1652*795d594fSAndroid Build Coastguard Worker 
1653*795d594fSAndroid Build Coastguard Worker   // Copy `obj` in `objects_` and relocate references. Returns the offset
1654*795d594fSAndroid Build Coastguard Worker   // within our buffer.
CopyObject(ObjPtr<mirror::Object> obj)1655*795d594fSAndroid Build Coastguard Worker   uint32_t CopyObject(ObjPtr<mirror::Object> obj) REQUIRES_SHARED(Locks::mutator_lock_) {
1656*795d594fSAndroid Build Coastguard Worker     // Copy the object in `objects_`.
1657*795d594fSAndroid Build Coastguard Worker     size_t object_size = obj->SizeOf();
1658*795d594fSAndroid Build Coastguard Worker     size_t offset = objects_.size();
1659*795d594fSAndroid Build Coastguard Worker     DCHECK(IsAligned<kObjectAlignment>(offset));
1660*795d594fSAndroid Build Coastguard Worker     object_offsets_.push_back(offset);
1661*795d594fSAndroid Build Coastguard Worker     objects_.resize(RoundUp(offset + object_size, kObjectAlignment));
1662*795d594fSAndroid Build Coastguard Worker 
1663*795d594fSAndroid Build Coastguard Worker     mirror::Object* copy = reinterpret_cast<mirror::Object*>(objects_.data() + offset);
1664*795d594fSAndroid Build Coastguard Worker     mirror::Object::CopyRawObjectData(
1665*795d594fSAndroid Build Coastguard Worker         reinterpret_cast<uint8_t*>(copy), obj, object_size - sizeof(mirror::Object));
1666*795d594fSAndroid Build Coastguard Worker     // Clear any lockword data.
1667*795d594fSAndroid Build Coastguard Worker     copy->SetLockWord(LockWord::Default(), /* as_volatile= */ false);
1668*795d594fSAndroid Build Coastguard Worker     copy->SetClass(obj->GetClass());
1669*795d594fSAndroid Build Coastguard Worker 
1670*795d594fSAndroid Build Coastguard Worker     // Fixup reference pointers.
1671*795d594fSAndroid Build Coastguard Worker     FixupVisitor visitor(this, offset);
1672*795d594fSAndroid Build Coastguard Worker     obj->VisitReferences</*kVisitNativeRoots=*/ false>(visitor, visitor);
1673*795d594fSAndroid Build Coastguard Worker 
1674*795d594fSAndroid Build Coastguard Worker     if (obj->IsString()) {
1675*795d594fSAndroid Build Coastguard Worker       // Ensure a string always has a hashcode stored. This is checked at
1676*795d594fSAndroid Build Coastguard Worker       // runtime because boot images don't want strings dirtied due to hashcode.
1677*795d594fSAndroid Build Coastguard Worker       reinterpret_cast<mirror::String*>(copy)->GetHashCode();
1678*795d594fSAndroid Build Coastguard Worker     }
1679*795d594fSAndroid Build Coastguard Worker 
1680*795d594fSAndroid Build Coastguard Worker     object_section_size_ += RoundUp(object_size, kObjectAlignment);
1681*795d594fSAndroid Build Coastguard Worker     return offset;
1682*795d594fSAndroid Build Coastguard Worker   }
1683*795d594fSAndroid Build Coastguard Worker 
1684*795d594fSAndroid Build Coastguard Worker   class CollectDexCacheVisitor : public DexCacheVisitor {
1685*795d594fSAndroid Build Coastguard Worker    public:
CollectDexCacheVisitor(VariableSizedHandleScope & handles)1686*795d594fSAndroid Build Coastguard Worker     explicit CollectDexCacheVisitor(VariableSizedHandleScope& handles) : handles_(handles) {}
1687*795d594fSAndroid Build Coastguard Worker 
Visit(ObjPtr<mirror::DexCache> dex_cache)1688*795d594fSAndroid Build Coastguard Worker     void Visit(ObjPtr<mirror::DexCache> dex_cache)
1689*795d594fSAndroid Build Coastguard Worker         REQUIRES_SHARED(Locks::dex_lock_, Locks::mutator_lock_) override {
1690*795d594fSAndroid Build Coastguard Worker       dex_caches_.push_back(handles_.NewHandle(dex_cache));
1691*795d594fSAndroid Build Coastguard Worker     }
GetDexCaches() const1692*795d594fSAndroid Build Coastguard Worker     const std::vector<Handle<mirror::DexCache>>& GetDexCaches() const {
1693*795d594fSAndroid Build Coastguard Worker       return dex_caches_;
1694*795d594fSAndroid Build Coastguard Worker     }
1695*795d594fSAndroid Build Coastguard Worker    private:
1696*795d594fSAndroid Build Coastguard Worker     VariableSizedHandleScope& handles_;
1697*795d594fSAndroid Build Coastguard Worker     std::vector<Handle<mirror::DexCache>> dex_caches_;
1698*795d594fSAndroid Build Coastguard Worker   };
1699*795d594fSAndroid Build Coastguard Worker 
1700*795d594fSAndroid Build Coastguard Worker   // Find dex caches corresponding to the primary APK.
FindDexCaches(Thread * self,dchecked_vector<Handle<mirror::DexCache>> & dex_caches,VariableSizedHandleScope & handles)1701*795d594fSAndroid Build Coastguard Worker   void FindDexCaches(Thread* self,
1702*795d594fSAndroid Build Coastguard Worker                      dchecked_vector<Handle<mirror::DexCache>>& dex_caches,
1703*795d594fSAndroid Build Coastguard Worker                      VariableSizedHandleScope& handles)
1704*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_) {
1705*795d594fSAndroid Build Coastguard Worker     ScopedTrace trace("Find dex caches");
1706*795d594fSAndroid Build Coastguard Worker     DCHECK(dex_caches.empty());
1707*795d594fSAndroid Build Coastguard Worker     // Collect all dex caches.
1708*795d594fSAndroid Build Coastguard Worker     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
1709*795d594fSAndroid Build Coastguard Worker     CollectDexCacheVisitor visitor(handles);
1710*795d594fSAndroid Build Coastguard Worker     {
1711*795d594fSAndroid Build Coastguard Worker       ReaderMutexLock mu(self, *Locks::dex_lock_);
1712*795d594fSAndroid Build Coastguard Worker       class_linker->VisitDexCaches(&visitor);
1713*795d594fSAndroid Build Coastguard Worker     }
1714*795d594fSAndroid Build Coastguard Worker 
1715*795d594fSAndroid Build Coastguard Worker     // Find the primary APK.
1716*795d594fSAndroid Build Coastguard Worker     AppInfo* app_info = Runtime::Current()->GetAppInfo();
1717*795d594fSAndroid Build Coastguard Worker     for (Handle<mirror::DexCache> cache : visitor.GetDexCaches()) {
1718*795d594fSAndroid Build Coastguard Worker       if (app_info->GetRegisteredCodeType(cache->GetDexFile()->GetLocation()) ==
1719*795d594fSAndroid Build Coastguard Worker               AppInfo::CodeType::kPrimaryApk) {
1720*795d594fSAndroid Build Coastguard Worker         dex_caches.push_back(handles.NewHandle(cache.Get()));
1721*795d594fSAndroid Build Coastguard Worker         break;
1722*795d594fSAndroid Build Coastguard Worker       }
1723*795d594fSAndroid Build Coastguard Worker     }
1724*795d594fSAndroid Build Coastguard Worker 
1725*795d594fSAndroid Build Coastguard Worker     if (dex_caches.empty()) {
1726*795d594fSAndroid Build Coastguard Worker       return;
1727*795d594fSAndroid Build Coastguard Worker     }
1728*795d594fSAndroid Build Coastguard Worker 
1729*795d594fSAndroid Build Coastguard Worker     const OatDexFile* oat_dex_file = dex_caches[0]->GetDexFile()->GetOatDexFile();
1730*795d594fSAndroid Build Coastguard Worker     if (oat_dex_file == nullptr) {
1731*795d594fSAndroid Build Coastguard Worker       // We need a .oat file for loading an app image;
1732*795d594fSAndroid Build Coastguard Worker       dex_caches.clear();
1733*795d594fSAndroid Build Coastguard Worker       return;
1734*795d594fSAndroid Build Coastguard Worker     }
1735*795d594fSAndroid Build Coastguard Worker 
1736*795d594fSAndroid Build Coastguard Worker     // Store the dex caches in the order in which their corresponding dex files
1737*795d594fSAndroid Build Coastguard Worker     // are stored in the oat file. When we check for checksums at the point of
1738*795d594fSAndroid Build Coastguard Worker     // loading the image, we rely on this order.
1739*795d594fSAndroid Build Coastguard Worker     for (const OatDexFile* current : oat_dex_file->GetOatFile()->GetOatDexFiles()) {
1740*795d594fSAndroid Build Coastguard Worker       if (current != oat_dex_file) {
1741*795d594fSAndroid Build Coastguard Worker         for (Handle<mirror::DexCache> cache : visitor.GetDexCaches()) {
1742*795d594fSAndroid Build Coastguard Worker           if (cache->GetDexFile()->GetOatDexFile() == current) {
1743*795d594fSAndroid Build Coastguard Worker             dex_caches.push_back(handles.NewHandle(cache.Get()));
1744*795d594fSAndroid Build Coastguard Worker           }
1745*795d594fSAndroid Build Coastguard Worker         }
1746*795d594fSAndroid Build Coastguard Worker       }
1747*795d594fSAndroid Build Coastguard Worker     }
1748*795d594fSAndroid Build Coastguard Worker   }
1749*795d594fSAndroid Build Coastguard Worker 
PointerToUint64(void * ptr)1750*795d594fSAndroid Build Coastguard Worker   static uint64_t PointerToUint64(void* ptr) {
1751*795d594fSAndroid Build Coastguard Worker     return reinterpret_cast64<uint64_t>(ptr);
1752*795d594fSAndroid Build Coastguard Worker   }
1753*795d594fSAndroid Build Coastguard Worker 
WriteImageMethods()1754*795d594fSAndroid Build Coastguard Worker   void WriteImageMethods() {
1755*795d594fSAndroid Build Coastguard Worker     ScopedObjectAccess soa(Thread::Current());
1756*795d594fSAndroid Build Coastguard Worker     // We can just use plain runtime pointers.
1757*795d594fSAndroid Build Coastguard Worker     Runtime* runtime = Runtime::Current();
1758*795d594fSAndroid Build Coastguard Worker     header_.image_methods_[ImageHeader::kResolutionMethod] =
1759*795d594fSAndroid Build Coastguard Worker         PointerToUint64(runtime->GetResolutionMethod());
1760*795d594fSAndroid Build Coastguard Worker     header_.image_methods_[ImageHeader::kImtConflictMethod] =
1761*795d594fSAndroid Build Coastguard Worker         PointerToUint64(runtime->GetImtConflictMethod());
1762*795d594fSAndroid Build Coastguard Worker     header_.image_methods_[ImageHeader::kImtUnimplementedMethod] =
1763*795d594fSAndroid Build Coastguard Worker         PointerToUint64(runtime->GetImtUnimplementedMethod());
1764*795d594fSAndroid Build Coastguard Worker     header_.image_methods_[ImageHeader::kSaveAllCalleeSavesMethod] =
1765*795d594fSAndroid Build Coastguard Worker         PointerToUint64(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveAllCalleeSaves));
1766*795d594fSAndroid Build Coastguard Worker     header_.image_methods_[ImageHeader::kSaveRefsOnlyMethod] =
1767*795d594fSAndroid Build Coastguard Worker         PointerToUint64(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsOnly));
1768*795d594fSAndroid Build Coastguard Worker     header_.image_methods_[ImageHeader::kSaveRefsAndArgsMethod] =
1769*795d594fSAndroid Build Coastguard Worker         PointerToUint64(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveRefsAndArgs));
1770*795d594fSAndroid Build Coastguard Worker     header_.image_methods_[ImageHeader::kSaveEverythingMethod] =
1771*795d594fSAndroid Build Coastguard Worker         PointerToUint64(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverything));
1772*795d594fSAndroid Build Coastguard Worker     header_.image_methods_[ImageHeader::kSaveEverythingMethodForClinit] =
1773*795d594fSAndroid Build Coastguard Worker         PointerToUint64(runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverythingForClinit));
1774*795d594fSAndroid Build Coastguard Worker     header_.image_methods_[ImageHeader::kSaveEverythingMethodForSuspendCheck] =
1775*795d594fSAndroid Build Coastguard Worker         PointerToUint64(
1776*795d594fSAndroid Build Coastguard Worker             runtime->GetCalleeSaveMethod(CalleeSaveType::kSaveEverythingForSuspendCheck));
1777*795d594fSAndroid Build Coastguard Worker   }
1778*795d594fSAndroid Build Coastguard Worker 
1779*795d594fSAndroid Build Coastguard Worker   // Header for the image, created at the end once we know the size of all
1780*795d594fSAndroid Build Coastguard Worker   // sections.
1781*795d594fSAndroid Build Coastguard Worker   ImageHeader header_;
1782*795d594fSAndroid Build Coastguard Worker 
1783*795d594fSAndroid Build Coastguard Worker   // Allocator for the various data structures to allocate while generating the
1784*795d594fSAndroid Build Coastguard Worker   // image.
1785*795d594fSAndroid Build Coastguard Worker   ArenaAllocator allocator_;
1786*795d594fSAndroid Build Coastguard Worker 
1787*795d594fSAndroid Build Coastguard Worker   // Contents of the various sections.
1788*795d594fSAndroid Build Coastguard Worker   ArenaVector<uint8_t> objects_;
1789*795d594fSAndroid Build Coastguard Worker   ArenaVector<uint8_t> art_fields_;
1790*795d594fSAndroid Build Coastguard Worker   ArenaVector<uint8_t> art_methods_;
1791*795d594fSAndroid Build Coastguard Worker   ArenaVector<uint8_t> im_tables_;
1792*795d594fSAndroid Build Coastguard Worker   ArenaVector<uint8_t> metadata_;
1793*795d594fSAndroid Build Coastguard Worker   ArenaVector<uint8_t> dex_cache_arrays_;
1794*795d594fSAndroid Build Coastguard Worker 
1795*795d594fSAndroid Build Coastguard Worker   ArenaVector<AppImageReferenceOffsetInfo> string_reference_offsets_;
1796*795d594fSAndroid Build Coastguard Worker 
1797*795d594fSAndroid Build Coastguard Worker   // Bitmap of live objects in `objects_`. Populated from `object_offsets_`
1798*795d594fSAndroid Build Coastguard Worker   // once we know `object_section_size`.
1799*795d594fSAndroid Build Coastguard Worker   gc::accounting::ContinuousSpaceBitmap image_bitmap_;
1800*795d594fSAndroid Build Coastguard Worker 
1801*795d594fSAndroid Build Coastguard Worker   // Sections stored in the header.
1802*795d594fSAndroid Build Coastguard Worker   ArenaVector<ImageSection> sections_;
1803*795d594fSAndroid Build Coastguard Worker 
1804*795d594fSAndroid Build Coastguard Worker   // A list of offsets in `objects_` where objects begin.
1805*795d594fSAndroid Build Coastguard Worker   ArenaVector<uint32_t> object_offsets_;
1806*795d594fSAndroid Build Coastguard Worker 
1807*795d594fSAndroid Build Coastguard Worker   ArenaSafeMap<const dex::ClassDef*, uint32_t> classes_;
1808*795d594fSAndroid Build Coastguard Worker   ArenaSafeMap<std::string, uint32_t> array_classes_;
1809*795d594fSAndroid Build Coastguard Worker   ArenaSafeMap<const DexFile*, uint32_t> dex_caches_;
1810*795d594fSAndroid Build Coastguard Worker   ArenaSafeMap<uint32_t, uint32_t> class_hashes_;
1811*795d594fSAndroid Build Coastguard Worker 
1812*795d594fSAndroid Build Coastguard Worker   ArenaSafeMap<void*, std::pair<NativeRelocationKind, uint32_t>> native_relocations_;
1813*795d594fSAndroid Build Coastguard Worker 
1814*795d594fSAndroid Build Coastguard Worker   // Cached values of boot image information.
1815*795d594fSAndroid Build Coastguard Worker   const uint32_t boot_image_begin_;
1816*795d594fSAndroid Build Coastguard Worker   const uint32_t boot_image_size_;
1817*795d594fSAndroid Build Coastguard Worker 
1818*795d594fSAndroid Build Coastguard Worker   // Where the image begins: just after the boot image.
1819*795d594fSAndroid Build Coastguard Worker   const uint32_t image_begin_;
1820*795d594fSAndroid Build Coastguard Worker 
1821*795d594fSAndroid Build Coastguard Worker   // Size of the `kSectionObjects` section.
1822*795d594fSAndroid Build Coastguard Worker   size_t object_section_size_;
1823*795d594fSAndroid Build Coastguard Worker 
1824*795d594fSAndroid Build Coastguard Worker   // The location of the primary APK / dex file.
1825*795d594fSAndroid Build Coastguard Worker   std::string dex_location_;
1826*795d594fSAndroid Build Coastguard Worker 
1827*795d594fSAndroid Build Coastguard Worker   // The intern table for strings that we will write to disk.
1828*795d594fSAndroid Build Coastguard Worker   InternTableSet intern_table_;
1829*795d594fSAndroid Build Coastguard Worker 
1830*795d594fSAndroid Build Coastguard Worker   // The class table holding classes that we will write to disk.
1831*795d594fSAndroid Build Coastguard Worker   ClassTableSet class_table_;
1832*795d594fSAndroid Build Coastguard Worker 
1833*795d594fSAndroid Build Coastguard Worker   friend class ClassDescriptorHash;
1834*795d594fSAndroid Build Coastguard Worker   friend class PruneVisitor;
1835*795d594fSAndroid Build Coastguard Worker   friend class NativePointerVisitor;
1836*795d594fSAndroid Build Coastguard Worker };
1837*795d594fSAndroid Build Coastguard Worker 
GetRuntimeImageDir(const std::string & app_data_dir)1838*795d594fSAndroid Build Coastguard Worker std::string RuntimeImage::GetRuntimeImageDir(const std::string& app_data_dir) {
1839*795d594fSAndroid Build Coastguard Worker   if (app_data_dir.empty()) {
1840*795d594fSAndroid Build Coastguard Worker     // The data directory is empty for tests.
1841*795d594fSAndroid Build Coastguard Worker     return "";
1842*795d594fSAndroid Build Coastguard Worker   }
1843*795d594fSAndroid Build Coastguard Worker   return app_data_dir + "/cache/oat_primary/";
1844*795d594fSAndroid Build Coastguard Worker }
1845*795d594fSAndroid Build Coastguard Worker 
1846*795d594fSAndroid Build Coastguard Worker // Note: this may return a relative path for tests.
GetRuntimeImagePath(const std::string & app_data_dir,const std::string & dex_location,const std::string & isa)1847*795d594fSAndroid Build Coastguard Worker std::string RuntimeImage::GetRuntimeImagePath(const std::string& app_data_dir,
1848*795d594fSAndroid Build Coastguard Worker                                               const std::string& dex_location,
1849*795d594fSAndroid Build Coastguard Worker                                               const std::string& isa) {
1850*795d594fSAndroid Build Coastguard Worker   std::string basename = android::base::Basename(dex_location);
1851*795d594fSAndroid Build Coastguard Worker   std::string filename = ReplaceFileExtension(basename, kArtExtension);
1852*795d594fSAndroid Build Coastguard Worker 
1853*795d594fSAndroid Build Coastguard Worker   return GetRuntimeImageDir(app_data_dir) + isa + "/" + filename;
1854*795d594fSAndroid Build Coastguard Worker }
1855*795d594fSAndroid Build Coastguard Worker 
GetRuntimeImagePath(const std::string & dex_location)1856*795d594fSAndroid Build Coastguard Worker std::string RuntimeImage::GetRuntimeImagePath(const std::string& dex_location) {
1857*795d594fSAndroid Build Coastguard Worker   return GetRuntimeImagePath(Runtime::Current()->GetProcessDataDirectory(),
1858*795d594fSAndroid Build Coastguard Worker                              dex_location,
1859*795d594fSAndroid Build Coastguard Worker                              GetInstructionSetString(kRuntimeQuickCodeISA));
1860*795d594fSAndroid Build Coastguard Worker }
1861*795d594fSAndroid Build Coastguard Worker 
EnsureDirectoryExists(const std::string & directory,std::string * error_msg)1862*795d594fSAndroid Build Coastguard Worker static bool EnsureDirectoryExists(const std::string& directory, std::string* error_msg) {
1863*795d594fSAndroid Build Coastguard Worker   if (!OS::DirectoryExists(directory.c_str())) {
1864*795d594fSAndroid Build Coastguard Worker     static constexpr mode_t kDirectoryMode = S_IRWXU | S_IRGRP | S_IXGRP| S_IROTH | S_IXOTH;
1865*795d594fSAndroid Build Coastguard Worker     if (mkdir(directory.c_str(), kDirectoryMode) != 0) {
1866*795d594fSAndroid Build Coastguard Worker       *error_msg =
1867*795d594fSAndroid Build Coastguard Worker           StringPrintf("Could not create directory %s: %s", directory.c_str(), strerror(errno));
1868*795d594fSAndroid Build Coastguard Worker       return false;
1869*795d594fSAndroid Build Coastguard Worker     }
1870*795d594fSAndroid Build Coastguard Worker   }
1871*795d594fSAndroid Build Coastguard Worker   return true;
1872*795d594fSAndroid Build Coastguard Worker }
1873*795d594fSAndroid Build Coastguard Worker 
WriteImageToDisk(std::string * error_msg)1874*795d594fSAndroid Build Coastguard Worker bool RuntimeImage::WriteImageToDisk(std::string* error_msg) {
1875*795d594fSAndroid Build Coastguard Worker   if (gPageSize != kMinPageSize) {
1876*795d594fSAndroid Build Coastguard Worker     *error_msg = "Writing runtime image is only supported on devices with 4K page size";
1877*795d594fSAndroid Build Coastguard Worker     return false;
1878*795d594fSAndroid Build Coastguard Worker   }
1879*795d594fSAndroid Build Coastguard Worker 
1880*795d594fSAndroid Build Coastguard Worker   gc::Heap* heap = Runtime::Current()->GetHeap();
1881*795d594fSAndroid Build Coastguard Worker   if (!heap->HasBootImageSpace()) {
1882*795d594fSAndroid Build Coastguard Worker     *error_msg = "Cannot generate an app image without a boot image";
1883*795d594fSAndroid Build Coastguard Worker     return false;
1884*795d594fSAndroid Build Coastguard Worker   }
1885*795d594fSAndroid Build Coastguard Worker   std::string oat_path = GetRuntimeImageDir(Runtime::Current()->GetProcessDataDirectory());
1886*795d594fSAndroid Build Coastguard Worker   if (!oat_path.empty() && !EnsureDirectoryExists(oat_path, error_msg)) {
1887*795d594fSAndroid Build Coastguard Worker     return false;
1888*795d594fSAndroid Build Coastguard Worker   }
1889*795d594fSAndroid Build Coastguard Worker 
1890*795d594fSAndroid Build Coastguard Worker   ScopedTrace generate_image_trace("Generating runtime image");
1891*795d594fSAndroid Build Coastguard Worker   std::unique_ptr<RuntimeImageHelper> image(new RuntimeImageHelper(heap));
1892*795d594fSAndroid Build Coastguard Worker   if (!image->Generate(error_msg)) {
1893*795d594fSAndroid Build Coastguard Worker     return false;
1894*795d594fSAndroid Build Coastguard Worker   }
1895*795d594fSAndroid Build Coastguard Worker 
1896*795d594fSAndroid Build Coastguard Worker   ScopedTrace write_image_trace("Writing runtime image to disk");
1897*795d594fSAndroid Build Coastguard Worker 
1898*795d594fSAndroid Build Coastguard Worker   const std::string path = GetRuntimeImagePath(image->GetDexLocation());
1899*795d594fSAndroid Build Coastguard Worker   if (!EnsureDirectoryExists(android::base::Dirname(path), error_msg)) {
1900*795d594fSAndroid Build Coastguard Worker     return false;
1901*795d594fSAndroid Build Coastguard Worker   }
1902*795d594fSAndroid Build Coastguard Worker 
1903*795d594fSAndroid Build Coastguard Worker   // We first generate the app image in a temporary file, which we will then
1904*795d594fSAndroid Build Coastguard Worker   // move to `path`.
1905*795d594fSAndroid Build Coastguard Worker   const std::string temp_path = ReplaceFileExtension(path, std::to_string(getpid()) + ".tmp");
1906*795d594fSAndroid Build Coastguard Worker   ImageFileGuard image_file;
1907*795d594fSAndroid Build Coastguard Worker   image_file.reset(OS::CreateEmptyFileWriteOnly(temp_path.c_str()));
1908*795d594fSAndroid Build Coastguard Worker 
1909*795d594fSAndroid Build Coastguard Worker   if (image_file == nullptr) {
1910*795d594fSAndroid Build Coastguard Worker     *error_msg = "Could not open " + temp_path + " for writing";
1911*795d594fSAndroid Build Coastguard Worker     return false;
1912*795d594fSAndroid Build Coastguard Worker   }
1913*795d594fSAndroid Build Coastguard Worker 
1914*795d594fSAndroid Build Coastguard Worker   std::vector<uint8_t> full_data(image->GetHeader()->GetImageSize());
1915*795d594fSAndroid Build Coastguard Worker   image->FillData(full_data);
1916*795d594fSAndroid Build Coastguard Worker 
1917*795d594fSAndroid Build Coastguard Worker   // Specify default block size of 512K to enable parallel image decompression.
1918*795d594fSAndroid Build Coastguard Worker   static constexpr size_t kMaxImageBlockSize = 524288;
1919*795d594fSAndroid Build Coastguard Worker   // Use LZ4 as good compromise between CPU time and compression. LZ4HC
1920*795d594fSAndroid Build Coastguard Worker   // empirically takes 10x more time compressing.
1921*795d594fSAndroid Build Coastguard Worker   static constexpr ImageHeader::StorageMode kImageStorageMode = ImageHeader::kStorageModeLZ4;
1922*795d594fSAndroid Build Coastguard Worker   // Note: no need to update the checksum of the runtime app image: we have no
1923*795d594fSAndroid Build Coastguard Worker   // use for it, and computing it takes CPU time.
1924*795d594fSAndroid Build Coastguard Worker   if (!image->GetHeader()->WriteData(
1925*795d594fSAndroid Build Coastguard Worker           image_file,
1926*795d594fSAndroid Build Coastguard Worker           full_data.data(),
1927*795d594fSAndroid Build Coastguard Worker           reinterpret_cast<const uint8_t*>(image->GetImageBitmap().Begin()),
1928*795d594fSAndroid Build Coastguard Worker           kImageStorageMode,
1929*795d594fSAndroid Build Coastguard Worker           kMaxImageBlockSize,
1930*795d594fSAndroid Build Coastguard Worker           /* update_checksum= */ false,
1931*795d594fSAndroid Build Coastguard Worker           error_msg)) {
1932*795d594fSAndroid Build Coastguard Worker     return false;
1933*795d594fSAndroid Build Coastguard Worker   }
1934*795d594fSAndroid Build Coastguard Worker 
1935*795d594fSAndroid Build Coastguard Worker   if (!image_file.WriteHeaderAndClose(temp_path, image->GetHeader(), error_msg)) {
1936*795d594fSAndroid Build Coastguard Worker     return false;
1937*795d594fSAndroid Build Coastguard Worker   }
1938*795d594fSAndroid Build Coastguard Worker 
1939*795d594fSAndroid Build Coastguard Worker   if (rename(temp_path.c_str(), path.c_str()) != 0) {
1940*795d594fSAndroid Build Coastguard Worker     *error_msg =
1941*795d594fSAndroid Build Coastguard Worker         "Failed to move runtime app image to " + path + ": " + std::string(strerror(errno));
1942*795d594fSAndroid Build Coastguard Worker     // Unlink directly: we cannot use `out` as we have closed it.
1943*795d594fSAndroid Build Coastguard Worker     unlink(temp_path.c_str());
1944*795d594fSAndroid Build Coastguard Worker     return false;
1945*795d594fSAndroid Build Coastguard Worker   }
1946*795d594fSAndroid Build Coastguard Worker 
1947*795d594fSAndroid Build Coastguard Worker   return true;
1948*795d594fSAndroid Build Coastguard Worker }
1949*795d594fSAndroid Build Coastguard Worker 
1950*795d594fSAndroid Build Coastguard Worker }  // namespace art
1951