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