image_writer.cc revision 357e9be24c17a6bc2ae9fb53f25c73503116101d
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "image_writer.h"
18
19#include <sys/stat.h>
20
21#include <vector>
22
23#include "class_linker.h"
24#include "class_loader.h"
25#include "compiled_method.h"
26#include "compiler.h"
27#include "dex_cache.h"
28#include "file.h"
29#include "globals.h"
30#include "heap.h"
31#include "image.h"
32#include "intern_table.h"
33#include "logging.h"
34#include "oat_file.h"
35#include "object.h"
36#include "object_utils.h"
37#include "runtime.h"
38#include "scoped_thread_state_change.h"
39#include "space.h"
40#include "UniquePtr.h"
41#include "utils.h"
42
43namespace art {
44
45bool ImageWriter::Write(const std::string& image_filename,
46                        uintptr_t image_begin,
47                        const std::string& oat_filename,
48                        const std::string& oat_location,
49                        const Compiler& compiler) {
50  CHECK(!image_filename.empty());
51
52  CHECK_NE(image_begin, 0U);
53  image_begin_ = reinterpret_cast<byte*>(image_begin);
54
55  Heap* heap = Runtime::Current()->GetHeap();
56  const Spaces& spaces = heap->GetSpaces();
57
58  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
59  const std::vector<DexCache*>& all_dex_caches = class_linker->GetDexCaches();
60  for (size_t i = 0; i < all_dex_caches.size(); i++) {
61    DexCache* dex_cache = all_dex_caches[i];
62    if (InSourceSpace(dex_cache)) {
63      dex_caches_.insert(dex_cache);
64    }
65  }
66
67  oat_file_ = OatFile::Open(oat_filename, oat_location, NULL,
68                            OatFile::kRelocNone, true);
69  if (oat_file_ == NULL) {
70    LOG(ERROR) << "Failed to open oat file " << oat_filename;
71    return false;
72  }
73  class_linker->RegisterOatFile(*oat_file_);
74
75  {
76    Thread::Current()->TransitionFromSuspendedToRunnable();
77    PruneNonImageClasses();  // Remove junk
78    ComputeLazyFieldsForImageClasses();  // Add useful information
79    ComputeEagerResolvedStrings();
80    Thread::Current()->TransitionFromRunnableToSuspended(kNative);
81  }
82  heap->CollectGarbage(false);  // Remove garbage
83  // Trim size of alloc spaces
84  // TODO: C++0x auto
85  for (Spaces::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) {
86    if ((*cur)->IsAllocSpace()) {
87      (*cur)->AsAllocSpace()->Trim();
88    }
89  }
90
91  if (!AllocMemory()) {
92    return false;
93  }
94#ifndef NDEBUG
95  {
96    ScopedObjectAccess soa(Thread::Current());
97    CheckNonImageClassesRemoved();
98  }
99#endif
100  heap->DisableCardMarking();
101  {
102    Thread::Current()->TransitionFromSuspendedToRunnable();
103    CalculateNewObjectOffsets();
104    CopyAndFixupObjects();
105    PatchOatCodeAndMethods(compiler);
106    Thread::Current()->TransitionFromRunnableToSuspended(kNative);
107  }
108
109  UniquePtr<File> file(OS::OpenFile(image_filename.c_str(), true));
110  if (file.get() == NULL) {
111    LOG(ERROR) << "Failed to open image file " << image_filename;
112    return false;
113  }
114  if (fchmod(file->Fd(), 0644) != 0) {
115    PLOG(ERROR) << "Failed to make image file world readable: " << image_filename;
116    return EXIT_FAILURE;
117  }
118  bool success = file->WriteFully(image_->Begin(), image_end_);
119  if (!success) {
120    PLOG(ERROR) << "Failed to write image file " << image_filename;
121    return false;
122  }
123  return true;
124}
125
126bool ImageWriter::InSourceSpace(const Object* object) const {
127  const Spaces& spaces = Runtime::Current()->GetHeap()->GetSpaces();
128  // TODO: C++0x auto
129  for (Spaces::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) {
130    if ((*cur)->IsAllocSpace() && (*cur)->Contains(object)) {
131      return true;
132    }
133  }
134  return false;
135}
136
137bool ImageWriter::AllocMemory() {
138  typedef std::vector<Space*> SpaceVec;
139  const SpaceVec& spaces = Runtime::Current()->GetHeap()->GetSpaces();
140  size_t size = 0;
141  for (SpaceVec::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) {
142    if ((*cur)->IsAllocSpace()) {
143      size += (*cur)->Size();
144    }
145  }
146
147  int prot = PROT_READ | PROT_WRITE;
148  size_t length = RoundUp(size, kPageSize);
149  image_.reset(MemMap::MapAnonymous("image-writer-image", NULL, length, prot));
150  if (image_.get() == NULL) {
151    LOG(ERROR) << "Failed to allocate memory for image file generation";
152    return false;
153  }
154  return true;
155}
156
157void ImageWriter::ComputeLazyFieldsForImageClasses() {
158  Runtime* runtime = Runtime::Current();
159  ClassLinker* class_linker = runtime->GetClassLinker();
160  class_linker->VisitClassesWithoutClassesLock(ComputeLazyFieldsForClassesVisitor, NULL);
161}
162
163bool ImageWriter::ComputeLazyFieldsForClassesVisitor(Class* c, void* /*arg*/) {
164  c->ComputeName();
165  return true;
166}
167
168void ImageWriter::ComputeEagerResolvedStringsCallback(Object* obj, void* arg) {
169  if (!obj->GetClass()->IsStringClass()) {
170    return;
171  }
172  String* string = obj->AsString();
173  std::string utf8_string(string->ToModifiedUtf8());
174  ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg);
175  ClassLinker* linker = Runtime::Current()->GetClassLinker();
176  typedef Set::const_iterator CacheIt;  // TODO: C++0x auto
177  for (CacheIt it = writer->dex_caches_.begin(), end = writer->dex_caches_.end(); it != end; ++it) {
178    DexCache* dex_cache = *it;
179    const DexFile& dex_file = linker->FindDexFile(dex_cache);
180    const DexFile::StringId* string_id = dex_file.FindStringId(utf8_string);
181    if (string_id != NULL) {
182      // This string occurs in this dex file, assign the dex cache entry.
183      uint32_t string_idx = dex_file.GetIndexForStringId(*string_id);
184      if (dex_cache->GetResolvedString(string_idx) == NULL) {
185        dex_cache->SetResolvedString(string_idx, string);
186      }
187    }
188  }
189}
190
191void ImageWriter::ComputeEagerResolvedStrings()
192    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
193  // TODO: Check image spaces only?
194  Heap* heap = Runtime::Current()->GetHeap();
195  ReaderMutexLock mu(*GlobalSynchronization::heap_bitmap_lock_);
196  heap->FlushAllocStack();
197  heap->GetLiveBitmap()->Walk(ComputeEagerResolvedStringsCallback, this);
198}
199
200bool ImageWriter::IsImageClass(const Class* klass) {
201  if (image_classes_ == NULL) {
202    return true;
203  }
204  while (klass->IsArrayClass()) {
205    klass = klass->GetComponentType();
206  }
207  if (klass->IsPrimitive()) {
208    return true;
209  }
210  const std::string descriptor(ClassHelper(klass).GetDescriptor());
211  return image_classes_->find(descriptor) != image_classes_->end();
212}
213
214
215struct NonImageClasses {
216  ImageWriter* image_writer;
217  std::set<std::string>* non_image_classes;
218};
219
220void ImageWriter::PruneNonImageClasses() {
221  if (image_classes_ == NULL) {
222    return;
223  }
224  Runtime* runtime = Runtime::Current();
225  ClassLinker* class_linker = runtime->GetClassLinker();
226
227  std::set<std::string> non_image_classes;
228  NonImageClasses context;
229  context.image_writer = this;
230  context.non_image_classes = &non_image_classes;
231  class_linker->VisitClasses(NonImageClassesVisitor, &context);
232
233  typedef std::set<std::string>::const_iterator ClassIt;  // TODO: C++0x auto
234  for (ClassIt it = non_image_classes.begin(), end = non_image_classes.end(); it != end; ++it) {
235    class_linker->RemoveClass((*it).c_str(), NULL);
236  }
237
238  Method* resolution_method = runtime->GetResolutionMethod();
239  typedef Set::const_iterator CacheIt;  // TODO: C++0x auto
240  for (CacheIt it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it) {
241    DexCache* dex_cache = *it;
242    for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
243      Class* klass = dex_cache->GetResolvedType(i);
244      if (klass != NULL && !IsImageClass(klass)) {
245        dex_cache->SetResolvedType(i, NULL);
246        dex_cache->GetInitializedStaticStorage()->Set(i, NULL);
247      }
248    }
249    for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
250      Method* method = dex_cache->GetResolvedMethod(i);
251      if (method != NULL && !IsImageClass(method->GetDeclaringClass())) {
252        dex_cache->SetResolvedMethod(i, resolution_method);
253      }
254    }
255    for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
256      Field* field = dex_cache->GetResolvedField(i);
257      if (field != NULL && !IsImageClass(field->GetDeclaringClass())) {
258        dex_cache->SetResolvedField(i, NULL);
259      }
260    }
261  }
262}
263
264bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) {
265  NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg);
266  if (!context->image_writer->IsImageClass(klass)) {
267    context->non_image_classes->insert(ClassHelper(klass).GetDescriptor());
268  }
269  return true;
270}
271
272void ImageWriter::CheckNonImageClassesRemoved()
273    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
274  if (image_classes_ == NULL) {
275    return;
276  }
277
278  Heap* heap = Runtime::Current()->GetHeap();
279  {
280    WriterMutexLock mu(*GlobalSynchronization::heap_bitmap_lock_);
281    heap->FlushAllocStack();
282  }
283
284  ReaderMutexLock mu(*GlobalSynchronization::heap_bitmap_lock_);
285  heap->GetLiveBitmap()->Walk(CheckNonImageClassesRemovedCallback, this);
286}
287
288void ImageWriter::CheckNonImageClassesRemovedCallback(Object* obj, void* arg) {
289  ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
290  if (!obj->IsClass()) {
291    return;
292  }
293  Class* klass = obj->AsClass();
294  if (!image_writer->IsImageClass(klass)) {
295    image_writer->DumpImageClasses();
296    CHECK(image_writer->IsImageClass(klass)) << ClassHelper(klass).GetDescriptor()
297                                             << " " << PrettyDescriptor(klass);
298  }
299}
300
301void ImageWriter::DumpImageClasses() {
302  typedef std::set<std::string>::const_iterator It;  // TODO: C++0x auto
303  for (It it = image_classes_->begin(), end = image_classes_->end(); it != end; ++it) {
304    LOG(INFO) << " " << *it;
305  }
306}
307
308void ImageWriter::CalculateNewObjectOffsetsCallback(Object* obj, void* arg) {
309  DCHECK(obj != NULL);
310  DCHECK(arg != NULL);
311  ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
312  if (!image_writer->InSourceSpace(obj)) {
313    return;
314  }
315
316  // if it is a string, we want to intern it if its not interned.
317  if (obj->GetClass()->IsStringClass()) {
318    // we must be an interned string that was forward referenced and already assigned
319    if (image_writer->IsImageOffsetAssigned(obj)) {
320      DCHECK_EQ(obj, obj->AsString()->Intern());
321      return;
322    }
323    SirtRef<String> interned(obj->AsString()->Intern());
324    if (obj != interned.get()) {
325      if (!image_writer->IsImageOffsetAssigned(interned.get())) {
326        // interned obj is after us, allocate its location early
327        image_writer->AssignImageOffset(interned.get());
328      }
329      // point those looking for this object to the interned version.
330      image_writer->SetImageOffset(obj, image_writer->GetImageOffset(interned.get()));
331      return;
332    }
333    // else (obj == interned), nothing to do but fall through to the normal case
334  }
335
336  image_writer->AssignImageOffset(obj);
337}
338
339ObjectArray<Object>* ImageWriter::CreateImageRoots() const {
340  Runtime* runtime = Runtime::Current();
341  ClassLinker* class_linker = runtime->GetClassLinker();
342  Class* object_array_class = class_linker->FindSystemClass("[Ljava/lang/Object;");
343
344  // build an Object[] of all the DexCaches used in the source_space_
345  ObjectArray<Object>* dex_caches = ObjectArray<Object>::Alloc(object_array_class,
346                                                               dex_caches_.size());
347  int i = 0;
348  typedef Set::const_iterator It;  // TODO: C++0x auto
349  for (It it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it, ++i) {
350    dex_caches->Set(i, *it);
351  }
352
353  // build an Object[] of the roots needed to restore the runtime
354  SirtRef<ObjectArray<Object> > image_roots(
355      ObjectArray<Object>::Alloc(object_array_class, ImageHeader::kImageRootsMax));
356  image_roots->Set(ImageHeader::kJniStubArray, runtime->GetJniDlsymLookupStub());
357  image_roots->Set(ImageHeader::kAbstractMethodErrorStubArray,
358                   runtime->GetAbstractMethodErrorStubArray());
359  image_roots->Set(ImageHeader::kStaticResolutionStubArray,
360                   runtime->GetResolutionStubArray(Runtime::kStaticMethod));
361  image_roots->Set(ImageHeader::kUnknownMethodResolutionStubArray,
362                   runtime->GetResolutionStubArray(Runtime::kUnknownMethod));
363  image_roots->Set(ImageHeader::kResolutionMethod, runtime->GetResolutionMethod());
364  image_roots->Set(ImageHeader::kCalleeSaveMethod,
365                   runtime->GetCalleeSaveMethod(Runtime::kSaveAll));
366  image_roots->Set(ImageHeader::kRefsOnlySaveMethod,
367                   runtime->GetCalleeSaveMethod(Runtime::kRefsOnly));
368  image_roots->Set(ImageHeader::kRefsAndArgsSaveMethod,
369                   runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs));
370  image_roots->Set(ImageHeader::kOatLocation,
371                   String::AllocFromModifiedUtf8(oat_file_->GetLocation().c_str()));
372  image_roots->Set(ImageHeader::kDexCaches,
373                   dex_caches);
374  image_roots->Set(ImageHeader::kClassRoots,
375                   class_linker->GetClassRoots());
376  for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
377    CHECK(image_roots->Get(i) != NULL);
378  }
379  return image_roots.get();
380}
381
382void ImageWriter::CalculateNewObjectOffsets() {
383  SirtRef<ObjectArray<Object> > image_roots(CreateImageRoots());
384
385  Heap* heap = Runtime::Current()->GetHeap();
386  typedef std::vector<Space*> SpaceVec;
387  const SpaceVec& spaces = heap->GetSpaces();
388  DCHECK(!spaces.empty());
389  DCHECK_EQ(0U, image_end_);
390
391  // leave space for the header, but do not write it yet, we need to
392  // know where image_roots is going to end up
393  image_end_ += RoundUp(sizeof(ImageHeader), 8); // 64-bit-alignment
394
395  {
396    Heap* heap = Runtime::Current()->GetHeap();
397    ReaderMutexLock mu(*GlobalSynchronization::heap_bitmap_lock_);
398    heap->FlushAllocStack();
399  }
400
401  // TODO: Image spaces only?
402  {
403    for (SpaceVec::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) {
404      (*cur)->GetLiveBitmap()->InOrderWalk(CalculateNewObjectOffsetsCallback, this);
405      DCHECK_LT(image_end_, image_->Size());
406    }
407  }
408
409  // Note that image_top_ is left at end of used space
410  oat_begin_ = image_begin_ +  RoundUp(image_end_, kPageSize);
411  const byte* oat_limit = oat_begin_ +  oat_file_->Size();
412
413  // return to write header at start of image with future location of image_roots
414  ImageHeader image_header(reinterpret_cast<uint32_t>(image_begin_),
415                           reinterpret_cast<uint32_t>(GetImageAddress(image_roots.get())),
416                           oat_file_->GetOatHeader().GetChecksum(),
417                           reinterpret_cast<uint32_t>(oat_begin_),
418                           reinterpret_cast<uint32_t>(oat_limit));
419  memcpy(image_->Begin(), &image_header, sizeof(image_header));
420}
421
422void ImageWriter::CopyAndFixupObjects()
423    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
424  Heap* heap = Runtime::Current()->GetHeap();
425  // TODO: heap validation can't handle this fix up pass
426  heap->DisableObjectValidation();
427  // TODO: Image spaces only?
428  ReaderMutexLock mu(*GlobalSynchronization::heap_bitmap_lock_);
429  heap->FlushAllocStack();
430  heap->GetLiveBitmap()->Walk(CopyAndFixupObjectsCallback, this);
431}
432
433void ImageWriter::CopyAndFixupObjectsCallback(Object* object, void* arg) {
434  DCHECK(object != NULL);
435  DCHECK(arg != NULL);
436  const Object* obj = object;
437  ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
438  if (!image_writer->InSourceSpace(object)) {
439    return;
440  }
441
442  // see GetLocalAddress for similar computation
443  size_t offset = image_writer->GetImageOffset(obj);
444  byte* dst = image_writer->image_->Begin() + offset;
445  const byte* src = reinterpret_cast<const byte*>(obj);
446  size_t n = obj->SizeOf();
447  DCHECK_LT(offset + n, image_writer->image_->Size());
448  memcpy(dst, src, n);
449  Object* copy = reinterpret_cast<Object*>(dst);
450  copy->monitor_ = 0; // We may have inflated the lock during compilation.
451  image_writer->FixupObject(obj, copy);
452}
453
454void ImageWriter::FixupObject(const Object* orig, Object* copy) {
455  DCHECK(orig != NULL);
456  DCHECK(copy != NULL);
457  copy->SetClass(down_cast<Class*>(GetImageAddress(orig->GetClass())));
458  // TODO: special case init of pointers to malloc data (or removal of these pointers)
459  if (orig->IsClass()) {
460    FixupClass(orig->AsClass(), down_cast<Class*>(copy));
461  } else if (orig->IsObjectArray()) {
462    FixupObjectArray(orig->AsObjectArray<Object>(), down_cast<ObjectArray<Object>*>(copy));
463  } else if (orig->IsMethod()) {
464    FixupMethod(orig->AsMethod(), down_cast<Method*>(copy));
465  } else {
466    FixupInstanceFields(orig, copy);
467  }
468}
469
470void ImageWriter::FixupClass(const Class* orig, Class* copy) {
471  FixupInstanceFields(orig, copy);
472  FixupStaticFields(orig, copy);
473}
474
475void ImageWriter::FixupMethod(const Method* orig, Method* copy) {
476  FixupInstanceFields(orig, copy);
477
478  // OatWriter replaces the code_ and invoke_stub_ with offset values.
479  // Here we readjust to a pointer relative to oat_begin_
480
481  // Every type of method can have an invoke stub
482  uint32_t invoke_stub_offset = orig->GetOatInvokeStubOffset();
483  const byte* invoke_stub = GetOatAddress(invoke_stub_offset);
484  copy->invoke_stub_ = reinterpret_cast<const Method::InvokeStub*>(invoke_stub);
485
486  if (orig->IsAbstract()) {
487    // Abstract methods are pointed to a stub that will throw AbstractMethodError if they are called
488    ByteArray* orig_ame_stub_array_ = Runtime::Current()->GetAbstractMethodErrorStubArray();
489    ByteArray* copy_ame_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_ame_stub_array_));
490    copy->code_ = copy_ame_stub_array_->GetData();
491    return;
492  }
493
494  if (orig == Runtime::Current()->GetResolutionMethod()) {
495    // The resolution stub's code points at the unknown resolution trampoline
496    ByteArray* orig_res_stub_array_ =
497        Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod);
498    CHECK(orig->GetCode() == orig_res_stub_array_->GetData());
499    ByteArray* copy_res_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_res_stub_array_));
500    copy->code_ = copy_res_stub_array_->GetData();
501    return;
502  }
503
504  // Non-abstract methods typically have code
505  uint32_t code_offset = orig->GetOatCodeOffset();
506  const byte* code = NULL;
507  if (orig->IsStatic()) {
508    // Static methods may point at the resolution trampoline stub
509    ByteArray* orig_res_stub_array_ =
510        Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod);
511    if (reinterpret_cast<int8_t*>(code_offset) == orig_res_stub_array_->GetData()) {
512      ByteArray* copy_res_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_res_stub_array_));
513      code = reinterpret_cast<const byte*>(copy_res_stub_array_->GetData());
514    }
515  }
516  if (code == NULL) {
517    code = GetOatAddress(code_offset);
518  }
519  copy->code_ = code;
520
521  if (orig->IsNative()) {
522    // The native method's pointer is directed to a stub to lookup via dlsym.
523    // Note this is not the code_ pointer, that is handled above.
524    ByteArray* orig_jni_stub_array_ = Runtime::Current()->GetJniDlsymLookupStub();
525    ByteArray* copy_jni_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_jni_stub_array_));
526    copy->native_method_ = copy_jni_stub_array_->GetData();
527  } else {
528    // normal (non-abstract non-native) methods have mapping tables to relocate
529    uint32_t mapping_table_off = orig->GetOatMappingTableOffset();
530    const byte* mapping_table = GetOatAddress(mapping_table_off);
531    copy->mapping_table_ = reinterpret_cast<const uint32_t*>(mapping_table);
532
533    uint32_t vmap_table_offset = orig->GetOatVmapTableOffset();
534    const byte* vmap_table = GetOatAddress(vmap_table_offset);
535    copy->vmap_table_ = reinterpret_cast<const uint16_t*>(vmap_table);
536
537    uint32_t gc_map_offset = orig->GetOatGcMapOffset();
538    const byte* gc_map = GetOatAddress(gc_map_offset);
539    copy->gc_map_ = reinterpret_cast<const uint8_t*>(gc_map);
540  }
541}
542
543void ImageWriter::FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy) {
544  for (int32_t i = 0; i < orig->GetLength(); ++i) {
545    const Object* element = orig->Get(i);
546    copy->SetWithoutChecks(i, GetImageAddress(element));
547  }
548}
549
550void ImageWriter::FixupInstanceFields(const Object* orig, Object* copy) {
551  DCHECK(orig != NULL);
552  DCHECK(copy != NULL);
553  Class* klass = orig->GetClass();
554  DCHECK(klass != NULL);
555  FixupFields(orig,
556              copy,
557              klass->GetReferenceInstanceOffsets(),
558              false);
559}
560
561void ImageWriter::FixupStaticFields(const Class* orig, Class* copy) {
562  DCHECK(orig != NULL);
563  DCHECK(copy != NULL);
564  FixupFields(orig,
565              copy,
566              orig->GetReferenceStaticOffsets(),
567              true);
568}
569
570void ImageWriter::FixupFields(const Object* orig,
571                              Object* copy,
572                              uint32_t ref_offsets,
573                              bool is_static) {
574  if (ref_offsets != CLASS_WALK_SUPER) {
575    // Found a reference offset bitmap.  Fixup the specified offsets.
576    while (ref_offsets != 0) {
577      size_t right_shift = CLZ(ref_offsets);
578      MemberOffset byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
579      const Object* ref = orig->GetFieldObject<const Object*>(byte_offset, false);
580      copy->SetFieldObject(byte_offset, GetImageAddress(ref), false);
581      ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
582    }
583  } else {
584    // There is no reference offset bitmap.  In the non-static case,
585    // walk up the class inheritance hierarchy and find reference
586    // offsets the hard way. In the static case, just consider this
587    // class.
588    for (const Class *klass = is_static ? orig->AsClass() : orig->GetClass();
589         klass != NULL;
590         klass = is_static ? NULL : klass->GetSuperClass()) {
591      size_t num_reference_fields = (is_static
592                                     ? klass->NumReferenceStaticFields()
593                                     : klass->NumReferenceInstanceFields());
594      for (size_t i = 0; i < num_reference_fields; ++i) {
595        Field* field = (is_static
596                        ? klass->GetStaticField(i)
597                        : klass->GetInstanceField(i));
598        MemberOffset field_offset = field->GetOffset();
599        const Object* ref = orig->GetFieldObject<const Object*>(field_offset, false);
600        copy->SetFieldObject(field_offset, GetImageAddress(ref), false);
601      }
602    }
603  }
604}
605
606static Method* GetReferrerMethod(const Compiler::PatchInformation* patch)
607    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
608  ScopedObjectAccessUnchecked soa(Thread::Current());
609  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
610  DexCache* dex_cache = class_linker->FindDexCache(patch->GetDexFile());
611  Method* method = class_linker->ResolveMethod(patch->GetDexFile(),
612                                               patch->GetReferrerMethodIdx(),
613                                               dex_cache,
614                                               NULL,
615                                               patch->GetReferrerIsDirect());
616  CHECK(method != NULL)
617    << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx();
618  CHECK(!method->IsRuntimeMethod())
619    << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx();
620  CHECK(dex_cache->GetResolvedMethods()->Get(patch->GetReferrerMethodIdx()) == method)
621    << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx() << " "
622    << PrettyMethod(dex_cache->GetResolvedMethods()->Get(patch->GetReferrerMethodIdx())) << " "
623    << PrettyMethod(method);
624  return method;
625}
626
627static Method* GetTargetMethod(const Compiler::PatchInformation* patch)
628    SHARED_LOCKS_REQUIRED(GlobalSynchronization::mutator_lock_) {
629  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
630  DexCache* dex_cache = class_linker->FindDexCache(patch->GetDexFile());
631  Method* method = class_linker->ResolveMethod(patch->GetDexFile(),
632                                               patch->GetTargetMethodIdx(),
633                                               dex_cache,
634                                               NULL,
635                                               patch->GetTargetIsDirect());
636  CHECK(method != NULL)
637    << patch->GetDexFile().GetLocation() << " " << patch->GetTargetMethodIdx();
638  CHECK(!method->IsRuntimeMethod())
639    << patch->GetDexFile().GetLocation() << " " << patch->GetTargetMethodIdx();
640  CHECK(dex_cache->GetResolvedMethods()->Get(patch->GetTargetMethodIdx()) == method)
641    << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx() << " "
642    << PrettyMethod(dex_cache->GetResolvedMethods()->Get(patch->GetTargetMethodIdx())) << " "
643    << PrettyMethod(method);
644  return method;
645}
646
647void ImageWriter::PatchOatCodeAndMethods(const Compiler& compiler) {
648  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
649
650  const std::vector<const Compiler::PatchInformation*>& code_to_patch = compiler.GetCodeToPatch();
651  for (size_t i = 0; i < code_to_patch.size(); i++) {
652    const Compiler::PatchInformation* patch = code_to_patch[i];
653    Method* target = GetTargetMethod(patch);
654    uint32_t code = reinterpret_cast<uint32_t>(class_linker->GetOatCodeFor(target));
655    uint32_t code_base = reinterpret_cast<uint32_t>(&oat_file_->GetOatHeader());
656    uint32_t code_offset = code - code_base;
657    SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetOatAddress(code_offset)));
658  }
659
660  const std::vector<const Compiler::PatchInformation*>& methods_to_patch
661      = compiler.GetMethodsToPatch();
662  for (size_t i = 0; i < methods_to_patch.size(); i++) {
663    const Compiler::PatchInformation* patch = methods_to_patch[i];
664    Method* target = GetTargetMethod(patch);
665    SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetImageAddress(target)));
666  }
667}
668
669void ImageWriter::SetPatchLocation(const Compiler::PatchInformation* patch, uint32_t value) {
670  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
671  Method* method = GetReferrerMethod(patch);
672  // Goodbye const, we are about to modify some code.
673  void* code = const_cast<void*>(class_linker->GetOatCodeFor(method));
674  // TODO: make this Thumb2 specific
675  uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uint32_t>(code) & ~0x1);
676  uint32_t* patch_location = reinterpret_cast<uint32_t*>(base + patch->GetLiteralOffset());
677#ifndef NDEBUG
678  const DexFile::MethodId& id = patch->GetDexFile().GetMethodId(patch->GetTargetMethodIdx());
679  uint32_t expected = reinterpret_cast<uint32_t>(&id);
680  uint32_t actual = *patch_location;
681  CHECK(actual == expected || actual == value) << std::hex
682    << "actual=" << actual
683    << "expected=" << expected
684    << "value=" << value;
685#endif
686  *patch_location = value;
687}
688
689}  // namespace art
690