Commit c7392f2e authored by fedor's avatar fedor Committed by Commit bot

[heap] introduce ArrayBufferTracker

Move various ArrayBuffer-related methods from Heap class to the newly
created ArrayBufferTracker. Consolidate and simplify things!

BUG=
R=mlippautz@chromium.org

Review URL: https://codereview.chromium.org/1324023007

Cr-Commit-Position: refs/heads/master@{#30624}
parent 0014ad92
......@@ -958,6 +958,8 @@ source_set("v8_base") {
"src/heap-snapshot-generator-inl.h",
"src/heap-snapshot-generator.cc",
"src/heap-snapshot-generator.h",
"src/heap/array-buffer-tracker.cc",
"src/heap/array-buffer-tracker.h",
"src/heap/gc-idle-time-handler.cc",
"src/heap/gc-idle-time-handler.h",
"src/heap/gc-tracer.cc",
......
......@@ -6501,8 +6501,7 @@ v8::ArrayBuffer::Contents v8::ArrayBuffer::Externalize() {
Utils::ApiCheck(!self->is_external(), "v8::ArrayBuffer::Externalize",
"ArrayBuffer already externalized");
self->set_is_external(true);
isolate->heap()->UnregisterArrayBuffer(isolate->heap()->InNewSpace(*self),
self->backing_store());
isolate->heap()->UnregisterArrayBuffer(*self);
return GetContents();
}
......@@ -6711,8 +6710,7 @@ v8::SharedArrayBuffer::Contents v8::SharedArrayBuffer::Externalize() {
Utils::ApiCheck(!self->is_external(), "v8::SharedArrayBuffer::Externalize",
"SharedArrayBuffer already externalized");
self->set_is_external(true);
isolate->heap()->UnregisterArrayBuffer(isolate->heap()->InNewSpace(*self),
self->backing_store());
isolate->heap()->UnregisterArrayBuffer(*self);
return GetContents();
}
......
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/heap/array-buffer-tracker.h"
#include "src/heap/heap.h"
#include "src/isolate.h"
#include "src/objects.h"
#include "src/objects-inl.h"
#include "src/v8.h"
namespace v8 {
namespace internal {
ArrayBufferTracker::~ArrayBufferTracker() {
Isolate* isolate = heap()->isolate();
size_t freed_memory = 0;
for (auto& buffer : live_array_buffers_) {
isolate->array_buffer_allocator()->Free(buffer.first, buffer.second);
freed_memory += buffer.second;
}
for (auto& buffer : live_array_buffers_for_scavenge_) {
isolate->array_buffer_allocator()->Free(buffer.first, buffer.second);
freed_memory += buffer.second;
}
live_array_buffers_.clear();
live_array_buffers_for_scavenge_.clear();
not_yet_discovered_array_buffers_.clear();
not_yet_discovered_array_buffers_for_scavenge_.clear();
if (freed_memory > 0) {
heap()->update_amount_of_external_allocated_memory(
-static_cast<int64_t>(freed_memory));
}
}
void ArrayBufferTracker::RegisterNew(JSArrayBuffer* buffer) {
void* data = buffer->backing_store();
if (!data) return;
bool in_new_space = heap()->InNewSpace(buffer);
size_t length = NumberToSize(heap()->isolate(), buffer->byte_length());
if (in_new_space) {
live_array_buffers_for_scavenge_[data] = length;
} else {
live_array_buffers_[data] = length;
}
// We may go over the limit of externally allocated memory here. We call the
// api function to trigger a GC in this case.
reinterpret_cast<v8::Isolate*>(heap()->isolate())
->AdjustAmountOfExternalAllocatedMemory(length);
}
void ArrayBufferTracker::Unregister(JSArrayBuffer* buffer) {
void* data = buffer->backing_store();
if (!data) return;
bool in_new_space = heap()->InNewSpace(buffer);
std::map<void*, size_t>* live_buffers =
in_new_space ? &live_array_buffers_for_scavenge_ : &live_array_buffers_;
std::map<void*, size_t>* not_yet_discovered_buffers =
in_new_space ? &not_yet_discovered_array_buffers_for_scavenge_
: &not_yet_discovered_array_buffers_;
DCHECK(live_buffers->count(data) > 0);
size_t length = (*live_buffers)[data];
live_buffers->erase(data);
not_yet_discovered_buffers->erase(data);
heap()->update_amount_of_external_allocated_memory(
-static_cast<int64_t>(length));
}
void ArrayBufferTracker::MarkLive(JSArrayBuffer* buffer) {
void* data = buffer->backing_store();
// ArrayBuffer might be in the middle of being constructed.
if (data == heap()->undefined_value()) return;
if (heap()->InNewSpace(buffer)) {
not_yet_discovered_array_buffers_for_scavenge_.erase(data);
} else {
not_yet_discovered_array_buffers_.erase(data);
}
}
void ArrayBufferTracker::FreeDead(bool from_scavenge) {
size_t freed_memory = 0;
Isolate* isolate = heap()->isolate();
for (auto& buffer : not_yet_discovered_array_buffers_for_scavenge_) {
isolate->array_buffer_allocator()->Free(buffer.first, buffer.second);
freed_memory += buffer.second;
live_array_buffers_for_scavenge_.erase(buffer.first);
}
if (!from_scavenge) {
for (auto& buffer : not_yet_discovered_array_buffers_) {
isolate->array_buffer_allocator()->Free(buffer.first, buffer.second);
freed_memory += buffer.second;
live_array_buffers_.erase(buffer.first);
}
}
not_yet_discovered_array_buffers_for_scavenge_ =
live_array_buffers_for_scavenge_;
if (!from_scavenge) not_yet_discovered_array_buffers_ = live_array_buffers_;
// Do not call through the api as this code is triggered while doing a GC.
heap()->update_amount_of_external_allocated_memory(
-static_cast<int64_t>(freed_memory));
}
void ArrayBufferTracker::PrepareDiscoveryInNewSpace() {
not_yet_discovered_array_buffers_for_scavenge_ =
live_array_buffers_for_scavenge_;
}
void ArrayBufferTracker::Promote(JSArrayBuffer* buffer) {
if (buffer->is_external()) return;
void* data = buffer->backing_store();
if (!data) return;
// ArrayBuffer might be in the middle of being constructed.
if (data == heap()->undefined_value()) return;
DCHECK(live_array_buffers_for_scavenge_.count(data) > 0);
live_array_buffers_[data] = live_array_buffers_for_scavenge_[data];
live_array_buffers_for_scavenge_.erase(data);
not_yet_discovered_array_buffers_for_scavenge_.erase(data);
}
} // namespace internal
} // namespace v8
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_HEAP_ARRAY_BUFFER_TRACKER_H_
#define V8_HEAP_ARRAY_BUFFER_TRACKER_H_
#include <map>
#include "src/globals.h"
namespace v8 {
namespace internal {
// Forward declarations.
class Heap;
class JSArrayBuffer;
class ArrayBufferTracker {
public:
explicit ArrayBufferTracker(Heap* heap) : heap_(heap) {}
~ArrayBufferTracker();
inline Heap* heap() { return heap_; }
// The following methods are used to track raw C++ pointers to externally
// allocated memory used as backing store in live array buffers.
// A new ArrayBuffer was created with |data| as backing store.
void RegisterNew(JSArrayBuffer* buffer);
// The backing store |data| is no longer owned by V8.
void Unregister(JSArrayBuffer* buffer);
// A live ArrayBuffer was discovered during marking/scavenge.
void MarkLive(JSArrayBuffer* buffer);
// Frees all backing store pointers that weren't discovered in the previous
// marking or scavenge phase.
void FreeDead(bool from_scavenge);
// Prepare for a new scavenge phase. A new marking phase is implicitly
// prepared by finishing the previous one.
void PrepareDiscoveryInNewSpace();
// An ArrayBuffer moved from new space to old space.
void Promote(JSArrayBuffer* buffer);
private:
Heap* heap_;
// |live_array_buffers_| maps externally allocated memory used as backing
// store for ArrayBuffers to the length of the respective memory blocks.
//
// At the beginning of mark/compact, |not_yet_discovered_array_buffers_| is
// a copy of |live_array_buffers_| and we remove pointers as we discover live
// ArrayBuffer objects during marking. At the end of mark/compact, the
// remaining memory blocks can be freed.
std::map<void*, size_t> live_array_buffers_;
std::map<void*, size_t> not_yet_discovered_array_buffers_;
// To be able to free memory held by ArrayBuffers during scavenge as well, we
// have a separate list of allocated memory held by ArrayBuffers in new space.
//
// Since mark/compact also evacuates the new space, all pointers in the
// |live_array_buffers_for_scavenge_| list are also in the
// |live_array_buffers_| list.
std::map<void*, size_t> live_array_buffers_for_scavenge_;
std::map<void*, size_t> not_yet_discovered_array_buffers_for_scavenge_;
};
}
} // namespace v8::internal
#endif // V8_HEAP_ARRAY_BUFFER_TRACKER_H_
......@@ -17,6 +17,7 @@
#include "src/debug/debug.h"
#include "src/deoptimizer.h"
#include "src/global-handles.h"
#include "src/heap/array-buffer-tracker.h"
#include "src/heap/gc-idle-time-handler.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/incremental-marking.h"
......@@ -144,7 +145,8 @@ Heap::Heap()
gc_callbacks_depth_(0),
deserialization_complete_(false),
concurrent_sweeping_enabled_(false),
strong_roots_list_(NULL) {
strong_roots_list_(NULL),
array_buffer_tracker_(NULL) {
// Allow build-time customization of the max semispace size. Building
// V8 with snapshots and a non-default max semispace size is much
// easier if you can define it as part of the build environment.
......@@ -1547,7 +1549,7 @@ void Heap::Scavenge() {
SelectScavengingVisitorsTable();
PrepareArrayBufferDiscoveryInNewSpace();
array_buffer_tracker()->PrepareDiscoveryInNewSpace();
// Flip the semispaces. After flipping, to space is empty, from space has
// live objects.
......@@ -1649,7 +1651,7 @@ void Heap::Scavenge() {
new_space_.LowerInlineAllocationLimit(
new_space_.inline_allocation_limit_step());
FreeDeadArrayBuffers(true);
array_buffer_tracker()->FreeDead(true);
// Update how much has survived scavenge.
IncrementYoungSurvivorsCounter(static_cast<int>(
......@@ -1744,120 +1746,6 @@ void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer) {
}
void Heap::RegisterNewArrayBuffer(bool in_new_space, void* data,
size_t length) {
if (!data) return;
if (in_new_space) {
live_array_buffers_for_scavenge_[data] = length;
} else {
live_array_buffers_[data] = length;
}
// We may go over the limit of externally allocated memory here. We call the
// api function to trigger a GC in this case.
reinterpret_cast<v8::Isolate*>(isolate_)
->AdjustAmountOfExternalAllocatedMemory(length);
}
void Heap::UnregisterArrayBuffer(bool in_new_space, void* data) {
if (!data) return;
std::map<void*, size_t>* live_buffers =
in_new_space ? &live_array_buffers_for_scavenge_ : &live_array_buffers_;
std::map<void*, size_t>* not_yet_discovered_buffers =
in_new_space ? &not_yet_discovered_array_buffers_for_scavenge_
: &not_yet_discovered_array_buffers_;
DCHECK(live_buffers->count(data) > 0);
size_t length = (*live_buffers)[data];
live_buffers->erase(data);
not_yet_discovered_buffers->erase(data);
amount_of_external_allocated_memory_ -= length;
}
void Heap::RegisterLiveArrayBuffer(bool in_new_space, void* data) {
// ArrayBuffer might be in the middle of being constructed.
if (data == undefined_value()) return;
if (in_new_space) {
not_yet_discovered_array_buffers_for_scavenge_.erase(data);
} else {
not_yet_discovered_array_buffers_.erase(data);
}
}
void Heap::FreeDeadArrayBuffers(bool from_scavenge) {
size_t freed_memory = 0;
for (auto& buffer : not_yet_discovered_array_buffers_for_scavenge_) {
isolate()->array_buffer_allocator()->Free(buffer.first, buffer.second);
freed_memory += buffer.second;
live_array_buffers_for_scavenge_.erase(buffer.first);
}
if (!from_scavenge) {
for (auto& buffer : not_yet_discovered_array_buffers_) {
isolate()->array_buffer_allocator()->Free(buffer.first, buffer.second);
freed_memory += buffer.second;
live_array_buffers_.erase(buffer.first);
}
}
not_yet_discovered_array_buffers_for_scavenge_ =
live_array_buffers_for_scavenge_;
if (!from_scavenge) not_yet_discovered_array_buffers_ = live_array_buffers_;
// Do not call through the api as this code is triggered while doing a GC.
amount_of_external_allocated_memory_ -= freed_memory;
}
void Heap::TearDownArrayBuffers() {
size_t freed_memory = 0;
for (auto& buffer : live_array_buffers_) {
isolate()->array_buffer_allocator()->Free(buffer.first, buffer.second);
freed_memory += buffer.second;
}
for (auto& buffer : live_array_buffers_for_scavenge_) {
isolate()->array_buffer_allocator()->Free(buffer.first, buffer.second);
freed_memory += buffer.second;
}
live_array_buffers_.clear();
live_array_buffers_for_scavenge_.clear();
not_yet_discovered_array_buffers_.clear();
not_yet_discovered_array_buffers_for_scavenge_.clear();
if (freed_memory > 0) {
reinterpret_cast<v8::Isolate*>(isolate_)
->AdjustAmountOfExternalAllocatedMemory(
-static_cast<int64_t>(freed_memory));
}
}
void Heap::PrepareArrayBufferDiscoveryInNewSpace() {
not_yet_discovered_array_buffers_for_scavenge_ =
live_array_buffers_for_scavenge_;
}
void Heap::PromoteArrayBuffer(Object* obj) {
JSArrayBuffer* buffer = JSArrayBuffer::cast(obj);
if (buffer->is_external()) return;
void* data = buffer->backing_store();
if (!data) return;
// ArrayBuffer might be in the middle of being constructed.
if (data == undefined_value()) return;
DCHECK(live_array_buffers_for_scavenge_.count(data) > 0);
live_array_buffers_[data] = live_array_buffers_for_scavenge_[data];
live_array_buffers_for_scavenge_.erase(data);
not_yet_discovered_array_buffers_for_scavenge_.erase(data);
}
void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer) {
Object* allocation_site_obj =
VisitWeakList<AllocationSite>(this, allocation_sites_list(), retainer);
......@@ -2087,6 +1975,16 @@ HeapObject* Heap::DoubleAlignForDeserialization(HeapObject* object, int size) {
}
void Heap::RegisterNewArrayBuffer(JSArrayBuffer* buffer) {
return array_buffer_tracker()->RegisterNew(buffer);
}
void Heap::UnregisterArrayBuffer(JSArrayBuffer* buffer) {
return array_buffer_tracker()->Unregister(buffer);
}
enum LoggingAndProfiling {
LOGGING_AND_PROFILING_ENABLED,
LOGGING_AND_PROFILING_DISABLED
......@@ -2388,7 +2286,9 @@ class ScavengingVisitor : public StaticVisitorBase {
MapWord map_word = object->map_word();
DCHECK(map_word.IsForwardingAddress());
HeapObject* target = map_word.ToForwardingAddress();
if (!heap->InNewSpace(target)) heap->PromoteArrayBuffer(target);
if (!heap->InNewSpace(target)) {
heap->array_buffer_tracker()->Promote(JSArrayBuffer::cast(target));
}
}
......@@ -5659,6 +5559,8 @@ bool Heap::SetUp() {
object_stats_ = new ObjectStats(this);
object_stats_->ClearObjectStats(true);
array_buffer_tracker_ = new ArrayBufferTracker(this);
LOG(isolate_, IntPtrTEvent("heap-capacity", Capacity()));
LOG(isolate_, IntPtrTEvent("heap-available", Available()));
......@@ -5774,7 +5676,8 @@ void Heap::TearDown() {
WaitUntilUnmappingOfFreeChunksCompleted();
TearDownArrayBuffers();
delete array_buffer_tracker_;
array_buffer_tracker_ = nullptr;
isolate_->global_handles()->TearDown();
......
......@@ -421,6 +421,7 @@ namespace internal {
PRIVATE_SYMBOL_LIST(V)
// Forward declarations.
class ArrayBufferTracker;
class HeapObjectsFilter;
class HeapStats;
class Isolate;
......@@ -982,6 +983,10 @@ class Heap {
return amount_of_external_allocated_memory_;
}
void update_amount_of_external_allocated_memory(int64_t delta) {
amount_of_external_allocated_memory_ += delta;
}
void DeoptMarkedAllocationSites();
bool DeoptMaybeTenuredAllocationSites() {
......@@ -1007,29 +1012,6 @@ class Heap {
bool deserialization_complete() const { return deserialization_complete_; }
// The following methods are used to track raw C++ pointers to externally
// allocated memory used as backing store in live array buffers.
// A new ArrayBuffer was created with |data| as backing store.
void RegisterNewArrayBuffer(bool in_new_space, void* data, size_t length);
// The backing store |data| is no longer owned by V8.
void UnregisterArrayBuffer(bool in_new_space, void* data);
// A live ArrayBuffer was discovered during marking/scavenge.
void RegisterLiveArrayBuffer(bool in_new_space, void* data);
// Frees all backing store pointers that weren't discovered in the previous
// marking or scavenge phase.
void FreeDeadArrayBuffers(bool from_scavenge);
// Prepare for a new scavenge phase. A new marking phase is implicitly
// prepared by finishing the previous one.
void PrepareArrayBufferDiscoveryInNewSpace();
// An ArrayBuffer moved from new space to old space.
void PromoteArrayBuffer(Object* buffer);
bool HasLowAllocationRate();
bool HasHighFragmentation();
bool HasHighFragmentation(intptr_t used, intptr_t committed);
......@@ -1524,6 +1506,16 @@ class Heap {
int allocation_size,
AllocationAlignment alignment);
// ===========================================================================
// ArrayBufferTracker. =======================================================
// ===========================================================================
void RegisterNewArrayBuffer(JSArrayBuffer* buffer);
void UnregisterArrayBuffer(JSArrayBuffer* buffer);
inline ArrayBufferTracker* array_buffer_tracker() {
return array_buffer_tracker_;
}
// =============================================================================
#ifdef VERIFY_HEAP
......@@ -1757,9 +1749,6 @@ class Heap {
// the old space.
void EvaluateOldSpaceLocalPretenuring(uint64_t size_of_objects_before_gc);
// Called on heap tear-down. Frees all remaining ArrayBuffer backing stores.
void TearDownArrayBuffers();
// Record statistics before and after garbage collection.
void ReportStatisticsBeforeGC();
void ReportStatisticsAfterGC();
......@@ -2343,27 +2332,10 @@ class Heap {
bool concurrent_sweeping_enabled_;
// |live_array_buffers_| maps externally allocated memory used as backing
// store for ArrayBuffers to the length of the respective memory blocks.
//
// At the beginning of mark/compact, |not_yet_discovered_array_buffers_| is
// a copy of |live_array_buffers_| and we remove pointers as we discover live
// ArrayBuffer objects during marking. At the end of mark/compact, the
// remaining memory blocks can be freed.
std::map<void*, size_t> live_array_buffers_;
std::map<void*, size_t> not_yet_discovered_array_buffers_;
// To be able to free memory held by ArrayBuffers during scavenge as well, we
// have a separate list of allocated memory held by ArrayBuffers in new space.
//
// Since mark/compact also evacuates the new space, all pointers in the
// |live_array_buffers_for_scavenge_| list are also in the
// |live_array_buffers_| list.
std::map<void*, size_t> live_array_buffers_for_scavenge_;
std::map<void*, size_t> not_yet_discovered_array_buffers_for_scavenge_;
StrongRootsList* strong_roots_list_;
ArrayBufferTracker* array_buffer_tracker_;
// Classes in "heap" can be friends.
friend class AlwaysAllocateScope;
friend class GCCallbacksScope;
......
......@@ -14,6 +14,7 @@
#include "src/frames-inl.h"
#include "src/gdb-jit.h"
#include "src/global-handles.h"
#include "src/heap/array-buffer-tracker.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/incremental-marking.h"
#include "src/heap/mark-compact-inl.h"
......@@ -1721,8 +1722,7 @@ int MarkCompactCollector::DiscoverAndEvacuateBlackObjectsOnPage(
MigrateObject(HeapObject::cast(target), object, size, NEW_SPACE);
if (V8_UNLIKELY(target->IsJSArrayBuffer())) {
heap()->RegisterLiveArrayBuffer(
true, JSArrayBuffer::cast(target)->backing_store());
heap()->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(target));
}
heap()->IncrementSemiSpaceCopiedObjectSize(size);
}
......@@ -2948,7 +2948,7 @@ bool MarkCompactCollector::TryPromoteObject(HeapObject* object,
MigrateObject(target, object, object_size, old_space->identity());
// If we end up needing more special cases, we should factor this out.
if (V8_UNLIKELY(target->IsJSArrayBuffer())) {
heap()->PromoteArrayBuffer(target);
heap()->array_buffer_tracker()->Promote(JSArrayBuffer::cast(target));
}
heap()->IncrementPromotedObjectsSize(object_size);
return true;
......@@ -4293,7 +4293,7 @@ void MarkCompactCollector::SweepSpaces() {
// EvacuateNewSpaceAndCandidates iterates over new space objects and for
// ArrayBuffers either re-registers them as live or promotes them. This is
// needed to properly free them.
heap()->FreeDeadArrayBuffers(false);
heap()->array_buffer_tracker()->FreeDead(false);
// Clear the marking state of live large objects.
heap_->lo_space()->ClearMarkingStateOfLiveObjects();
......
......@@ -5,6 +5,7 @@
#ifndef V8_OBJECTS_VISITING_INL_H_
#define V8_OBJECTS_VISITING_INL_H_
#include "src/heap/array-buffer-tracker.h"
#include "src/heap/objects-visiting.h"
#include "src/ic/ic-state.h"
#include "src/macro-assembler.h"
......@@ -96,8 +97,7 @@ int StaticNewSpaceVisitor<StaticVisitor>::VisitJSArrayBuffer(
HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset),
HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields));
if (!JSArrayBuffer::cast(object)->is_external()) {
heap->RegisterLiveArrayBuffer(true,
JSArrayBuffer::cast(object)->backing_store());
heap->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(object));
}
return JSArrayBuffer::kSizeWithInternalFields;
}
......@@ -534,8 +534,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitJSArrayBuffer(
HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields));
if (!JSArrayBuffer::cast(object)->is_external() &&
!heap->InNewSpace(object)) {
heap->RegisterLiveArrayBuffer(false,
JSArrayBuffer::cast(object)->backing_store());
heap->array_buffer_tracker()->MarkLive(JSArrayBuffer::cast(object));
}
}
......
......@@ -15950,15 +15950,14 @@ void JSArrayBuffer::Setup(Handle<JSArrayBuffer> array_buffer, Isolate* isolate,
array_buffer->set_is_neuterable(shared == SharedFlag::kNotShared);
array_buffer->set_is_shared(shared == SharedFlag::kShared);
if (data && !is_external) {
isolate->heap()->RegisterNewArrayBuffer(
isolate->heap()->InNewSpace(*array_buffer), data, allocated_length);
}
Handle<Object> byte_length =
isolate->factory()->NewNumberFromSize(allocated_length);
CHECK(byte_length->IsSmi() || byte_length->IsHeapNumber());
array_buffer->set_byte_length(*byte_length);
if (data && !is_external) {
isolate->heap()->RegisterNewArrayBuffer(*array_buffer);
}
}
......@@ -16006,9 +16005,7 @@ Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
fixed_typed_array->DataSize());
buffer->set_backing_store(backing_store);
buffer->set_is_external(false);
isolate->heap()->RegisterNewArrayBuffer(isolate->heap()->InNewSpace(*buffer),
backing_store,
fixed_typed_array->DataSize());
isolate->heap()->RegisterNewArrayBuffer(*buffer);
memcpy(buffer->backing_store(),
fixed_typed_array->DataPtr(),
fixed_typed_array->DataSize());
......
......@@ -92,9 +92,8 @@ RUNTIME_FUNCTION(Runtime_ArrayBufferNeuter) {
void* backing_store = array_buffer->backing_store();
size_t byte_length = NumberToSize(isolate, array_buffer->byte_length());
array_buffer->set_is_external(true);
isolate->heap()->UnregisterArrayBuffer(*array_buffer);
array_buffer->Neuter();
isolate->heap()->UnregisterArrayBuffer(
isolate->heap()->InNewSpace(*array_buffer), backing_store);
isolate->array_buffer_allocator()->Free(backing_store, byte_length);
return isolate->heap()->undefined_value();
}
......
......@@ -707,6 +707,8 @@
'../../src/heap-snapshot-generator-inl.h',
'../../src/heap-snapshot-generator.cc',
'../../src/heap-snapshot-generator.h',
'../../src/heap/array-buffer-tracker.cc',
'../../src/heap/array-buffer-tracker.h',
'../../src/heap/memory-reducer.cc',
'../../src/heap/memory-reducer.h',
'../../src/heap/gc-idle-time-handler.cc',
......
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