image_writer.cc revision b062fdd4cb097fbae69b4bcb479c34d83ecab8ca
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 16db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 17db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "image_writer.h" 18db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 196cd40e5cc59259a0b7636eb5532c76de9b8a7286Brian Carlstrom#include <sys/stat.h> 2090a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes 21db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include <vector> 22db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 23a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom#include "class_linker.h" 241f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "class_loader.h" 25ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom#include "compiled_method.h" 26f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom#include "compiler.h" 2790a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes#include "dex_cache.h" 28db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "file.h" 29db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "globals.h" 30db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "heap.h" 314a289ed61242964b921434de7d375f46480472a1Brian Carlstrom#include "image.h" 32a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom#include "intern_table.h" 33db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "logging.h" 340c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien#include "oat_file.h" 35db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "object.h" 366d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h" 371f87008b165d26541d832ff805250afdc89c253dBrian Carlstrom#include "runtime.h" 38db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "space.h" 39a168c83a1d247094e9efb1244b0f73a5f1e1ed97Elliott Hughes#include "UniquePtr.h" 40db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom#include "utils.h" 41db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 42db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstromnamespace art { 43db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 44a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrombool ImageWriter::Write(const std::string& image_filename, 4530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers uintptr_t image_begin, 46ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom const std::string& oat_filename, 47f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom const std::string& oat_location, 48f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom const Compiler& compiler) { 49a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom CHECK(!image_filename.empty()); 50aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 5130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers CHECK_NE(image_begin, 0U); 5230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers image_begin_ = reinterpret_cast<byte*>(image_begin); 5369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom 54b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes Heap* heap = Runtime::Current()->GetHeap(); 55b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier const Spaces& spaces = heap->GetSpaces(); 5669b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom 57ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 58ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom const std::vector<DexCache*>& all_dex_caches = class_linker->GetDexCaches(); 59ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom for (size_t i = 0; i < all_dex_caches.size(); i++) { 60ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom DexCache* dex_cache = all_dex_caches[i]; 61ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (InSourceSpace(dex_cache)) { 62ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom dex_caches_.insert(dex_cache); 63ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 64ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 65ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 660c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien oat_file_ = OatFile::Open(oat_filename, oat_location, NULL, 670c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien OatFile::kRelocNone, true); 68f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom if (oat_file_ == NULL) { 69e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom LOG(ERROR) << "Failed to open oat file " << oat_filename; 70e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 71e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 72b25c3f6a86dc634ce44fb2849385b49465caa84dElliott Hughes class_linker->RegisterOatFile(*oat_file_); 73e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 74d857b632cb23846ef656c330b89c4d1cb727116eIan Rogers PruneNonImageClasses(); // Remove junk 75d857b632cb23846ef656c330b89c4d1cb727116eIan Rogers ComputeLazyFieldsForImageClasses(); // Add useful information 76d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers ComputeEagerResolvedStrings(); 77b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes heap->CollectGarbage(false); // Remove garbage 78b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier // Trim size of alloc spaces 79b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier // TODO: C++0x auto 80b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier for (Spaces::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) { 81b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier if ((*cur)->IsAllocSpace()) { 82b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier (*cur)->AsAllocSpace()->Trim(); 83b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier } 84b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier } 85b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier 86ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (!AllocMemory()) { 87db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom return false; 88db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 89ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom#ifndef NDEBUG 90ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom CheckNonImageClassesRemoved(); 91ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom#endif 92b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes heap->DisableCardMarking(); 93db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom CalculateNewObjectOffsets(); 94db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom CopyAndFixupObjects(); 95f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom PatchOatCodeAndMethods(compiler); 96d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes 97a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom UniquePtr<File> file(OS::OpenFile(image_filename.c_str(), true)); 9890a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes if (file.get() == NULL) { 99e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom LOG(ERROR) << "Failed to open image file " << image_filename; 100db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom return false; 101db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 1026cd40e5cc59259a0b7636eb5532c76de9b8a7286Brian Carlstrom if (fchmod(file->Fd(), 0644) != 0) { 1036cd40e5cc59259a0b7636eb5532c76de9b8a7286Brian Carlstrom PLOG(ERROR) << "Failed to make image file world readable: " << image_filename; 1046cd40e5cc59259a0b7636eb5532c76de9b8a7286Brian Carlstrom return EXIT_FAILURE; 1056cd40e5cc59259a0b7636eb5532c76de9b8a7286Brian Carlstrom } 10630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers bool success = file->WriteFully(image_->Begin(), image_end_); 107e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!success) { 108e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to write image file " << image_filename; 109e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 110e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 111e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 112db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 113db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 114b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartierbool ImageWriter::InSourceSpace(const Object* object) const { 115b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier const Spaces& spaces = Runtime::Current()->GetHeap()->GetSpaces(); 116b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier // TODO: C++0x auto 117b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier for (Spaces::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) { 118b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier if ((*cur)->IsAllocSpace() && (*cur)->Contains(object)) { 119b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier return true; 120b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier } 121b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier } 122b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier return false; 123b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier} 124b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier 125ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrombool ImageWriter::AllocMemory() { 126b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier typedef std::vector<Space*> SpaceVec; 127b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier const SpaceVec& spaces = Runtime::Current()->GetHeap()->GetSpaces(); 128b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier size_t size = 0; 129b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier for (SpaceVec::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) { 130b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier if ((*cur)->IsAllocSpace()) { 131b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier size += (*cur)->Size(); 132b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier } 133b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier } 134b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier 135db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom int prot = PROT_READ | PROT_WRITE; 136db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom size_t length = RoundUp(size, kPageSize); 13789521898b56f2ebc3fb68acfb6bc6dde9b6f5c38Brian Carlstrom image_.reset(MemMap::MapAnonymous("image-writer-image", NULL, length, prot)); 13890a3369d3b6238f1a4c9b19ca68978dab1c39bc4Elliott Hughes if (image_.get() == NULL) { 139e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom LOG(ERROR) << "Failed to allocate memory for image file generation"; 140db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom return false; 141db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 142db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom return true; 143db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 144db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 145d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogersvoid ImageWriter::ComputeLazyFieldsForImageClasses() { 146d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers Runtime* runtime = Runtime::Current(); 147d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers ClassLinker* class_linker = runtime->GetClassLinker(); 148d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers class_linker->VisitClasses(ComputeLazyFieldsForClassesVisitor, NULL); 149d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers} 150d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers 1511bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesbool ImageWriter::ComputeLazyFieldsForClassesVisitor(Class* c, void* /*arg*/) { 1521bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes c->ComputeName(); 153d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers return true; 154d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers} 155d418edaf4df0a410d678389e171ac6d96ae2af15Ian Rogers 156d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogersvoid ImageWriter::ComputeEagerResolvedStringsCallback(Object* obj, void* arg) { 157d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers if (!obj->GetClass()->IsStringClass()) { 158d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers return; 159d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers } 160d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers String* string = obj->AsString(); 161d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers std::string utf8_string(string->ToModifiedUtf8()); 162d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers ImageWriter* writer = reinterpret_cast<ImageWriter*>(arg); 163d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers ClassLinker* linker = Runtime::Current()->GetClassLinker(); 164d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers typedef Set::const_iterator CacheIt; // TODO: C++0x auto 165d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers for (CacheIt it = writer->dex_caches_.begin(), end = writer->dex_caches_.end(); it != end; ++it) { 166d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers DexCache* dex_cache = *it; 167d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers const DexFile& dex_file = linker->FindDexFile(dex_cache); 168d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers const DexFile::StringId* string_id = dex_file.FindStringId(utf8_string); 169d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers if (string_id != NULL) { 170d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers // This string occurs in this dex file, assign the dex cache entry. 171d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers uint32_t string_idx = dex_file.GetIndexForStringId(*string_id); 172d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers if (dex_cache->GetResolvedString(string_idx) == NULL) { 173d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers dex_cache->SetResolvedString(string_idx, string); 174d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers } 175d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers } 176d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers } 177d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers} 178d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers 179d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogersvoid ImageWriter::ComputeEagerResolvedStrings() { 180b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier // TODO: Check image spaces only? 181b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier Runtime::Current()->GetHeap()->GetLiveBitmap()->Walk(ComputeEagerResolvedStringsCallback, this); 182d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers} 183d1f1bf03e30320e5730790678f470ac8a610b6b6Ian Rogers 184ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrombool ImageWriter::IsImageClass(const Class* klass) { 185ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (image_classes_ == NULL) { 186ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom return true; 187ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 188ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom while (klass->IsArrayClass()) { 189ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom klass = klass->GetComponentType(); 190ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 191c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes if (klass->IsPrimitive()) { 192ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom return true; 193ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 1946d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers const std::string descriptor(ClassHelper(klass).GetDescriptor()); 195ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom return image_classes_->find(descriptor) != image_classes_->end(); 196ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom} 197ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 198ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 199ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromstruct NonImageClasses { 200ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom ImageWriter* image_writer; 201ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom std::set<std::string>* non_image_classes; 202ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom}; 203ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 204ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid ImageWriter::PruneNonImageClasses() { 205ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (image_classes_ == NULL) { 206ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom return; 207ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 208ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom Runtime* runtime = Runtime::Current(); 209ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom ClassLinker* class_linker = runtime->GetClassLinker(); 210ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 211ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom std::set<std::string> non_image_classes; 212ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom NonImageClasses context; 213ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom context.image_writer = this; 214ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom context.non_image_classes = &non_image_classes; 215ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom class_linker->VisitClasses(NonImageClassesVisitor, &context); 216ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 217ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom typedef std::set<std::string>::const_iterator ClassIt; // TODO: C++0x auto 218ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom for (ClassIt it = non_image_classes.begin(), end = non_image_classes.end(); it != end; ++it) { 219c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes class_linker->RemoveClass((*it).c_str(), NULL); 220ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 221ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 2221984651929744dd603fd082e23eacd877b9bc177Ian Rogers Method* resolution_method = runtime->GetResolutionMethod(); 223ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom typedef Set::const_iterator CacheIt; // TODO: C++0x auto 224ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom for (CacheIt it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it) { 225ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom DexCache* dex_cache = *it; 226ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) { 227ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom Class* klass = dex_cache->GetResolvedType(i); 228ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (klass != NULL && !IsImageClass(klass)) { 229ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom dex_cache->SetResolvedType(i, NULL); 230ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom dex_cache->GetInitializedStaticStorage()->Set(i, NULL); 231ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 232ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 233ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) { 234ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom Method* method = dex_cache->GetResolvedMethod(i); 235ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (method != NULL && !IsImageClass(method->GetDeclaringClass())) { 2361984651929744dd603fd082e23eacd877b9bc177Ian Rogers dex_cache->SetResolvedMethod(i, resolution_method); 237ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 238ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 239ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom for (size_t i = 0; i < dex_cache->NumResolvedFields(); i++) { 240ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom Field* field = dex_cache->GetResolvedField(i); 241ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (field != NULL && !IsImageClass(field->GetDeclaringClass())) { 242ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom dex_cache->SetResolvedField(i, NULL); 243ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 244ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 245ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 246ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom} 247ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 248ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrombool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) { 249ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg); 250ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (!context->image_writer->IsImageClass(klass)) { 2516d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers context->non_image_classes->insert(ClassHelper(klass).GetDescriptor()); 252ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 253ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom return true; 254ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom} 255ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 256ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid ImageWriter::CheckNonImageClassesRemoved() { 257ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (image_classes_ == NULL) { 258ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom return; 259ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 260b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier 261b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier Runtime::Current()->GetHeap()->GetLiveBitmap()->Walk(CheckNonImageClassesRemovedCallback, this); 262ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom} 263ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 264ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstromvoid ImageWriter::CheckNonImageClassesRemovedCallback(Object* obj, void* arg) { 265ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); 266ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom if (!obj->IsClass()) { 267ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom return; 268ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom } 269ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom Class* klass = obj->AsClass(); 270c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes if (!image_writer->IsImageClass(klass)) { 271c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes image_writer->DumpImageClasses(); 272c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes CHECK(image_writer->IsImageClass(klass)) << ClassHelper(klass).GetDescriptor() 273c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes << " " << PrettyDescriptor(klass); 274c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes } 275c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes} 276c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes 277c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughesvoid ImageWriter::DumpImageClasses() { 278c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes typedef std::set<std::string>::const_iterator It; // TODO: C++0x auto 279c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes for (It it = image_classes_->begin(), end = image_classes_->end(); it != end; ++it) { 280c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes LOG(INFO) << " " << *it; 281c3b77c7c2971124cbf3b2d9da64e7a8a9a649f2eElliott Hughes } 282ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom} 283ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom 28478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromvoid ImageWriter::CalculateNewObjectOffsetsCallback(Object* obj, void* arg) { 2854e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom DCHECK(obj != NULL); 2864e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom DCHECK(arg != NULL); 2874e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); 28869b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom if (!image_writer->InSourceSpace(obj)) { 28969b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom return; 29069b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom } 291c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom 292c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom // if it is a string, we want to intern it if its not interned. 293dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes if (obj->GetClass()->IsStringClass()) { 294c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom // we must be an interned string that was forward referenced and already assigned 295b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes if (image_writer->IsImageOffsetAssigned(obj)) { 296c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom DCHECK_EQ(obj, obj->AsString()->Intern()); 297c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom return; 298c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom } 29940381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom SirtRef<String> interned(obj->AsString()->Intern()); 30040381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom if (obj != interned.get()) { 301b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes if (!image_writer->IsImageOffsetAssigned(interned.get())) { 302c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom // interned obj is after us, allocate its location early 30340381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom image_writer->AssignImageOffset(interned.get()); 304c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom } 305c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom // point those looking for this object to the interned version. 306b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes image_writer->SetImageOffset(obj, image_writer->GetImageOffset(interned.get())); 307c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom return; 308c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom } 309c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom // else (obj == interned), nothing to do but fall through to the normal case 310c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom } 311c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom 312c74255fffb035001304c9a058a2e730a5a1a9604Brian Carlstrom image_writer->AssignImageOffset(obj); 3134e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom} 3144e777d4e005375a5a41c4ec3c55783c09565df0dBrian Carlstrom 315e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromObjectArray<Object>* ImageWriter::CreateImageRoots() const { 316161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom Runtime* runtime = Runtime::Current(); 317161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom ClassLinker* class_linker = runtime->GetClassLinker(); 318161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom Class* object_array_class = class_linker->FindSystemClass("[Ljava/lang/Object;"); 31958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom 32058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom // build an Object[] of all the DexCaches used in the source_space_ 32158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom ObjectArray<Object>* dex_caches = ObjectArray<Object>::Alloc(object_array_class, 322ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom dex_caches_.size()); 323ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom int i = 0; 324ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom typedef Set::const_iterator It; // TODO: C++0x auto 325ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom for (It it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it, ++i) { 326ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom dex_caches->Set(i, *it); 32758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom } 32858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom 32958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom // build an Object[] of the roots needed to restore the runtime 33040381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom SirtRef<ObjectArray<Object> > image_roots( 33140381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom ObjectArray<Object>::Alloc(object_array_class, ImageHeader::kImageRootsMax)); 332169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers image_roots->Set(ImageHeader::kJniStubArray, runtime->GetJniDlsymLookupStub()); 333e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom image_roots->Set(ImageHeader::kAbstractMethodErrorStubArray, 334e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom runtime->GetAbstractMethodErrorStubArray()); 3351cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers image_roots->Set(ImageHeader::kStaticResolutionStubArray, 3361cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers runtime->GetResolutionStubArray(Runtime::kStaticMethod)); 3371cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers image_roots->Set(ImageHeader::kUnknownMethodResolutionStubArray, 3381cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers runtime->GetResolutionStubArray(Runtime::kUnknownMethod)); 3391984651929744dd603fd082e23eacd877b9bc177Ian Rogers image_roots->Set(ImageHeader::kResolutionMethod, runtime->GetResolutionMethod()); 3404f0d07c783afef89703dce32c94440fc8621a29bIan Rogers image_roots->Set(ImageHeader::kCalleeSaveMethod, 3414f0d07c783afef89703dce32c94440fc8621a29bIan Rogers runtime->GetCalleeSaveMethod(Runtime::kSaveAll)); 3424f0d07c783afef89703dce32c94440fc8621a29bIan Rogers image_roots->Set(ImageHeader::kRefsOnlySaveMethod, 3434f0d07c783afef89703dce32c94440fc8621a29bIan Rogers runtime->GetCalleeSaveMethod(Runtime::kRefsOnly)); 3444f0d07c783afef89703dce32c94440fc8621a29bIan Rogers image_roots->Set(ImageHeader::kRefsAndArgsSaveMethod, 3454f0d07c783afef89703dce32c94440fc8621a29bIan Rogers runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs)); 346e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom image_roots->Set(ImageHeader::kOatLocation, 347e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom String::AllocFromModifiedUtf8(oat_file_->GetLocation().c_str())); 34858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom image_roots->Set(ImageHeader::kDexCaches, 34958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom dex_caches); 35034f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom image_roots->Set(ImageHeader::kClassRoots, 35134f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom class_linker->GetClassRoots()); 352e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (int i = 0; i < ImageHeader::kImageRootsMax; i++) { 353e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(image_roots->Get(i) != NULL); 354e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 35540381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom return image_roots.get(); 356161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom} 357161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom 358db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstromvoid ImageWriter::CalculateNewObjectOffsets() { 35940381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom SirtRef<ObjectArray<Object> > image_roots(CreateImageRoots()); 360161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom 361b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier Heap* heap = Runtime::Current()->GetHeap(); 362b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier typedef std::vector<Space*> SpaceVec; 363b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier const SpaceVec& spaces = heap->GetSpaces(); 364b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier DCHECK(!spaces.empty()); 36530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers DCHECK_EQ(0U, image_end_); 366a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom 367161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom // leave space for the header, but do not write it yet, we need to 368161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom // know where image_roots is going to end up 36930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers image_end_ += RoundUp(sizeof(ImageHeader), 8); // 64-bit-alignment 370a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom 371b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier // TODO: Image spaces only? 372b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier for (SpaceVec::const_iterator cur = spaces.begin(); cur != spaces.end(); ++cur) { 373b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier (*cur)->GetLiveBitmap()->InOrderWalk(CalculateNewObjectOffsetsCallback, this); 374b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier DCHECK_LT(image_end_, image_->Size()); 375b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier } 376a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom 377e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // Note that image_top_ is left at end of used space 37830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers oat_begin_ = image_begin_ + RoundUp(image_end_, kPageSize); 37930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers const byte* oat_limit = oat_begin_ + oat_file_->Size(); 380e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 381161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom // return to write header at start of image with future location of image_roots 38230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers ImageHeader image_header(reinterpret_cast<uint32_t>(image_begin_), 38340381fb9dc4b4cf274f1e58b2cdf4396202c6189Brian Carlstrom reinterpret_cast<uint32_t>(GetImageAddress(image_roots.get())), 384e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_file_->GetOatHeader().GetChecksum(), 38530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers reinterpret_cast<uint32_t>(oat_begin_), 386e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom reinterpret_cast<uint32_t>(oat_limit)); 38730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers memcpy(image_->Begin(), &image_header, sizeof(image_header)); 388db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 389db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 390db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstromvoid ImageWriter::CopyAndFixupObjects() { 391b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes Heap* heap = Runtime::Current()->GetHeap(); 3920cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers // TODO: heap validation can't handle this fix up pass 393b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes heap->DisableObjectValidation(); 394b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier // TODO: Image spaces only? 395b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier heap->GetLiveBitmap()->Walk(CopyAndFixupObjectsCallback, this); 396db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 397db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 39878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromvoid ImageWriter::CopyAndFixupObjectsCallback(Object* object, void* arg) { 3994873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom DCHECK(object != NULL); 400db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom DCHECK(arg != NULL); 4014873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom const Object* obj = object; 402db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); 40369b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom if (!image_writer->InSourceSpace(object)) { 40469b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom return; 40569b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom } 406d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes 40769b15fb098162f19a4c20e6dccdcead04d9c77f0Brian Carlstrom // see GetLocalAddress for similar computation 408db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom size_t offset = image_writer->GetImageOffset(obj); 40930fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers byte* dst = image_writer->image_->Begin() + offset; 4104873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom const byte* src = reinterpret_cast<const byte*>(obj); 41104b63fd60de0d9e6f07763511a1a9622accfeed7Elliott Hughes size_t n = obj->SizeOf(); 41230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers DCHECK_LT(offset + n, image_writer->image_->Size()); 413db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom memcpy(dst, src, n); 414db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom Object* copy = reinterpret_cast<Object*>(dst); 415d9c67be7c116875d96b31e640ad47d587b205605Elliott Hughes copy->monitor_ = 0; // We may have inflated the lock during compilation. 416db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom image_writer->FixupObject(obj, copy); 417db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 418db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 4194873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupObject(const Object* orig, Object* copy) { 420db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom DCHECK(orig != NULL); 421db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom DCHECK(copy != NULL); 4220cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers copy->SetClass(down_cast<Class*>(GetImageAddress(orig->GetClass()))); 4239cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom // TODO: special case init of pointers to malloc data (or removal of these pointers) 4249cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom if (orig->IsClass()) { 4259cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom FixupClass(orig->AsClass(), down_cast<Class*>(copy)); 4269cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom } else if (orig->IsObjectArray()) { 427db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom FixupObjectArray(orig->AsObjectArray<Object>(), down_cast<ObjectArray<Object>*>(copy)); 428161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom } else if (orig->IsMethod()) { 429161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom FixupMethod(orig->AsMethod(), down_cast<Method*>(copy)); 430db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } else { 431db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom FixupInstanceFields(orig, copy); 432db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 433db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 434db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 4354873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupClass(const Class* orig, Class* copy) { 4369cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom FixupInstanceFields(orig, copy); 4374873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom FixupStaticFields(orig, copy); 4389cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom} 4399cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom 4404873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupMethod(const Method* orig, Method* copy) { 441a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom FixupInstanceFields(orig, copy); 442e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 4433320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // OatWriter replaces the code_ and invoke_stub_ with offset values. 44430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers // Here we readjust to a pointer relative to oat_begin_ 4453320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 4463320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // Every type of method can have an invoke stub 4473320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t invoke_stub_offset = orig->GetOatInvokeStubOffset(); 448ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom const byte* invoke_stub = GetOatAddress(invoke_stub_offset); 4493320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom copy->invoke_stub_ = reinterpret_cast<const Method::InvokeStub*>(invoke_stub); 4503320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 4513320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (orig->IsAbstract()) { 4523320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // Abstract methods are pointed to a stub that will throw AbstractMethodError if they are called 4533320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom ByteArray* orig_ame_stub_array_ = Runtime::Current()->GetAbstractMethodErrorStubArray(); 4543320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom ByteArray* copy_ame_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_ame_stub_array_)); 4553320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom copy->code_ = copy_ame_stub_array_->GetData(); 4563320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return; 4573320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 4583320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 4591984651929744dd603fd082e23eacd877b9bc177Ian Rogers if (orig == Runtime::Current()->GetResolutionMethod()) { 4601984651929744dd603fd082e23eacd877b9bc177Ian Rogers // The resolution stub's code points at the unknown resolution trampoline 4611984651929744dd603fd082e23eacd877b9bc177Ian Rogers ByteArray* orig_res_stub_array_ = 4621984651929744dd603fd082e23eacd877b9bc177Ian Rogers Runtime::Current()->GetResolutionStubArray(Runtime::kUnknownMethod); 4631984651929744dd603fd082e23eacd877b9bc177Ian Rogers CHECK(orig->GetCode() == orig_res_stub_array_->GetData()); 4641984651929744dd603fd082e23eacd877b9bc177Ian Rogers ByteArray* copy_res_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_res_stub_array_)); 4651984651929744dd603fd082e23eacd877b9bc177Ian Rogers copy->code_ = copy_res_stub_array_->GetData(); 4661984651929744dd603fd082e23eacd877b9bc177Ian Rogers return; 4671984651929744dd603fd082e23eacd877b9bc177Ian Rogers } 4681984651929744dd603fd082e23eacd877b9bc177Ian Rogers 4693320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // Non-abstract methods typically have code 4703320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t code_offset = orig->GetOatCodeOffset(); 4711984651929744dd603fd082e23eacd877b9bc177Ian Rogers const byte* code = NULL; 4721984651929744dd603fd082e23eacd877b9bc177Ian Rogers if (orig->IsStatic()) { 4731984651929744dd603fd082e23eacd877b9bc177Ian Rogers // Static methods may point at the resolution trampoline stub 4741984651929744dd603fd082e23eacd877b9bc177Ian Rogers ByteArray* orig_res_stub_array_ = 4751984651929744dd603fd082e23eacd877b9bc177Ian Rogers Runtime::Current()->GetResolutionStubArray(Runtime::kStaticMethod); 4761984651929744dd603fd082e23eacd877b9bc177Ian Rogers if (reinterpret_cast<int8_t*>(code_offset) == orig_res_stub_array_->GetData()) { 4771984651929744dd603fd082e23eacd877b9bc177Ian Rogers ByteArray* copy_res_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_res_stub_array_)); 4781984651929744dd603fd082e23eacd877b9bc177Ian Rogers code = reinterpret_cast<const byte*>(copy_res_stub_array_->GetData()); 4791984651929744dd603fd082e23eacd877b9bc177Ian Rogers } 4801984651929744dd603fd082e23eacd877b9bc177Ian Rogers } 4811984651929744dd603fd082e23eacd877b9bc177Ian Rogers if (code == NULL) { 4821984651929744dd603fd082e23eacd877b9bc177Ian Rogers code = GetOatAddress(code_offset); 4831984651929744dd603fd082e23eacd877b9bc177Ian Rogers } 4843320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom copy->code_ = code; 4853320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 486161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom if (orig->IsNative()) { 4873320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // The native method's pointer is directed to a stub to lookup via dlsym. 4883320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // Note this is not the code_ pointer, that is handled above. 489169c9a7f46776b235d0a37d5e0ff27682deffe06Ian Rogers ByteArray* orig_jni_stub_array_ = Runtime::Current()->GetJniDlsymLookupStub(); 490161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom ByteArray* copy_jni_stub_array_ = down_cast<ByteArray*>(GetImageAddress(orig_jni_stub_array_)); 491161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom copy->native_method_ = copy_jni_stub_array_->GetData(); 492161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom } else { 4933320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // normal (non-abstract non-native) methods have mapping tables to relocate 4943320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t mapping_table_off = orig->GetOatMappingTableOffset(); 495ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom const byte* mapping_table = GetOatAddress(mapping_table_off); 4963320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom copy->mapping_table_ = reinterpret_cast<const uint32_t*>(mapping_table); 4973320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 4983320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t vmap_table_offset = orig->GetOatVmapTableOffset(); 499ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom const byte* vmap_table = GetOatAddress(vmap_table_offset); 5003320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom copy->vmap_table_ = reinterpret_cast<const uint16_t*>(vmap_table); 501e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom 502e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom uint32_t gc_map_offset = orig->GetOatGcMapOffset(); 503e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom const byte* gc_map = GetOatAddress(gc_map_offset); 504e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom copy->gc_map_ = reinterpret_cast<const uint8_t*>(gc_map); 505161928613d3f097108319de60494fab1aab8d48aBrian Carlstrom } 506a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom} 507a663ea5de4c9ab6b1510fdebd6d8eca77ba699aeBrian Carlstrom 5084873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy) { 509d8ddfd5eadde1d5f53ef1419f529c799233eaa62Elliott Hughes for (int32_t i = 0; i < orig->GetLength(); ++i) { 510db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom const Object* element = orig->Get(i); 5110cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers copy->SetWithoutChecks(i, GetImageAddress(element)); 512db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 513db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 514db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 5154873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupInstanceFields(const Object* orig, Object* copy) { 5164873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom DCHECK(orig != NULL); 5174873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom DCHECK(copy != NULL); 5184873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom Class* klass = orig->GetClass(); 5194873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom DCHECK(klass != NULL); 5204873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom FixupFields(orig, 5214873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom copy, 5224873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom klass->GetReferenceInstanceOffsets(), 5234873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom false); 5244873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom} 5254873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom 5264873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupStaticFields(const Class* orig, Class* copy) { 5274873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom DCHECK(orig != NULL); 5284873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom DCHECK(copy != NULL); 5294873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom FixupFields(orig, 5304873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom copy, 5314873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom orig->GetReferenceStaticOffsets(), 5324873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom true); 5334873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom} 5344873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom 5354873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstromvoid ImageWriter::FixupFields(const Object* orig, 5364873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom Object* copy, 5374873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom uint32_t ref_offsets, 5384873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom bool is_static) { 539db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom if (ref_offsets != CLASS_WALK_SUPER) { 540db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom // Found a reference offset bitmap. Fixup the specified offsets. 541db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom while (ref_offsets != 0) { 542db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom size_t right_shift = CLZ(ref_offsets); 5430cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers MemberOffset byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift); 5440cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers const Object* ref = orig->GetFieldObject<const Object*>(byte_offset, false); 5450cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers copy->SetFieldObject(byte_offset, GetImageAddress(ref), false); 546db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift); 547db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 548db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } else { 5494873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom // There is no reference offset bitmap. In the non-static case, 5504873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom // walk up the class inheritance hierarchy and find reference 5514873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom // offsets the hard way. In the static case, just consider this 5524873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom // class. 5534873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom for (const Class *klass = is_static ? orig->AsClass() : orig->GetClass(); 554db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom klass != NULL; 5554873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom klass = is_static ? NULL : klass->GetSuperClass()) { 5564873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom size_t num_reference_fields = (is_static 5574873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom ? klass->NumReferenceStaticFields() 5584873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom : klass->NumReferenceInstanceFields()); 5594873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom for (size_t i = 0; i < num_reference_fields; ++i) { 5604873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom Field* field = (is_static 5614873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom ? klass->GetStaticField(i) 5624873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom : klass->GetInstanceField(i)); 5630cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers MemberOffset field_offset = field->GetOffset(); 5640cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers const Object* ref = orig->GetFieldObject<const Object*>(field_offset, false); 5650cfe1fb7060576d047f7f894fc0d8b87de84fcabIan Rogers copy->SetFieldObject(field_offset, GetImageAddress(ref), false); 566db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 567db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 568db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom } 569db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} 570db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom 571f582258f0e296223a091fd64231a203ad71e9649Brian Carlstromstatic Method* GetReferrerMethod(const Compiler::PatchInformation* patch) { 572f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 573f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom Method* method = class_linker->ResolveMethod(patch->GetDexFile(), 574f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom patch->GetReferrerMethodIdx(), 575f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom patch->GetDexCache(), 576f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom NULL, 577f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom patch->GetReferrerIsDirect()); 578f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom CHECK(method != NULL) 579f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx(); 5800637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom CHECK(!method->IsRuntimeMethod()) 5810637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx(); 5820637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom CHECK(patch->GetDexCache()->GetResolvedMethods()->Get(patch->GetReferrerMethodIdx()) == method) 5830637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx() << " " 5840637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom << PrettyMethod(patch->GetDexCache()->GetResolvedMethods()->Get(patch->GetReferrerMethodIdx())) << " " 5850637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom << PrettyMethod(method); 586f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom return method; 587f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom} 588f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom 589f582258f0e296223a091fd64231a203ad71e9649Brian Carlstromstatic Method* GetTargetMethod(const Compiler::PatchInformation* patch) { 590f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 591f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom Method* method = class_linker->ResolveMethod(patch->GetDexFile(), 592f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom patch->GetTargetMethodIdx(), 593f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom patch->GetDexCache(), 594f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom NULL, 595f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom patch->GetTargetIsDirect()); 596f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom CHECK(method != NULL) 597f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom << patch->GetDexFile().GetLocation() << " " << patch->GetTargetMethodIdx(); 5980637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom CHECK(!method->IsRuntimeMethod()) 5990637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom << patch->GetDexFile().GetLocation() << " " << patch->GetTargetMethodIdx(); 6000637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom CHECK(patch->GetDexCache()->GetResolvedMethods()->Get(patch->GetTargetMethodIdx()) == method) 6010637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx() << " " 6020637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom << PrettyMethod(patch->GetDexCache()->GetResolvedMethods()->Get(patch->GetTargetMethodIdx())) << " " 6030637e27af8e54f39634024dc77e8b094f21782f9Brian Carlstrom << PrettyMethod(method); 604f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom return method; 605f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom} 606f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom 607f582258f0e296223a091fd64231a203ad71e9649Brian Carlstromvoid ImageWriter::PatchOatCodeAndMethods(const Compiler& compiler) { 608f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 609f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom 610f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom const std::vector<const Compiler::PatchInformation*>& code_to_patch = compiler.GetCodeToPatch(); 611f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom for (size_t i = 0; i < code_to_patch.size(); i++) { 612f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom const Compiler::PatchInformation* patch = code_to_patch[i]; 613f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom Method* target = GetTargetMethod(patch); 614f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom uint32_t code = reinterpret_cast<uint32_t>(class_linker->GetOatCodeFor(target)); 615f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom uint32_t code_base = reinterpret_cast<uint32_t>(&oat_file_->GetOatHeader()); 616f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom uint32_t code_offset = code - code_base; 617f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetOatAddress(code_offset))); 618f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom } 619f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom 620f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom const std::vector<const Compiler::PatchInformation*>& methods_to_patch 621f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom = compiler.GetMethodsToPatch(); 622f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom for (size_t i = 0; i < methods_to_patch.size(); i++) { 623f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom const Compiler::PatchInformation* patch = methods_to_patch[i]; 624f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom Method* target = GetTargetMethod(patch); 625f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetImageAddress(target))); 626f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom } 627f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom} 628f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom 629f582258f0e296223a091fd64231a203ad71e9649Brian Carlstromvoid ImageWriter::SetPatchLocation(const Compiler::PatchInformation* patch, uint32_t value) { 630f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 631f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom Method* method = GetReferrerMethod(patch); 632f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom // Goodbye const, we are about to modify some code. 633f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom void* code = const_cast<void*>(class_linker->GetOatCodeFor(method)); 634f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom // TODO: make this Thumb2 specific 635f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uint32_t>(code) & ~0x1); 636f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom uint32_t* patch_location = reinterpret_cast<uint32_t*>(base + patch->GetLiteralOffset()); 637f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom#ifndef NDEBUG 638f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom const DexFile::MethodId& id = patch->GetDexFile().GetMethodId(patch->GetTargetMethodIdx()); 639f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom uint32_t expected = reinterpret_cast<uint32_t>(&id); 640f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom uint32_t actual = *patch_location; 641f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom CHECK(actual == expected || actual == value) << std::hex 642f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom << "actual=" << actual 643f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom << "expected=" << expected 644f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom << "value=" << value; 645f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom#endif 646b25c3f6a86dc634ce44fb2849385b49465caa84dElliott Hughes *patch_location = value; 647f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom} 648f582258f0e296223a091fd64231a203ad71e9649Brian Carlstrom 649db4d54081f09abcbe97ffdf615874f2809a9e777Brian Carlstrom} // namespace art 650