summaryrefslogtreecommitdiff
path: root/src/image_writer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/image_writer.cc')
-rw-r--r--src/image_writer.cc64
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.