diff options
Diffstat (limited to 'src/image_writer.cc')
| -rw-r--r-- | src/image_writer.cc | 64 |
1 files changed, 60 insertions, 4 deletions
diff --git a/src/image_writer.cc b/src/image_writer.cc index faa13f7a60..4ba99fe3d0 100644 --- a/src/image_writer.cc +++ b/src/image_writer.cc @@ -81,6 +81,10 @@ bool ImageWriter::Write(const std::string& image_filename, } oat_file_ = OatFile::OpenWritable(oat_file.get(), oat_location); class_linker->RegisterOatFile(*oat_file_); + interpreter_to_interpreter_entry_offset_ = oat_file_->GetOatHeader().GetInterpreterToInterpreterEntryOffset(); + interpreter_to_quick_entry_offset_ = oat_file_->GetOatHeader().GetInterpreterToQuickEntryOffset(); + portable_resolution_trampoline_offset_ = oat_file_->GetOatHeader().GetPortableResolutionTrampolineOffset(); + quick_resolution_trampoline_offset_ = oat_file_->GetOatHeader().GetQuickResolutionTrampolineOffset(); { Thread::Current()->TransitionFromSuspendedToRunnable(); @@ -221,17 +225,30 @@ void ImageWriter::PruneNonImageClasses() { Runtime* runtime = Runtime::Current(); ClassLinker* class_linker = runtime->GetClassLinker(); + // Update image_classes_ with classes for objects created by <clinit> methods. + Thread* self = Thread::Current(); + const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter"); + Heap* heap = Runtime::Current()->GetHeap(); + // TODO: Image spaces only? + WriterMutexLock mu(self, *Locks::heap_bitmap_lock_); + heap->FlushAllocStack(); + heap->GetLiveBitmap()->Walk(FindClinitImageClassesCallback, this); + self->EndAssertNoThreadSuspension(old_cause); + + // Make a list of classes we would like to prune. std::set<std::string> non_image_classes; NonImageClasses context; context.image_writer = this; context.non_image_classes = &non_image_classes; class_linker->VisitClasses(NonImageClassesVisitor, &context); + // Remove the undesired classes from the class roots. typedef std::set<std::string>::const_iterator ClassIt; // TODO: C++0x auto for (ClassIt it = non_image_classes.begin(), end = non_image_classes.end(); it != end; ++it) { class_linker->RemoveClass((*it).c_str(), NULL); } + // Clear references to removed classes from the DexCaches. AbstractMethod* resolution_method = runtime->GetResolutionMethod(); typedef Set::const_iterator CacheIt; // TODO: C++0x auto for (CacheIt it = dex_caches_.begin(), end = dex_caches_.end(); it != end; ++it) { @@ -258,6 +275,28 @@ void ImageWriter::PruneNonImageClasses() { } } +void ImageWriter::FindClinitImageClassesCallback(Object* object, void* arg) { + DCHECK(object != NULL); + DCHECK(arg != NULL); + ImageWriter* image_writer = reinterpret_cast<ImageWriter*>(arg); + Class* klass = object->GetClass(); + while (klass->IsArrayClass()) { + klass = klass->GetComponentType(); + } + if (klass->IsPrimitive()) { + return; + } + while (!klass->IsObjectClass()) { + ClassHelper kh(klass); + const char* descriptor = kh.GetDescriptor(); + std::pair<DescriptorSet::iterator, bool> result = image_writer->image_classes_->insert(descriptor); + if (result.second) { + LOG(INFO) << "Adding " << descriptor << " to image classes"; + } + klass = klass->GetSuperClass(); + } +} + bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) { NonImageClasses* context = reinterpret_cast<NonImageClasses*>(arg); if (!context->image_writer->IsImageClass(klass)) { @@ -477,17 +516,34 @@ void ImageWriter::FixupMethod(const AbstractMethod* orig, AbstractMethod* copy) if (orig->IsAbstract()) { // Code for abstract methods is set to the abstract method error stub when we load the image. copy->SetEntryPointFromCompiledCode(NULL); + copy->SetEntryPointFromInterpreter(reinterpret_cast<EntryPointFromInterpreter*> + (GetOatAddress(interpreter_to_interpreter_entry_offset_))); return; + } else { + copy->SetEntryPointFromInterpreter(reinterpret_cast<EntryPointFromInterpreter*> + (GetOatAddress(interpreter_to_quick_entry_offset_))); } if (orig == Runtime::Current()->GetResolutionMethod()) { - // The resolution method's code is set to the resolution trampoline when we load the image. - copy->SetEntryPointFromCompiledCode(NULL); +#if defined(ART_USE_PORTABLE_COMPILER) + copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_resolution_trampoline_offset_)); +#else + copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_resolution_trampoline_offset_)); +#endif return; } - // Non-abstract methods have code - copy->SetEntryPointFromCompiledCode(GetOatAddress(orig->GetOatCodeOffset())); + // Use original code if it exists. Otherwise, set the code pointer to the resolution trampoline. + const byte* code = GetOatAddress(orig->GetOatCodeOffset()); + if (code != NULL) { + copy->SetEntryPointFromCompiledCode(code); + } else { +#if defined(ART_USE_PORTABLE_COMPILER) + copy->SetEntryPointFromCompiledCode(GetOatAddress(portable_resolution_trampoline_offset_)); +#else + copy->SetEntryPointFromCompiledCode(GetOatAddress(quick_resolution_trampoline_offset_)); +#endif + } if (orig->IsNative()) { // The native method's pointer is set to a stub to lookup via dlsym when we load the image. |