diff options
-rw-r--r-- | runtime/gc/heap.cc | 114 | ||||
-rw-r--r-- | runtime/gc/space/image_space.cc | 75 | ||||
-rw-r--r-- | runtime/gc/space/image_space.h | 5 |
3 files changed, 120 insertions, 74 deletions
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index b74071b8aa..589e9a4826 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -312,24 +312,63 @@ Heap::Heap(size_t initial_size, ChangeCollector(desired_collector_type_); live_bitmap_.reset(new accounting::HeapBitmap(this)); mark_bitmap_.reset(new accounting::HeapBitmap(this)); - // Requested begin for the alloc space, to follow the mapped image and oat files - uint8_t* requested_alloc_space_begin = nullptr; - if (foreground_collector_type_ == kCollectorTypeCC) { - // Need to use a low address so that we can allocate a contiguous 2 * Xmx space when there's no - // image (dex2oat for target). - requested_alloc_space_begin = kPreferredAllocSpaceBegin; + + // We don't have hspace compaction enabled with GSS or CC. + if (foreground_collector_type_ == kCollectorTypeGSS || + foreground_collector_type_ == kCollectorTypeCC) { + use_homogeneous_space_compaction_for_oom_ = false; + } + bool support_homogeneous_space_compaction = + background_collector_type_ == gc::kCollectorTypeHomogeneousSpaceCompact || + use_homogeneous_space_compaction_for_oom_; + // We may use the same space the main space for the non moving space if we don't need to compact + // from the main space. + // This is not the case if we support homogeneous compaction or have a moving background + // collector type. + bool separate_non_moving_space = is_zygote || + support_homogeneous_space_compaction || IsMovingGc(foreground_collector_type_) || + IsMovingGc(background_collector_type_); + if (foreground_collector_type_ == kCollectorTypeGSS) { + separate_non_moving_space = false; } + // Requested begin for the alloc space, to follow the mapped image and oat files + uint8_t* request_begin = nullptr; + // Calculate the extra space required after the boot image, see allocations below. + size_t heap_reservation_size = separate_non_moving_space + ? non_moving_space_capacity + : ((is_zygote && foreground_collector_type_ != kCollectorTypeCC) ? capacity_ : 0u); + heap_reservation_size = RoundUp(heap_reservation_size, kPageSize); // Load image space(s). std::vector<std::unique_ptr<space::ImageSpace>> boot_image_spaces; + MemMap heap_reservation; if (space::ImageSpace::LoadBootImage(image_file_name, image_instruction_set, + heap_reservation_size, &boot_image_spaces, - &requested_alloc_space_begin)) { + &heap_reservation)) { + DCHECK_EQ(heap_reservation_size, heap_reservation.IsValid() ? heap_reservation.Size() : 0u); + DCHECK(!boot_image_spaces.empty()); + request_begin = boot_image_spaces.back()->GetImageHeader().GetOatFileEnd(); + DCHECK(!heap_reservation.IsValid() || request_begin == heap_reservation.Begin()) + << "request_begin=" << static_cast<const void*>(request_begin) + << " heap_reservation.Begin()=" << static_cast<const void*>(heap_reservation.Begin()); for (std::unique_ptr<space::ImageSpace>& space : boot_image_spaces) { boot_image_spaces_.push_back(space.get()); AddSpace(space.release()); } + } else { + if (foreground_collector_type_ == kCollectorTypeCC) { + // Need to use a low address so that we can allocate a contiguous 2 * Xmx space + // when there's no image (dex2oat for target). + request_begin = kPreferredAllocSpaceBegin; + } + // Gross hack to make dex2oat deterministic. + if (foreground_collector_type_ == kCollectorTypeMS && Runtime::Current()->IsAotCompiler()) { + // Currently only enabled for MS collector since that is what the deterministic dex2oat uses. + // b/26849108 + request_begin = reinterpret_cast<uint8_t*>(kAllocSpaceBeginForDeterministicAoT); + } } /* @@ -345,39 +384,10 @@ Heap::Heap(size_t initial_size, +-main alloc space2 / bump space 2 (capacity_)+- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- */ - // We don't have hspace compaction enabled with GSS or CC. - if (foreground_collector_type_ == kCollectorTypeGSS || - foreground_collector_type_ == kCollectorTypeCC) { - use_homogeneous_space_compaction_for_oom_ = false; - } - bool support_homogeneous_space_compaction = - background_collector_type_ == gc::kCollectorTypeHomogeneousSpaceCompact || - use_homogeneous_space_compaction_for_oom_; - // We may use the same space the main space for the non moving space if we don't need to compact - // from the main space. - // This is not the case if we support homogeneous compaction or have a moving background - // collector type. - bool separate_non_moving_space = is_zygote || - support_homogeneous_space_compaction || IsMovingGc(foreground_collector_type_) || - IsMovingGc(background_collector_type_); - if (foreground_collector_type_ == kCollectorTypeGSS) { - separate_non_moving_space = false; - } + MemMap main_mem_map_1; MemMap main_mem_map_2; - // Gross hack to make dex2oat deterministic. - if (foreground_collector_type_ == kCollectorTypeMS && - requested_alloc_space_begin == nullptr && - Runtime::Current()->IsAotCompiler()) { - // Currently only enabled for MS collector since that is what the deterministic dex2oat uses. - // b/26849108 - requested_alloc_space_begin = reinterpret_cast<uint8_t*>(kAllocSpaceBeginForDeterministicAoT); - } - uint8_t* request_begin = requested_alloc_space_begin; - if (request_begin != nullptr && separate_non_moving_space) { - request_begin += non_moving_space_capacity; - } std::string error_str; MemMap non_moving_space_mem_map; if (separate_non_moving_space) { @@ -388,9 +398,16 @@ Heap::Heap(size_t initial_size, const char* space_name = is_zygote ? kZygoteSpaceName : kNonMovingSpaceName; // Reserve the non moving mem map before the other two since it needs to be at a specific // address. - non_moving_space_mem_map = MapAnonymousPreferredAddress( - space_name, requested_alloc_space_begin, non_moving_space_capacity, &error_str); + DCHECK_EQ(heap_reservation.IsValid(), !boot_image_spaces_.empty()); + if (heap_reservation.IsValid()) { + non_moving_space_mem_map = heap_reservation.RemapAtEnd( + heap_reservation.Begin(), space_name, PROT_READ | PROT_WRITE, &error_str); + } else { + non_moving_space_mem_map = MapAnonymousPreferredAddress( + space_name, request_begin, non_moving_space_capacity, &error_str); + } CHECK(non_moving_space_mem_map.IsValid()) << error_str; + DCHECK(!heap_reservation.IsValid()); // Try to reserve virtual memory at a lower address if we have a separate non moving space. request_begin = kPreferredAllocSpaceBegin + non_moving_space_capacity; } @@ -404,14 +421,19 @@ Heap::Heap(size_t initial_size, // If no separate non-moving space and we are the zygote, the main space must come right // after the image space to avoid a gap. This is required since we want the zygote space to // be adjacent to the image space. - main_mem_map_1 = MemMap::MapAnonymous(kMemMapSpaceName[0], - request_begin, - capacity_, - PROT_READ | PROT_WRITE, - /* low_4gb */ true, - &error_str); + DCHECK_EQ(heap_reservation.IsValid(), !boot_image_spaces_.empty()); + main_mem_map_1 = MemMap::MapAnonymous( + kMemMapSpaceName[0], + request_begin, + capacity_, + PROT_READ | PROT_WRITE, + /* low_4gb */ true, + /* reuse */ false, + heap_reservation.IsValid() ? &heap_reservation : nullptr, + &error_str); } CHECK(main_mem_map_1.IsValid()) << error_str; + DCHECK(!heap_reservation.IsValid()); } if (support_homogeneous_space_compaction || background_collector_type_ == kCollectorTypeSS || @@ -437,7 +459,7 @@ Heap::Heap(size_t initial_size, /* can_move_objects */ false); non_moving_space_->SetFootprintLimit(non_moving_space_->Capacity()); CHECK(non_moving_space_ != nullptr) << "Failed creating non moving space " - << requested_alloc_space_begin; + << non_moving_space_mem_map.Begin(); AddSpace(non_moving_space_); } // Create other spaces based on whether or not we have a moving GC. diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc index 0af049a7a8..f308f63386 100644 --- a/runtime/gc/space/image_space.cc +++ b/runtime/gc/space/image_space.cc @@ -1461,9 +1461,10 @@ class ImageSpace::BootImageLoader { return cache_filename_; } - bool LoadFromSystem(/*out*/ std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces, - /*out*/ uint8_t** oat_file_end, - /*out*/ std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) { + bool LoadFromSystem(size_t extra_reservation_size, + /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces, + /*out*/MemMap* extra_reservation, + /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) { std::string filename = GetSystemImageFilename(image_location_.c_str(), image_isa_); std::vector<std::string> locations; if (!GetBootClassPathImageLocations(image_location_, filename, &locations, error_msg)) { @@ -1484,11 +1485,14 @@ class ImageSpace::BootImageLoader { } MemMap image_reservation; MemMap oat_reservation; + MemMap local_extra_reservation; if (!ReserveBootImageMemory(image_start, image_end, oat_end, + extra_reservation_size, &image_reservation, &oat_reservation, + &local_extra_reservation, error_msg)) { return false; } @@ -1511,7 +1515,7 @@ class ImageSpace::BootImageLoader { return false; } - *oat_file_end = GetOatFileEnd(spaces); + *extra_reservation = std::move(local_extra_reservation); boot_image_spaces->swap(spaces); return true; } @@ -1519,9 +1523,10 @@ class ImageSpace::BootImageLoader { bool LoadFromDalvikCache( bool validate_system_checksums, bool validate_oat_file, - /*out*/ std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces, - /*out*/ uint8_t** oat_file_end, - /*out*/ std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) { + size_t extra_reservation_size, + /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces, + /*out*/MemMap* extra_reservation, + /*out*/std::string* error_msg) REQUIRES_SHARED(Locks::mutator_lock_) { DCHECK(DalvikCacheExists()); std::vector<std::string> locations; if (!GetBootClassPathImageLocations(image_location_, cache_filename_, &locations, error_msg)) { @@ -1548,11 +1553,14 @@ class ImageSpace::BootImageLoader { } MemMap image_reservation; MemMap oat_reservation; + MemMap local_extra_reservation; if (!ReserveBootImageMemory(image_start, image_end, oat_end, + extra_reservation_size, &image_reservation, &oat_reservation, + &local_extra_reservation, error_msg)) { return false; } @@ -1594,7 +1602,7 @@ class ImageSpace::BootImageLoader { return false; } - *oat_file_end = GetOatFileEnd(spaces); + *extra_reservation = std::move(local_extra_reservation); boot_image_spaces->swap(spaces); return true; } @@ -1692,14 +1700,18 @@ class ImageSpace::BootImageLoader { bool ReserveBootImageMemory(uint32_t image_start, uint32_t image_end, uint32_t oat_end, + size_t extra_reservation_size, /*out*/MemMap* image_reservation, /*out*/MemMap* oat_reservation, + /*out*/MemMap* extra_reservation, /*out*/std::string* error_msg) { DCHECK(!image_reservation->IsValid()); + size_t total_size = + dchecked_integral_cast<size_t>(oat_end - image_start) + extra_reservation_size; *image_reservation = MemMap::MapAnonymous("Boot image reservation", reinterpret_cast32<uint8_t*>(image_start), - oat_end - image_start, + total_size, PROT_NONE, /* low_4gb */ true, /* reuse */ false, @@ -1708,6 +1720,19 @@ class ImageSpace::BootImageLoader { if (!image_reservation->IsValid()) { return false; } + DCHECK(!extra_reservation->IsValid()); + if (extra_reservation_size != 0u) { + DCHECK_ALIGNED(extra_reservation_size, kPageSize); + DCHECK_LT(extra_reservation_size, image_reservation->Size()); + uint8_t* split = image_reservation->End() - extra_reservation_size; + *extra_reservation = image_reservation->RemapAtEnd(split, + "Boot image extra reservation", + PROT_NONE, + error_msg); + if (!extra_reservation->IsValid()) { + return false; + } + } DCHECK(!oat_reservation->IsValid()); *oat_reservation = image_reservation->RemapAtEnd(reinterpret_cast32<uint8_t*>(image_end), "Boot image oat reservation", @@ -1738,16 +1763,6 @@ class ImageSpace::BootImageLoader { return true; } - uint8_t* GetOatFileEnd(const std::vector<std::unique_ptr<ImageSpace>>& spaces) { - DCHECK(std::is_sorted( - spaces.begin(), - spaces.end(), - [](const std::unique_ptr<ImageSpace>& lhs, const std::unique_ptr<ImageSpace>& rhs) { - return lhs->GetOatFileEnd() < rhs->GetOatFileEnd(); - })); - return AlignUp(spaces.back()->GetOatFileEnd(), kPageSize); - } - const std::string& image_location_; InstructionSet image_isa_; bool is_zygote_; @@ -1797,13 +1812,15 @@ static bool CheckSpace(const std::string& cache_filename, std::string* error_msg bool ImageSpace::LoadBootImage( const std::string& image_location, const InstructionSet image_isa, - /*out*/ std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces, - /*out*/ uint8_t** oat_file_end) { + size_t extra_reservation_size, + /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces, + /*out*/MemMap* extra_reservation) { ScopedTrace trace(__FUNCTION__); DCHECK(boot_image_spaces != nullptr); DCHECK(boot_image_spaces->empty()); - DCHECK(oat_file_end != nullptr); + DCHECK_ALIGNED(extra_reservation_size, kPageSize); + DCHECK(extra_reservation != nullptr); DCHECK_NE(image_isa, InstructionSet::kNone); if (image_location.empty()) { @@ -1860,8 +1877,9 @@ bool ImageSpace::LoadBootImage( // If we have system image, validate system image checksums, otherwise validate the oat file. if (loader.LoadFromDalvikCache(/* validate_system_checksums */ loader.HasSystem(), /* validate_oat_file */ !loader.HasSystem(), + extra_reservation_size, boot_image_spaces, - oat_file_end, + extra_reservation, &local_error_msg)) { return true; } @@ -1875,7 +1893,10 @@ bool ImageSpace::LoadBootImage( if (loader.HasSystem() && !relocate) { std::string local_error_msg; - if (loader.LoadFromSystem(boot_image_spaces, oat_file_end, &local_error_msg)) { + if (loader.LoadFromSystem(extra_reservation_size, + boot_image_spaces, + extra_reservation, + &local_error_msg)) { return true; } error_msgs.push_back(local_error_msg); @@ -1892,8 +1913,9 @@ bool ImageSpace::LoadBootImage( if (patch_success) { if (loader.LoadFromDalvikCache(/* validate_system_checksums */ false, /* validate_oat_file */ false, + extra_reservation_size, boot_image_spaces, - oat_file_end, + extra_reservation, &local_error_msg)) { return true; } @@ -1917,8 +1939,9 @@ bool ImageSpace::LoadBootImage( if (compilation_success) { if (loader.LoadFromDalvikCache(/* validate_system_checksums */ false, /* validate_oat_file */ false, + extra_reservation_size, boot_image_spaces, - oat_file_end, + extra_reservation, &local_error_msg)) { return true; } diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h index bd686be62e..a2490acdbb 100644 --- a/runtime/gc/space/image_space.h +++ b/runtime/gc/space/image_space.h @@ -44,8 +44,9 @@ class ImageSpace : public MemMapSpace { static bool LoadBootImage( const std::string& image_location, const InstructionSet image_isa, - /*out*/ std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces, - /*out*/ uint8_t** oat_file_end) REQUIRES_SHARED(Locks::mutator_lock_); + size_t extra_reservation_size, + /*out*/std::vector<std::unique_ptr<space::ImageSpace>>* boot_image_spaces, + /*out*/MemMap* extra_reservation) REQUIRES_SHARED(Locks::mutator_lock_); // Try to open an existing app image space. static std::unique_ptr<ImageSpace> CreateFromAppImage(const char* image, |