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