12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
16db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
17db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "image_writer.h"
18db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
196cd40e5cc59259a0b7636eb5532c76de9b8a7286Brian Carlstrom#include <sys/stat.h>
2090a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes
21700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers#include <memory>
2220f85597828194c12be10d3a927999def066555eVladimir Marko#include <numeric>
23db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include <vector>
24db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
25c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier#include "art_field-inl.h"
263d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier#include "art_method-inl.h"
2707ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
28761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h"
293481ba2c4e4f3aa80d8c6d50a9f85dacb56b508bVladimir Marko#include "class_linker-inl.h"
30ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom#include "compiled_method.h"
314f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
327940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "driver/compiler_driver.h"
3353cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "elf_file.h"
3453cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light#include "elf_utils.h"
357940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "elf_writer.h"
361d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/card_table-inl.h"
371d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/heap_bitmap.h"
3831e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier#include "gc/accounting/space_bitmap-inl.h"
391d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/heap.h"
401d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/large_object_space.h"
411d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space-inl.h"
42db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "globals.h"
434a289ed61242964b921434de7d375f46480472a1Brian Carlstrom#include "image.h"
44a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom#include "intern_table.h"
45c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier#include "linear_alloc.h"
46ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier#include "lock_word.h"
473d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier#include "mirror/abstract_method.h"
482dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/array-inl.h"
492dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h"
502dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h"
5139ebcb800aabedd0ffa6aa4aeac8aa4194c66e61Ian Rogers#include "mirror/dex_cache-inl.h"
523d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier#include "mirror/method.h"
532dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
542dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h"
55b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers#include "mirror/string-inl.h"
56700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "oat.h"
570c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien#include "oat_file.h"
581f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "runtime.h"
5900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
60eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier#include "handle_scope-inl.h"
6120f85597828194c12be10d3a927999def066555eVladimir Marko#include "utils/dex_cache_arrays_layout-inl.h"
62db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
633e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::Class;
643e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::DexCache;
653e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::Object;
663e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::ObjectArray;
673e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::String;
682dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers
69db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstromnamespace art {
70db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
71f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin// Separate objects into multiple bins to optimize dirty memory use.
72f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkinstatic constexpr bool kBinObjects = true;
73de486925d74f229e00b568200035eb9ed40aaa62Mathieu Chartierstatic constexpr bool kComputeEagerResolvedStrings = false;
74f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
75dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampestatic void CheckNoDexObjectsCallback(Object* obj, void* arg ATTRIBUTE_UNUSED)
76dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
77dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe  Class* klass = obj->GetClass();
78dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe  CHECK_NE(PrettyClass(klass), "com.android.dex.Dex");
79dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe}
80dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe
81dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampestatic void CheckNoDexObjects() {
82dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe  ScopedObjectAccess soa(Thread::Current());
83dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe  Runtime::Current()->GetHeap()->VisitObjects(CheckNoDexObjectsCallback, nullptr);
84dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe}
85dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe
86f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Markobool ImageWriter::PrepareImageAddressSpace() {
872d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier  target_ptr_size_ = InstructionSetPointerSize(compiler_driver_.GetInstructionSet());
88f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  {
89f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko    Thread::Current()->TransitionFromSuspendedToRunnable();
90f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko    PruneNonImageClasses();  // Remove junk
91f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko    ComputeLazyFieldsForImageClasses();  // Add useful information
92848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao
93848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    // Calling this can in theory fill in some resolved strings. However, in practice it seems to
94848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    // never resolve any.
95848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    if (kComputeEagerResolvedStrings) {
96848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao      ComputeEagerResolvedStrings();
97848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao    }
98f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko    Thread::Current()->TransitionFromRunnableToSuspended(kNative);
99f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  }
100f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  gc::Heap* heap = Runtime::Current()->GetHeap();
101f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  heap->CollectGarbage(false);  // Remove garbage.
102f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko
103dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe  // Dex caches must not have their dex fields set in the image. These are memory buffers of mapped
104dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe  // dex files.
105dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe  //
106dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe  // We may open them in the unstarted-runtime code for class metadata. Their fields should all be
107dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe  // reset in PruneNonImageClasses and the objects reclaimed in the GC. Make sure that's actually
108dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe  // true.
109dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe  if (kIsDebugBuild) {
110dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe    CheckNoDexObjects();
111dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe  }
112dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe
113f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  if (kIsDebugBuild) {
114f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko    ScopedObjectAccess soa(Thread::Current());
115f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko    CheckNonImageClassesRemoved();
116f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  }
117f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko
118f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  Thread::Current()->TransitionFromSuspendedToRunnable();
119f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  CalculateNewObjectOffsets();
120f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  Thread::Current()->TransitionFromRunnableToSuspended(kNative);
121f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko
122fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  // This needs to happen after CalculateNewObjectOffsets since it relies on intern_table_bytes_ and
123fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  // bin size sums being calculated.
124fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  if (!AllocMemory()) {
125fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier    return false;
126fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  }
127fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier
128f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  return true;
129f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko}
130f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko
131a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrombool ImageWriter::Write(const std::string& image_filename,
132ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                        const std::string& oat_filename,
13396391606d8adfc661e1c21703ded1e7a39377a76Brian Carlstrom                        const std::string& oat_location) {
134a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  CHECK(!image_filename.empty());
135aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
136ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
137ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
138700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<File> oat_file(OS::OpenFileReadWrite(oat_filename.c_str()));
1392cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (oat_file.get() == nullptr) {
14088ec7f45c0e2c3f659048fbe4b1dc78730fdaea8Andreas Gampe    PLOG(ERROR) << "Failed to open oat file " << oat_filename << " for " << oat_location;
141e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return false;
142e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
1438d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  std::string error_msg;
144e5fed03772144595c0904faf3d6974cc55214c8cRichard Uhler  oat_file_ = OatFile::OpenReadable(oat_file.get(), oat_location, nullptr, &error_msg);
1458d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  if (oat_file_ == nullptr) {
14688ec7f45c0e2c3f659048fbe4b1dc78730fdaea8Andreas Gampe    PLOG(ERROR) << "Failed to open writable oat file " << oat_filename << " for " << oat_location
1478d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers        << ": " << error_msg;
1480b7fcf94bdf8880862eb305454714a72da04cedbAndreas Gampe    oat_file->Erase();
149c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom    return false;
150c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom  }
1518d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  CHECK_EQ(class_linker->RegisterOatFile(oat_file_), oat_file_);
152e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
153848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  interpreter_to_interpreter_bridge_offset_ =
154848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers      oat_file_->GetOatHeader().GetInterpreterToInterpreterBridgeOffset();
155848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  interpreter_to_compiled_code_bridge_offset_ =
156848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers      oat_file_->GetOatHeader().GetInterpreterToCompiledCodeBridgeOffset();
157848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers
158848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  jni_dlsym_lookup_offset_ = oat_file_->GetOatHeader().GetJniDlsymLookupOffset();
159848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers
1602da882315a61072664f7ce3c212307342e907207Andreas Gampe  quick_generic_jni_trampoline_offset_ =
1612da882315a61072664f7ce3c212307342e907207Andreas Gampe      oat_file_->GetOatHeader().GetQuickGenericJniTrampolineOffset();
16288474b416eb257078e590bf9bc7957cee604a186Jeff Hao  quick_imt_conflict_trampoline_offset_ =
16388474b416eb257078e590bf9bc7957cee604a186Jeff Hao      oat_file_->GetOatHeader().GetQuickImtConflictTrampolineOffset();
164848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  quick_resolution_trampoline_offset_ =
165848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers      oat_file_->GetOatHeader().GetQuickResolutionTrampolineOffset();
166848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  quick_to_interpreter_bridge_offset_ =
167848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers      oat_file_->GetOatHeader().GetQuickToInterpreterBridgeOffset();
168b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier
169700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  size_t oat_loaded_size = 0;
170700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  size_t oat_data_offset = 0;
171a36098b3717e14baf6a173e72082f6ef3b7bcefdVladimir Marko  ElfWriter::GetOatElfInformation(oat_file.get(), &oat_loaded_size, &oat_data_offset);
17253cb16b98acf3cf6f3a1e2204ad4958ecf1b5a3cAlex Light
173f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  Thread::Current()->TransitionFromSuspendedToRunnable();
1743d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier
175f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  CreateHeader(oat_loaded_size, oat_data_offset);
1763d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  CopyAndFixupNativeData();
177c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  // TODO: heap validation can't handle these fix up passes.
178c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  Runtime::Current()->GetHeap()->DisableObjectValidation();
179f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  CopyAndFixupObjects();
180e35517ad40e0713df8420aeb5d3540f146a59f62Mathieu Chartier  Thread::Current()->TransitionFromRunnableToSuspended(kNative);
181d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes
182f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  SetOatChecksumFromElfFile(oat_file.get());
183f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko
1844303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe  if (oat_file->FlushCloseOrErase() != 0) {
1854303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe    LOG(ERROR) << "Failed to flush and close oat file " << oat_filename << " for " << oat_location;
1864303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe    return false;
1874303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe  }
1884303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe
189700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<File> image_file(OS::CreateEmptyFile(image_filename.c_str()));
19031e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
1912cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (image_file.get() == nullptr) {
192e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    LOG(ERROR) << "Failed to open image file " << image_filename;
193db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    return false;
194db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  }
195700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  if (fchmod(image_file->Fd(), 0644) != 0) {
1966cd40e5cc59259a0b7636eb5532c76de9b8a7286Brian Carlstrom    PLOG(ERROR) << "Failed to make image file world readable: " << image_filename;
1974303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe    image_file->Erase();
1986cd40e5cc59259a0b7636eb5532c76de9b8a7286Brian Carlstrom    return EXIT_FAILURE;
1996cd40e5cc59259a0b7636eb5532c76de9b8a7286Brian Carlstrom  }
20031e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier
2013d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Write out the image + fields + methods.
2023d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  const auto write_count = image_header->GetImageSize();
203c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  if (!image_file->WriteFully(image_->Begin(), write_count)) {
20431e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier    PLOG(ERROR) << "Failed to write image file " << image_filename;
2054303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe    image_file->Erase();
20631e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier    return false;
20731e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  }
20831e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier
20931e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  // Write out the image bitmap at the page aligned start of the image end.
210fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  const ImageSection& bitmap_section = image_header->GetImageSection(ImageHeader::kSectionImageBitmap);
2113d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  CHECK_ALIGNED(bitmap_section.Offset(), kPageSize);
21231e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  if (!image_file->Write(reinterpret_cast<char*>(image_bitmap_->Begin()),
2133d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                         bitmap_section.Size(), bitmap_section.Offset())) {
214e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    PLOG(ERROR) << "Failed to write image file " << image_filename;
2154303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe    image_file->Erase();
216e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return false;
217e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
21831e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier
2193d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  CHECK_EQ(bitmap_section.End(), static_cast<size_t>(image_file->GetLength()));
2204303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe  if (image_file->FlushCloseOrErase() != 0) {
2214303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe    PLOG(ERROR) << "Failed to flush and close image file " << image_filename;
2224303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe    return false;
2234303ba97313458491e038d78efa041d41cf7bb43Andreas Gampe  }
224e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return true;
225db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
226db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
227fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartiervoid ImageWriter::SetImageOffset(mirror::Object* object, size_t offset) {
228590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  DCHECK(object != nullptr);
229590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  DCHECK_NE(offset, 0U);
230f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
231f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // The object is already deflated from when we set the bin slot. Just overwrite the lock word.
232f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  object->SetLockWord(LockWord::FromForwardingAddress(offset), false);
2333d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  DCHECK_EQ(object->GetLockWord(false).ReadBarrierState(), 0u);
234f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK(IsImageOffsetAssigned(object));
235f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin}
236f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
2373d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartiervoid ImageWriter::UpdateImageOffset(mirror::Object* obj, uintptr_t offset) {
2383d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  DCHECK(IsImageOffsetAssigned(obj)) << obj << " " << offset;
2393d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  obj->SetLockWord(LockWord::FromForwardingAddress(offset), false);
2403d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  DCHECK_EQ(obj->GetLockWord(false).ReadBarrierState(), 0u);
2413d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier}
2423d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier
243f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkinvoid ImageWriter::AssignImageOffset(mirror::Object* object, ImageWriter::BinSlot bin_slot) {
244f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK(object != nullptr);
245f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK_NE(image_objects_offset_begin_, 0u);
246f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
24720f85597828194c12be10d3a927999def066555eVladimir Marko  size_t previous_bin_sizes = bin_slot_previous_sizes_[bin_slot.GetBin()];
248f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  size_t new_offset = image_objects_offset_begin_ + previous_bin_sizes + bin_slot.GetIndex();
249f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK_ALIGNED(new_offset, kObjectAlignment);
250f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
251fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  SetImageOffset(object, new_offset);
252f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK_LT(new_offset, image_end_);
253f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin}
254f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
255f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkinbool ImageWriter::IsImageOffsetAssigned(mirror::Object* object) const {
256f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // Will also return true if the bin slot was assigned since we are reusing the lock word.
257f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK(object != nullptr);
258f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  return object->GetLockWord(false).GetState() == LockWord::kForwardingAddress;
259f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin}
260f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
261f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkinsize_t ImageWriter::GetImageOffset(mirror::Object* object) const {
262f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK(object != nullptr);
263f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK(IsImageOffsetAssigned(object));
264f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  LockWord lock_word = object->GetLockWord(false);
265f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  size_t offset = lock_word.ForwardingAddress();
266f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK_LT(offset, image_end_);
267f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  return offset;
268f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin}
269f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
270f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkinvoid ImageWriter::SetImageBinSlot(mirror::Object* object, BinSlot bin_slot) {
271f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK(object != nullptr);
272f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK(!IsImageOffsetAssigned(object));
273f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK(!IsImageBinSlotAssigned(object));
274f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
275590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  // Before we stomp over the lock word, save the hash code for later.
276590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  Monitor::Deflate(Thread::Current(), object);;
2774d7f61d44a732cfbc8573e5d93364983fd746888Mathieu Chartier  LockWord lw(object->GetLockWord(false));
278590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  switch (lw.GetState()) {
279590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    case LockWord::kFatLocked: {
280f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin      LOG(FATAL) << "Fat locked object " << object << " found during object copy";
281590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      break;
282590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    }
283590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    case LockWord::kThinLocked: {
284f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin      LOG(FATAL) << "Thin locked object " << object << " found during object copy";
285590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      break;
286590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    }
287590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    case LockWord::kUnlocked:
288590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      // No hash, don't need to save it.
289590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      break;
290590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    case LockWord::kHashCode:
291fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      DCHECK(saved_hashcode_map_.find(object) == saved_hashcode_map_.end());
292fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      saved_hashcode_map_.emplace(object, lw.GetHashCode());
293590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      break;
294590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    default:
295590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      LOG(FATAL) << "Unreachable.";
2962c4257be8191c5eefde744e8965fcefc80a0a97dIan Rogers      UNREACHABLE();
29731e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  }
298fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  object->SetLockWord(LockWord::FromForwardingAddress(bin_slot.Uint32Value()), false);
2993d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  DCHECK_EQ(object->GetLockWord(false).ReadBarrierState(), 0u);
300f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK(IsImageBinSlotAssigned(object));
30131e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier}
30231e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier
30320f85597828194c12be10d3a927999def066555eVladimir Markovoid ImageWriter::PrepareDexCacheArraySlots() {
30420f85597828194c12be10d3a927999def066555eVladimir Marko  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
30520f85597828194c12be10d3a927999def066555eVladimir Marko  ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock());
30620f85597828194c12be10d3a927999def066555eVladimir Marko  size_t dex_cache_count = class_linker->GetDexCacheCount();
30720f85597828194c12be10d3a927999def066555eVladimir Marko  uint32_t size = 0u;
30820f85597828194c12be10d3a927999def066555eVladimir Marko  for (size_t idx = 0; idx < dex_cache_count; ++idx) {
30920f85597828194c12be10d3a927999def066555eVladimir Marko    DexCache* dex_cache = class_linker->GetDexCache(idx);
31020f85597828194c12be10d3a927999def066555eVladimir Marko    const DexFile* dex_file = dex_cache->GetDexFile();
31120f85597828194c12be10d3a927999def066555eVladimir Marko    dex_cache_array_starts_.Put(dex_file, size);
312c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    DexCacheArraysLayout layout(target_ptr_size_, dex_file);
31320f85597828194c12be10d3a927999def066555eVladimir Marko    DCHECK(layout.Valid());
314c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    auto types_size = layout.TypesSize(dex_file->NumTypeIds());
315c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    auto methods_size = layout.MethodsSize(dex_file->NumMethodIds());
316c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    auto fields_size = layout.FieldsSize(dex_file->NumFieldIds());
317c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    auto strings_size = layout.StringsSize(dex_file->NumStringIds());
318c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    dex_cache_array_indexes_.Put(
319c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier        dex_cache->GetResolvedTypes(),
3203d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        DexCacheArrayLocation {size + layout.TypesOffset(), types_size, kBinRegular});
321c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    dex_cache_array_indexes_.Put(
322c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier        dex_cache->GetResolvedMethods(),
3233d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        DexCacheArrayLocation {size + layout.MethodsOffset(), methods_size, kBinArtMethodClean});
3243d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    AddMethodPointerArray(dex_cache->GetResolvedMethods());
325c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    dex_cache_array_indexes_.Put(
326c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier        dex_cache->GetResolvedFields(),
3273d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        DexCacheArrayLocation {size + layout.FieldsOffset(), fields_size, kBinArtField});
3283d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    pointer_arrays_.emplace(dex_cache->GetResolvedFields(), kBinArtField);
329c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    dex_cache_array_indexes_.Put(
330c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier        dex_cache->GetStrings(),
3313d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        DexCacheArrayLocation {size + layout.StringsOffset(), strings_size, kBinRegular});
33220f85597828194c12be10d3a927999def066555eVladimir Marko    size += layout.Size();
333c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    CHECK_EQ(layout.Size(), types_size + methods_size + fields_size + strings_size);
33420f85597828194c12be10d3a927999def066555eVladimir Marko  }
33520f85597828194c12be10d3a927999def066555eVladimir Marko  // Set the slot size early to avoid DCHECK() failures in IsImageBinSlotAssigned()
33620f85597828194c12be10d3a927999def066555eVladimir Marko  // when AssignImageBinSlot() assigns their indexes out or order.
33720f85597828194c12be10d3a927999def066555eVladimir Marko  bin_slot_sizes_[kBinDexCacheArray] = size;
33820f85597828194c12be10d3a927999def066555eVladimir Marko}
33920f85597828194c12be10d3a927999def066555eVladimir Marko
3403d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartiervoid ImageWriter::AddMethodPointerArray(mirror::PointerArray* arr) {
3413d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  DCHECK(arr != nullptr);
3423d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  if (kIsDebugBuild) {
3433d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    for (size_t i = 0, len = arr->GetLength(); i < len; i++) {
3443d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto* method = arr->GetElementPtrSize<ArtMethod*>(i, target_ptr_size_);
3453d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      if (method != nullptr && !method->IsRuntimeMethod()) {
3463d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        auto* klass = method->GetDeclaringClass();
3473d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        CHECK(klass == nullptr || IsImageClass(klass)) << PrettyClass(klass)
3483d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier            << " should be an image class";
3493d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      }
3503d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    }
3513d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  }
3523d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // kBinArtMethodClean picked arbitrarily, just required to differentiate between ArtFields and
3533d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // ArtMethods.
3543d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  pointer_arrays_.emplace(arr, kBinArtMethodClean);
3553d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier}
3563d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier
357f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkinvoid ImageWriter::AssignImageBinSlot(mirror::Object* object) {
358590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  DCHECK(object != nullptr);
359c7d11887725e28db2796c848f4485e59d5eb690cJeff Hao  size_t object_size = object->SizeOf();
360f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
361f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // The magic happens here. We segregate objects into different bins based
362f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // on how likely they are to get dirty at runtime.
363f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  //
364f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // Likely-to-dirty objects get packed together into the same bin so that
365f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // at runtime their page dirtiness ratio (how many dirty objects a page has) is
366f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // maximized.
367f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  //
368f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // This means more pages will stay either clean or shared dirty (with zygote) and
369f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // the app will use less of its own (private) memory.
370f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  Bin bin = kBinRegular;
37120f85597828194c12be10d3a927999def066555eVladimir Marko  size_t current_offset = 0u;
372f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
373f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  if (kBinObjects) {
374f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //
375f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    // Changing the bin of an object is purely a memory-use tuning.
376f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    // It has no change on runtime correctness.
377f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //
378f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    // Memory analysis has determined that the following types of objects get dirtied
379f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    // the most:
380f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //
38120f85597828194c12be10d3a927999def066555eVladimir Marko    // * Dex cache arrays are stored in a special bin. The arrays for each dex cache have
38220f85597828194c12be10d3a927999def066555eVladimir Marko    //   a fixed layout which helps improve generated code (using PC-relative addressing),
38320f85597828194c12be10d3a927999def066555eVladimir Marko    //   so we pre-calculate their offsets separately in PrepareDexCacheArraySlots().
38420f85597828194c12be10d3a927999def066555eVladimir Marko    //   Since these arrays are huge, most pages do not overlap other objects and it's not
38520f85597828194c12be10d3a927999def066555eVladimir Marko    //   really important where they are for the clean/dirty separation. Due to their
38620f85597828194c12be10d3a927999def066555eVladimir Marko    //   special PC-relative addressing, we arbitrarily keep them at the beginning.
387f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    // * Class'es which are verified [their clinit runs only at runtime]
388f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //   - classes in general [because their static fields get overwritten]
389f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //   - initialized classes with all-final statics are unlikely to be ever dirty,
390f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //     so bin them separately
391f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    // * Art Methods that are:
392f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //   - native [their native entry point is not looked up until runtime]
393f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //   - have declaring classes that aren't initialized
394f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //            [their interpreter/quick entry points are trampolines until the class
395f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //             becomes initialized]
396f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //
397f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    // We also assume the following objects get dirtied either never or extremely rarely:
398f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //  * Strings (they are immutable)
399f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //  * Art methods that aren't native and have initialized declared classes
400f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //
401f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    // We assume that "regular" bin objects are highly unlikely to become dirtied,
402f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    // so packing them together will not result in a noticeably tighter dirty-to-clean ratio.
403f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    //
404f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    if (object->IsClass()) {
405f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin      bin = kBinClassVerified;
406f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin      mirror::Class* klass = object->AsClass();
407f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
4083d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      // Add non-embedded vtable to the pointer array table if there is one.
4093d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto* vtable = klass->GetVTable();
4103d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      if (vtable != nullptr) {
4113d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        AddMethodPointerArray(vtable);
4123d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      }
4133d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto* iftable = klass->GetIfTable();
4143d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      if (iftable != nullptr) {
4153d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        for (int32_t i = 0; i < klass->GetIfTableCount(); ++i) {
4163d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          if (iftable->GetMethodArrayCount(i) > 0) {
4173d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier            AddMethodPointerArray(iftable->GetMethodArray(i));
4183d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          }
4193d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        }
4203d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      }
4213d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier
422f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin      if (klass->GetStatus() == Class::kStatusInitialized) {
423f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin        bin = kBinClassInitialized;
424f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
425f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin        // If the class's static fields are all final, put it into a separate bin
426f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin        // since it's very likely it will stay clean.
427f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin        uint32_t num_static_fields = klass->NumStaticFields();
428f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin        if (num_static_fields == 0) {
429f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin          bin = kBinClassInitializedFinalStatics;
430f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin        } else {
431f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin          // Maybe all the statics are final?
432f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin          bool all_final = true;
433f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin          for (uint32_t i = 0; i < num_static_fields; ++i) {
434f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin            ArtField* field = klass->GetStaticField(i);
435f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin            if (!field->IsFinal()) {
436f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin              all_final = false;
437f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin              break;
438f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin            }
439f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin          }
440f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
441f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin          if (all_final) {
442f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin            bin = kBinClassInitializedFinalStatics;
443f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin          }
444f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin        }
445f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin      }
446f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    } else if (object->GetClass<kVerifyNone>()->IsStringClass()) {
447f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin      bin = kBinString;  // Strings are almost always immutable (except for object header).
448c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    } else if (object->IsArrayInstance()) {
449c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      mirror::Class* klass = object->GetClass<kVerifyNone>();
4503d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      if (klass->IsObjectArrayClass() || klass->IsIntArrayClass() || klass->IsLongArrayClass()) {
451c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier        auto it = dex_cache_array_indexes_.find(object);
452c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier        if (it != dex_cache_array_indexes_.end()) {
453c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier          bin = kBinDexCacheArray;
454c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier          // Use prepared offset defined by the DexCacheLayout.
455c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier          current_offset = it->second.offset_;
456c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier          // Override incase of cross compilation.
457c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier          object_size = it->second.length_;
458c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier        }  // else bin = kBinRegular
459c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      }
460f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    }  // else bin = kBinRegular
461f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  }
462f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
463f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  size_t offset_delta = RoundUp(object_size, kObjectAlignment);  // 64-bit alignment
46420f85597828194c12be10d3a927999def066555eVladimir Marko  if (bin != kBinDexCacheArray) {
4653d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    DCHECK(dex_cache_array_indexes_.find(object) == dex_cache_array_indexes_.end()) << object;
46620f85597828194c12be10d3a927999def066555eVladimir Marko    current_offset = bin_slot_sizes_[bin];  // How many bytes the current bin is at (aligned).
46720f85597828194c12be10d3a927999def066555eVladimir Marko    // Move the current bin size up to accomodate the object we just assigned a bin slot.
46820f85597828194c12be10d3a927999def066555eVladimir Marko    bin_slot_sizes_[bin] += offset_delta;
46920f85597828194c12be10d3a927999def066555eVladimir Marko  }
470f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
471f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  BinSlot new_bin_slot(bin, current_offset);
472f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  SetImageBinSlot(object, new_bin_slot);
473f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
474f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  ++bin_slot_count_[bin];
475f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
476f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // Grow the image closer to the end by the object we just assigned.
477f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  image_end_ += offset_delta;
478590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier}
479b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier
4803d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartierbool ImageWriter::WillMethodBeDirty(ArtMethod* m) const {
4813d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  if (m->IsNative()) {
4823d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    return true;
4833d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  }
4843d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  mirror::Class* declaring_class = m->GetDeclaringClass();
4853d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Initialized is highly unlikely to dirty since there's no entry points to mutate.
4863d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  return declaring_class == nullptr || declaring_class->GetStatus() != Class::kStatusInitialized;
4873d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier}
4883d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier
489f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkinbool ImageWriter::IsImageBinSlotAssigned(mirror::Object* object) const {
490590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  DCHECK(object != nullptr);
491f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
492f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // We always stash the bin slot into a lockword, in the 'forwarding address' state.
493f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // If it's in some other state, then we haven't yet assigned an image bin slot.
494f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  if (object->GetLockWord(false).GetState() != LockWord::kForwardingAddress) {
495f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    return false;
496f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  } else if (kIsDebugBuild) {
497f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    LockWord lock_word = object->GetLockWord(false);
498f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    size_t offset = lock_word.ForwardingAddress();
499f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    BinSlot bin_slot(offset);
500f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    DCHECK_LT(bin_slot.GetIndex(), bin_slot_sizes_[bin_slot.GetBin()])
501f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin      << "bin slot offset should not exceed the size of that bin";
502f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  }
503f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  return true;
504590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier}
505590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
506f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor MurashkinImageWriter::BinSlot ImageWriter::GetImageBinSlot(mirror::Object* object) const {
507590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  DCHECK(object != nullptr);
508f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK(IsImageBinSlotAssigned(object));
509f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
5104d7f61d44a732cfbc8573e5d93364983fd746888Mathieu Chartier  LockWord lock_word = object->GetLockWord(false);
511f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  size_t offset = lock_word.ForwardingAddress();  // TODO: ForwardingAddress should be uint32_t
512f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK_LE(offset, std::numeric_limits<uint32_t>::max());
513f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
514f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  BinSlot bin_slot(static_cast<uint32_t>(offset));
515f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK_LT(bin_slot.GetIndex(), bin_slot_sizes_[bin_slot.GetBin()]);
516f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
517f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  return bin_slot;
518590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier}
519590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
520590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartierbool ImageWriter::AllocMemory() {
521fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  const size_t length = RoundUp(image_objects_offset_begin_ + GetBinSizeSum() + intern_table_bytes_,
522fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier                                kPageSize);
5238d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  std::string error_msg;
5245c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko  image_.reset(MemMap::MapAnonymous("image writer image", nullptr, length, PROT_READ | PROT_WRITE,
5255c42c29b89286e5efa4a4613132b09051ce5945bVladimir Marko                                    false, false, &error_msg));
5268d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers  if (UNLIKELY(image_.get() == nullptr)) {
5278d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    LOG(ERROR) << "Failed to allocate memory for image file generation: " << error_msg;
528db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    return false;
529db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  }
530590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
531fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  // Create the image bitmap, only needs to cover mirror object section which is up to image_end_.
532fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  CHECK_LE(image_end_, length);
533fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  image_bitmap_.reset(gc::accounting::ContinuousSpaceBitmap::Create(
534fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      "image bitmap", image_->Begin(), RoundUp(image_end_, kPageSize)));
535590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  if (image_bitmap_.get() == nullptr) {
536590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    LOG(ERROR) << "Failed to allocate memory for image bitmap";
537590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    return false;
538590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  }
539db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  return true;
540db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
541db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
542d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogersvoid ImageWriter::ComputeLazyFieldsForImageClasses() {
543590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
5442cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  class_linker->VisitClassesWithoutClassesLock(ComputeLazyFieldsForClassesVisitor, nullptr);
545d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers}
546d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers
5471bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesbool ImageWriter::ComputeLazyFieldsForClassesVisitor(Class* c, void* /*arg*/) {
548f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier  Thread* self = Thread::Current();
549f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier  StackHandleScope<1> hs(self);
550f832284dd847ff077577bb5712225430bbbb3b67Mathieu Chartier  mirror::Class::ComputeName(hs.NewHandle(c));
551d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers  return true;
552d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers}
553d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers
5546a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogersvoid ImageWriter::ComputeEagerResolvedStringsCallback(Object* obj, void* arg ATTRIBUTE_UNUSED) {
555d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers  if (!obj->GetClass()->IsStringClass()) {
556d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers    return;
557d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers  }
558590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  mirror::String* string = obj->AsString();
559848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao  const uint16_t* utf16_string = string->GetValue();
560a48aef4234768ed37828df613919391c21f561a7Vladimir Marko  size_t utf16_length = static_cast<size_t>(string->GetLength());
561e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
562e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  ReaderMutexLock mu(Thread::Current(), *class_linker->DexLock());
563e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  size_t dex_cache_count = class_linker->GetDexCacheCount();
564e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  for (size_t i = 0; i < dex_cache_count; ++i) {
565e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi    DexCache* dex_cache = class_linker->GetDexCache(i);
5664445a7e3398a6143939168097a3aa275b734504dIan Rogers    const DexFile& dex_file = *dex_cache->GetDexFile();
56724c534d740fc50d5ed03538ec725144f44b4c0f7Ian Rogers    const DexFile::StringId* string_id;
568a48aef4234768ed37828df613919391c21f561a7Vladimir Marko    if (UNLIKELY(utf16_length == 0)) {
56924c534d740fc50d5ed03538ec725144f44b4c0f7Ian Rogers      string_id = dex_file.FindStringId("");
57024c534d740fc50d5ed03538ec725144f44b4c0f7Ian Rogers    } else {
571a48aef4234768ed37828df613919391c21f561a7Vladimir Marko      string_id = dex_file.FindStringId(utf16_string, utf16_length);
57224c534d740fc50d5ed03538ec725144f44b4c0f7Ian Rogers    }
573590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    if (string_id != nullptr) {
574d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers      // This string occurs in this dex file, assign the dex cache entry.
575d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers      uint32_t string_idx = dex_file.GetIndexForStringId(*string_id);
5762cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      if (dex_cache->GetResolvedString(string_idx) == nullptr) {
577d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers        dex_cache->SetResolvedString(string_idx, string);
578d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers      }
579d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers    }
580d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers  }
581d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers}
582d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers
583fd04b6f89238af5da682805aa11899639fb4ee07Mathieu Chartiervoid ImageWriter::ComputeEagerResolvedStrings() {
584590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  Runtime::Current()->GetHeap()->VisitObjects(ComputeEagerResolvedStringsCallback, this);
585d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers}
586d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers
587ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersbool ImageWriter::IsImageClass(Class* klass) {
5883d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  if (klass == nullptr) {
5893d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    return false;
5903d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  }
5911ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  std::string temp;
5921ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers  return compiler_driver_.IsImageClass(klass->GetDescriptor(&temp));
593ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
594ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
595ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromstruct NonImageClasses {
596ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  ImageWriter* image_writer;
597ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  std::set<std::string>* non_image_classes;
598ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom};
599ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
600ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid ImageWriter::PruneNonImageClasses() {
6012cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  if (compiler_driver_.GetImageClasses() == nullptr) {
602ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return;
603ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
604ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  Runtime* runtime = Runtime::Current();
605ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  ClassLinker* class_linker = runtime->GetClassLinker();
6063d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  Thread* self = Thread::Current();
607ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
6084b7b9896856171a623d95f86a2676c81c258f408Brian Carlstrom  // Make a list of classes we would like to prune.
609ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  std::set<std::string> non_image_classes;
610ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  NonImageClasses context;
611ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  context.image_writer = this;
612ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  context.non_image_classes = &non_image_classes;
613ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  class_linker->VisitClasses(NonImageClassesVisitor, &context);
614ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
6154b7b9896856171a623d95f86a2676c81c258f408Brian Carlstrom  // Remove the undesired classes from the class roots.
61602e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  for (const std::string& it : non_image_classes) {
6172cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    bool result = class_linker->RemoveClass(it.c_str(), nullptr);
618c2e20629c7dfdb0f679fa30c14b41fe68588697fMathieu Chartier    DCHECK(result);
619ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
620ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
6214b7b9896856171a623d95f86a2676c81c258f408Brian Carlstrom  // Clear references to removed classes from the DexCaches.
6223d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  const ArtMethod* resolution_method = runtime->GetResolutionMethod();
6233d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  size_t dex_cache_count;
6243d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  {
6253d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    ReaderMutexLock mu(self, *class_linker->DexLock());
6263d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    dex_cache_count = class_linker->GetDexCacheCount();
6273d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  }
628e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  for (size_t idx = 0; idx < dex_cache_count; ++idx) {
6293d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    DexCache* dex_cache;
6303d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    {
6313d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      ReaderMutexLock mu(self, *class_linker->DexLock());
6323d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      dex_cache = class_linker->GetDexCache(idx);
6333d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    }
634ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
635ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      Class* klass = dex_cache->GetResolvedType(i);
6362cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier      if (klass != nullptr && !IsImageClass(klass)) {
6372cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier        dex_cache->SetResolvedType(i, nullptr);
638ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
639ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
6403d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto* resolved_methods = down_cast<mirror::PointerArray*>(dex_cache->GetResolvedMethods());
6413d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    for (size_t i = 0, len = resolved_methods->GetLength(); i < len; i++) {
6423d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto* method = resolved_methods->GetElementPtrSize<ArtMethod*>(i, target_ptr_size_);
6433d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      if (method != nullptr) {
6443d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        auto* declaring_class = method->GetDeclaringClass();
6453d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        // Miranda methods may be held live by a class which was not an image class but have a
6463d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        // declaring class which is an image class. Set it to the resolution method to be safe and
6473d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        // prevent dangling pointers.
6483d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        if (method->IsMiranda() || !IsImageClass(declaring_class)) {
6493d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          resolved_methods->SetElementPtrSize(i, resolution_method, target_ptr_size_);
6503d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        } else {
6513d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          // Check that the class is still in the classes table.
6523d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          DCHECK(class_linker->ClassInClassTable(declaring_class)) << "Class "
6533d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier              << PrettyClass(declaring_class) << " not in class linker table";
6543d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        }
655ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
656ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
657ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
6583d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      ArtField* field = dex_cache->GetResolvedField(i, target_ptr_size_);
659c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      if (field != nullptr && !IsImageClass(field->GetDeclaringClass())) {
6603d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        dex_cache->SetResolvedField(i, nullptr, target_ptr_size_);
661ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
662ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
663dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe    // Clean the dex field. It might have been populated during the initialization phase, but
664dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe    // contains data only valid during a real run.
665dd9d055ddfe4bd66fcf58fde4e8066670acce011Andreas Gampe    dex_cache->SetFieldObject<false>(mirror::DexCache::DexOffset(), nullptr);
666ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
66744905ce1c97613a5cb44046049843fe1029a64cfAndreas Gampe
66844905ce1c97613a5cb44046049843fe1029a64cfAndreas Gampe  // Drop the array class cache in the ClassLinker, as these are roots holding those classes live.
66944905ce1c97613a5cb44046049843fe1029a64cfAndreas Gampe  class_linker->DropFindArrayClassCache();
670ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
671ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
672ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrombool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) {
673ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg);
674ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (!context->image_writer->IsImageClass(klass)) {
6751ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers    std::string temp;
6761ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers    context->non_image_classes->insert(klass->GetDescriptor(&temp));
677ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
678ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  return true;
679ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
680ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
681fd04b6f89238af5da682805aa11899639fb4ee07Mathieu Chartiervoid ImageWriter::CheckNonImageClassesRemoved() {
682590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  if (compiler_driver_.GetImageClasses() != nullptr) {
683590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    gc::Heap* heap = Runtime::Current()->GetHeap();
684590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    heap->VisitObjects(CheckNonImageClassesRemovedCallback, this);
685357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier  }
686ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
687ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
688ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid ImageWriter::CheckNonImageClassesRemovedCallback(Object* obj, void* arg) {
689ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
690590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  if (obj->IsClass()) {
691590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    Class* klass = obj->AsClass();
692590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    if (!image_writer->IsImageClass(klass)) {
693590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      image_writer->DumpImageClasses();
6941ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers      std::string temp;
6951ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers      CHECK(image_writer->IsImageClass(klass)) << klass->GetDescriptor(&temp)
696590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier                                               << " " << PrettyDescriptor(klass);
697590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    }
698c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes  }
699c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes}
700c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes
701c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughesvoid ImageWriter::DumpImageClasses() {
702b1fceadbd42b3047a9c06a8af6239c737d67344eAndreas Gampe  auto image_classes = compiler_driver_.GetImageClasses();
7032cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  CHECK(image_classes != nullptr);
70402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier  for (const std::string& image_class : *image_classes) {
70502e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    LOG(INFO) << " " << image_class;
706c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes  }
707ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
708ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
709f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkinvoid ImageWriter::CalculateObjectBinSlots(Object* obj) {
7102cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier  DCHECK(obj != nullptr);
711c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom  // if it is a string, we want to intern it if its not interned.
712dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  if (obj->GetClass()->IsStringClass()) {
713c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom    // we must be an interned string that was forward referenced and already assigned
714f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    if (IsImageBinSlotAssigned(obj)) {
715c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom      DCHECK_EQ(obj, obj->AsString()->Intern());
716c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom      return;
717c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom    }
718fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier    mirror::String* const interned = Runtime::Current()->GetInternTable()->InternStrong(
719fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier        obj->AsString()->Intern());
720eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    if (obj != interned) {
721f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin      if (!IsImageBinSlotAssigned(interned)) {
722c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom        // interned obj is after us, allocate its location early
723f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin        AssignImageBinSlot(interned);
724c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom      }
725c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom      // point those looking for this object to the interned version.
726f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin      SetImageBinSlot(obj, GetImageBinSlot(interned));
727c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom      return;
728c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom    }
729c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom    // else (obj == interned), nothing to do but fall through to the normal case
730c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom  }
731c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom
732f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  AssignImageBinSlot(obj);
7334e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom}
7344e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom
735e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromObjectArray<Object>* ImageWriter::CreateImageRoots() const {
736161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  Runtime* runtime = Runtime::Current();
737161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  ClassLinker* class_linker = runtime->GetClassLinker();
73850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers  Thread* self = Thread::Current();
739eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  StackHandleScope<3> hs(self);
740eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<Class> object_array_class(hs.NewHandle(
741eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier      class_linker->FindSystemClass(self, "[Ljava/lang/Object;")));
74258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
743e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  // build an Object[] of all the DexCaches used in the source_space_.
744e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  // Since we can't hold the dex lock when allocating the dex_caches
745e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  // ObjectArray, we lock the dex lock twice, first to get the number
746e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  // of dex caches first and then lock it again to copy the dex
747e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  // caches. We check that the number of dex caches does not change.
748e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  size_t dex_cache_count;
749e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  {
750c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    ReaderMutexLock mu(self, *class_linker->DexLock());
751e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi    dex_cache_count = class_linker->GetDexCacheCount();
752e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  }
753eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<ObjectArray<Object>> dex_caches(
754eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier      hs.NewHandle(ObjectArray<Object>::Alloc(self, object_array_class.Get(),
755e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi                                              dex_cache_count)));
756e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  CHECK(dex_caches.Get() != nullptr) << "Failed to allocate a dex cache array.";
757e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi  {
758c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    ReaderMutexLock mu(self, *class_linker->DexLock());
759e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi    CHECK_EQ(dex_cache_count, class_linker->GetDexCacheCount())
760e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi        << "The number of dex caches changed.";
761e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi    for (size_t i = 0; i < dex_cache_count; ++i) {
762e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi      dex_caches->Set<false>(i, class_linker->GetDexCache(i));
763e9e3e697f0c426132bee10aaa6aee9107d2d7dc6Hiroshi Yamauchi    }
76458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
76558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
76658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  // build an Object[] of the roots needed to restore the runtime
7673d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto image_roots(hs.NewHandle(
768eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier      ObjectArray<Object>::Alloc(self, object_array_class.Get(), ImageHeader::kImageRootsMax)));
769eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  image_roots->Set<false>(ImageHeader::kDexCaches, dex_caches.Get());
770d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz  image_roots->Set<false>(ImageHeader::kClassRoots, class_linker->GetClassRoots());
771e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
7722cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier    CHECK(image_roots->Get(i) != nullptr);
773e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
774eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  return image_roots.Get();
775161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom}
776161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom
777590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier// Walk instance fields of the given Class. Separate function to allow recursion on the super
778590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier// class.
779590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartiervoid ImageWriter::WalkInstanceFields(mirror::Object* obj, mirror::Class* klass) {
780590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  // Visit fields of parent classes first.
781eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  StackHandleScope<1> hs(Thread::Current());
782eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<mirror::Class> h_class(hs.NewHandle(klass));
783eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  mirror::Class* super = h_class->GetSuperClass();
784590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  if (super != nullptr) {
785590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    WalkInstanceFields(obj, super);
786590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  }
787590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  //
788eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  size_t num_reference_fields = h_class->NumReferenceInstanceFields();
78976649e8d775519fe19f2b14d18ac488c13296054Vladimir Marko  MemberOffset field_offset = h_class->GetFirstReferenceInstanceFieldOffset();
790590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  for (size_t i = 0; i < num_reference_fields; ++i) {
791b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers    mirror::Object* value = obj->GetFieldObject<mirror::Object>(field_offset);
792590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    if (value != nullptr) {
793590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      WalkFieldsInOrder(value);
794590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    }
79576649e8d775519fe19f2b14d18ac488c13296054Vladimir Marko    field_offset = MemberOffset(field_offset.Uint32Value() +
79676649e8d775519fe19f2b14d18ac488c13296054Vladimir Marko                                sizeof(mirror::HeapReference<mirror::Object>));
797590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  }
798590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier}
799590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
800590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier// For an unvisited object, visit it then all its children found via fields.
801590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartiervoid ImageWriter::WalkFieldsInOrder(mirror::Object* obj) {
802f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // Use our own visitor routine (instead of GC visitor) to get better locality between
803f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // an object and its fields
804f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  if (!IsImageBinSlotAssigned(obj)) {
805590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    // Walk instance fields of all objects
806eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    StackHandleScope<2> hs(Thread::Current());
807eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::Object> h_obj(hs.NewHandle(obj));
808eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    Handle<mirror::Class> klass(hs.NewHandle(obj->GetClass()));
809590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    // visit the object itself.
810f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    CalculateObjectBinSlots(h_obj.Get());
811eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    WalkInstanceFields(h_obj.Get(), klass.Get());
812590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    // Walk static fields of a Class.
813eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    if (h_obj->IsClass()) {
814c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      size_t num_reference_static_fields = klass->NumReferenceStaticFields();
8153d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      MemberOffset field_offset = klass->GetFirstReferenceStaticFieldOffset(target_ptr_size_);
816c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      for (size_t i = 0; i < num_reference_static_fields; ++i) {
817eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier        mirror::Object* value = h_obj->GetFieldObject<mirror::Object>(field_offset);
818590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier        if (value != nullptr) {
819590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier          WalkFieldsInOrder(value);
820590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier        }
82176649e8d775519fe19f2b14d18ac488c13296054Vladimir Marko        field_offset = MemberOffset(field_offset.Uint32Value() +
82276649e8d775519fe19f2b14d18ac488c13296054Vladimir Marko                                    sizeof(mirror::HeapReference<mirror::Object>));
823590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      }
824c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      // Visit and assign offsets for fields.
8253d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto* as_klass = h_obj->AsClass();
8263d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      ArtField* fields[] = { as_klass->GetSFields(), as_klass->GetIFields() };
8273d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      size_t num_fields[] = { as_klass->NumStaticFields(), as_klass->NumInstanceFields() };
828c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      for (size_t i = 0; i < 2; ++i) {
829c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier        for (size_t j = 0; j < num_fields[i]; ++j) {
830c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier          auto* field = fields[i] + j;
8313d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          auto it = native_object_reloc_.find(field);
8323d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          CHECK(it == native_object_reloc_.end()) << "Field at index " << i << ":" << j
833c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier              << " already assigned " << PrettyField(field);
8343d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          native_object_reloc_.emplace(
8353d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier              field, NativeObjectReloc { bin_slot_sizes_[kBinArtField], kBinArtField });
836c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier          bin_slot_sizes_[kBinArtField] += sizeof(ArtField);
837c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier        }
838c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      }
8393d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      // Visit and assign offsets for methods.
8403d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      IterationRange<StrideIterator<ArtMethod>> method_arrays[] = {
8413d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          as_klass->GetDirectMethods(target_ptr_size_),
8423d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          as_klass->GetVirtualMethods(target_ptr_size_)
8433d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      };
8443d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      for (auto& array : method_arrays) {
8453d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        bool any_dirty = false;
8463d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        size_t count = 0;
8473d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        for (auto& m : array) {
8483d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          any_dirty = any_dirty || WillMethodBeDirty(&m);
8493d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          ++count;
8503d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        }
8513d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        for (auto& m : array) {
8523d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          AssignMethodOffset(&m, any_dirty ? kBinArtMethodDirty : kBinArtMethodClean);
8533d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        }
8543d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        (any_dirty ? dirty_methods_ : clean_methods_) += count;
8553d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      }
856eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier    } else if (h_obj->IsObjectArray()) {
857590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      // Walk elements of an object array.
858eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier      int32_t length = h_obj->AsObjectArray<mirror::Object>()->GetLength();
859590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      for (int32_t i = 0; i < length; i++) {
860eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier        mirror::ObjectArray<mirror::Object>* obj_array = h_obj->AsObjectArray<mirror::Object>();
861590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier        mirror::Object* value = obj_array->Get(i);
862590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier        if (value != nullptr) {
863590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier          WalkFieldsInOrder(value);
864590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier        }
865590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      }
866590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    }
867590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  }
868590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier}
869590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
8703d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartiervoid ImageWriter::AssignMethodOffset(ArtMethod* method, Bin bin) {
8713d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto it = native_object_reloc_.find(method);
8723d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  CHECK(it == native_object_reloc_.end()) << "Method " << method << " already assigned "
8733d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      << PrettyMethod(method);
8743d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  native_object_reloc_.emplace(method, NativeObjectReloc { bin_slot_sizes_[bin], bin });
8753d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  bin_slot_sizes_[bin] += ArtMethod::ObjectSize(target_ptr_size_);
8763d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier}
8773d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier
878590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartiervoid ImageWriter::WalkFieldsCallback(mirror::Object* obj, void* arg) {
879590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg);
880590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  DCHECK(writer != nullptr);
881590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  writer->WalkFieldsInOrder(obj);
882590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier}
883590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
884f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkinvoid ImageWriter::UnbinObjectsIntoOffsetCallback(mirror::Object* obj, void* arg) {
885f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg);
886f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK(writer != nullptr);
887f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  writer->UnbinObjectsIntoOffset(obj);
888f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin}
889f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
890f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkinvoid ImageWriter::UnbinObjectsIntoOffset(mirror::Object* obj) {
891f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  CHECK(obj != nullptr);
892f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
893f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // We know the bin slot, and the total bin sizes for all objects by now,
894f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // so calculate the object's final image offset.
895f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
896f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK(IsImageBinSlotAssigned(obj));
897f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  BinSlot bin_slot = GetImageBinSlot(obj);
898f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // Change the lockword from a bin slot into an offset
899f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  AssignImageOffset(obj, bin_slot);
900f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin}
901f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
902f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Markovoid ImageWriter::CalculateNewObjectOffsets() {
9033d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  Thread* const self = Thread::Current();
904eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  StackHandleScope<1> hs(self);
905eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier  Handle<ObjectArray<Object>> image_roots(hs.NewHandle(CreateImageRoots()));
906161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom
9073d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto* runtime = Runtime::Current();
9083d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto* heap = runtime->GetHeap();
90930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  DCHECK_EQ(0U, image_end_);
910a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom
91131e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier  // Leave space for the header, but do not write it yet, we need to
912161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  // know where image_roots is going to end up
913f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  image_end_ += RoundUp(sizeof(ImageHeader), kObjectAlignment);  // 64-bit-alignment
914a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom
9150c8c303c20cdaaf54d26e45cc17dc5afb820d8efHiroshi Yamauchi  image_objects_offset_begin_ = image_end_;
91620f85597828194c12be10d3a927999def066555eVladimir Marko  // Prepare bin slots for dex cache arrays.
91720f85597828194c12be10d3a927999def066555eVladimir Marko  PrepareDexCacheArraySlots();
9180c8c303c20cdaaf54d26e45cc17dc5afb820d8efHiroshi Yamauchi  // Clear any pre-existing monitors which may have been in the monitor words, assign bin slots.
9190c8c303c20cdaaf54d26e45cc17dc5afb820d8efHiroshi Yamauchi  heap->VisitObjects(WalkFieldsCallback, this);
9203d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Write the image runtime methods.
9213d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  image_methods_[ImageHeader::kResolutionMethod] = runtime->GetResolutionMethod();
9223d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  image_methods_[ImageHeader::kImtConflictMethod] = runtime->GetImtConflictMethod();
9233d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  image_methods_[ImageHeader::kImtUnimplementedMethod] = runtime->GetImtUnimplementedMethod();
9243d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  image_methods_[ImageHeader::kCalleeSaveMethod] = runtime->GetCalleeSaveMethod(Runtime::kSaveAll);
9253d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  image_methods_[ImageHeader::kRefsOnlySaveMethod] =
9263d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      runtime->GetCalleeSaveMethod(Runtime::kRefsOnly);
9273d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  image_methods_[ImageHeader::kRefsAndArgsSaveMethod] =
9283d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs);
9293d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  for (auto* m : image_methods_) {
9303d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    CHECK(m != nullptr);
9313d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    CHECK(m->IsRuntimeMethod());
9323d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    AssignMethodOffset(m, kBinArtMethodDirty);
9333d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  }
9343d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier
93520f85597828194c12be10d3a927999def066555eVladimir Marko  // Calculate cumulative bin slot sizes.
93620f85597828194c12be10d3a927999def066555eVladimir Marko  size_t previous_sizes = 0u;
93720f85597828194c12be10d3a927999def066555eVladimir Marko  for (size_t i = 0; i != kBinSize; ++i) {
93820f85597828194c12be10d3a927999def066555eVladimir Marko    bin_slot_previous_sizes_[i] = previous_sizes;
93920f85597828194c12be10d3a927999def066555eVladimir Marko    previous_sizes += bin_slot_sizes_[i];
94020f85597828194c12be10d3a927999def066555eVladimir Marko  }
94120f85597828194c12be10d3a927999def066555eVladimir Marko  DCHECK_EQ(previous_sizes, GetBinSizeSum());
942c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  DCHECK_EQ(image_end_, GetBinSizeSum(kBinMirrorCount) + image_objects_offset_begin_);
943c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier
9440c8c303c20cdaaf54d26e45cc17dc5afb820d8efHiroshi Yamauchi  // Transform each object's bin slot into an offset which will be used to do the final copy.
9450c8c303c20cdaaf54d26e45cc17dc5afb820d8efHiroshi Yamauchi  heap->VisitObjects(UnbinObjectsIntoOffsetCallback, this);
946a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom
947c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  DCHECK_EQ(image_end_, GetBinSizeSum(kBinMirrorCount) + image_objects_offset_begin_);
948f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
949f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  image_roots_address_ = PointerToLowMemUInt32(GetImageAddress(image_roots.Get()));
950f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko
9513d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Update the native relocations by adding their bin sums.
9523d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  for (auto& pair : native_object_reloc_) {
9533d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto& native_reloc = pair.second;
9543d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    native_reloc.offset += image_objects_offset_begin_ +
9553d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        bin_slot_previous_sizes_[native_reloc.bin_type];
9563d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  }
9573d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier
958fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  // Calculate how big the intern table will be after being serialized.
959fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  auto* const intern_table = Runtime::Current()->GetInternTable();
960fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  CHECK_EQ(intern_table->WeakSize(), 0u) << " should have strong interned all the strings";
961fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  intern_table_bytes_ = intern_table->WriteToMemory(nullptr);
962fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier
9633d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Note that image_end_ is left at end of used mirror object section.
964f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko}
965f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko
966f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Markovoid ImageWriter::CreateHeader(size_t oat_loaded_size, size_t oat_data_offset) {
967f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko  CHECK_NE(0U, oat_loaded_size);
96813735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* oat_file_begin = GetOatFileBegin();
96913735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* oat_file_end = oat_file_begin + oat_loaded_size;
970700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom  oat_data_begin_ = oat_file_begin + oat_data_offset;
97113735955f39b3b304c37d2b2840663c131262c18Ian Rogers  const uint8_t* oat_data_end = oat_data_begin_ + oat_file_->Size();
9723d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier
9733d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Create the image sections.
9743d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  ImageSection sections[ImageHeader::kSectionCount];
9753d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Objects section
9763d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto* objects_section = &sections[ImageHeader::kSectionObjects];
9773d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  *objects_section = ImageSection(0u, image_end_);
9783d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  size_t cur_pos = objects_section->End();
9793d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Add field section.
9803d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto* field_section = &sections[ImageHeader::kSectionArtFields];
9813d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  *field_section = ImageSection(cur_pos, bin_slot_sizes_[kBinArtField]);
9823d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  CHECK_EQ(image_objects_offset_begin_ + bin_slot_previous_sizes_[kBinArtField],
9833d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier           field_section->Offset());
9843d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  cur_pos = field_section->End();
9853d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Add method section.
9863d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto* methods_section = &sections[ImageHeader::kSectionArtMethods];
9873d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  *methods_section = ImageSection(cur_pos, bin_slot_sizes_[kBinArtMethodClean] +
9883d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                                  bin_slot_sizes_[kBinArtMethodDirty]);
9893d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  CHECK_EQ(image_objects_offset_begin_ + bin_slot_previous_sizes_[kBinArtMethodClean],
9903d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier           methods_section->Offset());
9913d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  cur_pos = methods_section->End();
992fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  // Calculate the size of the interned strings.
993fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  auto* interned_strings_section = &sections[ImageHeader::kSectionInternedStrings];
994fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  *interned_strings_section = ImageSection(cur_pos, intern_table_bytes_);
995fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  cur_pos = interned_strings_section->End();
9963d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Finally bitmap section.
997c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  const size_t bitmap_bytes = image_bitmap_->Size();
9983d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto* bitmap_section = &sections[ImageHeader::kSectionImageBitmap];
9993d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  *bitmap_section = ImageSection(RoundUp(cur_pos, kPageSize), RoundUp(bitmap_bytes, kPageSize));
10003d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  cur_pos = bitmap_section->End();
10013d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  if (kIsDebugBuild) {
10023d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    size_t idx = 0;
1003fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier    for (const ImageSection& section : sections) {
10043d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      LOG(INFO) << static_cast<ImageHeader::ImageSections>(idx) << " " << section;
10053d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      ++idx;
10063d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    }
10073d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    LOG(INFO) << "Methods: clean=" << clean_methods_ << " dirty=" << dirty_methods_;
10083d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  }
1009fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  const size_t image_end = static_cast<uint32_t>(interned_strings_section->End());
1010fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  CHECK_EQ(AlignUp(image_begin_ + image_end, kPageSize), oat_file_begin) <<
1011fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      "Oat file should be right after the image.";
10123d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Create the header.
10133d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  new (image_->Begin()) ImageHeader(
1014fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      PointerToLowMemUInt32(image_begin_), image_end,
1015fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      sections, image_roots_address_, oat_file_->GetOatHeader().GetChecksum(),
10163d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      PointerToLowMemUInt32(oat_file_begin), PointerToLowMemUInt32(oat_data_begin_),
10173d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      PointerToLowMemUInt32(oat_data_end), PointerToLowMemUInt32(oat_file_end), target_ptr_size_,
10183d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      compile_pic_);
10193d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier}
10203d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier
10213d21bdf8894e780d349c481e5c9e29fe1556051cMathieu ChartierArtMethod* ImageWriter::GetImageMethodAddress(ArtMethod* method) {
10223d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto it = native_object_reloc_.find(method);
10233d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  CHECK(it != native_object_reloc_.end()) << PrettyMethod(method) << " @ " << method;
10243d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  CHECK_GE(it->second.offset, image_end_) << "ArtMethods should be after Objects";
10253d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  return reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset);
1026db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
1027db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
1028fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartierclass FixupRootVisitor : public RootVisitor {
1029fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier public:
1030fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  explicit FixupRootVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {
1031fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  }
1032fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier
1033fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  void VisitRoots(mirror::Object*** roots, size_t count, const RootInfo& info ATTRIBUTE_UNUSED)
1034fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1035fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier    for (size_t i = 0; i < count; ++i) {
1036fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      *roots[i] = ImageAddress(*roots[i]);
1037fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier    }
1038fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  }
1039fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier
1040fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  void VisitRoots(mirror::CompressedReference<mirror::Object>** roots, size_t count,
1041fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier                  const RootInfo& info ATTRIBUTE_UNUSED)
1042fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      OVERRIDE SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1043fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier    for (size_t i = 0; i < count; ++i) {
1044fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      roots[i]->Assign(ImageAddress(roots[i]->AsMirrorPtr()));
1045fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier    }
1046fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  }
1047fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier
1048fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier private:
1049fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  ImageWriter* const image_writer_;
1050fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier
1051fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  mirror::Object* ImageAddress(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1052fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier    const size_t offset = image_writer_->GetImageOffset(obj);
1053fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier    auto* const dest = reinterpret_cast<Object*>(image_writer_->image_begin_ + offset);
1054fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier    VLOG(compiler) << "Update root from " << obj << " to " << dest;
1055fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier    return dest;
1056fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  }
1057fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier};
1058fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier
1059c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartiervoid ImageWriter::CopyAndFixupNativeData() {
10603d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Copy ArtFields and methods to their locations and update the array for convenience.
10613d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  for (auto& pair : native_object_reloc_) {
10623d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto& native_reloc = pair.second;
10633d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    if (native_reloc.bin_type == kBinArtField) {
10643d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto* dest = image_->Begin() + native_reloc.offset;
10653d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      DCHECK_GE(dest, image_->Begin() + image_end_);
10663d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      memcpy(dest, pair.first, sizeof(ArtField));
10673d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      reinterpret_cast<ArtField*>(dest)->SetDeclaringClass(
10683d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          GetImageAddress(reinterpret_cast<ArtField*>(pair.first)->GetDeclaringClass()));
10693d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    } else {
10703d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      CHECK(IsArtMethodBin(native_reloc.bin_type)) << native_reloc.bin_type;
10713d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto* dest = image_->Begin() + native_reloc.offset;
10723d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      DCHECK_GE(dest, image_->Begin() + image_end_);
10733d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      CopyAndFixupMethod(reinterpret_cast<ArtMethod*>(pair.first),
10743d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                         reinterpret_cast<ArtMethod*>(dest));
10753d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    }
10763d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  }
10773d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Fixup the image method roots.
10783d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
1079fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  const ImageSection& methods_section = image_header->GetMethodsSection();
10803d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  for (size_t i = 0; i < ImageHeader::kImageMethodsCount; ++i) {
10813d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto* m = image_methods_[i];
10823d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    CHECK(m != nullptr);
10833d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto it = native_object_reloc_.find(m);
10843d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    CHECK(it != native_object_reloc_.end()) << "No fowarding for " << PrettyMethod(m);
10853d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto& native_reloc = it->second;
10863d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    CHECK(methods_section.Contains(native_reloc.offset)) << native_reloc.offset << " not in "
10873d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        << methods_section;
10883d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    CHECK(IsArtMethodBin(native_reloc.bin_type)) << native_reloc.bin_type;
10893d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto* dest = reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset);
10903d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    image_header->SetImageMethod(static_cast<ImageHeader::ImageMethod>(i), dest);
1091c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  }
1092fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  // Write the intern table into the image.
1093fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  const ImageSection& intern_table_section = image_header->GetImageSection(
1094fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      ImageHeader::kSectionInternedStrings);
1095fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  InternTable* const intern_table = Runtime::Current()->GetInternTable();
1096fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  uint8_t* const memory_ptr = image_->Begin() + intern_table_section.Offset();
1097fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  const size_t intern_table_bytes = intern_table->WriteToMemory(memory_ptr);
1098fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  // Fixup the pointers in the newly written intern table to contain image addresses.
1099fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  InternTable temp_table;
1100fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  // Note that we require that ReadFromMemory does not make an internal copy of the elements so that
1101fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  // the VisitRoots() will update the memory directly rather than the copies.
1102fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  // This also relies on visit roots not doing any verification which could fail after we update
1103fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  // the roots to be the image addresses.
1104fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  temp_table.ReadFromMemory(memory_ptr);
1105fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  CHECK_EQ(temp_table.Size(), intern_table->Size());
1106fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  FixupRootVisitor visitor(this);
1107fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  temp_table.VisitRoots(&visitor, kVisitRootFlagAllRoots);
1108fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  CHECK_EQ(intern_table_bytes, intern_table_bytes_);
1109c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier}
1110c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier
1111fd04b6f89238af5da682805aa11899639fb4ee07Mathieu Chartiervoid ImageWriter::CopyAndFixupObjects() {
11121d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  gc::Heap* heap = Runtime::Current()->GetHeap();
1113590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  heap->VisitObjects(CopyAndFixupObjectsCallback, this);
1114590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  // Fix up the object previously had hash codes.
1115fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  for (const auto& hash_pair : saved_hashcode_map_) {
1116fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier    Object* const obj = hash_pair.first;
1117e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    DCHECK_EQ(obj->GetLockWord(false).ReadBarrierState(), 0U);
1118e15ea086439b41a805d164d2beb07b4ba96aaa97Hiroshi Yamauchi    obj->SetLockWord(LockWord::FromHashCode(hash_pair.second, 0U), false);
1119590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  }
1120fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  saved_hashcode_map_.clear();
1121db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
1122db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
1123590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartiervoid ImageWriter::CopyAndFixupObjectsCallback(Object* obj, void* arg) {
11244d7f61d44a732cfbc8573e5d93364983fd746888Mathieu Chartier  DCHECK(obj != nullptr);
11254d7f61d44a732cfbc8573e5d93364983fd746888Mathieu Chartier  DCHECK(arg != nullptr);
1126c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  reinterpret_cast<ImageWriter*>(arg)->CopyAndFixupObject(obj);
1127c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier}
1128c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier
11293d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartiervoid ImageWriter::FixupPointerArray(mirror::Object* dst, mirror::PointerArray* arr,
11303d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier                                    mirror::Class* klass, Bin array_type) {
11313d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  CHECK(klass->IsArrayClass());
11323d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  CHECK(arr->IsIntArray() || arr->IsLongArray()) << PrettyClass(klass) << " " << arr;
11333d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Fixup int and long pointers for the ArtMethod or ArtField arrays.
1134c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  const size_t num_elements = arr->GetLength();
11353d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  dst->SetClass(GetImageAddress(arr->GetClass()));
11363d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto* dest_array = down_cast<mirror::PointerArray*>(dst);
1137c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  for (size_t i = 0, count = num_elements; i < count; ++i) {
11383d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto* elem = arr->GetElementPtrSize<void*>(i, target_ptr_size_);
11393d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    if (elem != nullptr) {
11403d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto it = native_object_reloc_.find(elem);
11413d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      if (it == native_object_reloc_.end()) {
11423d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        if (IsArtMethodBin(array_type)) {
11433d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          auto* method = reinterpret_cast<ArtMethod*>(elem);
11443d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          LOG(FATAL) << "No relocation entry for ArtMethod " << PrettyMethod(method) << " @ "
11453d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier              << method << " idx=" << i << "/" << num_elements << " with declaring class "
11463d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier              << PrettyClass(method->GetDeclaringClass());
11473d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        } else {
11483d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          CHECK_EQ(array_type, kBinArtField);
11493d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          auto* field = reinterpret_cast<ArtField*>(elem);
11503d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          LOG(FATAL) << "No relocation entry for ArtField " << PrettyField(field) << " @ "
11513d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier              << field << " idx=" << i << "/" << num_elements << " with declaring class "
11523d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier              << PrettyClass(field->GetDeclaringClass());
11533d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        }
11543d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      } else {
11553d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        elem = image_begin_ + it->second.offset;
11563d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      }
1157c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    }
11583d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    dest_array->SetElementPtrSize<false, true>(i, elem, target_ptr_size_);
1159c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  }
1160c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier}
1161c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier
1162c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartiervoid ImageWriter::CopyAndFixupObject(Object* obj) {
1163c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  size_t offset = GetImageOffset(obj);
1164c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  auto* dst = reinterpret_cast<Object*>(image_->Begin() + offset);
1165fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  DCHECK_LT(offset, image_end_);
1166fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  const auto* src = reinterpret_cast<const uint8_t*>(obj);
1167fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier
1168fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  image_bitmap_->Set(dst);  // Mark the obj as live.
1169c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier
1170fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  const size_t n = obj->SizeOf();
1171c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  DCHECK_LE(offset + n, image_->Size());
1172db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  memcpy(dst, src, n);
1173c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier
1174ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier  // Write in a hash code of objects which have inflated monitors or a hash code in their monitor
1175ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier  // word.
1176fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  const auto it = saved_hashcode_map_.find(obj);
1177fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  dst->SetLockWord(it != saved_hashcode_map_.end() ?
1178fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      LockWord::FromHashCode(it->second, 0u) : LockWord::Default(), false);
1179c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  FixupObject(obj, dst);
1180db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
1181db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
1182f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin// Rewrite all the references in the copied object to point to their image address equivalent
1183b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartierclass FixupVisitor {
1184b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier public:
1185b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier  FixupVisitor(ImageWriter* image_writer, Object* copy) : image_writer_(image_writer), copy_(copy) {
1186b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier  }
1187b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier
1188fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  void operator()(Object* obj, MemberOffset offset, bool is_static ATTRIBUTE_UNUSED) const
1189b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
11906e83c172f385cb45dd13bbcf41d2df8e410828c6Hiroshi Yamauchi    Object* ref = obj->GetFieldObject<Object, kVerifyNone>(offset);
1191b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier    // Use SetFieldObjectWithoutWriteBarrier to avoid card marking since we are writing to the
1192b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier    // image.
1193b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier    copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(
1194b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers        offset, image_writer_->GetImageAddress(ref));
1195b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier  }
1196b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier
1197b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier  // java.lang.ref.Reference visitor.
1198fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  void operator()(mirror::Class* klass ATTRIBUTE_UNUSED, mirror::Reference* ref) const
1199b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
1200b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
1201b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier    copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(
1202b0fa5dc7769c1e054032f39de0a3f6d6dd06f8cfIan Rogers        mirror::Reference::ReferentOffset(), image_writer_->GetImageAddress(ref->GetReferent()));
1203b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier  }
1204b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier
120598d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang protected:
1206b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier  ImageWriter* const image_writer_;
1207b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier  mirror::Object* const copy_;
1208b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier};
1209b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier
121098d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yangclass FixupClassVisitor FINAL : public FixupVisitor {
121198d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang public:
121298d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  FixupClassVisitor(ImageWriter* image_writer, Object* copy) : FixupVisitor(image_writer, copy) {
121398d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  }
121498d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang
1215c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  void operator()(Object* obj, MemberOffset offset, bool is_static ATTRIBUTE_UNUSED) const
121698d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang      EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) {
121798d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    DCHECK(obj->IsClass());
1218f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    FixupVisitor::operator()(obj, offset, /*is_static*/false);
121998d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  }
122098d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang
12216a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers  void operator()(mirror::Class* klass ATTRIBUTE_UNUSED,
12226a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers                  mirror::Reference* ref ATTRIBUTE_UNUSED) const
122398d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
122498d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang      EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) {
122598d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    LOG(FATAL) << "Reference not expected here.";
122698d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  }
122798d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang};
122898d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang
1229c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartiervoid ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) {
1230c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  // Copy and fix up ArtFields in the class.
12313d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  ArtField* fields[2] = { orig->GetSFields(), orig->GetIFields() };
12323d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  size_t num_fields[2] = { orig->NumStaticFields(), orig->NumInstanceFields() };
12333d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Update the field arrays.
1234c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  for (size_t i = 0; i < 2; ++i) {
1235c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    if (num_fields[i] == 0) {
1236c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      CHECK(fields[i] == nullptr);
1237c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier      continue;
1238c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    }
12393d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto it = native_object_reloc_.find(fields[i]);
12403d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    CHECK(it != native_object_reloc_.end()) << PrettyClass(orig) << " : " << PrettyField(fields[i]);
12413d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto* image_fields = reinterpret_cast<ArtField*>(image_begin_ + it->second.offset);
1242c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    if (i == 0) {
12433d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      copy->SetSFieldsUnchecked(image_fields);
1244c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    } else {
12453d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      copy->SetIFieldsUnchecked(image_fields);
12463d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    }
12473d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  }
12483d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Update direct / virtual method arrays.
12493d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto* direct_methods = orig->GetDirectMethodsPtr();
12503d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  if (direct_methods != nullptr) {
12513d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto it = native_object_reloc_.find(direct_methods);
12523d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    CHECK(it != native_object_reloc_.end()) << PrettyClass(orig);
12533d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    copy->SetDirectMethodsPtrUnchecked(
12543d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset));
12553d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  }
12563d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto* virtual_methods = orig->GetVirtualMethodsPtr();
12573d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  if (virtual_methods != nullptr) {
12583d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto it = native_object_reloc_.find(virtual_methods);
12593d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    CHECK(it != native_object_reloc_.end()) << PrettyClass(orig);
12603d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    copy->SetVirtualMethodsPtr(
12613d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset));
12623d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  }
12633d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  // Fix up embedded tables.
12643d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  if (orig->ShouldHaveEmbeddedImtAndVTable()) {
12653d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    for (int32_t i = 0; i < orig->GetEmbeddedVTableLength(); ++i) {
12663d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto it = native_object_reloc_.find(orig->GetEmbeddedVTableEntry(i, target_ptr_size_));
12673d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      CHECK(it != native_object_reloc_.end()) << PrettyClass(orig);
12683d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      copy->SetEmbeddedVTableEntryUnchecked(
12693d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          i, reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset), target_ptr_size_);
12703d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    }
12713d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    for (size_t i = 0; i < mirror::Class::kImtSize; ++i) {
12723d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto it = native_object_reloc_.find(orig->GetEmbeddedImTableEntry(i, target_ptr_size_));
12733d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      CHECK(it != native_object_reloc_.end()) << PrettyClass(orig);
12743d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      copy->SetEmbeddedImTableEntry(
12753d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          i, reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset), target_ptr_size_);
1276c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    }
1277c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  }
1278c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  FixupClassVisitor visitor(this, copy);
1279c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  static_cast<mirror::Object*>(orig)->VisitReferences<true /*visit class*/>(visitor, visitor);
1280c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier}
1281c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier
1282ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersvoid ImageWriter::FixupObject(Object* orig, Object* copy) {
1283b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier  DCHECK(orig != nullptr);
1284b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier  DCHECK(copy != nullptr);
1285624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi  if (kUseBakerOrBrooksReadBarrier) {
1286624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi    orig->AssertReadBarrierPointer();
1287624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi    if (kUseBrooksReadBarrier) {
1288624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi      // Note the address 'copy' isn't the same as the image address of 'orig'.
1289624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi      copy->SetReadBarrierPointer(GetImageAddress(orig));
1290624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi      DCHECK_EQ(copy->GetReadBarrierPointer(), GetImageAddress(orig));
1291624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi    }
1292b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier  }
12933d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  auto* klass = orig->GetClass();
12943d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  if (klass->IsIntArrayClass() || klass->IsLongArrayClass()) {
12953d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    // Is this a native dex cache array?
12963d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    auto it = pointer_arrays_.find(down_cast<mirror::PointerArray*>(orig));
12973d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    if (it != pointer_arrays_.end()) {
12983d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      // Should only need to fixup every pointer array exactly once.
12993d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      FixupPointerArray(copy, down_cast<mirror::PointerArray*>(orig), klass, it->second);
13003d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      pointer_arrays_.erase(it);
13013d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      return;
13023d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    }
13033d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    CHECK(dex_cache_array_indexes_.find(orig) == dex_cache_array_indexes_.end())
13043d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        << "Should have been pointer array.";
13053d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  }
1306c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier  if (orig->IsClass()) {
1307c785344b87221f5e4e6473e5b762e4e61fe65dcfMathieu Chartier    FixupClass(orig->AsClass<kVerifyNone>(), down_cast<mirror::Class*>(copy));
130898d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  } else {
13093d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    if (klass == mirror::Method::StaticClass() || klass == mirror::Constructor::StaticClass()) {
13103d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      // Need to go update the ArtMethod.
13113d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto* dest = down_cast<mirror::AbstractMethod*>(copy);
13123d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto* src = down_cast<mirror::AbstractMethod*>(orig);
13133d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      ArtMethod* src_method = src->GetArtMethod();
13143d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto it = native_object_reloc_.find(src_method);
13153d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      CHECK(it != native_object_reloc_.end()) << "Missing relocation for AbstractMethod.artMethod "
13163d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          << PrettyMethod(src_method);
13173d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      dest->SetArtMethod(
13183d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier          reinterpret_cast<ArtMethod*>(image_begin_ + it->second.offset));
13193d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    }
132098d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    FixupVisitor visitor(this, copy);
132198d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    orig->VisitReferences<true /*visit class*/>(visitor, visitor);
132298d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  }
1323db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
1324db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
13253d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartierconst uint8_t* ImageWriter::GetQuickCode(ArtMethod* method, bool* quick_is_interpreted) {
132698d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  DCHECK(!method->IsResolutionMethod() && !method->IsImtConflictMethod() &&
13272d2621a1463d2f3f03fa73503fa42e43657cdcfcMathieu Chartier         !method->IsImtUnimplementedMethod() && !method->IsAbstract()) << PrettyMethod(method);
132898d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang
132998d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  // Use original code if it exists. Otherwise, set the code pointer to the resolution
133098d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  // trampoline.
133198d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang
133298d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  // Quick entrypoint:
1333c7d11887725e28db2796c848f4485e59d5eb690cJeff Hao  uint32_t quick_oat_code_offset = PointerToLowMemUInt32(
1334c7d11887725e28db2796c848f4485e59d5eb690cJeff Hao      method->GetEntryPointFromQuickCompiledCodePtrSize(target_ptr_size_));
1335c7d11887725e28db2796c848f4485e59d5eb690cJeff Hao  const uint8_t* quick_code = GetOatAddress(quick_oat_code_offset);
133698d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  *quick_is_interpreted = false;
13373d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  if (quick_code != nullptr && (!method->IsStatic() || method->IsConstructor() ||
13383d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      method->GetDeclaringClass()->IsInitialized())) {
133998d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    // We have code for a non-static or initialized method, just use the code.
13403d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    DCHECK_GE(quick_code, oat_data_begin_);
134198d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  } else if (quick_code == nullptr && method->IsNative() &&
134298d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang      (!method->IsStatic() || method->GetDeclaringClass()->IsInitialized())) {
134398d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    // Non-static or initialized native method missing compiled code, use generic JNI version.
134498d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    quick_code = GetOatAddress(quick_generic_jni_trampoline_offset_);
13453d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    DCHECK_GE(quick_code, oat_data_begin_);
134698d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  } else if (quick_code == nullptr && !method->IsNative()) {
134798d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    // We don't have code at all for a non-native method, use the interpreter.
134898d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    quick_code = GetOatAddress(quick_to_interpreter_bridge_offset_);
134998d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    *quick_is_interpreted = true;
13503d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    DCHECK_GE(quick_code, oat_data_begin_);
135198d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  } else {
135298d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    CHECK(!method->GetDeclaringClass()->IsInitialized());
135398d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    // We have code for a static method, but need to go through the resolution stub for class
135498d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    // initialization.
135598d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    quick_code = GetOatAddress(quick_resolution_trampoline_offset_);
13563d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    DCHECK_GE(quick_code, oat_data_begin_);
135798d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  }
135898d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  return quick_code;
135998d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang}
136098d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang
13613d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartierconst uint8_t* ImageWriter::GetQuickEntryPoint(ArtMethod* method) {
136298d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  // Calculate the quick entry point following the same logic as FixupMethod() below.
136398d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  // The resolution method has a special trampoline to call.
13642d2621a1463d2f3f03fa73503fa42e43657cdcfcMathieu Chartier  Runtime* runtime = Runtime::Current();
13652d2621a1463d2f3f03fa73503fa42e43657cdcfcMathieu Chartier  if (UNLIKELY(method == runtime->GetResolutionMethod())) {
136698d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    return GetOatAddress(quick_resolution_trampoline_offset_);
13672d2621a1463d2f3f03fa73503fa42e43657cdcfcMathieu Chartier  } else if (UNLIKELY(method == runtime->GetImtConflictMethod() ||
13682d2621a1463d2f3f03fa73503fa42e43657cdcfcMathieu Chartier                      method == runtime->GetImtUnimplementedMethod())) {
136998d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    return GetOatAddress(quick_imt_conflict_trampoline_offset_);
137098d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  } else {
137198d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    // We assume all methods have code. If they don't currently then we set them to the use the
137298d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    // resolution trampoline. Abstract methods never have code and so we need to make sure their
137398d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    // use results in an AbstractMethodError. We use the interpreter to achieve this.
137498d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    if (UNLIKELY(method->IsAbstract())) {
137598d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang      return GetOatAddress(quick_to_interpreter_bridge_offset_);
137698d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    } else {
137798d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang      bool quick_is_interpreted;
137898d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang      return GetQuickCode(method, &quick_is_interpreted);
137998d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    }
138098d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang  }
138198d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang}
138298d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang
13833d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartiervoid ImageWriter::CopyAndFixupMethod(ArtMethod* orig, ArtMethod* copy) {
13843d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  memcpy(copy, orig, ArtMethod::ObjectSize(target_ptr_size_));
13853d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier
13863d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  copy->SetDeclaringClass(GetImageAddress(orig->GetDeclaringClassUnchecked()));
13873d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  copy->SetDexCacheResolvedMethods(GetImageAddress(orig->GetDexCacheResolvedMethods()));
13883d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  copy->SetDexCacheResolvedTypes(GetImageAddress(orig->GetDexCacheResolvedTypes()));
13893d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier
1390848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  // OatWriter replaces the code_ with an offset value. Here we re-adjust to a pointer relative to
1391848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  // oat_begin_
13923320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
1393848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers  // The resolution method has a special trampoline to call.
13942d2621a1463d2f3f03fa73503fa42e43657cdcfcMathieu Chartier  Runtime* runtime = Runtime::Current();
13952d2621a1463d2f3f03fa73503fa42e43657cdcfcMathieu Chartier  if (UNLIKELY(orig == runtime->GetResolutionMethod())) {
13963d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    copy->SetEntryPointFromQuickCompiledCodePtrSize(
13972d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier        GetOatAddress(quick_resolution_trampoline_offset_), target_ptr_size_);
13982d2621a1463d2f3f03fa73503fa42e43657cdcfcMathieu Chartier  } else if (UNLIKELY(orig == runtime->GetImtConflictMethod() ||
13992d2621a1463d2f3f03fa73503fa42e43657cdcfcMathieu Chartier                      orig == runtime->GetImtUnimplementedMethod())) {
14003d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    copy->SetEntryPointFromQuickCompiledCodePtrSize(
14012d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier        GetOatAddress(quick_imt_conflict_trampoline_offset_), target_ptr_size_);
14023d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  } else if (UNLIKELY(orig->IsRuntimeMethod())) {
14033d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    bool found_one = false;
14043d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    for (size_t i = 0; i < static_cast<size_t>(Runtime::kLastCalleeSaveType); ++i) {
14053d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      auto idx = static_cast<Runtime::CalleeSaveType>(i);
14063d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      if (runtime->HasCalleeSaveMethod(idx) && runtime->GetCalleeSaveMethod(idx) == orig) {
14073d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        found_one = true;
14083d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        break;
14093d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      }
14103d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    }
14113d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    CHECK(found_one) << "Expected to find callee save method but got " << PrettyMethod(orig);
14123d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier    CHECK(copy->IsRuntimeMethod());
14130aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao  } else {
1414848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers    // We assume all methods have code. If they don't currently then we set them to the use the
1415848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers    // resolution trampoline. Abstract methods never have code and so we need to make sure their
1416848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers    // use results in an AbstractMethodError. We use the interpreter to achieve this.
1417848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers    if (UNLIKELY(orig->IsAbstract())) {
14183d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      copy->SetEntryPointFromQuickCompiledCodePtrSize(
14192d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier          GetOatAddress(quick_to_interpreter_bridge_offset_), target_ptr_size_);
14203d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      copy->SetEntryPointFromInterpreterPtrSize(
14212d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier          reinterpret_cast<EntryPointFromInterpreter*>(const_cast<uint8_t*>(
14222d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier                  GetOatAddress(interpreter_to_interpreter_bridge_offset_))), target_ptr_size_);
1423848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers    } else {
142498d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang      bool quick_is_interpreted;
142513735955f39b3b304c37d2b2840663c131262c18Ian Rogers      const uint8_t* quick_code = GetQuickCode(orig, &quick_is_interpreted);
14263d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      copy->SetEntryPointFromQuickCompiledCodePtrSize(quick_code, target_ptr_size_);
1427e1d07816510e0f6c9969cddd7d7b683698f93b26Sebastien Hertz
1428e1d07816510e0f6c9969cddd7d7b683698f93b26Sebastien Hertz      // JNI entrypoint:
1429848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers      if (orig->IsNative()) {
1430848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers        // The native method's pointer is set to a stub to lookup via dlsym.
1431848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers        // Note this is not the code_ pointer, that is handled above.
14323d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier        copy->SetEntryPointFromJniPtrSize(
14333d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier            GetOatAddress(jni_dlsym_lookup_offset_), target_ptr_size_);
1434848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers      }
1435e1d07816510e0f6c9969cddd7d7b683698f93b26Sebastien Hertz
1436e1d07816510e0f6c9969cddd7d7b683698f93b26Sebastien Hertz      // Interpreter entrypoint:
1437e1d07816510e0f6c9969cddd7d7b683698f93b26Sebastien Hertz      // Set the interpreter entrypoint depending on whether there is compiled code or not.
1438956af0f0cb05422e38c1d22cbef309d16b8a1a12Elliott Hughes      uint32_t interpreter_code = (quick_is_interpreted)
1439e1d07816510e0f6c9969cddd7d7b683698f93b26Sebastien Hertz          ? interpreter_to_interpreter_bridge_offset_
1440e1d07816510e0f6c9969cddd7d7b683698f93b26Sebastien Hertz          : interpreter_to_compiled_code_bridge_offset_;
14412d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier      EntryPointFromInterpreter* interpreter_entrypoint =
1442e1d07816510e0f6c9969cddd7d7b683698f93b26Sebastien Hertz          reinterpret_cast<EntryPointFromInterpreter*>(
14432d7210188805292e463be4bcf7a133b654d7e0eaMathieu Chartier              const_cast<uint8_t*>(GetOatAddress(interpreter_code)));
14443d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier      copy->SetEntryPointFromInterpreterPtrSize(interpreter_entrypoint, target_ptr_size_);
1445848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers    }
1446161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  }
1447a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom}
1448a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom
1449a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Lightstatic OatHeader* GetOatHeaderFromElf(ElfFile* elf) {
145062d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  uint64_t data_sec_offset;
145162d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  bool has_data_sec = elf->GetSectionOffsetAndSize(".rodata", &data_sec_offset, nullptr);
145262d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  if (!has_data_sec) {
1453a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    return nullptr;
1454a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  }
145562d1ca3182a6cbb921799825f43ad36821233fd7Tong Shen  return reinterpret_cast<OatHeader*>(elf->Begin() + data_sec_offset);
1456be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi}
1457be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi
1458f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Markovoid ImageWriter::SetOatChecksumFromElfFile(File* elf_file) {
1459a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  std::string error_msg;
1460a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  std::unique_ptr<ElfFile> elf(ElfFile::Open(elf_file, PROT_READ|PROT_WRITE,
1461a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light                                             MAP_SHARED, &error_msg));
1462a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  if (elf.get() == nullptr) {
1463f4da675bbc4615c5f854c81964cac9dd1153baeaVladimir Marko    LOG(FATAL) << "Unable open oat file: " << error_msg;
1464a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    return;
1465be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi  }
1466a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  OatHeader* oat_header = GetOatHeaderFromElf(elf.get());
1467a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK(oat_header != nullptr);
1468a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  CHECK(oat_header->IsValid());
1469be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi
1470a85b8376740641f13dc078aea6be94d15a800803Brian Carlstrom  ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
1471a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light  image_header->SetOatChecksum(oat_header->GetChecksum());
1472f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom}
1473f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom
1474f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkinsize_t ImageWriter::GetBinSizeSum(ImageWriter::Bin up_to) const {
1475f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK_LE(up_to, kBinSize);
1476f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  return std::accumulate(&bin_slot_sizes_[0], &bin_slot_sizes_[up_to], /*init*/0);
1477f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin}
1478f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
1479f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor MurashkinImageWriter::BinSlot::BinSlot(uint32_t lockword) : lockword_(lockword) {
1480f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  // These values may need to get updated if more bins are added to the enum Bin
14813d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  static_assert(kBinBits == 3, "wrong number of bin bits");
14823d21bdf8894e780d349c481e5c9e29fe1556051cMathieu Chartier  static_assert(kBinShift == 27, "wrong number of shift");
1483f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  static_assert(sizeof(BinSlot) == sizeof(LockWord), "BinSlot/LockWord must have equal sizes");
1484f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
1485f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK_LT(GetBin(), kBinSize);
1486f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK_ALIGNED(GetIndex(), kObjectAlignment);
1487f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin}
1488f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
1489f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor MurashkinImageWriter::BinSlot::BinSlot(Bin bin, uint32_t index)
1490f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin    : BinSlot(index | (static_cast<uint32_t>(bin) << kBinShift)) {
1491f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  DCHECK_EQ(index, GetIndex());
1492f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin}
1493f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
1494f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor MurashkinImageWriter::Bin ImageWriter::BinSlot::GetBin() const {
1495f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  return static_cast<Bin>((lockword_ & kBinMask) >> kBinShift);
1496f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin}
1497f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
1498f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkinuint32_t ImageWriter::BinSlot::GetIndex() const {
1499f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin  return lockword_ & ~kBinMask;
1500f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin}
1501f5b4c50f52d1bde054deee33a8ef6fa18a0eff33Igor Murashkin
1502fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartieruint8_t* ImageWriter::GetOatFileBegin() const {
1503fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  DCHECK_GT(intern_table_bytes_, 0u);
1504fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier  return image_begin_ + RoundUp(
1505fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      image_end_ + bin_slot_sizes_[kBinArtField] + bin_slot_sizes_[kBinArtMethodDirty] +
1506fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier      bin_slot_sizes_[kBinArtMethodClean] + intern_table_bytes_, kPageSize);
1507fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier}
1508fac3a390a247fe33d4873773d742aad4cc100118Mathieu Chartier
1509db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}  // namespace art
1510