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 = §ions[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 = §ions[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 = §ions[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 = §ions[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 = §ions[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