diff options
Diffstat (limited to 'runtime/gc/heap.cc')
-rw-r--r-- | runtime/gc/heap.cc | 105 |
1 files changed, 76 insertions, 29 deletions
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 6d72f3142e..d6c1817f13 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -233,8 +233,7 @@ Heap::Heap(size_t initial_size, backtrace_lock_(nullptr), seen_backtrace_count_(0u), unique_backtrace_count_(0u), - gc_disabled_for_shutdown_(false), - boot_image_space_(nullptr) { + gc_disabled_for_shutdown_(false) { if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) { LOG(INFO) << "Heap() entering"; } @@ -260,23 +259,63 @@ Heap::Heap(size_t initial_size, CHECK_GE(300 * MB, non_moving_space_capacity); requested_alloc_space_begin = reinterpret_cast<uint8_t*>(300 * MB) - non_moving_space_capacity; } + + // Load image space(s). if (!image_file_name.empty()) { - ATRACE_BEGIN("ImageSpace::Create"); - std::string error_msg; - boot_image_space_ = space::ImageSpace::Create(image_file_name.c_str(), - image_instruction_set, - &error_msg); - ATRACE_END(); - 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 = 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 << "'. " - << "Attempting to fall back to imageless running. Error was: " << error_msg; + // For code reuse, handle this like a work queue. + std::vector<std::string> image_file_names; + image_file_names.push_back(image_file_name); + // The loaded spaces. Secondary images may fail to load, in which case we need to remove + // already added spaces. + std::vector<space::Space*> added_image_spaces; + + for (size_t index = 0; index < image_file_names.size(); ++index) { + std::string& image_name = image_file_names[index]; + ATRACE_BEGIN("ImageSpace::Create"); + std::string error_msg; + space::ImageSpace* boot_image_space = space::ImageSpace::Create(image_name.c_str(), + image_instruction_set, + index > 0, + &error_msg); + ATRACE_END(); + if (boot_image_space != nullptr) { + AddSpace(boot_image_space); + added_image_spaces.push_back(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 = 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); + boot_image_spaces_.push_back(boot_image_space); + + if (index == 0) { + // If this was the first space, check whether there are more images to load. + const OatFile* boot_oat_file = boot_image_space->GetOatFile(); + if (boot_oat_file == nullptr) { + continue; + } + + const OatHeader& boot_oat_header = boot_oat_file->GetOatHeader(); + const char* boot_classpath = + boot_oat_header.GetStoreValueByKey(OatHeader::kBootClassPath); + if (boot_classpath == nullptr) { + continue; + } + + space::ImageSpace::CreateMultiImageLocations(image_file_name, + boot_classpath, + &image_file_names); + } + } else { + LOG(ERROR) << "Could not create image space with image file '" << image_file_name << "'. " + << "Attempting to fall back to imageless running. Error was: " << error_msg + << "\nAttempted image: " << image_name; + // Remove already loaded spaces. + for (space::Space* loaded_space : added_image_spaces) { + RemoveSpace(loaded_space); + } + break; + } } } /* @@ -456,13 +495,15 @@ Heap::Heap(size_t initial_size, rb_table_.reset(new accounting::ReadBarrierTable()); DCHECK(rb_table_->IsAllCleared()); } - if (GetBootImageSpace() != nullptr) { + if (HasBootImageSpace()) { // 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, GetBootImageSpace()); - CHECK(mod_union_table != nullptr) << "Failed to create image mod-union table"; - AddModUnionTable(mod_union_table); + for (space::ImageSpace* image_space : GetBootImageSpaces()) { + accounting::ModUnionTable* mod_union_table = new accounting::ModUnionTableToZygoteAllocspace( + "Image mod-union table", this, image_space); + CHECK(mod_union_table != nullptr) << "Failed to create image mod-union table"; + AddModUnionTable(mod_union_table); + } } if (collector::SemiSpace::kUseRememberedSet && non_moving_space_ != main_space_) { accounting::RememberedSet* non_moving_space_rem_set = @@ -525,13 +566,19 @@ Heap::Heap(size_t initial_size, garbage_collectors_.push_back(mark_compact_collector_); } } - if (GetBootImageSpace() != nullptr && non_moving_space_ != nullptr && + if (!GetBootImageSpaces().empty() && 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(GetBootImageSpace()->GetMemMap(), - non_moving_space_->GetMemMap()); + // Space with smallest Begin(). + space::ImageSpace* first_space = nullptr; + for (space::ImageSpace* space : boot_image_spaces_) { + if (first_space == nullptr || space->Begin() < first_space->Begin()) { + first_space = space; + } + } + bool no_gap = MemMap::CheckNoGaps(first_space->GetMemMap(), non_moving_space_->GetMemMap()); if (!no_gap) { PrintFileToLog("/proc/self/maps", LogSeverity::ERROR); MemMap::DumpMaps(LOG(ERROR), true); @@ -1202,8 +1249,8 @@ space::Space* Heap::FindSpaceFromObject(const mirror::Object* obj, bool fail_ok) return FindDiscontinuousSpaceFromObject(obj, fail_ok); } -space::ImageSpace* Heap::GetBootImageSpace() const { - return boot_image_space_; +std::vector<space::ImageSpace*> Heap::GetBootImageSpaces() const { + return boot_image_spaces_; } void Heap::ThrowOutOfMemoryError(Thread* self, size_t byte_count, AllocatorType allocator_type) { @@ -2290,7 +2337,7 @@ void Heap::PreZygoteFork() { if (HasZygoteSpace()) { return; } - Runtime::Current()->GetInternTable()->SwapPostZygoteWithPreZygote(); + Runtime::Current()->GetInternTable()->AddNewTable(); Runtime::Current()->GetClassLinker()->MoveClassTableToPreZygote(); VLOG(heap) << "Starting PreZygoteFork"; // Trim the pages at the end of the non moving space. |