image_writer.cc revision 4d7f61d44a732cfbc8573e5d93364983fd746888
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 21db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include <vector> 22db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 2307ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h" 24761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h" 25a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom#include "class_linker.h" 26ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom#include "compiled_method.h" 274f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h" 287940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "driver/compiler_driver.h" 297940e44f4517de5e2634a7e07d58d0fb26160513Brian Carlstrom#include "elf_writer.h" 301d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/card_table-inl.h" 311d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/accounting/heap_bitmap.h" 3231e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier#include "gc/accounting/space_bitmap-inl.h" 331d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/heap.h" 341d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/large_object_space.h" 351d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space-inl.h" 36db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "globals.h" 374a289ed61242964b921434de7d375f46480472a1Brian Carlstrom#include "image.h" 38a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom#include "intern_table.h" 39ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier#include "lock_word.h" 40ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h" 41ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h" 422dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/array-inl.h" 432dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h" 442dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h" 4539ebcb800aabedd0ffa6aa4aeac8aa4194c66e61Ian Rogers#include "mirror/dex_cache-inl.h" 462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h" 472dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h" 48700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "oat.h" 490c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien#include "oat_file.h" 506d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h" 511f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "runtime.h" 5200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h" 53c645f1ddb7c40bea6a38eda4b3f83f6b6dec405bMathieu Chartier#include "sirt_ref-inl.h" 54a168c83a1d247094e9efb1244b0f73a5f1e1ed97Elliott Hughes#include "UniquePtr.h" 55db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "utils.h" 56db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 57ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromusing ::art::mirror::ArtField; 58ea46f950e7a51585db293cd7f047de190a482414Brian Carlstromusing ::art::mirror::ArtMethod; 593e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::Class; 603e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::DexCache; 613e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::EntryPointFromInterpreter; 623e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::Object; 633e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::ObjectArray; 643e3d591f781b771de89f3b989830da2b6ac6fac8Brian Carlstromusing ::art::mirror::String; 652dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers 66db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstromnamespace art { 67db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 68a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrombool ImageWriter::Write(const std::string& image_filename, 6930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers uintptr_t image_begin, 70ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom const std::string& oat_filename, 7196391606d8adfc661e1c21703ded1e7a39377a76Brian Carlstrom const std::string& oat_location) { 72a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom CHECK(!image_filename.empty()); 73aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 7430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers CHECK_NE(image_begin, 0U); 7530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers image_begin_ = reinterpret_cast<byte*>(image_begin); 7669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom 77ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 78ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 797571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom UniquePtr<File> oat_file(OS::OpenFileReadWrite(oat_filename.c_str())); 80700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom if (oat_file.get() == NULL) { 81700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom LOG(ERROR) << "Failed to open oat file " << oat_filename << " for " << oat_location; 82e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 83e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 848d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string error_msg; 858d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers oat_file_ = OatFile::OpenWritable(oat_file.get(), oat_location, &error_msg); 868d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (oat_file_ == nullptr) { 878d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers LOG(ERROR) << "Failed to open writable oat file " << oat_filename << " for " << oat_location 888d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers << ": " << error_msg; 89c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom return false; 90c50d8e11a098cc5c6239aa86b47d4fcf8cbb4899Brian Carlstrom } 918d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers CHECK_EQ(class_linker->RegisterOatFile(oat_file_), oat_file_); 92e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 93848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers interpreter_to_interpreter_bridge_offset_ = 94848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_file_->GetOatHeader().GetInterpreterToInterpreterBridgeOffset(); 95848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers interpreter_to_compiled_code_bridge_offset_ = 96848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_file_->GetOatHeader().GetInterpreterToCompiledCodeBridgeOffset(); 97848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 98848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers jni_dlsym_lookup_offset_ = oat_file_->GetOatHeader().GetJniDlsymLookupOffset(); 99848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 10088474b416eb257078e590bf9bc7957cee604a186Jeff Hao portable_imt_conflict_trampoline_offset_ = 10188474b416eb257078e590bf9bc7957cee604a186Jeff Hao oat_file_->GetOatHeader().GetPortableImtConflictTrampolineOffset(); 102848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers portable_resolution_trampoline_offset_ = 103848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_file_->GetOatHeader().GetPortableResolutionTrampolineOffset(); 104848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers portable_to_interpreter_bridge_offset_ = 105848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_file_->GetOatHeader().GetPortableToInterpreterBridgeOffset(); 106848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 1072da882315a61072664f7ce3c212307342e907207Andreas Gampe quick_generic_jni_trampoline_offset_ = 1082da882315a61072664f7ce3c212307342e907207Andreas Gampe oat_file_->GetOatHeader().GetQuickGenericJniTrampolineOffset(); 10988474b416eb257078e590bf9bc7957cee604a186Jeff Hao quick_imt_conflict_trampoline_offset_ = 11088474b416eb257078e590bf9bc7957cee604a186Jeff Hao oat_file_->GetOatHeader().GetQuickImtConflictTrampolineOffset(); 111848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers quick_resolution_trampoline_offset_ = 112848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_file_->GetOatHeader().GetQuickResolutionTrampolineOffset(); 113848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers quick_to_interpreter_bridge_offset_ = 114848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers oat_file_->GetOatHeader().GetQuickToInterpreterBridgeOffset(); 11500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 11600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers Thread::Current()->TransitionFromSuspendedToRunnable(); 11700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers PruneNonImageClasses(); // Remove junk 11800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ComputeLazyFieldsForImageClasses(); // Add useful information 11900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ComputeEagerResolvedStrings(); 12000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers Thread::Current()->TransitionFromRunnableToSuspended(kNative); 12100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 1221d54e73444e017d3a65234e0f193846f3e27472bIan Rogers gc::Heap* heap = Runtime::Current()->GetHeap(); 1231d54e73444e017d3a65234e0f193846f3e27472bIan Rogers heap->CollectGarbage(false); // Remove garbage. 124b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier 125ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (!AllocMemory()) { 126db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom return false; 127db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 128590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier 129590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (kIsDebugBuild) { 130357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier ScopedObjectAccess soa(Thread::Current()); 131357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier CheckNonImageClassesRemoved(); 132357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier } 133590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier 134e35517ad40e0713df8420aeb5d3540f146a59f62Mathieu Chartier Thread::Current()->TransitionFromSuspendedToRunnable(); 135700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom size_t oat_loaded_size = 0; 136700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom size_t oat_data_offset = 0; 13751c2467e8771b56e25ae4f17f66522f979f57a7eBrian Carlstrom ElfWriter::GetOatElfInformation(oat_file.get(), oat_loaded_size, oat_data_offset); 138700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom CalculateNewObjectOffsets(oat_loaded_size, oat_data_offset); 139e35517ad40e0713df8420aeb5d3540f146a59f62Mathieu Chartier CopyAndFixupObjects(); 14096391606d8adfc661e1c21703ded1e7a39377a76Brian Carlstrom PatchOatCodeAndMethods(); 141e35517ad40e0713df8420aeb5d3540f146a59f62Mathieu Chartier Thread::Current()->TransitionFromRunnableToSuspended(kNative); 142d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes 1437571e8b761ebc2c923525e12ea9fcf07e62cb33eBrian Carlstrom UniquePtr<File> image_file(OS::CreateEmptyFile(image_filename.c_str())); 14431e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin()); 145700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom if (image_file.get() == NULL) { 146e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom LOG(ERROR) << "Failed to open image file " << image_filename; 147db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom return false; 148db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 149700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom if (fchmod(image_file->Fd(), 0644) != 0) { 1506cd40e5cc59259a0b7636eb5532c76de9b8a7286Brian Carlstrom PLOG(ERROR) << "Failed to make image file world readable: " << image_filename; 1516cd40e5cc59259a0b7636eb5532c76de9b8a7286Brian Carlstrom return EXIT_FAILURE; 1526cd40e5cc59259a0b7636eb5532c76de9b8a7286Brian Carlstrom } 15331e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier 15431e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier // Write out the image. 15531e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier CHECK_EQ(image_end_, image_header->GetImageSize()); 15631e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier if (!image_file->WriteFully(image_->Begin(), image_end_)) { 15731e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier PLOG(ERROR) << "Failed to write image file " << image_filename; 15831e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier return false; 15931e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier } 16031e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier 16131e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier // Write out the image bitmap at the page aligned start of the image end. 16231e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier CHECK_ALIGNED(image_header->GetImageBitmapOffset(), kPageSize); 16331e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier if (!image_file->Write(reinterpret_cast<char*>(image_bitmap_->Begin()), 16431e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier image_header->GetImageBitmapSize(), 16531e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier image_header->GetImageBitmapOffset())) { 166e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to write image file " << image_filename; 167e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 168e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 16931e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier 170e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 171db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 172db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 173590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartiervoid ImageWriter::SetImageOffset(mirror::Object* object, size_t offset) { 174590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK(object != nullptr); 175590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK_NE(offset, 0U); 176590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK(!IsImageOffsetAssigned(object)); 177590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier mirror::Object* obj = reinterpret_cast<mirror::Object*>(image_->Begin() + offset); 178590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK_ALIGNED(obj, kObjectAlignment); 179590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier image_bitmap_->Set(obj); 180590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier // Before we stomp over the lock word, save the hash code for later. 181590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier Monitor::Deflate(Thread::Current(), object);; 1824d7f61d44a732cfbc8573e5d93364983fd746888Mathieu Chartier LockWord lw(object->GetLockWord(false)); 183590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier switch (lw.GetState()) { 184590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier case LockWord::kFatLocked: { 185590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier LOG(FATAL) << "Fat locked object " << obj << " found during object copy"; 186590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier break; 187590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 188590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier case LockWord::kThinLocked: { 189590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier LOG(FATAL) << "Thin locked object " << obj << " found during object copy"; 190590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier break; 191590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 192590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier case LockWord::kUnlocked: 193590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier // No hash, don't need to save it. 194590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier break; 195590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier case LockWord::kHashCode: 196590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier saved_hashes_.push_back(std::make_pair(obj, lw.GetHashCode())); 197590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier break; 198590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier default: 199590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier LOG(FATAL) << "Unreachable."; 200590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier break; 20131e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier } 2024d7f61d44a732cfbc8573e5d93364983fd746888Mathieu Chartier object->SetLockWord(LockWord::FromForwardingAddress(offset), false); 203590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK(IsImageOffsetAssigned(object)); 20431e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier} 20531e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier 206590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartiervoid ImageWriter::AssignImageOffset(mirror::Object* object) { 207590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK(object != nullptr); 208590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier SetImageOffset(object, image_end_); 209590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier image_end_ += RoundUp(object->SizeOf(), 8); // 64-bit alignment 210590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK_LT(image_end_, image_->Size()); 211590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier} 212b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier 213ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersbool ImageWriter::IsImageOffsetAssigned(mirror::Object* object) const { 214590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK(object != nullptr); 2154d7f61d44a732cfbc8573e5d93364983fd746888Mathieu Chartier return object->GetLockWord(false).GetState() == LockWord::kForwardingAddress; 216590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier} 217590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier 218ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogerssize_t ImageWriter::GetImageOffset(mirror::Object* object) const { 219590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK(object != nullptr); 220590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK(IsImageOffsetAssigned(object)); 2214d7f61d44a732cfbc8573e5d93364983fd746888Mathieu Chartier LockWord lock_word = object->GetLockWord(false); 222590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier size_t offset = lock_word.ForwardingAddress(); 223590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK_LT(offset, image_end_); 224590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier return offset; 225590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier} 226590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier 227590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartierbool ImageWriter::AllocMemory() { 228590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier size_t length = RoundUp(Runtime::Current()->GetHeap()->GetTotalMemory(), kPageSize); 2298d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers std::string error_msg; 230590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier image_.reset(MemMap::MapAnonymous("image writer image", NULL, length, PROT_READ | PROT_WRITE, 231ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers true, &error_msg)); 2328d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers if (UNLIKELY(image_.get() == nullptr)) { 2338d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers LOG(ERROR) << "Failed to allocate memory for image file generation: " << error_msg; 234db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom return false; 235db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 236590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier 237590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier // Create the image bitmap. 238a8e8f9c0a8e259a807d7b99a148d14104c24209dMathieu Chartier image_bitmap_.reset(gc::accounting::ContinuousSpaceBitmap::Create("image bitmap", image_->Begin(), 239a8e8f9c0a8e259a807d7b99a148d14104c24209dMathieu Chartier length)); 240590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (image_bitmap_.get() == nullptr) { 241590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier LOG(ERROR) << "Failed to allocate memory for image bitmap"; 242590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier return false; 243590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 244db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom return true; 245db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 246db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 247d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogersvoid ImageWriter::ComputeLazyFieldsForImageClasses() { 248590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 24900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers class_linker->VisitClassesWithoutClassesLock(ComputeLazyFieldsForClassesVisitor, NULL); 250d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers} 251d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers 2521bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesbool ImageWriter::ComputeLazyFieldsForClassesVisitor(Class* c, void* /*arg*/) { 2531bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes c->ComputeName(); 254d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers return true; 255d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers} 256d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers 257d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogersvoid ImageWriter::ComputeEagerResolvedStringsCallback(Object* obj, void* arg) { 258d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers if (!obj->GetClass()->IsStringClass()) { 259d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers return; 260d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers } 261590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier mirror::String* string = obj->AsString(); 262637c65b1e431fd90195b71c141b3590bd81cc91aIan Rogers const uint16_t* utf16_string = string->GetCharArray()->GetData() + string->GetOffset(); 263590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier for (DexCache* dex_cache : Runtime::Current()->GetClassLinker()->GetDexCaches()) { 2644445a7e3398a6143939168097a3aa275b734504dIan Rogers const DexFile& dex_file = *dex_cache->GetDexFile(); 26524c534d740fc50d5ed03538ec725144f44b4c0f7Ian Rogers const DexFile::StringId* string_id; 26624c534d740fc50d5ed03538ec725144f44b4c0f7Ian Rogers if (UNLIKELY(string->GetLength() == 0)) { 26724c534d740fc50d5ed03538ec725144f44b4c0f7Ian Rogers string_id = dex_file.FindStringId(""); 26824c534d740fc50d5ed03538ec725144f44b4c0f7Ian Rogers } else { 26924c534d740fc50d5ed03538ec725144f44b4c0f7Ian Rogers string_id = dex_file.FindStringId(utf16_string); 27024c534d740fc50d5ed03538ec725144f44b4c0f7Ian Rogers } 271590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (string_id != nullptr) { 272d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers // This string occurs in this dex file, assign the dex cache entry. 273d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers uint32_t string_idx = dex_file.GetIndexForStringId(*string_id); 274d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers if (dex_cache->GetResolvedString(string_idx) == NULL) { 275d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers dex_cache->SetResolvedString(string_idx, string); 276d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers } 277d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers } 278d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers } 279d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers} 280d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers 281590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartiervoid ImageWriter::ComputeEagerResolvedStrings() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 282590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); 283590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier Runtime::Current()->GetHeap()->VisitObjects(ComputeEagerResolvedStringsCallback, this); 284d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers} 285d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers 286ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersbool ImageWriter::IsImageClass(Class* klass) { 287dfb325e0ddd746cd8f7c2e3723b3a573eb7cc111Ian Rogers return compiler_driver_.IsImageClass(ClassHelper(klass).GetDescriptor()); 288ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom} 289ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 290ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromstruct NonImageClasses { 291ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom ImageWriter* image_writer; 292ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom std::set<std::string>* non_image_classes; 293ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}; 294ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 295ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid ImageWriter::PruneNonImageClasses() { 29696391606d8adfc661e1c21703ded1e7a39377a76Brian Carlstrom if (compiler_driver_.GetImageClasses() == NULL) { 297ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom return; 298ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 299ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom Runtime* runtime = Runtime::Current(); 300ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom ClassLinker* class_linker = runtime->GetClassLinker(); 301ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 3024b7b9896856171a623d95f86a2676c81c258f408Brian Carlstrom // Make a list of classes we would like to prune. 303ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom std::set<std::string> non_image_classes; 304ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom NonImageClasses context; 305ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom context.image_writer = this; 306ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom context.non_image_classes = &non_image_classes; 307ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom class_linker->VisitClasses(NonImageClassesVisitor, &context); 308ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 3094b7b9896856171a623d95f86a2676c81c258f408Brian Carlstrom // Remove the undesired classes from the class roots. 31002e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier for (const std::string& it : non_image_classes) { 31102e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier class_linker->RemoveClass(it.c_str(), NULL); 312ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 313ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 3144b7b9896856171a623d95f86a2676c81c258f408Brian Carlstrom // Clear references to removed classes from the DexCaches. 315ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom ArtMethod* resolution_method = runtime->GetResolutionMethod(); 316590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier for (DexCache* dex_cache : class_linker->GetDexCaches()) { 317ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) { 318ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom Class* klass = dex_cache->GetResolvedType(i); 319ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (klass != NULL && !IsImageClass(klass)) { 320ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom dex_cache->SetResolvedType(i, NULL); 321ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 322ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 323ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) { 324ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom ArtMethod* method = dex_cache->GetResolvedMethod(i); 325ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (method != NULL && !IsImageClass(method->GetDeclaringClass())) { 3261984651929744dd603fd082e23eacd877b9bc177Ian Rogers dex_cache->SetResolvedMethod(i, resolution_method); 327ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 328ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 329ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) { 330ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom ArtField* field = dex_cache->GetResolvedField(i); 331ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (field != NULL && !IsImageClass(field->GetDeclaringClass())) { 332ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom dex_cache->SetResolvedField(i, NULL); 333ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 334ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 335ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 336ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom} 337ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 338ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrombool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) { 339ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg); 340ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (!context->image_writer->IsImageClass(klass)) { 341dfb325e0ddd746cd8f7c2e3723b3a573eb7cc111Ian Rogers context->non_image_classes->insert(ClassHelper(klass).GetDescriptor()); 342ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 343ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom return true; 344ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom} 345ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 346357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartiervoid ImageWriter::CheckNonImageClassesRemoved() 347b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 348590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (compiler_driver_.GetImageClasses() != nullptr) { 349590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier gc::Heap* heap = Runtime::Current()->GetHeap(); 350590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_); 351590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier heap->VisitObjects(CheckNonImageClassesRemovedCallback, this); 352357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier } 353ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom} 354ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 355ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid ImageWriter::CheckNonImageClassesRemovedCallback(Object* obj, void* arg) { 356ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); 357590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (obj->IsClass()) { 358590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier Class* klass = obj->AsClass(); 359590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!image_writer->IsImageClass(klass)) { 360590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier image_writer->DumpImageClasses(); 361590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier CHECK(image_writer->IsImageClass(klass)) << ClassHelper(klass).GetDescriptor() 362590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier << " " << PrettyDescriptor(klass); 363590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 364c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes } 365c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes} 366c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes 367c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughesvoid ImageWriter::DumpImageClasses() { 36896391606d8adfc661e1c21703ded1e7a39377a76Brian Carlstrom CompilerDriver::DescriptorSet* image_classes = compiler_driver_.GetImageClasses(); 36996391606d8adfc661e1c21703ded1e7a39377a76Brian Carlstrom CHECK(image_classes != NULL); 37002e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier for (const std::string& image_class : *image_classes) { 37102e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier LOG(INFO) << " " << image_class; 372c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes } 373ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom} 374ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 375590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartiervoid ImageWriter::CalculateObjectOffsets(Object* obj) { 3764e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom DCHECK(obj != NULL); 377c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom // if it is a string, we want to intern it if its not interned. 378dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes if (obj->GetClass()->IsStringClass()) { 379c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom // we must be an interned string that was forward referenced and already assigned 380590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (IsImageOffsetAssigned(obj)) { 381c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom DCHECK_EQ(obj, obj->AsString()->Intern()); 382c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom return; 383c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom } 384590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier Thread* self = Thread::Current(); 385590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier SirtRef<Object> sirt_obj(self, obj); 386590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier mirror::String* interned = obj->AsString()->Intern(); 387590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (sirt_obj.get() != interned) { 388590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!IsImageOffsetAssigned(interned)) { 389c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom // interned obj is after us, allocate its location early 390590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier AssignImageOffset(interned); 391c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom } 392c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom // point those looking for this object to the interned version. 393590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier SetImageOffset(sirt_obj.get(), GetImageOffset(interned)); 394c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom return; 395c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom } 396c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom // else (obj == interned), nothing to do but fall through to the normal case 397c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom } 398c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom 399590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier AssignImageOffset(obj); 4004e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom} 4014e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom 402e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromObjectArray<Object>* ImageWriter::CreateImageRoots() const { 403161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom Runtime* runtime = Runtime::Current(); 404161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom ClassLinker* class_linker = runtime->GetClassLinker(); 40550b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers Thread* self = Thread::Current(); 4069837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers SirtRef<Class> object_array_class(self, class_linker->FindSystemClass(self, 4079837939678bb5dcba178e5fb00ed59b5d14c8d9bIan Rogers "[Ljava/lang/Object;")); 40858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom 40958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom // build an Object[] of all the DexCaches used in the source_space_ 410590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier ObjectArray<Object>* dex_caches = ObjectArray<Object>::Alloc(self, object_array_class.get(), 411590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier class_linker->GetDexCaches().size()); 412ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom int i = 0; 413590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier for (DexCache* dex_cache : class_linker->GetDexCaches()) { 414d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz dex_caches->Set<false>(i++, dex_cache); 41558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom } 41658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom 41758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom // build an Object[] of the roots needed to restore the runtime 418590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier SirtRef<ObjectArray<Object> > image_roots( 419590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier self, ObjectArray<Object>::Alloc(self, object_array_class.get(), ImageHeader::kImageRootsMax)); 420d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz image_roots->Set<false>(ImageHeader::kResolutionMethod, runtime->GetResolutionMethod()); 421d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz image_roots->Set<false>(ImageHeader::kImtConflictMethod, runtime->GetImtConflictMethod()); 422d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz image_roots->Set<false>(ImageHeader::kDefaultImt, runtime->GetDefaultImt()); 423d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz image_roots->Set<false>(ImageHeader::kCalleeSaveMethod, 424d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz runtime->GetCalleeSaveMethod(Runtime::kSaveAll)); 425d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz image_roots->Set<false>(ImageHeader::kRefsOnlySaveMethod, 426d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)); 427d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz image_roots->Set<false>(ImageHeader::kRefsAndArgsSaveMethod, 428d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)); 429d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz image_roots->Set<false>(ImageHeader::kDexCaches, dex_caches); 430d2fe10a3a34af171bf1631219cd2d6ff6b7778b5Sebastien Hertz image_roots->Set<false>(ImageHeader::kClassRoots, class_linker->GetClassRoots()); 431e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (int i = 0; i < ImageHeader::kImageRootsMax; i++) { 432e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(image_roots->Get(i) != NULL); 433e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 43440381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom return image_roots.get(); 435161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom} 436161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom 437590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier// Walk instance fields of the given Class. Separate function to allow recursion on the super 438590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier// class. 439590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartiervoid ImageWriter::WalkInstanceFields(mirror::Object* obj, mirror::Class* klass) { 440590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier // Visit fields of parent classes first. 441590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier SirtRef<mirror::Class> sirt_class(Thread::Current(), klass); 442590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier mirror::Class* super = sirt_class->GetSuperClass(); 443590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (super != nullptr) { 444590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier WalkInstanceFields(obj, super); 445590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 446590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier // 447590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier size_t num_reference_fields = sirt_class->NumReferenceInstanceFields(); 448590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier for (size_t i = 0; i < num_reference_fields; ++i) { 449590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier mirror::ArtField* field = sirt_class->GetInstanceField(i); 450590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier MemberOffset field_offset = field->GetOffset(); 451ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::Object* value = obj->GetFieldObject<mirror::Object>(field_offset, false); 452590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (value != nullptr) { 453590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier WalkFieldsInOrder(value); 454590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 455590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 456590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier} 457590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier 458590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier// For an unvisited object, visit it then all its children found via fields. 459590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartiervoid ImageWriter::WalkFieldsInOrder(mirror::Object* obj) { 460590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (!IsImageOffsetAssigned(obj)) { 461590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier // Walk instance fields of all objects 462590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier Thread* self = Thread::Current(); 463590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier SirtRef<mirror::Object> sirt_obj(self, obj); 464590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier SirtRef<mirror::Class> klass(self, obj->GetClass()); 465590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier // visit the object itself. 466590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier CalculateObjectOffsets(sirt_obj.get()); 467590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier WalkInstanceFields(sirt_obj.get(), klass.get()); 468590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier // Walk static fields of a Class. 469590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (sirt_obj->IsClass()) { 470590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier size_t num_static_fields = klass->NumReferenceStaticFields(); 471590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier for (size_t i = 0; i < num_static_fields; ++i) { 472590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier mirror::ArtField* field = klass->GetStaticField(i); 473590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier MemberOffset field_offset = field->GetOffset(); 474ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers mirror::Object* value = sirt_obj->GetFieldObject<mirror::Object>(field_offset, false); 475590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (value != nullptr) { 476590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier WalkFieldsInOrder(value); 477590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 478590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 479590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } else if (sirt_obj->IsObjectArray()) { 480590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier // Walk elements of an object array. 481590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier int32_t length = sirt_obj->AsObjectArray<mirror::Object>()->GetLength(); 482590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier for (int32_t i = 0; i < length; i++) { 483590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier mirror::ObjectArray<mirror::Object>* obj_array = sirt_obj->AsObjectArray<mirror::Object>(); 484590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier mirror::Object* value = obj_array->Get(i); 485590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (value != nullptr) { 486590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier WalkFieldsInOrder(value); 487590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 488590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 489590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 490590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 491590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier} 492590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier 493590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartiervoid ImageWriter::WalkFieldsCallback(mirror::Object* obj, void* arg) { 494590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg); 495590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK(writer != nullptr); 496590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier writer->WalkFieldsInOrder(obj); 497590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier} 498590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier 499700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstromvoid ImageWriter::CalculateNewObjectOffsets(size_t oat_loaded_size, size_t oat_data_offset) { 500700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom CHECK_NE(0U, oat_loaded_size); 5011f5393447b9f45be7918042d9ee7b521376de866Ian Rogers Thread* self = Thread::Current(); 5021f5393447b9f45be7918042d9ee7b521376de866Ian Rogers SirtRef<ObjectArray<Object> > image_roots(self, CreateImageRoots()); 503161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom 5041d54e73444e017d3a65234e0f193846f3e27472bIan Rogers gc::Heap* heap = Runtime::Current()->GetHeap(); 50530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers DCHECK_EQ(0U, image_end_); 506a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom 50731e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier // Leave space for the header, but do not write it yet, we need to 508161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom // know where image_roots is going to end up 5097934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom image_end_ += RoundUp(sizeof(ImageHeader), 8); // 64-bit-alignment 510a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom 511357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier { 512e35517ad40e0713df8420aeb5d3540f146a59f62Mathieu Chartier WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); 51366f19258f9728d4ffe026074d8fd429d639802faMathieu Chartier // TODO: Image spaces only? 5141f5393447b9f45be7918042d9ee7b521376de866Ian Rogers const char* old = self->StartAssertNoThreadSuspension("ImageWriter"); 515590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier DCHECK_LT(image_end_, image_->Size()); 516590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier // Clear any pre-existing monitors which may have been in the monitor words. 517590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier heap->VisitObjects(WalkFieldsCallback, this); 5181f5393447b9f45be7918042d9ee7b521376de866Ian Rogers self->EndAssertNoThreadSuspension(old); 519b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier } 520a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom 521700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom const byte* oat_file_begin = image_begin_ + RoundUp(image_end_, kPageSize); 522700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom const byte* oat_file_end = oat_file_begin + oat_loaded_size; 523700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom oat_data_begin_ = oat_file_begin + oat_data_offset; 524700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom const byte* oat_data_end = oat_data_begin_ + oat_file_->Size(); 525e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 52631e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier // Return to write header at start of image with future location of image_roots. At this point, 52731e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier // image_end_ is the size of the image (excluding bitmaps). 528a8e8f9c0a8e259a807d7b99a148d14104c24209dMathieu Chartier const size_t heap_bytes_per_bitmap_byte = kBitsPerByte * kObjectAlignment; 52912aeccd09a87be7a0b995182151d778cfeb50e73Mathieu Chartier const size_t bitmap_bytes = RoundUp(image_end_, heap_bytes_per_bitmap_byte) / 53012aeccd09a87be7a0b995182151d778cfeb50e73Mathieu Chartier heap_bytes_per_bitmap_byte; 531ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers ImageHeader image_header(PointerToLowMemUInt32(image_begin_), 53231e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier static_cast<uint32_t>(image_end_), 53331e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier RoundUp(image_end_, kPageSize), 53412aeccd09a87be7a0b995182151d778cfeb50e73Mathieu Chartier RoundUp(bitmap_bytes, kPageSize), 535ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers PointerToLowMemUInt32(GetImageAddress(image_roots.get())), 536e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_file_->GetOatHeader().GetChecksum(), 537ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers PointerToLowMemUInt32(oat_file_begin), 538ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers PointerToLowMemUInt32(oat_data_begin_), 539ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers PointerToLowMemUInt32(oat_data_end), 540ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers PointerToLowMemUInt32(oat_file_end)); 54130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers memcpy(image_->Begin(), &image_header, sizeof(image_header)); 542700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom 543700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom // Note that image_end_ is left at end of used space 544db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 545db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 546357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartiervoid ImageWriter::CopyAndFixupObjects() 547b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 54850b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers Thread* self = Thread::Current(); 54950b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter"); 5501d54e73444e017d3a65234e0f193846f3e27472bIan Rogers gc::Heap* heap = Runtime::Current()->GetHeap(); 5510cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers // TODO: heap validation can't handle this fix up pass 552b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes heap->DisableObjectValidation(); 553b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier // TODO: Image spaces only? 554e35517ad40e0713df8420aeb5d3540f146a59f62Mathieu Chartier WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); 555590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier heap->VisitObjects(CopyAndFixupObjectsCallback, this); 556590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier // Fix up the object previously had hash codes. 557590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier for (const std::pair<mirror::Object*, uint32_t>& hash_pair : saved_hashes_) { 5584d7f61d44a732cfbc8573e5d93364983fd746888Mathieu Chartier hash_pair.first->SetLockWord(LockWord::FromHashCode(hash_pair.second), false); 559590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 560590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier saved_hashes_.clear(); 56150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers self->EndAssertNoThreadSuspension(old_cause); 562db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 563db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 564590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartiervoid ImageWriter::CopyAndFixupObjectsCallback(Object* obj, void* arg) { 5654d7f61d44a732cfbc8573e5d93364983fd746888Mathieu Chartier DCHECK(obj != nullptr); 5664d7f61d44a732cfbc8573e5d93364983fd746888Mathieu Chartier DCHECK(arg != nullptr); 567db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); 56869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom // see GetLocalAddress for similar computation 569db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom size_t offset = image_writer->GetImageOffset(obj); 57030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers byte* dst = image_writer->image_->Begin() + offset; 5714873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom const byte* src = reinterpret_cast<const byte*>(obj); 57204b63fd60de0d9e6f07763511a1a9622accfeed7Elliott Hughes size_t n = obj->SizeOf(); 57330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers DCHECK_LT(offset + n, image_writer->image_->Size()); 574db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom memcpy(dst, src, n); 575db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom Object* copy = reinterpret_cast<Object*>(dst); 576ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier // Write in a hash code of objects which have inflated monitors or a hash code in their monitor 577ad2541a59c00c2c69e8973088891a2b5257c9780Mathieu Chartier // word. 5784d7f61d44a732cfbc8573e5d93364983fd746888Mathieu Chartier copy->SetLockWord(LockWord(), false); 579db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom image_writer->FixupObject(obj, copy); 580db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 581db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 582b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartierclass FixupVisitor { 583b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier public: 584b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier FixupVisitor(ImageWriter* image_writer, Object* copy) : image_writer_(image_writer), copy_(copy) { 585b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier } 586b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier 587b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier void operator()(Object* obj, MemberOffset offset, bool /*is_static*/) const 588b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier EXCLUSIVE_LOCKS_REQUIRED(Locks::mutator_lock_, Locks::heap_bitmap_lock_) { 589b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier Object* ref = obj->GetFieldObject<Object, kVerifyNone>(offset, false); 590b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier // Use SetFieldObjectWithoutWriteBarrier to avoid card marking since we are writing to the 591b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier // image. 592b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>( 593b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier offset, image_writer_->GetImageAddress(ref), false); 594b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier } 595b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier 596b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier // java.lang.ref.Reference visitor. 597b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier void operator()(mirror::Class* /*klass*/, mirror::Reference* ref) const 598b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 599b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier EXCLUSIVE_LOCKS_REQUIRED(Locks::heap_bitmap_lock_) { 600b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier copy_->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>( 601b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier mirror::Reference::ReferentOffset(), image_writer_->GetImageAddress(ref->GetReferent()), 602b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier false); 603b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier } 604b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier 605b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier private: 606b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier ImageWriter* const image_writer_; 607b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier mirror::Object* const copy_; 608b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier}; 609b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier 610ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersvoid ImageWriter::FixupObject(Object* orig, Object* copy) { 611b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier DCHECK(orig != nullptr); 612b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier DCHECK(copy != nullptr); 613624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi if (kUseBakerOrBrooksReadBarrier) { 614624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi orig->AssertReadBarrierPointer(); 615624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi if (kUseBrooksReadBarrier) { 616624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi // Note the address 'copy' isn't the same as the image address of 'orig'. 617624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi copy->SetReadBarrierPointer(GetImageAddress(orig)); 618624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi DCHECK_EQ(copy->GetReadBarrierPointer(), GetImageAddress(orig)); 619624468cd401cc1ac0dd70c746301e0788a597759Hiroshi Yamauchi } 620b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier } 621b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier FixupVisitor visitor(this, copy); 622b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier orig->VisitReferences<true /*visit class*/>(visitor, visitor); 623b7ea3acf7b83975a9effadb350c0b62ce4ab2142Mathieu Chartier if (orig->IsArtMethod<kVerifyNone>()) { 6244e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier FixupMethod(orig->AsArtMethod<kVerifyNone>(), down_cast<ArtMethod*>(copy)); 625db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 626db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 627db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 628ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogersvoid ImageWriter::FixupMethod(ArtMethod* orig, ArtMethod* copy) { 629848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // OatWriter replaces the code_ with an offset value. Here we re-adjust to a pointer relative to 630848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // oat_begin_ 6313320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 632848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // The resolution method has a special trampoline to call. 633848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers if (UNLIKELY(orig == Runtime::Current()->GetResolutionMethod())) { 6344e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetEntryPointFromPortableCompiledCode<kVerifyNone>(GetOatAddress(portable_resolution_trampoline_offset_)); 6354e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_resolution_trampoline_offset_)); 63688474b416eb257078e590bf9bc7957cee604a186Jeff Hao } else if (UNLIKELY(orig == Runtime::Current()->GetImtConflictMethod())) { 6374e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetEntryPointFromPortableCompiledCode<kVerifyNone>(GetOatAddress(portable_imt_conflict_trampoline_offset_)); 6384e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_imt_conflict_trampoline_offset_)); 6390aba0ba155bef7346bde19e53581200b89ae8a7aJeff Hao } else { 640848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // We assume all methods have code. If they don't currently then we set them to the use the 641848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // resolution trampoline. Abstract methods never have code and so we need to make sure their 642848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // use results in an AbstractMethodError. We use the interpreter to achieve this. 643848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers if (UNLIKELY(orig->IsAbstract())) { 6444e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetEntryPointFromPortableCompiledCode<kVerifyNone>(GetOatAddress(portable_to_interpreter_bridge_offset_)); 6454e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_to_interpreter_bridge_offset_)); 6464e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetEntryPointFromInterpreter<kVerifyNone>(reinterpret_cast<EntryPointFromInterpreter*> 647ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers (const_cast<byte*>(GetOatAddress(interpreter_to_interpreter_bridge_offset_)))); 648848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } else { 6494e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetEntryPointFromInterpreter<kVerifyNone>(reinterpret_cast<EntryPointFromInterpreter*> 650ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers (const_cast<byte*>(GetOatAddress(interpreter_to_compiled_code_bridge_offset_)))); 651848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Use original code if it exists. Otherwise, set the code pointer to the resolution 652848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // trampoline. 653ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const byte* quick_code = GetOatAddress(orig->GetQuickOatCodeOffset()); 6542ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom if (quick_code != nullptr && 6552ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom (!orig->IsStatic() || orig->IsConstructor() || orig->GetDeclaringClass()->IsInitialized())) { 6562ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom // We have code for a non-static or initialized method, just use the code. 6574e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(quick_code); 6581a5706611bffa5d6ed6843ee5e320f504590e097Ian Rogers } else if (quick_code == nullptr && orig->IsNative() && 6591a5706611bffa5d6ed6843ee5e320f504590e097Ian Rogers (!orig->IsStatic() || orig->GetDeclaringClass()->IsInitialized())) { 6601a5706611bffa5d6ed6843ee5e320f504590e097Ian Rogers // Non-static or initialized native method missing compiled code, use generic JNI version. 6612ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_generic_jni_trampoline_offset_)); 6622ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom } else if (quick_code == nullptr && !orig->IsNative()) { 6632ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom // We don't have code at all for a non-native method, use the interpreter. 6642ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_to_interpreter_bridge_offset_)); 665848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } else { 6661a5706611bffa5d6ed6843ee5e320f504590e097Ian Rogers CHECK(!orig->GetDeclaringClass()->IsInitialized()); 6671a5706611bffa5d6ed6843ee5e320f504590e097Ian Rogers // We have code for a static method, but need to go through the resolution stub for class 6681a5706611bffa5d6ed6843ee5e320f504590e097Ian Rogers // initialization. 6692ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom copy->SetEntryPointFromQuickCompiledCode<kVerifyNone>(GetOatAddress(quick_resolution_trampoline_offset_)); 670ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } 671ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const byte* portable_code = GetOatAddress(orig->GetPortableOatCodeOffset()); 672ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers if (portable_code != nullptr) { 6734e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetEntryPointFromPortableCompiledCode<kVerifyNone>(portable_code); 674ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers } else { 6754e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetEntryPointFromPortableCompiledCode<kVerifyNone>(GetOatAddress(portable_resolution_trampoline_offset_)); 676848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 677848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers if (orig->IsNative()) { 678848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // The native method's pointer is set to a stub to lookup via dlsym. 679848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Note this is not the code_ pointer, that is handled above. 6804e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetNativeMethod<kVerifyNone>(GetOatAddress(jni_dlsym_lookup_offset_)); 681848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } else { 682848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers // Normal (non-abstract non-native) methods have various tables to relocate. 683848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers uint32_t mapping_table_off = orig->GetOatMappingTableOffset(); 684848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers const byte* mapping_table = GetOatAddress(mapping_table_off); 6854e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetMappingTable<kVerifyNone>(mapping_table); 686848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 687848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers uint32_t vmap_table_offset = orig->GetOatVmapTableOffset(); 688848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers const byte* vmap_table = GetOatAddress(vmap_table_offset); 6894e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetVmapTable<kVerifyNone>(vmap_table); 690848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers 691848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers uint32_t native_gc_map_offset = orig->GetOatNativeGcMapOffset(); 692848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers const byte* native_gc_map = GetOatAddress(native_gc_map_offset); 6934e30541a92381fb280cd0be9a1763b713ee4d64cMathieu Chartier copy->SetNativeGcMap<kVerifyNone>(reinterpret_cast<const uint8_t*>(native_gc_map)); 694848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 695848871b4d8481229c32e0d048a9856e5a9a17ef9Ian Rogers } 696161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom } 697a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom} 698a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom 699be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchistatic ArtMethod* GetTargetMethod(const CompilerDriver::CallPatchInformation* patch) 700b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 701f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 702590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier Thread* self = Thread::Current(); 70349161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao SirtRef<mirror::DexCache> dex_cache(self, class_linker->FindDexCache(*patch->GetTargetDexFile())); 704590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier SirtRef<mirror::ClassLoader> class_loader(self, nullptr); 70549161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao ArtMethod* method = class_linker->ResolveMethod(*patch->GetTargetDexFile(), 706ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom patch->GetTargetMethodIdx(), 707ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom dex_cache, 708590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier class_loader, 709ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom NULL, 710ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom patch->GetTargetInvokeType()); 711f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom CHECK(method != NULL) 71249161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao << patch->GetTargetDexFile()->GetLocation() << " " << patch->GetTargetMethodIdx(); 7130637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom CHECK(!method->IsRuntimeMethod()) 71449161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao << patch->GetTargetDexFile()->GetLocation() << " " << patch->GetTargetMethodIdx(); 71500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers CHECK(dex_cache->GetResolvedMethods()->Get(patch->GetTargetMethodIdx()) == method) 71649161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao << patch->GetTargetDexFile()->GetLocation() << " " << patch->GetReferrerMethodIdx() << " " 71700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers << PrettyMethod(dex_cache->GetResolvedMethods()->Get(patch->GetTargetMethodIdx())) << " " 7180637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom << PrettyMethod(method); 719f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom return method; 720f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom} 721f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom 722be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchistatic Class* GetTargetType(const CompilerDriver::TypePatchInformation* patch) 723be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 724be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 725be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi Thread* self = Thread::Current(); 726be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi SirtRef<mirror::DexCache> dex_cache(self, class_linker->FindDexCache(patch->GetDexFile())); 727be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi SirtRef<mirror::ClassLoader> class_loader(self, nullptr); 728be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi Class* klass = class_linker->ResolveType(patch->GetDexFile(), 729be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi patch->GetTargetTypeIdx(), 730be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi dex_cache, 731be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi class_loader); 732be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi CHECK(klass != NULL) 733be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi << patch->GetDexFile().GetLocation() << " " << patch->GetTargetTypeIdx(); 734be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi CHECK(dex_cache->GetResolvedTypes()->Get(patch->GetTargetTypeIdx()) == klass) 735be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx() << " " 736be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi << PrettyClass(dex_cache->GetResolvedTypes()->Get(patch->GetTargetTypeIdx())) << " " 737be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi << PrettyClass(klass); 738be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi return klass; 739be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi} 740be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi 74196391606d8adfc661e1c21703ded1e7a39377a76Brian Carlstromvoid ImageWriter::PatchOatCodeAndMethods() { 742e35517ad40e0713df8420aeb5d3540f146a59f62Mathieu Chartier Thread* self = Thread::Current(); 743f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 744e35517ad40e0713df8420aeb5d3540f146a59f62Mathieu Chartier const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter"); 745f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom 746be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi typedef std::vector<const CompilerDriver::CallPatchInformation*> CallPatches; 747be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi const CallPatches& code_to_patch = compiler_driver_.GetCodeToPatch(); 748f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom for (size_t i = 0; i < code_to_patch.size(); i++) { 749be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi const CompilerDriver::CallPatchInformation* patch = code_to_patch[i]; 750ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom ArtMethod* target = GetTargetMethod(patch); 751ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uintptr_t quick_code = reinterpret_cast<uintptr_t>(class_linker->GetQuickOatCodeFor(target)); 752ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uintptr_t code_base = reinterpret_cast<uintptr_t>(&oat_file_->GetOatHeader()); 753ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uintptr_t code_offset = quick_code - code_base; 75455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell if (patch->IsRelative()) { 75555d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell // value to patch is relative to the location being patched 75655d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell const void* quick_oat_code = 75755d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell class_linker->GetQuickOatCodeFor(patch->GetDexFile(), 75855d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell patch->GetReferrerClassDefIdx(), 75955d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell patch->GetReferrerMethodIdx()); 76055d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell uintptr_t base = reinterpret_cast<uintptr_t>(quick_oat_code); 76155d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell uintptr_t patch_location = base + patch->GetLiteralOffset(); 76255d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell uintptr_t value = quick_code - patch_location + patch->RelativeOffset(); 76355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell SetPatchLocation(patch, value); 76455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } else { 7655e754d88c73f1f1fafbbf87d564df000d5a0a12cBrian Carlstrom if (quick_code == reinterpret_cast<uintptr_t>(GetQuickToInterpreterBridge())) { 7665e754d88c73f1f1fafbbf87d564df000d5a0a12cBrian Carlstrom if (target->IsNative()) { 7675e754d88c73f1f1fafbbf87d564df000d5a0a12cBrian Carlstrom // generic JNI, not interpreter bridge from GetQuickOatCodeFor(). 7685e754d88c73f1f1fafbbf87d564df000d5a0a12cBrian Carlstrom code_offset = quick_generic_jni_trampoline_offset_; 7695e754d88c73f1f1fafbbf87d564df000d5a0a12cBrian Carlstrom } else { 7705e754d88c73f1f1fafbbf87d564df000d5a0a12cBrian Carlstrom code_offset = quick_to_interpreter_bridge_offset_; 7715e754d88c73f1f1fafbbf87d564df000d5a0a12cBrian Carlstrom } 7722da882315a61072664f7ce3c212307342e907207Andreas Gampe } 77355d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell SetPatchLocation(patch, PointerToLowMemUInt32(GetOatAddress(code_offset))); 77455d0eac918321e0525f6e6491f36a80977e0d416Mark Mendell } 775f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom } 776f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom 777be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi const CallPatches& methods_to_patch = compiler_driver_.GetMethodsToPatch(); 778f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom for (size_t i = 0; i < methods_to_patch.size(); i++) { 779be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi const CompilerDriver::CallPatchInformation* patch = methods_to_patch[i]; 780ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom ArtMethod* target = GetTargetMethod(patch); 781ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers SetPatchLocation(patch, PointerToLowMemUInt32(GetImageAddress(target))); 782f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom } 783a85b8376740641f13dc078aea6be94d15a800803Brian Carlstrom 784be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi const std::vector<const CompilerDriver::TypePatchInformation*>& classes_to_patch = 785be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi compiler_driver_.GetClassesToPatch(); 786be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi for (size_t i = 0; i < classes_to_patch.size(); i++) { 787be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi const CompilerDriver::TypePatchInformation* patch = classes_to_patch[i]; 788be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi Class* target = GetTargetType(patch); 789ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers SetPatchLocation(patch, PointerToLowMemUInt32(GetImageAddress(target))); 790be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi } 791be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi 792a85b8376740641f13dc078aea6be94d15a800803Brian Carlstrom // Update the image header with the new checksum after patching 793a85b8376740641f13dc078aea6be94d15a800803Brian Carlstrom ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin()); 794a85b8376740641f13dc078aea6be94d15a800803Brian Carlstrom image_header->SetOatChecksum(oat_file_->GetOatHeader().GetChecksum()); 795e35517ad40e0713df8420aeb5d3540f146a59f62Mathieu Chartier self->EndAssertNoThreadSuspension(old_cause); 796f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom} 797f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom 7981212a022fa5f8ef9585d765b1809521812af882cIan Rogersvoid ImageWriter::SetPatchLocation(const CompilerDriver::PatchInformation* patch, uint32_t value) { 799f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 800ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers const void* quick_oat_code = class_linker->GetQuickOatCodeFor(patch->GetDexFile(), 801ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers patch->GetReferrerClassDefIdx(), 802ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers patch->GetReferrerMethodIdx()); 803a85b8376740641f13dc078aea6be94d15a800803Brian Carlstrom OatHeader& oat_header = const_cast<OatHeader&>(oat_file_->GetOatHeader()); 804f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom // TODO: make this Thumb2 specific 805ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uintptr_t>(quick_oat_code) & ~0x1); 806f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom uint32_t* patch_location = reinterpret_cast<uint32_t*>(base + patch->GetLiteralOffset()); 807590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier if (kIsDebugBuild) { 808be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi if (patch->IsCall()) { 809be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi const CompilerDriver::CallPatchInformation* cpatch = patch->AsCall(); 81049161cef10a308aedada18e9aa742498d6e6c8c7Jeff Hao const DexFile::MethodId& id = cpatch->GetTargetDexFile()->GetMethodId(cpatch->GetTargetMethodIdx()); 8112da882315a61072664f7ce3c212307342e907207Andreas Gampe uint32_t expected = reinterpret_cast<uintptr_t>(&id) & 0xFFFFFFFF; 812be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi uint32_t actual = *patch_location; 813be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi CHECK(actual == expected || actual == value) << std::hex 814be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi << "actual=" << actual 815be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi << "expected=" << expected 816be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi << "value=" << value; 817be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi } 818be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi if (patch->IsType()) { 819be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi const CompilerDriver::TypePatchInformation* tpatch = patch->AsType(); 820be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi const DexFile::TypeId& id = tpatch->GetDexFile().GetTypeId(tpatch->GetTargetTypeIdx()); 8212da882315a61072664f7ce3c212307342e907207Andreas Gampe uint32_t expected = reinterpret_cast<uintptr_t>(&id) & 0xFFFFFFFF; 822be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi uint32_t actual = *patch_location; 823be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi CHECK(actual == expected || actual == value) << std::hex 824be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi << "actual=" << actual 825be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi << "expected=" << expected 826be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi << "value=" << value; 827be1ca55db3362f5b100c4c65da5342fd299520bbHiroshi Yamauchi } 828590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier } 829b25c3f6a86dc634ce44fb2849385b49465caa84dElliott Hughes *patch_location = value; 830a85b8376740641f13dc078aea6be94d15a800803Brian Carlstrom oat_header.UpdateChecksum(patch_location, sizeof(value)); 831f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom} 832f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom 833db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} // namespace art 834