namespace art HIDDEN { namespace gc { namespace space {
static constexpr bool kPrefetchDuringRosAllocFreeList = false; static constexpr size_t kPrefetchLookAhead = 8; // Use this only for verification, it is not safe to use since the class of the object may have // been freed. static constexpr bool kVerifyFreedBytes = false;
// TODO: Fix // template class MemoryToolMallocSpace<RosAllocSpace, allocator::RosAlloc*>;
allocator::RosAlloc* rosalloc = CreateRosAlloc(mem_map.Begin(),
starting_size,
initial_size,
capacity,
low_memory_mode,
running_on_memory_tool); if (rosalloc == nullptr) {
LOG(ERROR) << "Failed to initialize rosalloc for alloc space (" << name << ")"; return nullptr;
}
// Protect memory beyond the starting size. MoreCore will add r/w permissions when necessory
uint8_t* end = mem_map.Begin() + starting_size; if (capacity - starting_size > 0) {
CheckedCall(mprotect, name.c_str(), end, capacity - starting_size, PROT_NONE);
}
// Everything is set so record in immutable structure and leave
uint8_t* begin = mem_map.Begin(); // TODO: Fix RosAllocSpace to support ASan. There is currently some issues with // AllocationSize caused by redzones. b/12944686 if (running_on_memory_tool) { returnnew MemoryToolMallocSpace<RosAllocSpace, kDefaultMemoryToolRedZoneBytes, false, true>(
std::move(mem_map),
initial_size,
name,
rosalloc,
begin,
end,
begin + capacity,
growth_limit,
can_move_objects,
starting_size,
low_memory_mode);
} else { returnnew RosAllocSpace(std::move(mem_map),
initial_size,
name,
rosalloc,
begin,
end,
begin + capacity,
growth_limit,
can_move_objects,
starting_size,
low_memory_mode);
}
}
// Memory we promise to rosalloc before it asks for morecore. // Note: making this value large means that large allocations are unlikely to succeed as rosalloc // will ask for this memory from sys_alloc which will fail as the footprint (this value plus the // size of the large allocation) will be greater than the footprint limit.
size_t starting_size = Heap::GetDefaultStartingSize();
MemMap mem_map = CreateMemMap(name, starting_size, &initial_size, &growth_limit, &capacity); if (!mem_map.IsValid()) {
LOG(ERROR) << "Failed to create mem map for alloc space (" << name << ") of size "
<< PrettySize(capacity); return nullptr;
}
RosAllocSpace* space = CreateFromMemMap(std::move(mem_map),
name,
starting_size,
initial_size,
growth_limit,
capacity,
low_memory_mode,
can_move_objects); // We start out with only the initial size possibly containing objects. if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) {
LOG(INFO) << "RosAllocSpace::Create exiting (" << PrettyDuration(NanoTime() - start_time)
<< " ) " << *space;
} return space;
}
allocator::RosAlloc* RosAllocSpace::CreateRosAlloc(void* begin, size_t morecore_start,
size_t initial_size,
size_t maximum_size, bool low_memory_mode, bool running_on_memory_tool) { // clear errno to allow PLOG on error
errno = 0; // create rosalloc using our backing storage starting at begin and // with a footprint of morecore_start. When morecore_start bytes of // memory is exhaused morecore will be called.
allocator::RosAlloc* rosalloc = new art::gc::allocator::RosAlloc(
begin, morecore_start, maximum_size,
low_memory_mode ?
art::gc::allocator::RosAlloc::kPageReleaseModeAll :
art::gc::allocator::RosAlloc::kPageReleaseModeSizeAndEnd,
running_on_memory_tool); if (rosalloc != nullptr) {
rosalloc->SetFootprintLimit(initial_size);
} else {
PLOG(ERROR) << "RosAlloc::Create failed";
} return rosalloc;
}
mirror::Object* RosAllocSpace::AllocWithGrowth(Thread* self, size_t num_bytes,
size_t* bytes_allocated, size_t* usable_size,
size_t* bytes_tl_bulk_allocated) {
mirror::Object* result;
{
MutexLock mu(self, lock_); // Grow as much as possible within the space.
size_t max_allowed = Capacity();
rosalloc_->SetFootprintLimit(max_allowed); // Try the allocation.
result = AllocCommon(self, num_bytes, bytes_allocated, usable_size,
bytes_tl_bulk_allocated); // Shrink back down as small as possible.
size_t footprint = rosalloc_->Footprint();
rosalloc_->SetFootprintLimit(footprint);
} // Note RosAlloc zeroes memory internally. // Return the new allocation or null.
CHECK(!kDebugSpaces || result == nullptr || Contains(result)); return result;
}
size_t RosAllocSpace::Trim() {
VLOG(heap) << "RosAllocSpace::Trim() ";
{
Thread* const self = Thread::Current(); // SOA required for Rosalloc::Trim() -> ArtRosAllocMoreCore() -> Heap::GetRosAllocSpace.
ScopedObjectAccess soa(self);
MutexLock mu(self, lock_); // Trim to release memory at the end of the space.
rosalloc_->Trim();
} // Attempt to release pages if it does not release all empty pages. if (!rosalloc_->DoesReleaseAllPages()) { return rosalloc_->ReleasePages();
} return0;
}
void RosAllocSpace::SetFootprintLimit(size_t new_size) {
MutexLock mu(Thread::Current(), lock_);
VLOG(heap) << "RosAllocSpace::SetFootprintLimit " << PrettySize(new_size); // Compare against the actual footprint, rather than the Size(), because the heap may not have // grown all the way to the allowed size yet.
size_t current_space_size = rosalloc_->Footprint(); if (new_size < current_space_size) { // Don't let the space grow any more.
new_size = current_space_size;
}
rosalloc_->SetFootprintLimit(new_size);
}
void RosAllocSpace::InspectAllRosAlloc(void (*callback)(void *start, void *end, size_t num_bytes, void* callback_arg), void* arg, bool do_null_callback_at_end) NO_THREAD_SAFETY_ANALYSIS { // TODO: NO_THREAD_SAFETY_ANALYSIS.
Thread* self = Thread::Current(); if (Locks::mutator_lock_->IsExclusiveHeld(self)) { // The mutators are already suspended. For example, a call path // from SignalCatcher::HandleSigQuit().
rosalloc_->InspectAll(callback, arg); if (do_null_callback_at_end) {
callback(nullptr, nullptr, 0, arg); // Indicate end of a space.
}
} elseif (Locks::mutator_lock_->IsSharedHeld(self)) { // The mutators are not suspended yet and we have a shared access // to the mutator lock. Temporarily release the shared access by // transitioning to the suspend state, and suspend the mutators.
ScopedThreadSuspension sts(self, ThreadState::kSuspended);
InspectAllRosAllocWithSuspendAll(callback, arg, do_null_callback_at_end);
} else { // The mutators are not suspended yet. Suspend the mutators.
InspectAllRosAllocWithSuspendAll(callback, arg, do_null_callback_at_end);
}
}
template<bool kMaybeIsRunningOnMemoryTool>
size_t RosAllocSpace::AllocationSizeNonvirtual(mirror::Object* obj, size_t* usable_size) { // obj is a valid object. Use its class in the header to get the size. // Don't use verification since the object may be dead if we are sweeping.
size_t size = obj->SizeOf<kVerifyNone>(); bool add_redzones = false; if (kMaybeIsRunningOnMemoryTool) {
add_redzones = kRunningOnMemoryTool && kMemoryToolAddsRedzones; if (add_redzones) {
size += 2 * kDefaultMemoryToolRedZoneBytes;
}
} else {
DCHECK(!kRunningOnMemoryTool);
}
size_t size_by_size = rosalloc_->UsableSize(size); if (kIsDebugBuild) { // On memory tool, the red zone has an impact... const uint8_t* obj_ptr = reinterpret_cast<const uint8_t*>(obj);
size_t size_by_ptr = rosalloc_->UsableSize(
obj_ptr - (add_redzones ? kDefaultMemoryToolRedZoneBytes : 0)); if (size_by_size != size_by_ptr) {
LOG(INFO) << "Found a bad sized obj of size " << size
<< " at " << std::hex << reinterpret_cast<intptr_t>(obj_ptr) << std::dec
<< " size_by_size=" << size_by_size << " size_by_ptr=" << size_by_ptr;
}
DCHECK_EQ(size_by_size, size_by_ptr);
} if (usable_size != nullptr) {
*usable_size = size_by_size;
} return size_by_size;
}
} // namespace space
namespace allocator {
// Callback from rosalloc when it needs to increase the footprint. void* ArtRosAllocMoreCore(allocator::RosAlloc* rosalloc, intptr_t increment)
REQUIRES_SHARED(Locks::mutator_lock_) {
Heap* heap = Runtime::Current()->GetHeap();
art::gc::space::RosAllocSpace* rosalloc_space = heap->GetRosAllocSpace(rosalloc);
DCHECK(rosalloc_space != nullptr);
DCHECK_EQ(rosalloc_space->GetRosAlloc(), rosalloc); return rosalloc_space->MoreCore(increment);
}
} // namespace allocator
} // namespace gc
} // namespace art
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.