Commit b0ced926 authored by Eric Holk's avatar Eric Holk Committed by Commit Bot

Track committed array buffer size rather than allocation length

WebAssembly creates ArrayBuffers with large allocations where only a small
amount is committed. The uncommitted address space should not be counted as used
memory. Doing so can lead to the GC spending unnecessary time collecting memory
when there is not really pressure.

Bug: 
Change-Id: Ife7b84e9858e87faabc360a61f887b2fda6d99db
Reviewed-on: https://chromium-review.googlesource.com/710227Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Eric Holk <eholk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48462}
parent 1a4d84f4
......@@ -17,7 +17,7 @@ void ArrayBufferTracker::RegisterNew(Heap* heap, JSArrayBuffer* buffer) {
void* data = buffer->backing_store();
if (!data) return;
size_t length = buffer->allocation_length();
size_t length = static_cast<size_t>(buffer->byte_length()->Number());
Page* page = Page::FromAddress(buffer->address());
{
base::LockGuard<base::RecursiveMutex> guard(page->mutex());
......@@ -40,7 +40,7 @@ void ArrayBufferTracker::Unregister(Heap* heap, JSArrayBuffer* buffer) {
if (!data) return;
Page* page = Page::FromAddress(buffer->address());
size_t length = buffer->allocation_length();
size_t length = static_cast<size_t>(buffer->byte_length()->Number());
{
base::LockGuard<base::RecursiveMutex> guard(page->mutex());
LocalArrayBufferTracker* tracker = page->local_tracker();
......@@ -50,6 +50,22 @@ void ArrayBufferTracker::Unregister(Heap* heap, JSArrayBuffer* buffer) {
heap->update_external_memory(-static_cast<intptr_t>(length));
}
void ArrayBufferTracker::IncreaseArrayBufferSize(Heap* heap,
JSArrayBuffer* buffer,
size_t delta) {
DCHECK_NOT_NULL(buffer->backing_store());
Page* const page = Page::FromAddress(buffer->address());
{
base::LockGuard<base::RecursiveMutex> guard(page->mutex());
LocalArrayBufferTracker* tracker = page->local_tracker();
DCHECK_NOT_NULL(tracker);
DCHECK(tracker->IsTracked(buffer));
tracker->IncreaseRetainedSize(delta);
}
heap->update_external_memory(delta);
}
template <typename Callback>
void LocalArrayBufferTracker::Free(Callback should_free) {
size_t freed_memory = 0;
......@@ -57,7 +73,7 @@ void LocalArrayBufferTracker::Free(Callback should_free) {
for (TrackingData::iterator it = array_buffers_.begin();
it != array_buffers_.end();) {
JSArrayBuffer* buffer = reinterpret_cast<JSArrayBuffer*>(*it);
const size_t length = buffer->allocation_length();
const size_t length = static_cast<size_t>(buffer->byte_length()->Number());
if (should_free(buffer)) {
freed_memory += length;
buffer->FreeBackingStore();
......@@ -106,6 +122,11 @@ void LocalArrayBufferTracker::Remove(JSArrayBuffer* buffer, size_t length) {
array_buffers_.erase(it);
}
void LocalArrayBufferTracker::IncreaseRetainedSize(size_t delta) {
DCHECK_GE(retained_size_ + delta, retained_size_);
retained_size_ += delta;
}
} // namespace internal
} // namespace v8
......
......@@ -33,6 +33,10 @@ class ArrayBufferTracker : public AllStatic {
// access to the tracker by taking the page lock for the corresponding page.
inline static void RegisterNew(Heap* heap, JSArrayBuffer* buffer);
inline static void Unregister(Heap* heap, JSArrayBuffer* buffer);
// Tells the tracker that the array buffer has increased in size. The buffer
// must already be tracked.
inline static void IncreaseArrayBufferSize(Heap* heap, JSArrayBuffer* buffer,
size_t delta);
// Frees all backing store pointers for dead JSArrayBuffers in new space.
// Does not take any locks and can only be called during Scavenge.
......@@ -73,6 +77,7 @@ class LocalArrayBufferTracker {
inline void Add(JSArrayBuffer* buffer, size_t length);
inline void Remove(JSArrayBuffer* buffer, size_t length);
inline void IncreaseRetainedSize(size_t delta);
// Frees up array buffers.
//
......
......@@ -2323,6 +2323,10 @@ void Heap::UnregisterArrayBuffer(JSArrayBuffer* buffer) {
ArrayBufferTracker::Unregister(this, buffer);
}
void Heap::TrackIncreasedArrayBufferSize(JSArrayBuffer* buffer, size_t delta) {
ArrayBufferTracker::IncreaseArrayBufferSize(this, buffer, delta);
}
void Heap::ConfigureInitialOldGenerationSize() {
if (!old_generation_size_configured_ && tracer()->SurvivalEventsRecorded()) {
old_generation_allocation_limit_ =
......
......@@ -1473,6 +1473,7 @@ class Heap {
// unregistered buffer, too, and the name is confusing.
void RegisterNewArrayBuffer(JSArrayBuffer* buffer);
void UnregisterArrayBuffer(JSArrayBuffer* buffer);
void TrackIncreasedArrayBufferSize(JSArrayBuffer* buffer, size_t delta);
// ===========================================================================
// Allocation site tracking. =================================================
......
......@@ -331,8 +331,9 @@ Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
const bool enable_guard_regions = old_buffer.is_null()
? trap_handler::UseTrapHandler()
: old_buffer->has_guard_region();
size_t new_size =
static_cast<size_t>(old_pages + pages) * WasmModule::kPageSize;
const uint32_t size_increase = pages * WasmModule::kPageSize;
const uint32_t new_size = old_size + size_increase;
if (enable_guard_regions && old_size != 0) {
DCHECK_NOT_NULL(old_buffer->backing_store());
if (new_size > FLAG_wasm_max_mem_pages * WasmModule::kPageSize ||
......@@ -346,6 +347,10 @@ Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
->AdjustAmountOfExternalAllocatedMemory(pages * WasmModule::kPageSize);
Handle<Object> length_obj = isolate->factory()->NewNumberFromSize(new_size);
old_buffer->set_byte_length(*length_obj);
if (!old_buffer->is_external()) {
isolate->heap()->TrackIncreasedArrayBufferSize(*old_buffer,
size_increase);
}
return old_buffer;
} else {
Handle<JSArrayBuffer> new_buffer;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment