diff options
-rw-r--r-- | compiler/optimizing/intrinsics.cc | 45 | ||||
-rw-r--r-- | dex2oat/linker/image_writer.cc | 87 | ||||
-rw-r--r-- | dex2oat/linker/image_writer.h | 2 | ||||
-rw-r--r-- | runtime/class_linker.cc | 8 | ||||
-rw-r--r-- | runtime/image.cc | 2 | ||||
-rw-r--r-- | runtime/image.h | 12 | ||||
-rw-r--r-- | runtime/runtime.cc | 1 |
7 files changed, 104 insertions, 53 deletions
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc index 056f533398..02f736d775 100644 --- a/compiler/optimizing/intrinsics.cc +++ b/compiler/optimizing/intrinsics.cc @@ -272,34 +272,33 @@ IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo ClassLinker* class_linker = runtime->GetClassLinker(); gc::Heap* heap = runtime->GetHeap(); IntegerValueOfInfo info; - info.integer_cache = - class_linker->FindSystemClass(self, "Ljava/lang/Integer$IntegerCache;").Ptr(); - if (info.integer_cache == nullptr) { - self->ClearException(); + info.integer_cache = class_linker->LookupClass(self, + "Ljava/lang/Integer$IntegerCache;", + /* class_loader */ nullptr).Ptr(); + if (info.integer_cache == nullptr || !info.integer_cache->IsInitialized()) { + // Optimization only works if the class is initialized. return info; } - if (!heap->ObjectIsInBootImageSpace(info.integer_cache) || !info.integer_cache->IsInitialized()) { - // Optimization only works if the class is initialized and in the boot image. + if (!heap->ObjectIsInBootImageSpace(info.integer_cache)) { + // Optimization only works if the class is in the boot image. + // TODO: Implement the intrinsic for boot image compilation. return info; } - info.integer = class_linker->FindSystemClass(self, "Ljava/lang/Integer;").Ptr(); - if (info.integer == nullptr) { - self->ClearException(); - return info; - } - if (!heap->ObjectIsInBootImageSpace(info.integer) || !info.integer->IsInitialized()) { - // Optimization only works if the class is initialized and in the boot image. + info.integer = + class_linker->LookupClass(self, "Ljava/lang/Integer;", /* class_loader */ nullptr).Ptr(); + DCHECK(info.integer != nullptr); + DCHECK(info.integer->IsInitialized()); // Must be initialized since IntegerCache is initialized. + if (!heap->ObjectIsInBootImageSpace(info.integer)) { + // Optimization only works if the class is in the boot image. return info; } ArtField* field = info.integer_cache->FindDeclaredStaticField("cache", "[Ljava/lang/Integer;"); - if (field == nullptr) { - return info; - } + CHECK(field != nullptr); info.cache = static_cast<mirror::ObjectArray<mirror::Object>*>( field->GetObject(info.integer_cache).Ptr()); if (info.cache == nullptr) { - return info; + return info; // Did someone mess up the IntegerCache using reflection? } if (!heap->ObjectIsInBootImageSpace(info.cache)) { @@ -308,21 +307,15 @@ IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo } field = info.integer->FindDeclaredInstanceField("value", "I"); - if (field == nullptr) { - return info; - } + CHECK(field != nullptr); info.value_offset = field->GetOffset().Int32Value(); field = info.integer_cache->FindDeclaredStaticField("low", "I"); - if (field == nullptr) { - return info; - } + CHECK(field != nullptr); info.low = field->GetInt(info.integer_cache); field = info.integer_cache->FindDeclaredStaticField("high", "I"); - if (field == nullptr) { - return info; - } + CHECK(field != nullptr); info.high = field->GetInt(info.integer_cache); DCHECK_EQ(info.cache->GetLength(), info.high - info.low + 1); diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc index dc0709013c..f1cb068a38 100644 --- a/dex2oat/linker/image_writer.cc +++ b/dex2oat/linker/image_writer.cc @@ -1261,15 +1261,8 @@ mirror::String* ImageWriter::FindInternedString(mirror::String* string) { return nullptr; } - -ObjectArray<Object>* ImageWriter::CreateImageRoots(size_t oat_index) const { - Runtime* runtime = Runtime::Current(); - ClassLinker* class_linker = runtime->GetClassLinker(); - Thread* self = Thread::Current(); - StackHandleScope<3> hs(self); - Handle<Class> object_array_class(hs.NewHandle( - class_linker->FindSystemClass(self, "[Ljava/lang/Object;"))); - +ObjPtr<mirror::ObjectArray<mirror::Object>> ImageWriter::CollectDexCaches(Thread* self, + size_t oat_index) const { std::unordered_set<const DexFile*> image_dex_files; for (auto& pair : dex_file_oat_index_map_) { const DexFile* image_dex_file = pair.first; @@ -1284,6 +1277,7 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots(size_t oat_index) const { // ObjectArray, we lock the dex lock twice, first to get the number // of dex caches first and then lock it again to copy the dex // caches. We check that the number of dex caches does not change. + ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); size_t dex_cache_count = 0; { ReaderMutexLock mu(self, *Locks::dex_lock_); @@ -1300,8 +1294,8 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots(size_t oat_index) const { } } } - Handle<ObjectArray<Object>> dex_caches( - hs.NewHandle(ObjectArray<Object>::Alloc(self, object_array_class.Get(), dex_cache_count))); + ObjPtr<ObjectArray<Object>> dex_caches = ObjectArray<Object>::Alloc( + self, GetClassRoot<ObjectArray<Object>>(class_linker), dex_cache_count); CHECK(dex_caches != nullptr) << "Failed to allocate a dex cache array."; { ReaderMutexLock mu(self, *Locks::dex_lock_); @@ -1335,11 +1329,62 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots(size_t oat_index) const { } } } + return dex_caches; +} + +static ObjPtr<mirror::ObjectArray<mirror::Object>> LookupIntegerCache(Thread* self, + ClassLinker* class_linker) + REQUIRES_SHARED(Locks::mutator_lock_) { + ObjPtr<mirror::Class> integer_cache_class = class_linker->LookupClass( + self, "Ljava/lang/Integer$IntegerCache;", /* class_linker */ nullptr); + if (integer_cache_class == nullptr || !integer_cache_class->IsInitialized()) { + return nullptr; + } + ArtField* cache_field = + integer_cache_class->FindDeclaredStaticField("cache", "[Ljava/lang/Integer;"); + CHECK(cache_field != nullptr); + ObjPtr<ObjectArray<mirror::Object>> integer_cache = + ObjPtr<ObjectArray<mirror::Object>>::DownCast(cache_field->GetObject(integer_cache_class)); + CHECK(integer_cache != nullptr); + return integer_cache; +} + +static ObjPtr<mirror::ObjectArray<mirror::Object>> CollectBootImageLiveObjects( + Thread* self, + ClassLinker* class_linker) REQUIRES_SHARED(Locks::mutator_lock_) { + // The objects used for the Integer.valueOf() intrinsic must remain live even if references + // to them are removed using reflection. Image roots are not accessible through reflection, + // so the array we construct here shall keep them alive. + StackHandleScope<1> hs(self); + Handle<ObjectArray<mirror::Object>> integer_cache = + hs.NewHandle(LookupIntegerCache(self, class_linker)); + size_t live_objects_size = + (integer_cache != nullptr) ? (/* cache */ 1u + integer_cache->GetLength()) : 0u; + ObjPtr<mirror::ObjectArray<mirror::Object>> live_objects = ObjectArray<Object>::Alloc( + self, GetClassRoot<ObjectArray<Object>>(class_linker), live_objects_size); + int32_t index = 0; + if (integer_cache != nullptr) { + live_objects->Set(index++, integer_cache.Get()); + for (int32_t i = 0, length = integer_cache->GetLength(); i != length; ++i) { + live_objects->Set(index++, integer_cache->Get(i)); + } + } + CHECK_EQ(index, live_objects->GetLength()); + return live_objects; +} + +ObjectArray<Object>* ImageWriter::CreateImageRoots(size_t oat_index) const { + Runtime* runtime = Runtime::Current(); + ClassLinker* class_linker = runtime->GetClassLinker(); + Thread* self = Thread::Current(); + StackHandleScope<2> hs(self); + + Handle<ObjectArray<Object>> dex_caches(hs.NewHandle(CollectDexCaches(self, oat_index))); // build an Object[] of the roots needed to restore the runtime int32_t image_roots_size = ImageHeader::NumberOfImageRoots(compile_app_image_); - auto image_roots(hs.NewHandle( - ObjectArray<Object>::Alloc(self, object_array_class.Get(), image_roots_size))); + Handle<ObjectArray<Object>> image_roots(hs.NewHandle(ObjectArray<Object>::Alloc( + self, GetClassRoot<ObjectArray<Object>>(class_linker), image_roots_size))); image_roots->Set<false>(ImageHeader::kDexCaches, dex_caches.Get()); image_roots->Set<false>(ImageHeader::kClassRoots, class_linker->GetClassRoots()); image_roots->Set<false>(ImageHeader::kOomeWhenThrowingException, @@ -1350,10 +1395,16 @@ ObjectArray<Object>* ImageWriter::CreateImageRoots(size_t oat_index) const { runtime->GetPreAllocatedOutOfMemoryErrorWhenHandlingStackOverflow()); image_roots->Set<false>(ImageHeader::kNoClassDefFoundError, runtime->GetPreAllocatedNoClassDefFoundError()); - // image_roots[ImageHeader::kClassLoader] will be set later for app image. - static_assert(ImageHeader::kClassLoader + 1u == ImageHeader::kImageRootsMax, - "Class loader should be the last image root."); - for (int32_t i = 0; i < ImageHeader::kImageRootsMax - 1; ++i) { + if (!compile_app_image_) { + ObjPtr<ObjectArray<Object>> boot_image_live_objects = + CollectBootImageLiveObjects(self, class_linker); + image_roots->Set<false>(ImageHeader::kBootImageLiveObjects, boot_image_live_objects); + } + for (int32_t i = 0, num = ImageHeader::NumberOfImageRoots(compile_app_image_); i != num; ++i) { + if (compile_app_image_ && i == ImageHeader::kAppImageClassLoader) { + // image_roots[ImageHeader::kAppImageClassLoader] will be set later for app image. + continue; + } CHECK(image_roots->Get(i) != nullptr); } return image_roots.Get(); @@ -1781,7 +1832,7 @@ void ImageWriter::CalculateNewObjectOffsets() { CHECK_EQ(class_loaders_.size(), 1u); CHECK_EQ(image_roots.size(), 1u); CHECK(*class_loaders_.begin() != nullptr); - image_roots[0]->Set<false>(ImageHeader::kClassLoader, *class_loaders_.begin()); + image_roots[0]->Set<false>(ImageHeader::kAppImageClassLoader, *class_loaders_.begin()); } // Verify that all objects have assigned image bin slots. diff --git a/dex2oat/linker/image_writer.h b/dex2oat/linker/image_writer.h index 960d698689..c282a2ade8 100644 --- a/dex2oat/linker/image_writer.h +++ b/dex2oat/linker/image_writer.h @@ -450,6 +450,8 @@ class ImageWriter FINAL { REQUIRES_SHARED(Locks::mutator_lock_); void CreateHeader(size_t oat_index) REQUIRES_SHARED(Locks::mutator_lock_); + ObjPtr<mirror::ObjectArray<mirror::Object>> CollectDexCaches(Thread* self, size_t oat_index) const + REQUIRES_SHARED(Locks::mutator_lock_); mirror::ObjectArray<mirror::Object>* CreateImageRoots(size_t oat_index) const REQUIRES_SHARED(Locks::mutator_lock_); void CalculateObjectBinSlots(mirror::Object* obj) diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index be636d80a8..45332c8a1a 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -990,8 +990,7 @@ bool ClassLinker::InitFromBootImage(std::string* error_msg) { class_roots_ = GcRoot<mirror::ObjectArray<mirror::Class>>( ObjPtr<mirror::ObjectArray<mirror::Class>>::DownCast(MakeObjPtr( spaces[0]->GetImageHeader().GetImageRoot(ImageHeader::kClassRoots)))); - DCHECK_EQ(GetClassRoot(ClassRoot::kJavaLangClass, this)->GetClassFlags(), - mirror::kClassFlagClass); + DCHECK_EQ(GetClassRoot<mirror::Class>(this)->GetClassFlags(), mirror::kClassFlagClass); ObjPtr<mirror::Class> java_lang_Object = GetClassRoot<mirror::Object>(this); java_lang_Object->SetObjectSize(sizeof(mirror::Object)); @@ -1610,10 +1609,9 @@ bool ClassLinker::AddImageSpace( hs.NewHandle(dex_caches_object->AsObjectArray<mirror::DexCache>())); Handle<mirror::ObjectArray<mirror::Class>> class_roots(hs.NewHandle( header.GetImageRoot(ImageHeader::kClassRoots)->AsObjectArray<mirror::Class>())); - static_assert(ImageHeader::kClassLoader + 1u == ImageHeader::kImageRootsMax, - "Class loader should be the last image root."); MutableHandle<mirror::ClassLoader> image_class_loader(hs.NewHandle( - app_image ? header.GetImageRoot(ImageHeader::kClassLoader)->AsClassLoader() : nullptr)); + app_image ? header.GetImageRoot(ImageHeader::kAppImageClassLoader)->AsClassLoader() + : nullptr)); DCHECK(class_roots != nullptr); if (class_roots->GetLength() != static_cast<int32_t>(ClassRoot::kMax)) { *error_msg = StringPrintf("Expected %d class roots but got %d", diff --git a/runtime/image.cc b/runtime/image.cc index 17fc664bd7..7819c0bc00 100644 --- a/runtime/image.cc +++ b/runtime/image.cc @@ -26,7 +26,7 @@ namespace art { const uint8_t ImageHeader::kImageMagic[] = { 'a', 'r', 't', '\n' }; -const uint8_t ImageHeader::kImageVersion[] = { '0', '6', '1', '\0' }; // Pre-allocated Throwables. +const uint8_t ImageHeader::kImageVersion[] = { '0', '6', '2', '\0' }; // Boot image live objects. ImageHeader::ImageHeader(uint32_t image_begin, uint32_t image_size, diff --git a/runtime/image.h b/runtime/image.h index c6fc052a60..c1cde0a74a 100644 --- a/runtime/image.h +++ b/runtime/image.h @@ -211,8 +211,12 @@ class PACKED(4) ImageHeader { kOomeWhenThrowingOome, // Pre-allocated OOME when throwing OOME. kOomeWhenHandlingStackOverflow, // Pre-allocated OOME when handling StackOverflowError. kNoClassDefFoundError, // Pre-allocated NoClassDefFoundError. - kClassLoader, // App image only. + kSpecialRoots, // Different for boot image and app image, see aliases below. kImageRootsMax, + + // Aliases. + kAppImageClassLoader = kSpecialRoots, // The class loader used to build the app image. + kBootImageLiveObjects = kSpecialRoots, // Array of boot image objects that must be kept live. }; enum ImageSections { @@ -229,8 +233,10 @@ class PACKED(4) ImageHeader { kSectionCount, // Number of elements in enum. }; - static size_t NumberOfImageRoots(bool app_image) { - return app_image ? kImageRootsMax : kImageRootsMax - 1u; + static size_t NumberOfImageRoots(bool app_image ATTRIBUTE_UNUSED) { + // At the moment, boot image and app image have the same number of roots, + // though the meaning of the kSpecialRoots is different. + return kImageRootsMax; } ArtMethod* GetImageMethod(ImageMethod index) const; diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 1e327fc8ed..b4dfc1195d 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -2045,6 +2045,7 @@ void Runtime::VisitNonThreadRoots(RootVisitor* visitor) { pre_allocated_OutOfMemoryError_when_handling_stack_overflow_ .VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal)); pre_allocated_NoClassDefFoundError_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal)); + VisitImageRoots(visitor); verifier::MethodVerifier::VisitStaticRoots(visitor); VisitTransactionRoots(visitor); } |