summaryrefslogtreecommitdiff
path: root/compiler/image_writer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/image_writer.cc')
-rw-r--r--compiler/image_writer.cc149
1 files changed, 65 insertions, 84 deletions
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 73574ba673..3d3130962a 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -124,7 +124,10 @@ bool ImageWriter::PrepareImageAddressSpace() {
{
ScopedObjectAccess soa(Thread::Current());
PruneNonImageClasses(); // Remove junk
- ComputeLazyFieldsForImageClasses(); // Add useful information
+ if (!compile_app_image_) {
+ // Avoid for app image since this may increase RAM and image size.
+ ComputeLazyFieldsForImageClasses(); // Add useful information
+ }
}
heap->CollectGarbage(false); // Remove garbage.
@@ -735,20 +738,20 @@ bool ImageWriter::IsBootClassLoaderNonImageClass(mirror::Class* klass) {
return IsBootClassLoaderClass(klass) && !IsInBootImage(klass);
}
-bool ImageWriter::ContainsBootClassLoaderNonImageClass(mirror::Class* klass) {
+bool ImageWriter::PruneAppImageClass(mirror::Class* klass) {
bool early_exit = false;
std::unordered_set<mirror::Class*> visited;
- return ContainsBootClassLoaderNonImageClassInternal(klass, &early_exit, &visited);
+ return PruneAppImageClassInternal(klass, &early_exit, &visited);
}
-bool ImageWriter::ContainsBootClassLoaderNonImageClassInternal(
+bool ImageWriter::PruneAppImageClassInternal(
mirror::Class* klass,
bool* early_exit,
std::unordered_set<mirror::Class*>* visited) {
DCHECK(early_exit != nullptr);
DCHECK(visited != nullptr);
DCHECK(compile_app_image_);
- if (klass == nullptr) {
+ if (klass == nullptr || IsInBootImage(klass)) {
return false;
}
auto found = prune_class_memo_.find(klass);
@@ -762,7 +765,11 @@ bool ImageWriter::ContainsBootClassLoaderNonImageClassInternal(
return false;
}
visited->emplace(klass);
- bool result = IsBootClassLoaderNonImageClass(klass);
+ bool result = IsBootClassLoaderClass(klass);
+ std::string temp;
+ // Prune if not an image class, this handles any broken sets of image classes such as having a
+ // class in the set but not it's superclass.
+ result = result || !compiler_driver_.IsImageClass(klass->GetDescriptor(&temp));
bool my_early_exit = false; // Only for ourselves, ignore caller.
// Remove classes that failed to verify since we don't want to have java.lang.VerifyError in the
// app image.
@@ -775,17 +782,15 @@ bool ImageWriter::ContainsBootClassLoaderNonImageClassInternal(
// Check interfaces since these wont be visited through VisitReferences.)
mirror::IfTable* if_table = klass->GetIfTable();
for (size_t i = 0, num_interfaces = klass->GetIfTableCount(); i < num_interfaces; ++i) {
- result = result || ContainsBootClassLoaderNonImageClassInternal(
- if_table->GetInterface(i),
- &my_early_exit,
- visited);
+ result = result || PruneAppImageClassInternal(if_table->GetInterface(i),
+ &my_early_exit,
+ visited);
}
}
if (klass->IsObjectArrayClass()) {
- result = result || ContainsBootClassLoaderNonImageClassInternal(
- klass->GetComponentType(),
- &my_early_exit,
- visited);
+ result = result || PruneAppImageClassInternal(klass->GetComponentType(),
+ &my_early_exit,
+ visited);
}
// Check static fields and their classes.
size_t num_static_fields = klass->NumReferenceStaticFields();
@@ -798,27 +803,22 @@ bool ImageWriter::ContainsBootClassLoaderNonImageClassInternal(
mirror::Object* ref = klass->GetFieldObject<mirror::Object>(field_offset);
if (ref != nullptr) {
if (ref->IsClass()) {
- result = result ||
- ContainsBootClassLoaderNonImageClassInternal(
- ref->AsClass(),
- &my_early_exit,
- visited);
+ result = result || PruneAppImageClassInternal(ref->AsClass(),
+ &my_early_exit,
+ visited);
+ } else {
+ result = result || PruneAppImageClassInternal(ref->GetClass(),
+ &my_early_exit,
+ visited);
}
- result = result ||
- ContainsBootClassLoaderNonImageClassInternal(
- ref->GetClass(),
- &my_early_exit,
- visited);
}
field_offset = MemberOffset(field_offset.Uint32Value() +
sizeof(mirror::HeapReference<mirror::Object>));
}
}
- result = result ||
- ContainsBootClassLoaderNonImageClassInternal(
- klass->GetSuperClass(),
- &my_early_exit,
- visited);
+ result = result || PruneAppImageClassInternal(klass->GetSuperClass(),
+ &my_early_exit,
+ visited);
// Erase the element we stored earlier since we are exiting the function.
auto it = visited->find(klass);
DCHECK(it != visited->end());
@@ -837,15 +837,21 @@ bool ImageWriter::KeepClass(Class* klass) {
if (klass == nullptr) {
return false;
}
+ if (compile_app_image_ && Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass)) {
+ // Already in boot image, return true.
+ return true;
+ }
+ std::string temp;
+ if (!compiler_driver_.IsImageClass(klass->GetDescriptor(&temp))) {
+ return false;
+ }
if (compile_app_image_) {
// For app images, we need to prune boot loader classes that are not in the boot image since
// these may have already been loaded when the app image is loaded.
// Keep classes in the boot image space since we don't want to re-resolve these.
- return Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(klass) ||
- !ContainsBootClassLoaderNonImageClass(klass);
+ return !PruneAppImageClass(klass);
}
- std::string temp;
- return compiler_driver_.IsImageClass(klass->GetDescriptor(&temp));
+ return true;
}
class NonImageClassesVisitor : public ClassVisitor {
@@ -873,6 +879,7 @@ void ImageWriter::PruneNonImageClasses() {
class_linker->VisitClasses(&visitor);
// Remove the undesired classes from the class roots.
+ VLOG(compiler) << "Pruning " << visitor.classes_to_prune_.size() << " classes";
for (mirror::Class* klass : visitor.classes_to_prune_) {
std::string temp;
const char* name = klass->GetDescriptor(&temp);
@@ -891,10 +898,10 @@ void ImageWriter::PruneNonImageClasses() {
ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); // For ClassInClassTable
ReaderMutexLock mu2(self, *class_linker->DexLock());
for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
- mirror::DexCache* dex_cache = down_cast<mirror::DexCache*>(self->DecodeJObject(data.weak_root));
- if (dex_cache == nullptr) {
+ if (self->IsJWeakCleared(data.weak_root)) {
continue;
}
+ mirror::DexCache* dex_cache = self->DecodeJObject(data.weak_root)->AsDexCache();
for (size_t i = 0; i < dex_cache->NumResolvedTypes(); i++) {
Class* klass = dex_cache->GetResolvedType(i);
if (klass != nullptr && !KeepClass(klass)) {
@@ -907,10 +914,10 @@ void ImageWriter::PruneNonImageClasses() {
mirror::DexCache::GetElementPtrSize(resolved_methods, i, target_ptr_size_);
DCHECK(method != nullptr) << "Expected resolution method instead of null method";
mirror::Class* declaring_class = method->GetDeclaringClass();
- // Miranda methods may be held live by a class which was not an image class but have a
+ // Copied methods may be held live by a class which was not an image class but have a
// declaring class which is an image class. Set it to the resolution method to be safe and
// prevent dangling pointers.
- if (method->IsMiranda() || !KeepClass(declaring_class)) {
+ if (method->IsCopied() || !KeepClass(declaring_class)) {
mirror::DexCache::SetElementPtrSize(resolved_methods,
i,
resolution_method,
@@ -1820,12 +1827,16 @@ uintptr_t ImageWriter::NativeOffsetInImage(void* obj) {
}
template <typename T>
-T* ImageWriter::NativeLocationInImage(T* obj, const char* oat_filename) {
+T* ImageWriter::NativeLocationInImage(T* obj) {
if (obj == nullptr || IsInBootImage(obj)) {
return obj;
} else {
- ImageInfo& image_info = GetImageInfo(oat_filename);
- return reinterpret_cast<T*>(image_info.image_begin_ + NativeOffsetInImage(obj));
+ auto it = native_object_relocations_.find(obj);
+ CHECK(it != native_object_relocations_.end()) << obj << " spaces "
+ << Runtime::Current()->GetHeap()->DumpSpaces();
+ const NativeObjectRelocation& relocation = it->second;
+ ImageInfo& image_info = GetImageInfo(relocation.oat_filename);
+ return reinterpret_cast<T*>(image_info.image_begin_ + relocation.offset);
}
}
@@ -1842,33 +1853,19 @@ T* ImageWriter::NativeCopyLocation(T* obj, mirror::DexCache* dex_cache) {
class NativeLocationVisitor {
public:
- explicit NativeLocationVisitor(ImageWriter* image_writer, const char* oat_filename)
- : image_writer_(image_writer), oat_filename_(oat_filename) {}
+ explicit NativeLocationVisitor(ImageWriter* image_writer) : image_writer_(image_writer) {}
template <typename T>
T* operator()(T* ptr) const SHARED_REQUIRES(Locks::mutator_lock_) {
- return image_writer_->NativeLocationInImage(ptr, oat_filename_);
- }
-
- ArtMethod* operator()(ArtMethod* method) const SHARED_REQUIRES(Locks::mutator_lock_) {
- const char* oat_filename = method->IsRuntimeMethod() ? image_writer_->GetDefaultOatFilename() :
- image_writer_->GetOatFilenameForDexCache(method->GetDexCache());
- return image_writer_->NativeLocationInImage(method, oat_filename);
- }
-
- ArtField* operator()(ArtField* field) const SHARED_REQUIRES(Locks::mutator_lock_) {
- const char* oat_filename = image_writer_->GetOatFilenameForDexCache(field->GetDexCache());
- return image_writer_->NativeLocationInImage(field, oat_filename);
+ return image_writer_->NativeLocationInImage(ptr);
}
private:
ImageWriter* const image_writer_;
- const char* oat_filename_;
};
void ImageWriter::FixupClass(mirror::Class* orig, mirror::Class* copy) {
- const char* oat_filename = GetOatFilename(orig);
- orig->FixupNativePointers(copy, target_ptr_size_, NativeLocationVisitor(this, oat_filename));
+ orig->FixupNativePointers(copy, target_ptr_size_, NativeLocationVisitor(this));
FixupClassVisitor visitor(this, copy);
static_cast<mirror::Object*>(orig)->VisitReferences(visitor, visitor);
@@ -1952,11 +1949,10 @@ void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache,
// 64-bit values here, clearing the top 32 bits for 32-bit targets. The zero-extension is
// done by casting to the unsigned type uintptr_t before casting to int64_t, i.e.
// static_cast<int64_t>(reinterpret_cast<uintptr_t>(image_begin_ + offset))).
- const char* oat_filename = GetOatFilenameForDexCache(orig_dex_cache);
GcRoot<mirror::String>* orig_strings = orig_dex_cache->GetStrings();
if (orig_strings != nullptr) {
copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::StringsOffset(),
- NativeLocationInImage(orig_strings, oat_filename),
+ NativeLocationInImage(orig_strings),
/*pointer size*/8u);
orig_dex_cache->FixupStrings(NativeCopyLocation(orig_strings, orig_dex_cache),
ImageAddressVisitor(this));
@@ -1964,7 +1960,7 @@ void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache,
GcRoot<mirror::Class>* orig_types = orig_dex_cache->GetResolvedTypes();
if (orig_types != nullptr) {
copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedTypesOffset(),
- NativeLocationInImage(orig_types, oat_filename),
+ NativeLocationInImage(orig_types),
/*pointer size*/8u);
orig_dex_cache->FixupResolvedTypes(NativeCopyLocation(orig_types, orig_dex_cache),
ImageAddressVisitor(this));
@@ -1972,32 +1968,25 @@ void ImageWriter::FixupDexCache(mirror::DexCache* orig_dex_cache,
ArtMethod** orig_methods = orig_dex_cache->GetResolvedMethods();
if (orig_methods != nullptr) {
copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedMethodsOffset(),
- NativeLocationInImage(orig_methods, oat_filename),
+ NativeLocationInImage(orig_methods),
/*pointer size*/8u);
ArtMethod** copy_methods = NativeCopyLocation(orig_methods, orig_dex_cache);
for (size_t i = 0, num = orig_dex_cache->NumResolvedMethods(); i != num; ++i) {
ArtMethod* orig = mirror::DexCache::GetElementPtrSize(orig_methods, i, target_ptr_size_);
- const char* method_oat_filename;
- if (orig == nullptr || orig->IsRuntimeMethod()) {
- method_oat_filename = default_oat_filename_;
- } else {
- method_oat_filename = GetOatFilenameForDexCache(orig->GetDexCache());
- }
- ArtMethod* copy = NativeLocationInImage(orig, method_oat_filename);
+ // NativeLocationInImage also handles runtime methods since these have relocation info.
+ ArtMethod* copy = NativeLocationInImage(orig);
mirror::DexCache::SetElementPtrSize(copy_methods, i, copy, target_ptr_size_);
}
}
ArtField** orig_fields = orig_dex_cache->GetResolvedFields();
if (orig_fields != nullptr) {
copy_dex_cache->SetFieldPtrWithSize<false>(mirror::DexCache::ResolvedFieldsOffset(),
- NativeLocationInImage(orig_fields, oat_filename),
+ NativeLocationInImage(orig_fields),
/*pointer size*/8u);
ArtField** copy_fields = NativeCopyLocation(orig_fields, orig_dex_cache);
for (size_t i = 0, num = orig_dex_cache->NumResolvedFields(); i != num; ++i) {
ArtField* orig = mirror::DexCache::GetElementPtrSize(orig_fields, i, target_ptr_size_);
- const char* field_oat_filename =
- orig == nullptr ? default_oat_filename_ : GetOatFilenameForDexCache(orig->GetDexCache());
- ArtField* copy = NativeLocationInImage(orig, field_oat_filename);
+ ArtField* copy = NativeLocationInImage(orig);
mirror::DexCache::SetElementPtrSize(copy_fields, i, copy, target_ptr_size_);
}
}
@@ -2089,20 +2078,10 @@ void ImageWriter::CopyAndFixupMethod(ArtMethod* orig,
copy->SetDeclaringClass(GetImageAddress(orig->GetDeclaringClassUnchecked()));
- const char* oat_filename;
- if (orig->IsRuntimeMethod() || compile_app_image_) {
- oat_filename = default_oat_filename_;
- } else {
- auto it = dex_file_oat_filename_map_.find(orig->GetDexFile());
- DCHECK(it != dex_file_oat_filename_map_.end()) << orig->GetDexFile()->GetLocation();
- oat_filename = it->second;
- }
ArtMethod** orig_resolved_methods = orig->GetDexCacheResolvedMethods(target_ptr_size_);
- copy->SetDexCacheResolvedMethods(NativeLocationInImage(orig_resolved_methods, oat_filename),
- target_ptr_size_);
+ copy->SetDexCacheResolvedMethods(NativeLocationInImage(orig_resolved_methods), target_ptr_size_);
GcRoot<mirror::Class>* orig_resolved_types = orig->GetDexCacheResolvedTypes(target_ptr_size_);
- copy->SetDexCacheResolvedTypes(NativeLocationInImage(orig_resolved_types, oat_filename),
- target_ptr_size_);
+ copy->SetDexCacheResolvedTypes(NativeLocationInImage(orig_resolved_types), target_ptr_size_);
// OatWriter replaces the code_ with an offset value. Here we re-adjust to a pointer relative to
// oat_begin_
@@ -2324,6 +2303,8 @@ ImageWriter::ImageWriter(
image_info_map_.emplace(oat_filename, ImageInfo());
}
std::fill_n(image_methods_, arraysize(image_methods_), nullptr);
+ CHECK_EQ(compile_app_image, !Runtime::Current()->GetHeap()->GetBootImageSpaces().empty())
+ << "Compiling a boot image should occur iff there are no boot image spaces loaded";
}
ImageWriter::ImageInfo::ImageInfo()