image_writer.cc revision d418edaf4df0a410d678389e171ac6d96ae2af15
1db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom// Copyright 2011 Google Inc. All Rights Reserved.
2db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
3db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "image_writer.h"
4db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
5db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include <sys/mman.h>
690a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes
7db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include <vector>
8db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
990a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "UniquePtr.h"
10a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom#include "class_linker.h"
111f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "class_loader.h"
12ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom#include "compiled_method.h"
1390a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "dex_cache.h"
14db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "file.h"
15db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "globals.h"
16db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "heap.h"
174a289ed61242964b921434de7d375f46480472a1Brian Carlstrom#include "image.h"
18a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom#include "intern_table.h"
19db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "logging.h"
20db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "object.h"
216d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h"
221f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "runtime.h"
23db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "space.h"
24db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "utils.h"
25db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
26db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstromnamespace art {
27db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
28ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrombool ImageWriter::Write(const char* image_filename,
2930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers                        uintptr_t image_begin,
30ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                        const std::string& oat_filename,
31ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                        const std::string& strip_location_prefix) {
32aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  CHECK(image_filename != NULL);
33aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
3430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  CHECK_NE(image_begin, 0U);
3530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  image_begin_ = reinterpret_cast<byte*>(image_begin);
3669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
3769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  const std::vector<Space*>& spaces = Heap::GetSpaces();
3869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  // currently just write the last space, assuming it is the space that was being used for allocation
3969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  CHECK_GE(spaces.size(), 1U);
4069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  source_space_ = spaces[spaces.size()-1];
4158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  CHECK(!source_space_->IsImageSpace());
4269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
43ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
44ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  const std::vector<DexCache*>& all_dex_caches = class_linker->GetDexCaches();
45ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (size_t i = 0; i < all_dex_caches.size(); i++) {
46ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    DexCache* dex_cache = all_dex_caches[i];
47ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    if (InSourceSpace(dex_cache)) {
48ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      dex_caches_.insert(dex_cache);
49ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
50ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
51ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
52e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  oat_file_.reset(OatFile::Open(oat_filename, strip_location_prefix, NULL));
53e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  if (oat_file_.get() == NULL) {
54e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    LOG(ERROR) << "Failed to open oat file " << oat_filename;
55e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return false;
56e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
57e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
58ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (!AllocMemory()) {
59db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    return false;
60db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  }
61ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  PruneNonImageClasses();
62d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers  ComputeLazyFieldsForImageClasses();
6330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  Heap::CollectGarbage(false);
64ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom#ifndef NDEBUG
65ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  CheckNonImageClassesRemoved();
66ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom#endif
675d76c435082332ef79a22962386fa92a0870e378Ian Rogers  Heap::DisableCardMarking();
68db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  CalculateNewObjectOffsets();
69db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  CopyAndFixupObjects();
70d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes
71e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  UniquePtr<File> file(OS::OpenFile(image_filename, true));
7290a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  if (file.get() == NULL) {
73e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    LOG(ERROR) << "Failed to open image file " << image_filename;
74db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    return false;
75db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  }
7630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  bool success = file->WriteFully(image_->Begin(), image_end_);
77e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  if (!success) {
78e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    PLOG(ERROR) << "Failed to write image file " << image_filename;
79e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    return false;
80e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
81e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  return true;
82db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
83db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
84ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrombool ImageWriter::AllocMemory() {
8569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  size_t size = source_space_->Size();
86db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  int prot = PROT_READ | PROT_WRITE;
87db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  size_t length = RoundUp(size, kPageSize);
8889521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom  image_.reset(MemMap::MapAnonymous("image-writer-image", NULL, length, prot));
8990a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes  if (image_.get() == NULL) {
90e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    LOG(ERROR) << "Failed to allocate memory for image file generation";
91db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    return false;
92db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  }
93db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  return true;
94db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
95db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
96d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogersvoid ImageWriter::ComputeLazyFieldsForImageClasses() {
97d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers  Runtime* runtime = Runtime::Current();
98d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers  ClassLinker* class_linker = runtime->GetClassLinker();
99d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers  class_linker->VisitClasses(ComputeLazyFieldsForClassesVisitor, NULL);
100d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers}
101d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers
102d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogersbool ImageWriter::ComputeLazyFieldsForClassesVisitor(Class* klass, void* arg) {
103d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers  klass->ComputeName();
104d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers  return true;
105d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers}
106d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers
107ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrombool ImageWriter::IsImageClass(const Class* klass) {
108ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (image_classes_ == NULL) {
109ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return true;
110ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
111ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  while (klass->IsArrayClass()) {
112ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    klass = klass->GetComponentType();
113ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
114c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes  if (klass->IsPrimitive()) {
115ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return true;
116ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
1176d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers  const std::string descriptor(ClassHelper(klass).GetDescriptor());
118ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  return image_classes_->find(descriptor) != image_classes_->end();
119ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
120ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
121ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
122ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromstruct NonImageClasses {
123ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  ImageWriter* image_writer;
124ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  std::set<std::string>* non_image_classes;
125ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom};
126ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
127ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid ImageWriter::PruneNonImageClasses() {
128ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (image_classes_ == NULL) {
129ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return;
130ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
131ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  Runtime* runtime = Runtime::Current();
132ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  ClassLinker* class_linker = runtime->GetClassLinker();
133ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
134ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  std::set<std::string> non_image_classes;
135ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  NonImageClasses context;
136ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  context.image_writer = this;
137ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  context.non_image_classes = &non_image_classes;
138ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  class_linker->VisitClasses(NonImageClassesVisitor, &context);
139ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
140ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  typedef std::set<std::string>::const_iterator ClassIt;  // TODO: C++0x auto
141ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (ClassIt it = non_image_classes.begin(), end = non_image_classes.end(); it != end; ++it) {
142c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes    class_linker->RemoveClass((*it).c_str(), NULL);
143ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
144ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
145ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  typedef Set::const_iterator CacheIt;  // TODO: C++0x auto
146ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (CacheIt it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it) {
147ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    DexCache* dex_cache = *it;
148ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
149ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      Class* klass = dex_cache->GetResolvedType(i);
150ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      if (klass != NULL && !IsImageClass(klass)) {
151ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        dex_cache->SetResolvedType(i, NULL);
152ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        dex_cache->GetInitializedStaticStorage()->Set(i, NULL);
153ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
154ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
155ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
156ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      Method* method = dex_cache->GetResolvedMethod(i);
157ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      if (method != NULL && !IsImageClass(method->GetDeclaringClass())) {
158ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        dex_cache->SetResolvedMethod(i, NULL);
159ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        Runtime::TrampolineType type = Runtime::GetTrampolineType(method);
160ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        ByteArray* res_trampoline = runtime->GetResolutionStubArray(type);
161ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        dex_cache->GetCodeAndDirectMethods()->SetResolvedDirectMethodTrampoline(i, res_trampoline);
162ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
163ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
164ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) {
165ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      Field* field = dex_cache->GetResolvedField(i);
166ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      if (field != NULL && !IsImageClass(field->GetDeclaringClass())) {
167ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        dex_cache->SetResolvedField(i, NULL);
168ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      }
169ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    }
170ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
171ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
172ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
173ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrombool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) {
174ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg);
175ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (!context->image_writer->IsImageClass(klass)) {
1766d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers    context->non_image_classes->insert(ClassHelper(klass).GetDescriptor());
177ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
178ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  return true;
179ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
180ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
181ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid ImageWriter::CheckNonImageClassesRemoved() {
182ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (image_classes_ == NULL) {
183ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return;
184ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
185ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  Heap::GetLiveBits()->Walk(CheckNonImageClassesRemovedCallback, this);
186ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
187ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
188ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid ImageWriter::CheckNonImageClassesRemovedCallback(Object* obj, void* arg) {
189ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
190ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if (!obj->IsClass()) {
191ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return;
192ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  }
193ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  Class* klass = obj->AsClass();
194c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes  if (!image_writer->IsImageClass(klass)) {
195c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes    image_writer->DumpImageClasses();
196c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes    CHECK(image_writer->IsImageClass(klass)) << ClassHelper(klass).GetDescriptor()
197c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes                                             << " " << PrettyDescriptor(klass);
198c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes  }
199c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes}
200c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes
201c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughesvoid ImageWriter::DumpImageClasses() {
202c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes  typedef std::set<std::string>::const_iterator It;  // TODO: C++0x auto
203c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes  for (It it = image_classes_->begin(), end = image_classes_->end(); it != end; ++it) {
204c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes    LOG(INFO) << " " << *it;
205c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes  }
206ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}
207ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom
20878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromvoid ImageWriter::CalculateNewObjectOffsetsCallback(Object* obj, void* arg) {
2094e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom  DCHECK(obj != NULL);
2104e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom  DCHECK(arg != NULL);
2114e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom  ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
21269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  if (!image_writer->InSourceSpace(obj)) {
21369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    return;
21469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
215c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom
216c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom  // if it is a string, we want to intern it if its not interned.
217dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes  if (obj->GetClass()->IsStringClass()) {
218c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom    // we must be an interned string that was forward referenced and already assigned
219c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom    if (IsImageOffsetAssigned(obj)) {
220c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom      DCHECK_EQ(obj, obj->AsString()->Intern());
221c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom      return;
222c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom    }
22340381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom    SirtRef<String> interned(obj->AsString()->Intern());
22440381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom    if (obj != interned.get()) {
22540381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom      if (!IsImageOffsetAssigned(interned.get())) {
226c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom        // interned obj is after us, allocate its location early
22740381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom        image_writer->AssignImageOffset(interned.get());
228c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom      }
229c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom      // point those looking for this object to the interned version.
23040381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom      SetImageOffset(obj, GetImageOffset(interned.get()));
231c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom      return;
232c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom    }
233c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom    // else (obj == interned), nothing to do but fall through to the normal case
234c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom  }
235c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom
236c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom  image_writer->AssignImageOffset(obj);
2374e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom}
2384e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom
239e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromObjectArray<Object>* ImageWriter::CreateImageRoots() const {
240161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  Runtime* runtime = Runtime::Current();
241161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  ClassLinker* class_linker = runtime->GetClassLinker();
242161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  Class* object_array_class = class_linker->FindSystemClass("[Ljava/lang/Object;");
24358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
24458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  // build an Object[] of all the DexCaches used in the source_space_
24558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  ObjectArray<Object>* dex_caches = ObjectArray<Object>::Alloc(object_array_class,
246ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                                                               dex_caches_.size());
247ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  int i = 0;
248ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  typedef Set::const_iterator It;  // TODO: C++0x auto
249ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  for (It it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it, ++i) {
250ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    dex_caches->Set(i, *it);
25158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
25258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
25358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  // build an Object[] of the roots needed to restore the runtime
25440381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom  SirtRef<ObjectArray<Object> > image_roots(
25540381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom      ObjectArray<Object>::Alloc(object_array_class, ImageHeader::kImageRootsMax));
256169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers  image_roots->Set(ImageHeader::kJniStubArray, runtime->GetJniDlsymLookupStub());
257e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  image_roots->Set(ImageHeader::kAbstractMethodErrorStubArray,
258e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom                   runtime->GetAbstractMethodErrorStubArray());
2591cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  image_roots->Set(ImageHeader::kInstanceResolutionStubArray,
2601cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers                   runtime->GetResolutionStubArray(Runtime::kInstanceMethod));
2611cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  image_roots->Set(ImageHeader::kStaticResolutionStubArray,
2621cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers                   runtime->GetResolutionStubArray(Runtime::kStaticMethod));
2631cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  image_roots->Set(ImageHeader::kUnknownMethodResolutionStubArray,
2641cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers                   runtime->GetResolutionStubArray(Runtime::kUnknownMethod));
2654f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  image_roots->Set(ImageHeader::kCalleeSaveMethod,
2664f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                   runtime->GetCalleeSaveMethod(Runtime::kSaveAll));
2674f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  image_roots->Set(ImageHeader::kRefsOnlySaveMethod,
2684f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                   runtime->GetCalleeSaveMethod(Runtime::kRefsOnly));
2694f0d07c783afef89703dce32c94440fc8621a29bIan Rogers  image_roots->Set(ImageHeader::kRefsAndArgsSaveMethod,
2704f0d07c783afef89703dce32c94440fc8621a29bIan Rogers                   runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs));
271e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  image_roots->Set(ImageHeader::kOatLocation,
272e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom                   String::AllocFromModifiedUtf8(oat_file_->GetLocation().c_str()));
27358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  image_roots->Set(ImageHeader::kDexCaches,
27458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom                   dex_caches);
27534f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom  image_roots->Set(ImageHeader::kClassRoots,
27634f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom                   class_linker->GetClassRoots());
277e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
278e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    CHECK(image_roots->Get(i) != NULL);
279e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  }
28040381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom  return image_roots.get();
281161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom}
282161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom
283db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstromvoid ImageWriter::CalculateNewObjectOffsets() {
28440381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom  SirtRef<ObjectArray<Object> > image_roots(CreateImageRoots());
285161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom
286db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  HeapBitmap* heap_bitmap = Heap::GetLiveBits();
287db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  DCHECK(heap_bitmap != NULL);
28830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  DCHECK_EQ(0U, image_end_);
289a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom
290161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  // leave space for the header, but do not write it yet, we need to
291161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  // know where image_roots is going to end up
29230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  image_end_ += RoundUp(sizeof(ImageHeader), 8); // 64-bit-alignment
293a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom
29469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  heap_bitmap->Walk(CalculateNewObjectOffsetsCallback, this);  // TODO: add Space-limited Walk
29530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  DCHECK_LT(image_end_, image_->Size());
296a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom
297e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  // Note that image_top_ is left at end of used space
29830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  oat_begin_ = image_begin_ +  RoundUp(image_end_, kPageSize);
29930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  const byte* oat_limit = oat_begin_ +  oat_file_->Size();
300e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
301161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  // return to write header at start of image with future location of image_roots
30230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  ImageHeader image_header(reinterpret_cast<uint32_t>(image_begin_),
30340381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom                           reinterpret_cast<uint32_t>(GetImageAddress(image_roots.get())),
304e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom                           oat_file_->GetOatHeader().GetChecksum(),
30530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers                           reinterpret_cast<uint32_t>(oat_begin_),
306e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom                           reinterpret_cast<uint32_t>(oat_limit));
30730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  memcpy(image_->Begin(), &image_header, sizeof(image_header));
308db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
309db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
310db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstromvoid ImageWriter::CopyAndFixupObjects() {
311db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  HeapBitmap* heap_bitmap = Heap::GetLiveBits();
312db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  DCHECK(heap_bitmap != NULL);
3130cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  // TODO: heap validation can't handle this fix up pass
3140cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  Heap::DisableObjectValidation();
31569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  heap_bitmap->Walk(CopyAndFixupObjectsCallback, this);  // TODO: add Space-limited Walk
31669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  FixupDexCaches();
317db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
318db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
31978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromvoid ImageWriter::CopyAndFixupObjectsCallback(Object* object, void* arg) {
3204873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom  DCHECK(object != NULL);
321db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  DCHECK(arg != NULL);
3224873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom  const Object* obj = object;
323db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg);
32469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  if (!image_writer->InSourceSpace(object)) {
32569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    return;
32669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
327d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes
32869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  // see GetLocalAddress for similar computation
329db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  size_t offset = image_writer->GetImageOffset(obj);
33030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  byte* dst = image_writer->image_->Begin() + offset;
3314873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom  const byte* src = reinterpret_cast<const byte*>(obj);
33204b63fd60de0d9e6f07763511a1a9622accfeed7Elliott Hughes  size_t n = obj->SizeOf();
33330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  DCHECK_LT(offset + n, image_writer->image_->Size());
334db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  memcpy(dst, src, n);
335db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  Object* copy = reinterpret_cast<Object*>(dst);
33669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  ResetImageOffset(copy);
337db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  image_writer->FixupObject(obj, copy);
338db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
339db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
3404873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupObject(const Object* orig, Object* copy) {
341db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  DCHECK(orig != NULL);
342db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  DCHECK(copy != NULL);
3430cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers  copy->SetClass(down_cast<Class*>(GetImageAddress(orig->GetClass())));
3449cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom  // TODO: special case init of pointers to malloc data (or removal of these pointers)
3459cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom  if (orig->IsClass()) {
3469cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom    FixupClass(orig->AsClass(), down_cast<Class*>(copy));
3479cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom  } else if (orig->IsObjectArray()) {
348db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    FixupObjectArray(orig->AsObjectArray<Object>(), down_cast<ObjectArray<Object>*>(copy));
349161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  } else if (orig->IsMethod()) {
350161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom    FixupMethod(orig->AsMethod(), down_cast<Method*>(copy));
351db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  } else {
352db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    FixupInstanceFields(orig, copy);
353db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  }
354db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
355db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
3564873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupClass(const Class* orig, Class* copy) {
3579cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom  FixupInstanceFields(orig, copy);
3584873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom  FixupStaticFields(orig, copy);
3599cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom}
3609cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom
361ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromstatic uint32_t FixupCode(const ByteArray* copy_code_array, uint32_t orig_code) {
36269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  // TODO: change to DCHECK when all code compiling
36369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  if (copy_code_array == NULL) {
364ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return 0;
36569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
366ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  uint32_t copy_code = reinterpret_cast<uint32_t>(copy_code_array->GetData());
36769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  // TODO: remember InstructionSet with each code array so we know if we need to do thumb fixup?
368ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  if ((orig_code % 2) == 1) {
369ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    return copy_code + 1;
37069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
37169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  return copy_code;
37269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom}
37369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
3744873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupMethod(const Method* orig, Method* copy) {
375a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom  FixupInstanceFields(orig, copy);
376e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
3773320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  // OatWriter replaces the code_ and invoke_stub_ with offset values.
37830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  // Here we readjust to a pointer relative to oat_begin_
3793320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
3803320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  // Every type of method can have an invoke stub
3813320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  uint32_t invoke_stub_offset = orig->GetOatInvokeStubOffset();
382ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  const byte* invoke_stub = GetOatAddress(invoke_stub_offset);
3833320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  copy->invoke_stub_ = reinterpret_cast<const Method::InvokeStub*>(invoke_stub);
3843320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
3853320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  if (orig->IsAbstract()) {
3863320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    // Abstract methods are pointed to a stub that will throw AbstractMethodError if they are called
3873320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    ByteArray* orig_ame_stub_array_ = Runtime::Current()->GetAbstractMethodErrorStubArray();
3883320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    ByteArray* copy_ame_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_ame_stub_array_));
3893320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    copy->code_ = copy_ame_stub_array_->GetData();
3903320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    return;
3913320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  }
3923320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
3933320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  // Non-abstract methods typically have code
3943320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  uint32_t code_offset = orig->GetOatCodeOffset();
395ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom  const byte* code = GetOatAddress(code_offset);
3963320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom  copy->code_ = code;
3973320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
398161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  if (orig->IsNative()) {
3993320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    // The native method's pointer is directed to a stub to lookup via dlsym.
4003320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    // Note this is not the code_ pointer, that is handled above.
401169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers    ByteArray* orig_jni_stub_array_ = Runtime::Current()->GetJniDlsymLookupStub();
402161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom    ByteArray* copy_jni_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_jni_stub_array_));
403161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom    copy->native_method_ = copy_jni_stub_array_->GetData();
404161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  } else {
4053320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    // normal (non-abstract non-native) methods have mapping tables to relocate
4063320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    uint32_t mapping_table_off = orig->GetOatMappingTableOffset();
407ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const byte* mapping_table = GetOatAddress(mapping_table_off);
4083320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    copy->mapping_table_ = reinterpret_cast<const uint32_t*>(mapping_table);
4093320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
4103320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    uint32_t vmap_table_offset = orig->GetOatVmapTableOffset();
411ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const byte* vmap_table = GetOatAddress(vmap_table_offset);
4123320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom    copy->vmap_table_ = reinterpret_cast<const uint16_t*>(vmap_table);
413e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
414e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    uint32_t gc_map_offset = orig->GetOatGcMapOffset();
415e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    const byte* gc_map = GetOatAddress(gc_map_offset);
416e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    copy->gc_map_ = reinterpret_cast<const uint8_t*>(gc_map);
417161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom  }
418a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom}
419a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom
4204873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy) {
421d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes  for (int32_t i = 0; i < orig->GetLength(); ++i) {
422db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    const Object* element = orig->Get(i);
4230cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers    copy->SetWithoutChecks(i, GetImageAddress(element));
424db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  }
425db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
426db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
4274873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupInstanceFields(const Object* orig, Object* copy) {
4284873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom  DCHECK(orig != NULL);
4294873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom  DCHECK(copy != NULL);
4304873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom  Class* klass = orig->GetClass();
4314873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom  DCHECK(klass != NULL);
4324873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom  FixupFields(orig,
4334873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom              copy,
4344873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom              klass->GetReferenceInstanceOffsets(),
4354873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom              false);
4364873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom}
4374873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom
4384873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupStaticFields(const Class* orig, Class* copy) {
4394873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom  DCHECK(orig != NULL);
4404873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom  DCHECK(copy != NULL);
4414873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom  FixupFields(orig,
4424873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom              copy,
4434873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom              orig->GetReferenceStaticOffsets(),
4444873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom              true);
4454873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom}
4464873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom
4474873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupFields(const Object* orig,
4484873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom                              Object* copy,
4494873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom                              uint32_t ref_offsets,
4504873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom                              bool is_static) {
451db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  if (ref_offsets != CLASS_WALK_SUPER) {
452db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    // Found a reference offset bitmap.  Fixup the specified offsets.
453db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    while (ref_offsets != 0) {
454db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom      size_t right_shift = CLZ(ref_offsets);
4550cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers      MemberOffset byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
4560cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers      const Object* ref = orig->GetFieldObject<const Object*>(byte_offset, false);
4570cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers      copy->SetFieldObject(byte_offset, GetImageAddress(ref), false);
458db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom      ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
459db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    }
460db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  } else {
4614873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom    // There is no reference offset bitmap.  In the non-static case,
4624873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom    // walk up the class inheritance hierarchy and find reference
4634873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom    // offsets the hard way. In the static case, just consider this
4644873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom    // class.
4654873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom    for (const Class *klass = is_static ? orig->AsClass() : orig->GetClass();
466db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom         klass != NULL;
4674873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom         klass = is_static ? NULL : klass->GetSuperClass()) {
4684873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom      size_t num_reference_fields = (is_static
4694873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom                                     ? klass->NumReferenceStaticFields()
4704873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom                                     : klass->NumReferenceInstanceFields());
4714873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom      for (size_t i = 0; i < num_reference_fields; ++i) {
4724873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom        Field* field = (is_static
4734873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom                        ? klass->GetStaticField(i)
4744873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom                        : klass->GetInstanceField(i));
4750cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers        MemberOffset field_offset = field->GetOffset();
4760cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers        const Object* ref = orig->GetFieldObject<const Object*>(field_offset, false);
4770cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers        copy->SetFieldObject(field_offset, GetImageAddress(ref), false);
478db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom      }
479db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom    }
480db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom  }
481db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}
482db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom
48369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstromvoid ImageWriter::FixupDexCaches() {
48469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  typedef Set::const_iterator It;  // TODO: C++0x auto
48569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  for (It it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it) {
48669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    DexCache* orig = *it;
48769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    DexCache* copy = down_cast<DexCache*>(GetLocalAddress(orig));
48869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    FixupDexCache(orig, copy);
48969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
49069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom}
49169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
49269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstromvoid ImageWriter::FixupDexCache(const DexCache* orig, DexCache* copy) {
49369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  CHECK(orig != NULL);
49469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  CHECK(copy != NULL);
49569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
496ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  // The original array value
49769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  CodeAndDirectMethods* orig_cadms = orig->GetCodeAndDirectMethods();
498ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  // The compacted object in local memory but not at the correct image address
49969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  CodeAndDirectMethods* copy_cadms = down_cast<CodeAndDirectMethods*>(GetLocalAddress(orig_cadms));
500ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers
5011cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  Runtime* runtime = Runtime::Current();
50269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  for (size_t i = 0; i < orig->NumResolvedMethods(); i++) {
50369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    Method* orig_method = orig->GetResolvedMethod(i);
504ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    if (orig_method != NULL && !InSourceSpace(orig_method)) {
505ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers      continue;
506ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    }
507ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    // if it was unresolved or a resolved static method in an uninit class, use a resolution stub
508ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    // we need to use the stub in the static method case to ensure <clinit> is run.
509c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes    if (orig_method == NULL
510ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom        || (orig_method->IsStatic() && !orig_method->GetDeclaringClass()->IsInitialized())) {
5111cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      uint32_t orig_res_stub_code = orig_cadms->Get(CodeAndDirectMethods::CodeIndex(i));
5121cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      if (orig_res_stub_code == 0) {
5131cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers        continue;  // NULL maps the same in the image and the original
5141cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      }
5151cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      Runtime::TrampolineType type = Runtime::GetTrampolineType(orig_method);  // Type of trampoline
5161cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      ByteArray* orig_res_stub_array = runtime->GetResolutionStubArray(type);
517ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers      // Do we need to relocate this for this space?
5181cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      if (!InSourceSpace(orig_res_stub_array)) {
5191cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers        continue;
5201cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      }
5211cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      // Compute address in image of resolution stub and the code address
5221cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      ByteArray* image_res_stub_array = down_cast<ByteArray*>(GetImageAddress(orig_res_stub_array));
523ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      uint32_t image_res_stub_code = FixupCode(image_res_stub_array, orig_res_stub_code);
5241cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      // Put the image code address in the array
5251cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers      copy_cadms->Set(CodeAndDirectMethods::CodeIndex(i), image_res_stub_code);
526ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers    } else if (orig_method->IsDirect()) {
527ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom      // if it was resolved in the original, resolve it in the copy
52869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      Method* copy_method = down_cast<Method*>(GetLocalAddress(orig_method));
52969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      copy_cadms->Set(CodeAndDirectMethods::CodeIndex(i),
53069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom                      reinterpret_cast<int32_t>(copy_method->code_));
53169b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom      copy_cadms->Set(CodeAndDirectMethods::MethodIndex(i),
53269b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom                      reinterpret_cast<int32_t>(GetImageAddress(orig_method)));
53369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom    }
53469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom  }
53569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom}
53669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom
537db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom}  // namespace art
538