diff options
36 files changed, 124 insertions, 211 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index ecbc3a2cf7..bf3a8658da 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -1552,7 +1552,7 @@ void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType* type, InvokeType *type = sharp_type; } } else { - auto* image_space = heap->GetImageSpace(); + auto* image_space = heap->GetBootImageSpace(); bool method_in_image = false; if (image_space != nullptr) { const auto& method_section = image_space->GetImageHeader().GetMethodsSection(); diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc index 90db7eb41a..73262333b6 100644 --- a/compiler/elf_writer_debug.cc +++ b/compiler/elf_writer_debug.cc @@ -451,12 +451,12 @@ void WriteDebugSections(ElfBuilder<ElfTypes>* builder, opcodes.EndSequence(); WriteDebugLineTable(directories, files, opcodes, &debug_line, &debug_line_patches); } + builder->WriteSection(".debug_line", &debug_line); + builder->WritePatches(".debug_line.oat_patches", &debug_line_patches); builder->WriteSection(".debug_info", &debug_info); builder->WritePatches(".debug_info.oat_patches", &debug_info_patches); builder->WriteSection(".debug_abbrev", &debug_abbrev); builder->WriteSection(".debug_str", &debug_str); - builder->WriteSection(".debug_line", &debug_line); - builder->WritePatches(".debug_line.oat_patches", &debug_line_patches); } // Explicit instantiations diff --git a/compiler/image_test.cc b/compiler/image_test.cc index a38e1f54c0..6df15279a0 100644 --- a/compiler/image_test.cc +++ b/compiler/image_test.cc @@ -181,7 +181,7 @@ TEST_F(ImageTest, WriteRead) { ASSERT_TRUE(heap->HasImageSpace()); ASSERT_TRUE(heap->GetNonMovingSpace()->IsMallocSpace()); - gc::space::ImageSpace* image_space = heap->GetImageSpace(); + gc::space::ImageSpace* image_space = heap->GetBootImageSpace(); ASSERT_TRUE(image_space != nullptr); ASSERT_LE(image_space->Size(), image_file_size); diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc index dd2ea9e443..3f18d9aa0f 100644 --- a/compiler/image_writer.cc +++ b/compiler/image_writer.cc @@ -1589,7 +1589,7 @@ const uint8_t* ImageWriter::GetOatAddress(OatAddress type) const { // If we are compiling an app image, we need to use the stubs of the boot image. if (compile_app_image_) { // Use the current image pointers. - gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace(); + gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetBootImageSpace(); DCHECK(image_space != nullptr); const OatFile* oat_file = image_space->GetOatFile(); CHECK(oat_file != nullptr); diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 3f2271ef11..40a3f14f93 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -899,7 +899,7 @@ class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { // NOTE: We're using linker patches for app->boot references when the image can // be relocated and therefore we need to emit .oat_patches. We're not using this // for app->app references, so check that the method is an image method. - gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace(); + gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetBootImageSpace(); size_t method_offset = reinterpret_cast<const uint8_t*>(method) - image_space->Begin(); CHECK(image_space->GetImageHeader().GetMethodsSection().Contains(method_offset)); } diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 92ed58cb86..68cf6d9233 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -1357,7 +1357,7 @@ class Dex2Oat FINAL { int32_t image_patch_delta = 0; if (app_image_ && image_base_ == 0) { - gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace(); + gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetBootImageSpace(); image_base_ = RoundUp( reinterpret_cast<uintptr_t>(image_space->GetImageHeader().GetOatFileEnd()), kPageSize); @@ -1370,7 +1370,7 @@ class Dex2Oat FINAL { if (!IsBootImage()) { TimingLogger::ScopedTiming t3("Loading image checksum", timings_); - gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace(); + gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetBootImageSpace(); image_file_location_oat_checksum = image_space->GetImageHeader().GetOatChecksum(); image_file_location_oat_data_begin = reinterpret_cast<uintptr_t>(image_space->GetImageHeader().GetOatDataBegin()); diff --git a/imgdiag/imgdiag.cc b/imgdiag/imgdiag.cc index 304d4e5860..5e710530b9 100644 --- a/imgdiag/imgdiag.cc +++ b/imgdiag/imgdiag.cc @@ -814,7 +814,7 @@ class ImgDiagDumper { static const ImageHeader& GetBootImageHeader() { gc::Heap* heap = Runtime::Current()->GetHeap(); - gc::space::ImageSpace* image_space = heap->GetImageSpace(); + gc::space::ImageSpace* image_space = heap->GetBootImageSpace(); CHECK(image_space != nullptr); const ImageHeader& image_header = image_space->GetImageHeader(); return image_header; @@ -838,7 +838,7 @@ static int DumpImage(Runtime* runtime, const char* image_location, std::ostream* os, pid_t image_diff_pid) { ScopedObjectAccess soa(Thread::Current()); gc::Heap* heap = runtime->GetHeap(); - gc::space::ImageSpace* image_space = heap->GetImageSpace(); + gc::space::ImageSpace* image_space = heap->GetBootImageSpace(); CHECK(image_space != nullptr); const ImageHeader& image_header = image_space->GetImageHeader(); if (!image_header.IsValid()) { diff --git a/imgdiag/imgdiag_test.cc b/imgdiag/imgdiag_test.cc index 82bc8b9521..0d6a8c9dee 100644 --- a/imgdiag/imgdiag_test.cc +++ b/imgdiag/imgdiag_test.cc @@ -42,7 +42,7 @@ class ImgDiagTest : public CommonRuntimeTest { CommonRuntimeTest::SetUp(); // We loaded the runtime with an explicit image. Therefore the image space must exist. - gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace(); + gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetBootImageSpace(); ASSERT_TRUE(image_space != nullptr); boot_image_location_ = image_space->GetImageLocation(); } diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index a163380b25..5a060af85c 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -2374,7 +2374,7 @@ static int DumpImage(Runtime* runtime, const char* image_location, OatDumperOpti ScopedObjectAccess soa(Thread::Current()); gc::Heap* heap = runtime->GetHeap(); - gc::space::ImageSpace* image_space = heap->GetImageSpace(); + gc::space::ImageSpace* image_space = heap->GetBootImageSpace(); CHECK(image_space != nullptr); const ImageHeader& image_header = image_space->GetImageHeader(); if (!image_header.IsValid()) { diff --git a/patchoat/patchoat.cc b/patchoat/patchoat.cc index 64b4722904..c587f68234 100644 --- a/patchoat/patchoat.cc +++ b/patchoat/patchoat.cc @@ -189,7 +189,7 @@ bool PatchOat::Patch(const std::string& image_location, off_t delta, LOG(ERROR) << "unable to map image file " << input_image->GetPath() << " : " << error_msg; return false; } - gc::space::ImageSpace* ispc = Runtime::Current()->GetHeap()->GetImageSpace(); + gc::space::ImageSpace* ispc = Runtime::Current()->GetHeap()->GetBootImageSpace(); PatchOat p(isa, image.release(), ispc->GetLiveBitmap(), ispc->GetMemMap(), delta, timings); t.NewTiming("Patching files"); @@ -288,7 +288,7 @@ bool PatchOat::Patch(File* input_oat, const std::string& image_location, off_t d LOG(ERROR) << "unable to map image file " << input_image->GetPath() << " : " << error_msg; return false; } - gc::space::ImageSpace* ispc = Runtime::Current()->GetHeap()->GetImageSpace(); + gc::space::ImageSpace* ispc = Runtime::Current()->GetHeap()->GetBootImageSpace(); std::unique_ptr<ElfFile> elf(ElfFile::Open(input_oat, PROT_READ | PROT_WRITE, MAP_PRIVATE, &error_msg)); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index f252c1edec..f649972096 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -303,7 +303,7 @@ static void ShuffleForward(size_t* current_field_idx, ClassLinker::ClassLinker(InternTable* intern_table) // dex_lock_ is recursive as it may be used in stack dumping. : dex_lock_("ClassLinker dex lock", kDefaultMutexLevel), - dex_cache_image_class_lookup_required_(false), + dex_cache_boot_image_class_lookup_required_(false), failed_dex_cache_class_lookups_(0), class_roots_(nullptr), array_iftable_(nullptr), @@ -794,7 +794,7 @@ static void SanityCheckObjectsCallback(mirror::Object* obj, void* arg ATTRIBUTE_ CHECK_EQ(field.GetDeclaringClass(), klass); } auto* runtime = Runtime::Current(); - auto* image_space = runtime->GetHeap()->GetImageSpace(); + auto* image_space = runtime->GetHeap()->GetBootImageSpace(); auto pointer_size = runtime->GetClassLinker()->GetImagePointerSize(); for (auto& m : klass->GetDirectMethods(pointer_size)) { SanityCheckArtMethod(&m, klass, image_space); @@ -855,10 +855,10 @@ void ClassLinker::InitFromImage() { Runtime* const runtime = Runtime::Current(); Thread* const self = Thread::Current(); gc::Heap* const heap = runtime->GetHeap(); - gc::space::ImageSpace* const space = heap->GetImageSpace(); + gc::space::ImageSpace* const space = heap->GetBootImageSpace(); CHECK(space != nullptr); image_pointer_size_ = space->GetImageHeader().GetPointerSize(); - dex_cache_image_class_lookup_required_ = true; + dex_cache_boot_image_class_lookup_required_ = true; const OatFile* oat_file = runtime->GetOatFileManager().RegisterImageOatFile(space); DCHECK(oat_file != nullptr); CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationOatChecksum(), 0U); @@ -1086,8 +1086,8 @@ void ClassLinker::VisitClassesInternal(ClassVisitor* visitor) { } void ClassLinker::VisitClasses(ClassVisitor* visitor) { - if (dex_cache_image_class_lookup_required_) { - MoveImageClassesToClassTable(); + if (dex_cache_boot_image_class_lookup_required_) { + AddBootImageClassesToClassTable(); } Thread* const self = Thread::Current(); ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); @@ -2643,11 +2643,13 @@ mirror::Class* ClassLinker::InsertClass(const char* descriptor, mirror::Class* k if (existing != nullptr) { return existing; } - if (kIsDebugBuild && !klass->IsTemp() && class_loader == nullptr && - dex_cache_image_class_lookup_required_) { + if (kIsDebugBuild && + !klass->IsTemp() && + class_loader == nullptr && + dex_cache_boot_image_class_lookup_required_) { // Check a class loaded with the system class loader matches one in the image if the class // is in the image. - existing = LookupClassFromImage(descriptor); + existing = LookupClassFromBootImage(descriptor); if (existing != nullptr) { CHECK_EQ(klass, existing); } @@ -2691,11 +2693,11 @@ mirror::Class* ClassLinker::LookupClass(Thread* self, } } } - if (class_loader != nullptr || !dex_cache_image_class_lookup_required_) { + if (class_loader != nullptr || !dex_cache_boot_image_class_lookup_required_) { return nullptr; } // Lookup failed but need to search dex_caches_. - mirror::Class* result = LookupClassFromImage(descriptor); + mirror::Class* result = LookupClassFromBootImage(descriptor); if (result != nullptr) { result = InsertClass(descriptor, result, hash); } else { @@ -2704,37 +2706,43 @@ mirror::Class* ClassLinker::LookupClass(Thread* self, // classes into the class table. constexpr uint32_t kMaxFailedDexCacheLookups = 1000; if (++failed_dex_cache_class_lookups_ > kMaxFailedDexCacheLookups) { - MoveImageClassesToClassTable(); + AddBootImageClassesToClassTable(); } } return result; } -static mirror::ObjectArray<mirror::DexCache>* GetImageDexCaches() +static mirror::ObjectArray<mirror::DexCache>* GetImageDexCaches(gc::space::ImageSpace* image_space) SHARED_REQUIRES(Locks::mutator_lock_) { - gc::space::ImageSpace* image = Runtime::Current()->GetHeap()->GetImageSpace(); - CHECK(image != nullptr); - mirror::Object* root = image->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches); + CHECK(image_space != nullptr); + mirror::Object* root = image_space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches); + DCHECK(root != nullptr); return root->AsObjectArray<mirror::DexCache>(); } -void ClassLinker::MoveImageClassesToClassTable() { +void ClassLinker::AddBootImageClassesToClassTable() { + if (dex_cache_boot_image_class_lookup_required_) { + AddImageClassesToClassTable(Runtime::Current()->GetHeap()->GetBootImageSpace(), + /*class_loader*/nullptr); + dex_cache_boot_image_class_lookup_required_ = false; + } +} + +void ClassLinker::AddImageClassesToClassTable(gc::space::ImageSpace* image_space, + mirror::ClassLoader* class_loader) { Thread* self = Thread::Current(); WriterMutexLock mu(self, *Locks::classlinker_classes_lock_); - if (!dex_cache_image_class_lookup_required_) { - return; // All dex cache classes are already in the class table. - } ScopedAssertNoThreadSuspension ants(self, "Moving image classes to class table"); - mirror::ObjectArray<mirror::DexCache>* dex_caches = GetImageDexCaches(); + mirror::ObjectArray<mirror::DexCache>* dex_caches = GetImageDexCaches(image_space); std::string temp; - ClassTable* const class_table = InsertClassTableForClassLoader(nullptr); + ClassTable* const class_table = InsertClassTableForClassLoader(class_loader); for (int32_t i = 0; i < dex_caches->GetLength(); i++) { mirror::DexCache* dex_cache = dex_caches->Get(i); GcRoot<mirror::Class>* types = dex_cache->GetResolvedTypes(); for (int32_t j = 0, num_types = dex_cache->NumResolvedTypes(); j < num_types; j++) { mirror::Class* klass = types[j].Read(); if (klass != nullptr) { - DCHECK(klass->GetClassLoader() == nullptr); + DCHECK_EQ(klass->GetClassLoader(), class_loader); const char* descriptor = klass->GetDescriptor(&temp); size_t hash = ComputeModifiedUtf8Hash(descriptor); mirror::Class* existing = class_table->Lookup(descriptor, hash); @@ -2750,7 +2758,6 @@ void ClassLinker::MoveImageClassesToClassTable() { } } } - dex_cache_image_class_lookup_required_ = false; } class MoveClassTableToPreZygoteVisitor : public ClassLoaderVisitor { @@ -2774,9 +2781,10 @@ void ClassLinker::MoveClassTableToPreZygote() { VisitClassLoaders(&visitor); } -mirror::Class* ClassLinker::LookupClassFromImage(const char* descriptor) { +mirror::Class* ClassLinker::LookupClassFromBootImage(const char* descriptor) { ScopedAssertNoThreadSuspension ants(Thread::Current(), "Image class lookup"); - mirror::ObjectArray<mirror::DexCache>* dex_caches = GetImageDexCaches(); + mirror::ObjectArray<mirror::DexCache>* dex_caches = GetImageDexCaches( + Runtime::Current()->GetHeap()->GetBootImageSpace()); for (int32_t i = 0; i < dex_caches->GetLength(); ++i) { mirror::DexCache* dex_cache = dex_caches->Get(i); const DexFile* dex_file = dex_cache->GetDexFile(); @@ -2818,8 +2826,8 @@ class LookupClassesVisitor : public ClassLoaderVisitor { void ClassLinker::LookupClasses(const char* descriptor, std::vector<mirror::Class*>& result) { result.clear(); - if (dex_cache_image_class_lookup_required_) { - MoveImageClassesToClassTable(); + if (dex_cache_boot_image_class_lookup_required_) { + AddBootImageClassesToClassTable(); } Thread* const self = Thread::Current(); ReaderMutexLock mu(self, *Locks::classlinker_classes_lock_); @@ -4142,10 +4150,10 @@ bool ClassLinker::LinkClass(Thread* self, Runtime::Current()->GetHeap()->WriteBarrierEveryFieldOf(class_loader); } CHECK_EQ(existing, klass.Get()); - if (kIsDebugBuild && class_loader == nullptr && dex_cache_image_class_lookup_required_) { + if (kIsDebugBuild && class_loader == nullptr && dex_cache_boot_image_class_lookup_required_) { // Check a class loaded with the system class loader matches one in the image if the class // is in the image. - mirror::Class* const image_class = LookupClassFromImage(descriptor); + mirror::Class* const image_class = LookupClassFromBootImage(descriptor); if (image_class != nullptr) { CHECK_EQ(klass.Get(), existing) << descriptor; } @@ -6423,8 +6431,8 @@ void ClassLinker::SetEntryPointsToInterpreter(ArtMethod* method) const { void ClassLinker::DumpForSigQuit(std::ostream& os) { ScopedObjectAccess soa(Thread::Current()); - if (dex_cache_image_class_lookup_required_) { - MoveImageClassesToClassTable(); + if (dex_cache_boot_image_class_lookup_required_) { + AddBootImageClassesToClassTable(); } ReaderMutexLock mu(soa.Self(), *Locks::classlinker_classes_lock_); os << "Zygote loaded classes=" << NumZygoteClasses() << " post zygote classes=" @@ -6461,8 +6469,8 @@ size_t ClassLinker::NumNonZygoteClasses() const { } size_t ClassLinker::NumLoadedClasses() { - if (dex_cache_image_class_lookup_required_) { - MoveImageClassesToClassTable(); + if (dex_cache_boot_image_class_lookup_required_) { + AddBootImageClassesToClassTable(); } ReaderMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); // Only return non zygote classes since these are the ones which apps which care about. diff --git a/runtime/class_linker.h b/runtime/class_linker.h index d6a27b18b2..21f9e7b73a 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -487,10 +487,17 @@ class ClassLinker { return class_roots; } - // Move all of the image classes into the class table for faster lookups. - void MoveImageClassesToClassTable() + // Move all of the boot image classes into the class table for faster lookups. + void AddBootImageClassesToClassTable() REQUIRES(!Locks::classlinker_classes_lock_) SHARED_REQUIRES(Locks::mutator_lock_); + + // Add image classes to the class table. + void AddImageClassesToClassTable(gc::space::ImageSpace* image_space, + mirror::ClassLoader* class_loader) + REQUIRES(!Locks::classlinker_classes_lock_) + SHARED_REQUIRES(Locks::mutator_lock_); + // Move the class table to the pre-zygote table to reduce memory usage. This works by ensuring // that no more classes are ever added to the pre zygote table which makes it that the pages // always remain shared dirty instead of private dirty. @@ -909,7 +916,7 @@ class ClassLinker { void EnsurePreverifiedMethods(Handle<mirror::Class> c) SHARED_REQUIRES(Locks::mutator_lock_); - mirror::Class* LookupClassFromImage(const char* descriptor) + mirror::Class* LookupClassFromBootImage(const char* descriptor) SHARED_REQUIRES(Locks::mutator_lock_); // Returns null if not found. @@ -973,8 +980,8 @@ class ClassLinker { // New class roots, only used by CMS since the GC needs to mark these in the pause. std::vector<GcRoot<mirror::Class>> new_class_roots_ GUARDED_BY(Locks::classlinker_classes_lock_); - // Do we need to search dex caches to find image classes? - bool dex_cache_image_class_lookup_required_; + // Do we need to search dex caches to find boot image classes? + bool dex_cache_boot_image_class_lookup_required_; // Number of times we've searched dex caches for a class. After a certain number of misses we move // the classes into the class_table_ to avoid dex cache based searches. Atomic<uint32_t> failed_dex_cache_class_lookups_; diff --git a/runtime/gc/accounting/mod_union_table.cc b/runtime/gc/accounting/mod_union_table.cc index 1361f7bcc5..8f7bb946c3 100644 --- a/runtime/gc/accounting/mod_union_table.cc +++ b/runtime/gc/accounting/mod_union_table.cc @@ -487,7 +487,7 @@ void ModUnionTableCardCache::ClearCards() { // Mark all references to the alloc space(s). void ModUnionTableCardCache::UpdateAndMarkReferences(MarkObjectVisitor* visitor) { - auto* image_space = heap_->GetImageSpace(); + auto* image_space = heap_->GetBootImageSpace(); // If we don't have an image space, just pass in space_ as the immune space. Pass in the same // space_ instead of image_space to avoid a null check in ModUnionUpdateObjectReferencesVisitor. CardBitVisitor bit_visitor(visitor, space_, image_space != nullptr ? image_space : space_, diff --git a/runtime/gc/collector/concurrent_copying.cc b/runtime/gc/collector/concurrent_copying.cc index 4a49712cbc..f4cf3ae260 100644 --- a/runtime/gc/collector/concurrent_copying.cc +++ b/runtime/gc/collector/concurrent_copying.cc @@ -23,7 +23,7 @@ #include "gc/accounting/space_bitmap-inl.h" #include "gc/reference_processor.h" #include "gc/space/image_space.h" -#include "gc/space/space.h" +#include "gc/space/space-inl.h" #include "intern_table.h" #include "mirror/class-inl.h" #include "mirror/object-inl.h" @@ -358,13 +358,17 @@ void ConcurrentCopying::MarkingPhase() { // scan the image objects from roots by relying on the card table, // but it's necessary for the RB to-space invariant to hold. TimingLogger::ScopedTiming split1("VisitImageRoots", GetTimings()); - gc::space::ImageSpace* image = heap_->GetImageSpace(); - if (image != nullptr) { - mirror::ObjectArray<mirror::Object>* image_root = image->GetImageHeader().GetImageRoots(); - mirror::Object* marked_image_root = Mark(image_root); - CHECK_EQ(image_root, marked_image_root) << "An image object does not move"; - if (ReadBarrier::kEnableToSpaceInvariantChecks) { - AssertToSpaceInvariant(nullptr, MemberOffset(0), marked_image_root); + for (space::ContinuousSpace* space : heap_->GetContinuousSpaces()) { + if (space->IsImageSpace()) { + gc::space::ImageSpace* image = space->AsImageSpace(); + if (image != nullptr) { + mirror::ObjectArray<mirror::Object>* image_root = image->GetImageHeader().GetImageRoots(); + mirror::Object* marked_image_root = Mark(image_root); + CHECK_EQ(image_root, marked_image_root) << "An image object does not move"; + if (ReadBarrier::kEnableToSpaceInvariantChecks) { + AssertToSpaceInvariant(nullptr, MemberOffset(0), marked_image_root); + } + } } } } diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index fd2426b716..da9a79e1a2 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -233,7 +233,8 @@ Heap::Heap(size_t initial_size, backtrace_lock_(nullptr), seen_backtrace_count_(0u), unique_backtrace_count_(0u), - gc_disabled_for_shutdown_(false) { + gc_disabled_for_shutdown_(false), + boot_image_space_(nullptr) { if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) { LOG(INFO) << "Heap() entering"; } @@ -262,15 +263,16 @@ Heap::Heap(size_t initial_size, if (!image_file_name.empty()) { ATRACE_BEGIN("ImageSpace::Create"); std::string error_msg; - auto* image_space = space::ImageSpace::Create(image_file_name.c_str(), image_instruction_set, + boot_image_space_ = space::ImageSpace::Create(image_file_name.c_str(), + image_instruction_set, &error_msg); ATRACE_END(); - if (image_space != nullptr) { - AddSpace(image_space); + if (boot_image_space_ != nullptr) { + AddSpace(boot_image_space_); // Oat files referenced by image files immediately follow them in memory, ensure alloc space // isn't going to get in the middle - uint8_t* oat_file_end_addr = image_space->GetImageHeader().GetOatFileEnd(); - CHECK_GT(oat_file_end_addr, image_space->End()); + uint8_t* oat_file_end_addr = boot_image_space_->GetImageHeader().GetOatFileEnd(); + CHECK_GT(oat_file_end_addr, boot_image_space_->End()); requested_alloc_space_begin = AlignUp(oat_file_end_addr, kPageSize); } else { LOG(ERROR) << "Could not create image space with image file '" << image_file_name << "'. " @@ -454,11 +456,11 @@ Heap::Heap(size_t initial_size, rb_table_.reset(new accounting::ReadBarrierTable()); DCHECK(rb_table_->IsAllCleared()); } - if (GetImageSpace() != nullptr) { + if (GetBootImageSpace() != nullptr) { // Don't add the image mod union table if we are running without an image, this can crash if // we use the CardCache implementation. accounting::ModUnionTable* mod_union_table = new accounting::ModUnionTableToZygoteAllocspace( - "Image mod-union table", this, GetImageSpace()); + "Image mod-union table", this, GetBootImageSpace()); CHECK(mod_union_table != nullptr) << "Failed to create image mod-union table"; AddModUnionTable(mod_union_table); } @@ -523,12 +525,12 @@ Heap::Heap(size_t initial_size, garbage_collectors_.push_back(mark_compact_collector_); } } - if (GetImageSpace() != nullptr && non_moving_space_ != nullptr && + if (GetBootImageSpace() != nullptr && non_moving_space_ != nullptr && (is_zygote || separate_non_moving_space || foreground_collector_type_ == kCollectorTypeGSS)) { // Check that there's no gap between the image space and the non moving space so that the // immune region won't break (eg. due to a large object allocated in the gap). This is only // required when we're the zygote or using GSS. - bool no_gap = MemMap::CheckNoGaps(GetImageSpace()->GetMemMap(), + bool no_gap = MemMap::CheckNoGaps(GetBootImageSpace()->GetMemMap(), non_moving_space_->GetMemMap()); if (!no_gap) { PrintFileToLog("/proc/self/maps", LogSeverity::ERROR); @@ -748,15 +750,6 @@ bool Heap::IsCompilingBoot() const { return true; } -bool Heap::HasImageSpace() const { - for (const auto& space : continuous_spaces_) { - if (space->IsImageSpace()) { - return true; - } - } - return false; -} - void Heap::IncrementDisableMovingGC(Thread* self) { // Need to do this holding the lock to prevent races where the GC is about to run / running when // we attempt to disable it. @@ -1209,13 +1202,8 @@ space::Space* Heap::FindSpaceFromObject(const mirror::Object* obj, bool fail_ok) return FindDiscontinuousSpaceFromObject(obj, fail_ok); } -space::ImageSpace* Heap::GetImageSpace() const { - for (const auto& space : continuous_spaces_) { - if (space->IsImageSpace()) { - return space->AsImageSpace(); - } - } - return nullptr; +space::ImageSpace* Heap::GetBootImageSpace() const { + return boot_image_space_; } void Heap::ThrowOutOfMemoryError(Thread* self, size_t byte_count, AllocatorType allocator_type) { diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index cc48172f71..e23b1a3166 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h @@ -580,9 +580,9 @@ class Heap { // Unbind any bound bitmaps. void UnBindBitmaps() REQUIRES(Locks::heap_bitmap_lock_); - // DEPRECATED: Should remove in "near" future when support for multiple image spaces is added. - // Assumes there is only one image space. - space::ImageSpace* GetImageSpace() const; + // Returns the boot image space. There may be multiple image spaces, but there is only one boot + // image space. + space::ImageSpace* GetBootImageSpace() const; // Permenantly disable moving garbage collection. void DisableMovingGc() REQUIRES(!*gc_complete_lock_); @@ -660,7 +660,9 @@ class Heap { void RemoveRememberedSet(space::Space* space); bool IsCompilingBoot() const; - bool HasImageSpace() const; + bool HasImageSpace() const { + return boot_image_space_ != nullptr; + } ReferenceProcessor* GetReferenceProcessor() { return reference_processor_.get(); @@ -1320,6 +1322,9 @@ class Heap { // allocating. bool gc_disabled_for_shutdown_ GUARDED_BY(gc_complete_lock_); + // Boot image space. + space::ImageSpace* boot_image_space_; + friend class CollectorTransitionTask; friend class collector::GarbageCollector; friend class collector::MarkCompact; diff --git a/runtime/intern_table.cc b/runtime/intern_table.cc index f4658d5342..e2e4782d00 100644 --- a/runtime/intern_table.cc +++ b/runtime/intern_table.cc @@ -187,7 +187,7 @@ mirror::String* InternTable::LookupStringFromImage(mirror::String* s) { if (image_added_to_intern_table_) { return nullptr; } - gc::space::ImageSpace* image = Runtime::Current()->GetHeap()->GetImageSpace(); + gc::space::ImageSpace* image = Runtime::Current()->GetHeap()->GetBootImageSpace(); if (image == nullptr) { return nullptr; // No image present. } diff --git a/runtime/monitor.cc b/runtime/monitor.cc index da21fee3d2..19c71f6d97 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc @@ -485,10 +485,7 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns, DCHECK(why == kTimedWaiting || why == kSleeping) << why; self->GetWaitConditionVariable()->TimedWait(self, ms, ns); } - if (self->IsInterruptedLocked()) { - was_interrupted = true; - } - self->SetInterruptedLocked(false); + was_interrupted = self->IsInterruptedLocked(); } } @@ -522,7 +519,7 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns, monitor_lock_.Unlock(self); - if (was_interrupted) { + if (was_interrupted && interruptShouldThrow) { /* * We were interrupted while waiting, or somebody interrupted an * un-interruptible thread earlier and we're bailing out immediately. @@ -534,9 +531,7 @@ void Monitor::Wait(Thread* self, int64_t ms, int32_t ns, MutexLock mu(self, *self->GetWaitMutex()); self->SetInterruptedLocked(false); } - if (interruptShouldThrow) { - self->ThrowNewException("Ljava/lang/InterruptedException;", nullptr); - } + self->ThrowNewException("Ljava/lang/InterruptedException;", nullptr); } } diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index 99080f611c..0f3a013d53 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -846,7 +846,7 @@ std::string OatFileAssistant::OldProfileFileName() { std::string OatFileAssistant::ImageLocation() { Runtime* runtime = Runtime::Current(); - const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace(); + const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetBootImageSpace(); if (image_space == nullptr) { return ""; } @@ -949,21 +949,23 @@ const OatFileAssistant::ImageInfo* OatFileAssistant::GetImageInfo() { image_info_load_attempted_ = true; Runtime* runtime = Runtime::Current(); - const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace(); + const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetBootImageSpace(); if (image_space != nullptr) { cached_image_info_.location = image_space->GetImageLocation(); if (isa_ == kRuntimeISA) { const ImageHeader& image_header = image_space->GetImageHeader(); cached_image_info_.oat_checksum = image_header.GetOatChecksum(); - cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()); + cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>( + image_header.GetOatDataBegin()); cached_image_info_.patch_delta = image_header.GetPatchDelta(); } else { std::unique_ptr<ImageHeader> image_header( gc::space::ImageSpace::ReadImageHeaderOrDie( cached_image_info_.location.c_str(), isa_)); cached_image_info_.oat_checksum = image_header->GetOatChecksum(); - cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(image_header->GetOatDataBegin()); + cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>( + image_header->GetOatDataBegin()); cached_image_info_.patch_delta = image_header->GetPatchDelta(); } } diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index c54d7f8761..8c7efb2ea8 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -223,7 +223,7 @@ class OatFileAssistantTest : public CommonRuntimeTest { false, dex_location.c_str(), &error_msg)); ASSERT_TRUE(odex_file.get() != nullptr) << error_msg; - const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace(); + const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetBootImageSpace(); ASSERT_TRUE(image_space != nullptr); const ImageHeader& image_header = image_space->GetImageHeader(); const OatHeader& oat_header = odex_file->GetOatHeader(); diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc index 9eee156bb0..ea6d3ff3dd 100644 --- a/runtime/oat_file_manager.cc +++ b/runtime/oat_file_manager.cc @@ -79,11 +79,8 @@ const OatFile* OatFileManager::FindOpenedOatFileFromOatLocationLocked( } const OatFile* OatFileManager::GetBootOatFile() const { - gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace(); - if (image_space == nullptr) { - return nullptr; - } - return image_space->GetOatFile(); + gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetBootImageSpace(); + return (image_space == nullptr) ? nullptr : image_space->GetOatFile(); } const OatFile* OatFileManager::GetPrimaryOatFile() const { diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 556ba56532..17f34c0e21 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -528,13 +528,13 @@ bool Runtime::Start() { // Use !IsAotCompiler so that we get test coverage, tests are never the zygote. if (!IsAotCompiler()) { ScopedObjectAccess soa(self); - gc::space::ImageSpace* image_space = heap_->GetImageSpace(); + gc::space::ImageSpace* image_space = heap_->GetBootImageSpace(); if (image_space != nullptr) { ATRACE_BEGIN("AddImageStringsToTable"); GetInternTable()->AddImageStringsToTable(image_space); ATRACE_END(); ATRACE_BEGIN("MoveImageClassesToClassTable"); - GetClassLinker()->MoveImageClassesToClassTable(); + GetClassLinker()->AddBootImageClassesToClassTable(); ATRACE_END(); } } @@ -930,7 +930,7 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) runtime_options.GetOrDefault(Opt::HSpaceCompactForOOMMinIntervalsMs)); ATRACE_END(); - if (heap_->GetImageSpace() == nullptr && !allow_dex_file_fallback_) { + if (heap_->GetBootImageSpace() == nullptr && !allow_dex_file_fallback_) { LOG(ERROR) << "Dex file fallback disabled, cannot continue without image."; ATRACE_END(); return false; @@ -1043,7 +1043,7 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) class_linker_->InitFromImage(); ATRACE_END(); if (kIsDebugBuild) { - GetHeap()->GetImageSpace()->VerifyImageAllocations(); + GetHeap()->GetBootImageSpace()->VerifyImageAllocations(); } if (boot_class_path_string_.empty()) { // The bootclasspath is not explicitly specified: construct it from the loaded dex files. diff --git a/test/117-nopatchoat/nopatchoat.cc b/test/117-nopatchoat/nopatchoat.cc index 3e533ad62e..b6b1c43589 100644 --- a/test/117-nopatchoat/nopatchoat.cc +++ b/test/117-nopatchoat/nopatchoat.cc @@ -35,7 +35,7 @@ class NoPatchoatTest { } static bool isRelocationDeltaZero() { - gc::space::ImageSpace* space = Runtime::Current()->GetHeap()->GetImageSpace(); + gc::space::ImageSpace* space = Runtime::Current()->GetHeap()->GetBootImageSpace(); return space != nullptr && space->GetImageHeader().GetPatchDelta() == 0; } diff --git a/test/137-cfi/cfi.cc b/test/137-cfi/cfi.cc index 78f884266a..7762b2d2e3 100644 --- a/test/137-cfi/cfi.cc +++ b/test/137-cfi/cfi.cc @@ -92,7 +92,7 @@ static bool CheckStack(Backtrace* bt, const std::vector<std::string>& seq) { // detecting this. #if __linux__ static bool IsPicImage() { - gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace(); + gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetBootImageSpace(); CHECK(image_space != nullptr); // We should be running with an image. const OatFile* oat_file = image_space->GetOatFile(); CHECK(oat_file != nullptr); // We should have an oat file to go with the image. diff --git a/test/956-checker-lambda/build b/test/956-checker-lambda/build deleted file mode 100755 index d666020c4e..0000000000 --- a/test/956-checker-lambda/build +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# -# Copyright 2015 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Make us exit on a failure. -set -e - -# Hard-wired use of experimental jack. -# TODO: fix this temporary work-around for lambdas, see b/19467889 -export USE_JACK=true -export JACK_VERSION="-1.1.PRE_ALPHA" -export JACK_SERVER=false -export JACK_REPOSITORY="${ANDROID_BUILD_TOP}/prebuilts/sdk/tools/jacks" - -./default-build "$@" --experimental lambdas diff --git a/test/956-checker-lambda/expected.txt b/test/956-checker-lambda/expected.txt deleted file mode 100644 index 521aed5901..0000000000 --- a/test/956-checker-lambda/expected.txt +++ /dev/null @@ -1,2 +0,0 @@ -Lambda 123 -passed diff --git a/test/956-checker-lambda/info.txt b/test/956-checker-lambda/info.txt deleted file mode 100644 index 6bc7442e19..0000000000 --- a/test/956-checker-lambda/info.txt +++ /dev/null @@ -1 +0,0 @@ -Test on lambda expressions. diff --git a/test/956-checker-lambda/run b/test/956-checker-lambda/run deleted file mode 100755 index 2fb2f89f6b..0000000000 --- a/test/956-checker-lambda/run +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# -# Copyright (C) 2015 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Ensure that the lambda experimental opcodes are turned on for dalvikvm and dex2oat -${RUN} "$@" --experimental lambdas diff --git a/test/956-checker-lambda/src/Main.java b/test/956-checker-lambda/src/Main.java deleted file mode 100644 index b5f4a94b9e..0000000000 --- a/test/956-checker-lambda/src/Main.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2015 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// -// Test on lambda expressions. -// -public class Main { - - @NeedsLambda - interface L1 { - public void run(int a); - } - - int d; - - public Main() { - d = 4; - } - - private void doit(int a) { - int b = 2; - // Captures parameter, local, and field. Takes its own parameter. - // TODO: add field d as well, b/25631011 prevents this - L1 lambda1 = (int c) -> { System.out.println("Lambda " + a + b + c); }; - lambda1.run(3); - } - - public static void main(String[] args) { - new Main().doit(1); - System.out.println("passed"); - } -} diff --git a/test/968-default-partial-compilation-generated/build b/test/968-default-partial-compile-generated/build index 1e9f8aadd5..1e9f8aadd5 100755 --- a/test/968-default-partial-compilation-generated/build +++ b/test/968-default-partial-compile-generated/build diff --git a/test/968-default-partial-compilation-generated/expected.txt b/test/968-default-partial-compile-generated/expected.txt index 1ddd65d177..1ddd65d177 100644 --- a/test/968-default-partial-compilation-generated/expected.txt +++ b/test/968-default-partial-compile-generated/expected.txt diff --git a/test/968-default-partial-compilation-generated/info.txt b/test/968-default-partial-compile-generated/info.txt index bc1c42816e..bc1c42816e 100644 --- a/test/968-default-partial-compilation-generated/info.txt +++ b/test/968-default-partial-compile-generated/info.txt diff --git a/test/968-default-partial-compilation-generated/run b/test/968-default-partial-compile-generated/run index 6d2930d463..6d2930d463 100755 --- a/test/968-default-partial-compilation-generated/run +++ b/test/968-default-partial-compile-generated/run diff --git a/test/968-default-partial-compilation-generated/util-src/generate_java.py b/test/968-default-partial-compile-generated/util-src/generate_java.py index 35290efe1d..35290efe1d 100755 --- a/test/968-default-partial-compilation-generated/util-src/generate_java.py +++ b/test/968-default-partial-compile-generated/util-src/generate_java.py diff --git a/test/968-default-partial-compilation-generated/util-src/generate_smali.py b/test/968-default-partial-compile-generated/util-src/generate_smali.py index 9855bcf854..9855bcf854 100755 --- a/test/968-default-partial-compilation-generated/util-src/generate_smali.py +++ b/test/968-default-partial-compile-generated/util-src/generate_smali.py diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index 3a0bea3971..b5287216ce 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -226,7 +226,7 @@ TEST_ART_PYTHON3_DEPENDENCY_RUN_TESTS := \ 960-default-smali \ 961-default-iface-resolution-generated \ 964-default-iface-init-generated \ - 968-default-partial-compilation-generated + 968-default-partial-compile-generated # Check if we have python3 to run our tests. ifeq ($(wildcard /usr/bin/python3),) |