Commit aab76eff authored by hpayer's avatar hpayer Committed by Commit bot

Just visit young array buffers during scavenge. Additionally keep the views in...

Just visit young array buffers during scavenge. Additionally keep the views in new space in a separate global list and move them to the corresponding array buffers when they get promoted.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#27128}
parent f71e2626
...@@ -1790,8 +1790,14 @@ void SetupArrayBufferView(i::Isolate* isolate, ...@@ -1790,8 +1790,14 @@ void SetupArrayBufferView(i::Isolate* isolate,
obj->set_buffer(*buffer); obj->set_buffer(*buffer);
obj->set_weak_next(buffer->weak_first_view()); Heap* heap = isolate->heap();
buffer->set_weak_first_view(*obj); if (heap->InNewSpace(*obj)) {
obj->set_weak_next(heap->new_array_buffer_views_list());
heap->set_new_array_buffer_views_list(*obj);
} else {
obj->set_weak_next(buffer->weak_first_view());
buffer->set_weak_first_view(*obj);
}
i::Handle<i::Object> byte_offset_object = i::Handle<i::Object> byte_offset_object =
isolate->factory()->NewNumberFromSize(byte_offset); isolate->factory()->NewNumberFromSize(byte_offset);
......
...@@ -143,7 +143,9 @@ Heap::Heap() ...@@ -143,7 +143,9 @@ Heap::Heap()
chunks_queued_for_free_(NULL), chunks_queued_for_free_(NULL),
gc_callbacks_depth_(0), gc_callbacks_depth_(0),
deserialization_complete_(false), deserialization_complete_(false),
concurrent_sweeping_enabled_(false) { concurrent_sweeping_enabled_(false),
migration_failure_(false),
previous_migration_failure_(false) {
// Allow build-time customization of the max semispace size. Building // Allow build-time customization of the max semispace size. Building
// V8 with snapshots and a non-default max semispace size is much // V8 with snapshots and a non-default max semispace size is much
// easier if you can define it as part of the build environment. // easier if you can define it as part of the build environment.
...@@ -737,6 +739,13 @@ void Heap::GarbageCollectionEpilogue() { ...@@ -737,6 +739,13 @@ void Heap::GarbageCollectionEpilogue() {
// Remember the last top pointer so that we can later find out // Remember the last top pointer so that we can later find out
// whether we allocated in new space since the last GC. // whether we allocated in new space since the last GC.
new_space_top_after_last_gc_ = new_space()->top(); new_space_top_after_last_gc_ = new_space()->top();
if (migration_failure_) {
set_previous_migration_failure(true);
} else {
set_previous_migration_failure(false);
}
set_migration_failure(false);
} }
...@@ -1738,29 +1747,63 @@ void Heap::UpdateReferencesInExternalStringTable( ...@@ -1738,29 +1747,63 @@ void Heap::UpdateReferencesInExternalStringTable(
void Heap::ProcessAllWeakReferences(WeakObjectRetainer* retainer) { void Heap::ProcessAllWeakReferences(WeakObjectRetainer* retainer) {
ProcessArrayBuffers(retainer); ProcessArrayBuffers(retainer, false);
ProcessNewArrayBufferViews(retainer);
ProcessNativeContexts(retainer); ProcessNativeContexts(retainer);
ProcessAllocationSites(retainer); ProcessAllocationSites(retainer);
} }
void Heap::ProcessYoungWeakReferences(WeakObjectRetainer* retainer) { void Heap::ProcessYoungWeakReferences(WeakObjectRetainer* retainer) {
ProcessArrayBuffers(retainer); ProcessArrayBuffers(retainer, true);
ProcessNewArrayBufferViews(retainer);
ProcessNativeContexts(retainer); ProcessNativeContexts(retainer);
} }
void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer) { void Heap::ProcessNativeContexts(WeakObjectRetainer* retainer) {
Object* head = VisitWeakList<Context>(this, native_contexts_list(), retainer); Object* head =
VisitWeakList<Context>(this, native_contexts_list(), retainer, false);
// Update the head of the list of contexts. // Update the head of the list of contexts.
set_native_contexts_list(head); set_native_contexts_list(head);
} }
void Heap::ProcessArrayBuffers(WeakObjectRetainer* retainer) { void Heap::ProcessArrayBuffers(WeakObjectRetainer* retainer,
Object* array_buffer_obj = bool stop_after_young) {
VisitWeakList<JSArrayBuffer>(this, array_buffers_list(), retainer); Object* array_buffer_obj = VisitWeakList<JSArrayBuffer>(
this, array_buffers_list(), retainer, stop_after_young);
set_array_buffers_list(array_buffer_obj); set_array_buffers_list(array_buffer_obj);
#ifdef DEBUG
// Verify invariant that young array buffers come before old array buffers
// in array buffers list if there was no promotion failure.
Object* undefined = undefined_value();
Object* next = array_buffers_list();
bool old_objects_recorded = false;
if (migration_failure()) return;
while (next != undefined) {
if (!old_objects_recorded) {
old_objects_recorded = !InNewSpace(next);
}
DCHECK((InNewSpace(next) && !old_objects_recorded) || !InNewSpace(next));
next = JSArrayBuffer::cast(next)->weak_next();
}
#endif
}
void Heap::ProcessNewArrayBufferViews(WeakObjectRetainer* retainer) {
// Retain the list of new space views.
Object* typed_array_obj = VisitWeakList<JSArrayBufferView>(
this, new_array_buffer_views_list_, retainer, false);
set_new_array_buffer_views_list(typed_array_obj);
// Some objects in the list may be in old space now. Find them
// and move them to the corresponding array buffer.
Object* view = VisitNewArrayBufferViewsWeakList(
this, new_array_buffer_views_list_, retainer);
set_new_array_buffer_views_list(view);
} }
...@@ -1776,8 +1819,8 @@ void Heap::TearDownArrayBuffers() { ...@@ -1776,8 +1819,8 @@ void Heap::TearDownArrayBuffers() {
void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer) { void Heap::ProcessAllocationSites(WeakObjectRetainer* retainer) {
Object* allocation_site_obj = Object* allocation_site_obj = VisitWeakList<AllocationSite>(
VisitWeakList<AllocationSite>(this, allocation_sites_list(), retainer); this, allocation_sites_list(), retainer, false);
set_allocation_sites_list(allocation_site_obj); set_allocation_sites_list(allocation_site_obj);
} }
...@@ -2189,6 +2232,7 @@ class ScavengingVisitor : public StaticVisitorBase { ...@@ -2189,6 +2232,7 @@ class ScavengingVisitor : public StaticVisitorBase {
if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) { if (SemiSpaceCopyObject<alignment>(map, slot, object, object_size)) {
return; return;
} }
heap->set_migration_failure(true);
} }
if (PromoteObject<object_contents, alignment>(map, slot, object, if (PromoteObject<object_contents, alignment>(map, slot, object,
...@@ -5542,6 +5586,7 @@ bool Heap::CreateHeapObjects() { ...@@ -5542,6 +5586,7 @@ bool Heap::CreateHeapObjects() {
set_native_contexts_list(undefined_value()); set_native_contexts_list(undefined_value());
set_array_buffers_list(undefined_value()); set_array_buffers_list(undefined_value());
set_new_array_buffer_views_list(undefined_value());
set_allocation_sites_list(undefined_value()); set_allocation_sites_list(undefined_value());
return true; return true;
} }
......
...@@ -870,6 +870,13 @@ class Heap { ...@@ -870,6 +870,13 @@ class Heap {
void set_array_buffers_list(Object* object) { array_buffers_list_ = object; } void set_array_buffers_list(Object* object) { array_buffers_list_ = object; }
Object* array_buffers_list() const { return array_buffers_list_; } Object* array_buffers_list() const { return array_buffers_list_; }
void set_new_array_buffer_views_list(Object* object) {
new_array_buffer_views_list_ = object;
}
Object* new_array_buffer_views_list() const {
return new_array_buffer_views_list_;
}
void set_allocation_sites_list(Object* object) { void set_allocation_sites_list(Object* object) {
allocation_sites_list_ = object; allocation_sites_list_ = object;
} }
...@@ -1469,6 +1476,18 @@ class Heap { ...@@ -1469,6 +1476,18 @@ class Heap {
bool deserialization_complete() const { return deserialization_complete_; } bool deserialization_complete() const { return deserialization_complete_; }
bool migration_failure() const { return migration_failure_; }
void set_migration_failure(bool migration_failure) {
migration_failure_ = migration_failure;
}
bool previous_migration_failure() const {
return previous_migration_failure_;
}
void set_previous_migration_failure(bool previous_migration_failure) {
previous_migration_failure_ = previous_migration_failure;
}
protected: protected:
// Methods made available to tests. // Methods made available to tests.
...@@ -1636,11 +1655,16 @@ class Heap { ...@@ -1636,11 +1655,16 @@ class Heap {
bool inline_allocation_disabled_; bool inline_allocation_disabled_;
// Weak list heads, threaded through the objects. // Weak list heads, threaded through the objects.
// List heads are initilized lazily and contain the undefined_value at start. // List heads are initialized lazily and contain the undefined_value at start.
Object* native_contexts_list_; Object* native_contexts_list_;
Object* array_buffers_list_; Object* array_buffers_list_;
Object* allocation_sites_list_; Object* allocation_sites_list_;
// This is a global list of array buffer views in new space. When the views
// get promoted, they are removed form the list and added to the corresponding
// array buffer.
Object* new_array_buffer_views_list_;
// List of encountered weak collections (JSWeakMap and JSWeakSet) during // List of encountered weak collections (JSWeakMap and JSWeakSet) during
// marking. It is initialized during marking, destroyed after marking and // marking. It is initialized during marking, destroyed after marking and
// contains Smi(0) while marking is not active. // contains Smi(0) while marking is not active.
...@@ -1973,7 +1997,8 @@ class Heap { ...@@ -1973,7 +1997,8 @@ class Heap {
void MarkCompactEpilogue(); void MarkCompactEpilogue();
void ProcessNativeContexts(WeakObjectRetainer* retainer); void ProcessNativeContexts(WeakObjectRetainer* retainer);
void ProcessArrayBuffers(WeakObjectRetainer* retainer); void ProcessArrayBuffers(WeakObjectRetainer* retainer, bool stop_after_young);
void ProcessNewArrayBufferViews(WeakObjectRetainer* retainer);
void ProcessAllocationSites(WeakObjectRetainer* retainer); void ProcessAllocationSites(WeakObjectRetainer* retainer);
// Deopts all code that contains allocation instruction which are tenured or // Deopts all code that contains allocation instruction which are tenured or
...@@ -2135,6 +2160,13 @@ class Heap { ...@@ -2135,6 +2160,13 @@ class Heap {
bool concurrent_sweeping_enabled_; bool concurrent_sweeping_enabled_;
// A migration failure indicates that a semi-space copy of an object during
// a scavenge failed and the object got promoted instead.
bool migration_failure_;
// A migration failure happened in the previous scavenge.
bool previous_migration_failure_;
friend class AlwaysAllocateScope; friend class AlwaysAllocateScope;
friend class Deserializer; friend class Deserializer;
friend class Factory; friend class Factory;
......
...@@ -191,15 +191,19 @@ struct WeakListVisitor; ...@@ -191,15 +191,19 @@ struct WeakListVisitor;
template <class T> template <class T>
Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer) { Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer,
bool stop_after_young) {
Object* undefined = heap->undefined_value(); Object* undefined = heap->undefined_value();
Object* head = undefined; Object* head = undefined;
T* tail = NULL; T* tail = NULL;
MarkCompactCollector* collector = heap->mark_compact_collector(); MarkCompactCollector* collector = heap->mark_compact_collector();
bool record_slots = MustRecordSlots(heap); bool record_slots = MustRecordSlots(heap);
while (list != undefined) { while (list != undefined) {
// Check whether to keep the candidate in the list. // Check whether to keep the candidate in the list.
T* candidate = reinterpret_cast<T*>(list); T* candidate = reinterpret_cast<T*>(list);
T* original_candidate = candidate;
Object* retained = retainer->RetainAs(list); Object* retained = retainer->RetainAs(list);
if (retained != NULL) { if (retained != NULL) {
if (head == undefined) { if (head == undefined) {
...@@ -220,9 +224,21 @@ Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer) { ...@@ -220,9 +224,21 @@ Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer) {
candidate = reinterpret_cast<T*>(retained); candidate = reinterpret_cast<T*>(retained);
tail = candidate; tail = candidate;
// tail is a live object, visit it. // tail is a live object, visit it.
WeakListVisitor<T>::VisitLiveObject(heap, tail, retainer); WeakListVisitor<T>::VisitLiveObject(heap, tail, retainer);
// The list of weak objects is usually order. It starts with objects
// recently allocated in the young generation followed by objects
// allocated in the old generation. When a migration failure happened,
// the list is not ordered until the next GC that has no migration
// failure.
// For young generation collections we just have to visit until the last
// young generation objects.
if (stop_after_young && !heap->migration_failure() &&
!heap->previous_migration_failure() &&
!heap->InNewSpace(original_candidate)) {
return head;
}
} else { } else {
WeakListVisitor<T>::VisitPhantomObject(heap, candidate); WeakListVisitor<T>::VisitPhantomObject(heap, candidate);
} }
...@@ -239,6 +255,56 @@ Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer) { ...@@ -239,6 +255,56 @@ Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer) {
} }
Object* VisitNewArrayBufferViewsWeakList(Heap* heap, Object* list,
WeakObjectRetainer* retainer) {
Object* undefined = heap->undefined_value();
Object* previous = undefined;
Object* head = undefined;
Object* next;
MarkCompactCollector* collector = heap->mark_compact_collector();
bool record_slots = MustRecordSlots(heap);
for (Object* o = list; o != undefined;) {
JSArrayBufferView* view = JSArrayBufferView::cast(o);
next = view->weak_next();
if (!heap->InNewSpace(view)) {
if (previous != undefined) {
// We are in the middle of the list, skip the old space element.
JSArrayBufferView* previous_view = JSArrayBufferView::cast(previous);
previous_view->set_weak_next(next);
if (record_slots) {
Object** next_slot = HeapObject::RawField(
previous_view, JSArrayBufferView::kWeakNextOffset);
collector->RecordSlot(next_slot, next_slot, next);
}
}
JSArrayBuffer* buffer = JSArrayBuffer::cast(view->buffer());
view->set_weak_next(buffer->weak_first_view());
if (record_slots) {
Object** next_slot =
HeapObject::RawField(view, JSArrayBufferView::kWeakNextOffset);
collector->RecordSlot(next_slot, next_slot, buffer->weak_first_view());
}
buffer->set_weak_first_view(view);
if (record_slots) {
Object** slot =
HeapObject::RawField(buffer, JSArrayBuffer::kWeakFirstViewOffset);
heap->mark_compact_collector()->RecordSlot(slot, slot, view);
}
} else {
// We found a valid new space view, remember it.
previous = view;
if (head == undefined) {
// We are at the list head.
head = view;
}
}
o = next;
}
return head;
}
template <class T> template <class T>
static void ClearWeakList(Heap* heap, Object* list) { static void ClearWeakList(Heap* heap, Object* list) {
Object* undefined = heap->undefined_value(); Object* undefined = heap->undefined_value();
...@@ -316,7 +382,8 @@ struct WeakListVisitor<Context> { ...@@ -316,7 +382,8 @@ struct WeakListVisitor<Context> {
static void DoWeakList(Heap* heap, Context* context, static void DoWeakList(Heap* heap, Context* context,
WeakObjectRetainer* retainer, int index) { WeakObjectRetainer* retainer, int index) {
// Visit the weak list, removing dead intermediate elements. // Visit the weak list, removing dead intermediate elements.
Object* list_head = VisitWeakList<T>(heap, context->get(index), retainer); Object* list_head =
VisitWeakList<T>(heap, context->get(index), retainer, false);
// Update the list head. // Update the list head.
context->set(index, list_head, UPDATE_WRITE_BARRIER); context->set(index, list_head, UPDATE_WRITE_BARRIER);
...@@ -368,7 +435,7 @@ struct WeakListVisitor<JSArrayBuffer> { ...@@ -368,7 +435,7 @@ struct WeakListVisitor<JSArrayBuffer> {
static void VisitLiveObject(Heap* heap, JSArrayBuffer* array_buffer, static void VisitLiveObject(Heap* heap, JSArrayBuffer* array_buffer,
WeakObjectRetainer* retainer) { WeakObjectRetainer* retainer) {
Object* typed_array_obj = VisitWeakList<JSArrayBufferView>( Object* typed_array_obj = VisitWeakList<JSArrayBufferView>(
heap, array_buffer->weak_first_view(), retainer); heap, array_buffer->weak_first_view(), retainer, false);
array_buffer->set_weak_first_view(typed_array_obj); array_buffer->set_weak_first_view(typed_array_obj);
if (typed_array_obj != heap->undefined_value() && MustRecordSlots(heap)) { if (typed_array_obj != heap->undefined_value() && MustRecordSlots(heap)) {
Object** slot = HeapObject::RawField(array_buffer, Object** slot = HeapObject::RawField(array_buffer,
...@@ -399,23 +466,21 @@ struct WeakListVisitor<AllocationSite> { ...@@ -399,23 +466,21 @@ struct WeakListVisitor<AllocationSite> {
}; };
template Object* VisitWeakList<Code>(Heap* heap, Object* list,
WeakObjectRetainer* retainer);
template Object* VisitWeakList<JSFunction>(Heap* heap, Object* list,
WeakObjectRetainer* retainer);
template Object* VisitWeakList<Context>(Heap* heap, Object* list, template Object* VisitWeakList<Context>(Heap* heap, Object* list,
WeakObjectRetainer* retainer); WeakObjectRetainer* retainer,
bool stop_after_young);
template Object* VisitWeakList<JSArrayBuffer>(Heap* heap, Object* list, template Object* VisitWeakList<JSArrayBuffer>(Heap* heap, Object* list,
WeakObjectRetainer* retainer); WeakObjectRetainer* retainer,
bool stop_after_young);
template Object* VisitWeakList<JSArrayBufferView>(Heap* heap, Object* list,
WeakObjectRetainer* retainer,
bool stop_after_young);
template Object* VisitWeakList<AllocationSite>(Heap* heap, Object* list, template Object* VisitWeakList<AllocationSite>(Heap* heap, Object* list,
WeakObjectRetainer* retainer); WeakObjectRetainer* retainer,
bool stop_after_young);
} }
} // namespace v8::internal } // namespace v8::internal
...@@ -489,7 +489,10 @@ class WeakObjectRetainer; ...@@ -489,7 +489,10 @@ class WeakObjectRetainer;
// pointers. The template parameter T is a WeakListVisitor that defines how to // pointers. The template parameter T is a WeakListVisitor that defines how to
// access the next-element pointers. // access the next-element pointers.
template <class T> template <class T>
Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer); Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer,
bool stop_after_young);
Object* VisitNewArrayBufferViewsWeakList(Heap* heap, Object* list,
WeakObjectRetainer* retainer);
} }
} // namespace v8::internal } // namespace v8::internal
......
...@@ -17008,8 +17008,15 @@ Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer( ...@@ -17008,8 +17008,15 @@ Handle<JSArrayBuffer> JSTypedArray::MaterializeArrayBuffer(
fixed_typed_array->length(), typed_array->type(), fixed_typed_array->length(), typed_array->type(),
static_cast<uint8_t*>(buffer->backing_store())); static_cast<uint8_t*>(buffer->backing_store()));
buffer->set_weak_first_view(*typed_array); Heap* heap = isolate->heap();
DCHECK(typed_array->weak_next() == isolate->heap()->undefined_value()); if (heap->InNewSpace(*typed_array)) {
DCHECK(typed_array->weak_next() == isolate->heap()->undefined_value());
typed_array->set_weak_next(heap->new_array_buffer_views_list());
heap->set_new_array_buffer_views_list(*typed_array);
} else {
buffer->set_weak_first_view(*typed_array);
DCHECK(typed_array->weak_next() == isolate->heap()->undefined_value());
}
typed_array->set_buffer(*buffer); typed_array->set_buffer(*buffer);
JSObject::SetMapAndElements(typed_array, new_map, new_elements); JSObject::SetMapAndElements(typed_array, new_map, new_elements);
......
...@@ -88,6 +88,8 @@ bool Runtime::SetupArrayBufferAllocatingData(Isolate* isolate, ...@@ -88,6 +88,8 @@ bool Runtime::SetupArrayBufferAllocatingData(Isolate* isolate,
void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) { void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) {
Isolate* isolate = array_buffer->GetIsolate(); Isolate* isolate = array_buffer->GetIsolate();
// Firstly, iterate over the views which are referenced directly by the array
// buffer.
for (Handle<Object> view_obj(array_buffer->weak_first_view(), isolate); for (Handle<Object> view_obj(array_buffer->weak_first_view(), isolate);
!view_obj->IsUndefined();) { !view_obj->IsUndefined();) {
Handle<JSArrayBufferView> view(JSArrayBufferView::cast(*view_obj)); Handle<JSArrayBufferView> view(JSArrayBufferView::cast(*view_obj));
...@@ -100,6 +102,24 @@ void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) { ...@@ -100,6 +102,24 @@ void Runtime::NeuterArrayBuffer(Handle<JSArrayBuffer> array_buffer) {
} }
view_obj = handle(view->weak_next(), isolate); view_obj = handle(view->weak_next(), isolate);
} }
// Secondly, iterate over the global list of new space views to find views
// that belong to the neutered array buffer.
Heap* heap = isolate->heap();
for (Handle<Object> view_obj(heap->new_array_buffer_views_list(), isolate);
!view_obj->IsUndefined();) {
Handle<JSArrayBufferView> view(JSArrayBufferView::cast(*view_obj));
if (view->buffer() == *array_buffer) {
if (view->IsJSTypedArray()) {
JSTypedArray::cast(*view)->Neuter();
} else if (view->IsJSDataView()) {
JSDataView::cast(*view)->Neuter();
} else {
UNREACHABLE();
}
}
view_obj = handle(view->weak_next(), isolate);
}
array_buffer->Neuter(); array_buffer->Neuter();
} }
...@@ -265,11 +285,18 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) { ...@@ -265,11 +285,18 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) {
holder->set_byte_offset(*byte_offset_object); holder->set_byte_offset(*byte_offset_object);
holder->set_byte_length(*byte_length_object); holder->set_byte_length(*byte_length_object);
Heap* heap = isolate->heap();
if (!maybe_buffer->IsNull()) { if (!maybe_buffer->IsNull()) {
Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer); Handle<JSArrayBuffer> buffer = Handle<JSArrayBuffer>::cast(maybe_buffer);
holder->set_buffer(*buffer); holder->set_buffer(*buffer);
holder->set_weak_next(buffer->weak_first_view());
buffer->set_weak_first_view(*holder); if (heap->InNewSpace(*holder)) {
holder->set_weak_next(heap->new_array_buffer_views_list());
heap->set_new_array_buffer_views_list(*holder);
} else {
holder->set_weak_next(buffer->weak_first_view());
buffer->set_weak_first_view(*holder);
}
Handle<ExternalArray> elements = isolate->factory()->NewExternalArray( Handle<ExternalArray> elements = isolate->factory()->NewExternalArray(
static_cast<int>(length), array_type, static_cast<int>(length), array_type,
...@@ -367,8 +394,15 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) { ...@@ -367,8 +394,15 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) {
isolate->factory()->NewNumberFromSize(byte_length)); isolate->factory()->NewNumberFromSize(byte_length));
holder->set_byte_length(*byte_length_obj); holder->set_byte_length(*byte_length_obj);
holder->set_length(*length_obj); holder->set_length(*length_obj);
holder->set_weak_next(buffer->weak_first_view());
buffer->set_weak_first_view(*holder); Heap* heap = isolate->heap();
if (heap->InNewSpace(*holder)) {
holder->set_weak_next(heap->new_array_buffer_views_list());
heap->set_new_array_buffer_views_list(*holder);
} else {
holder->set_weak_next(buffer->weak_first_view());
buffer->set_weak_first_view(*holder);
}
Handle<ExternalArray> elements = isolate->factory()->NewExternalArray( Handle<ExternalArray> elements = isolate->factory()->NewExternalArray(
static_cast<int>(length), array_type, static_cast<int>(length), array_type,
...@@ -542,8 +576,14 @@ RUNTIME_FUNCTION(Runtime_DataViewInitialize) { ...@@ -542,8 +576,14 @@ RUNTIME_FUNCTION(Runtime_DataViewInitialize) {
holder->set_byte_offset(*byte_offset); holder->set_byte_offset(*byte_offset);
holder->set_byte_length(*byte_length); holder->set_byte_length(*byte_length);
holder->set_weak_next(buffer->weak_first_view()); Heap* heap = isolate->heap();
buffer->set_weak_first_view(*holder); if (heap->InNewSpace(*holder)) {
holder->set_weak_next(heap->new_array_buffer_views_list());
heap->set_new_array_buffer_views_list(*holder);
} else {
holder->set_weak_next(buffer->weak_first_view());
buffer->set_weak_first_view(*holder);
}
return isolate->heap()->undefined_value(); return isolate->heap()->undefined_value();
} }
......
...@@ -572,6 +572,8 @@ void Deserializer::Deserialize(Isolate* isolate) { ...@@ -572,6 +572,8 @@ void Deserializer::Deserialize(Isolate* isolate) {
isolate_->heap()->undefined_value()); isolate_->heap()->undefined_value());
isolate_->heap()->set_array_buffers_list( isolate_->heap()->set_array_buffers_list(
isolate_->heap()->undefined_value()); isolate_->heap()->undefined_value());
isolate->heap()->set_new_array_buffer_views_list(
isolate_->heap()->undefined_value());
// The allocation site list is build during root iteration, but if no sites // The allocation site list is build during root iteration, but if no sites
// were encountered then it needs to be initialized to undefined. // were encountered then it needs to be initialized to undefined.
......
...@@ -62,7 +62,20 @@ static bool HasArrayBufferInWeakList(Heap* heap, JSArrayBuffer* ab) { ...@@ -62,7 +62,20 @@ static bool HasArrayBufferInWeakList(Heap* heap, JSArrayBuffer* ab) {
} }
static int CountViews(JSArrayBuffer* array_buffer) { static int CountViewsInNewSpaceList(Heap* heap, JSArrayBuffer* array_buffer) {
int count = 0;
for (Object* o = heap->new_array_buffer_views_list(); !o->IsUndefined();) {
JSArrayBufferView* view = JSArrayBufferView::cast(o);
if (array_buffer == view->buffer()) {
count++;
}
o = view->weak_next();
}
return count;
}
static int CountViews(Heap* heap, JSArrayBuffer* array_buffer) {
int count = 0; int count = 0;
for (Object* o = array_buffer->weak_first_view(); for (Object* o = array_buffer->weak_first_view();
!o->IsUndefined(); !o->IsUndefined();
...@@ -70,17 +83,27 @@ static int CountViews(JSArrayBuffer* array_buffer) { ...@@ -70,17 +83,27 @@ static int CountViews(JSArrayBuffer* array_buffer) {
count++; count++;
} }
return count; return count + CountViewsInNewSpaceList(heap, array_buffer);
} }
static bool HasViewInWeakList(JSArrayBuffer* array_buffer,
static bool HasViewInNewSpaceList(Heap* heap, JSArrayBufferView* ta) {
for (Object* o = heap->new_array_buffer_views_list(); !o->IsUndefined();
o = JSArrayBufferView::cast(o)->weak_next()) {
if (ta == o) return true;
}
return false;
}
static bool HasViewInWeakList(Heap* heap, JSArrayBuffer* array_buffer,
JSArrayBufferView* ta) { JSArrayBufferView* ta) {
for (Object* o = array_buffer->weak_first_view(); for (Object* o = array_buffer->weak_first_view();
!o->IsUndefined(); !o->IsUndefined();
o = JSArrayBufferView::cast(o)->weak_next()) { o = JSArrayBufferView::cast(o)->weak_next()) {
if (ta == o) return true; if (ta == o) return true;
} }
return false; return HasViewInNewSpaceList(heap, ta);
} }
...@@ -200,18 +223,18 @@ void TestViewFromApi() { ...@@ -200,18 +223,18 @@ void TestViewFromApi() {
Handle<JSArrayBufferView> ita1 = v8::Utils::OpenHandle(*ta1); Handle<JSArrayBufferView> ita1 = v8::Utils::OpenHandle(*ta1);
Handle<JSArrayBufferView> ita2 = v8::Utils::OpenHandle(*ta2); Handle<JSArrayBufferView> ita2 = v8::Utils::OpenHandle(*ta2);
CHECK_EQ(2, CountViews(*iab)); CHECK_EQ(2, CountViews(isolate->heap(), *iab));
CHECK(HasViewInWeakList(*iab, *ita1)); CHECK(HasViewInWeakList(isolate->heap(), *iab, *ita1));
CHECK(HasViewInWeakList(*iab, *ita2)); CHECK(HasViewInWeakList(isolate->heap(), *iab, *ita2));
} }
isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
CHECK_EQ(1, CountViews(*iab)); CHECK_EQ(1, CountViews(isolate->heap(), *iab));
Handle<JSArrayBufferView> ita1 = v8::Utils::OpenHandle(*ta1); Handle<JSArrayBufferView> ita1 = v8::Utils::OpenHandle(*ta1);
CHECK(HasViewInWeakList(*iab, *ita1)); CHECK(HasViewInWeakList(isolate->heap(), *iab, *ita1));
} }
isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask);
CHECK_EQ(0, CountViews(*iab)); CHECK_EQ(0, CountViews(isolate->heap(), *iab));
} }
...@@ -299,10 +322,13 @@ static void TestTypedArrayFromScript(const char* constructor) { ...@@ -299,10 +322,13 @@ static void TestTypedArrayFromScript(const char* constructor) {
v8::Handle<TypedArray>::Cast(CompileRun("ta3")); v8::Handle<TypedArray>::Cast(CompileRun("ta3"));
CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start); CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start);
Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab); Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
CHECK_EQ(3, CountViews(*iab)); CHECK_EQ(3, CountViews(isolate->heap(), *iab));
CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta1))); CHECK(HasViewInWeakList(isolate->heap(), *iab,
CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta2))); *v8::Utils::OpenHandle(*ta1)));
CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta3))); CHECK(HasViewInWeakList(isolate->heap(), *iab,
*v8::Utils::OpenHandle(*ta2)));
CHECK(HasViewInWeakList(isolate->heap(), *iab,
*v8::Utils::OpenHandle(*ta3)));
} }
i::SNPrintF(source, "ta%d = null;", i); i::SNPrintF(source, "ta%d = null;", i);
...@@ -316,13 +342,14 @@ static void TestTypedArrayFromScript(const char* constructor) { ...@@ -316,13 +342,14 @@ static void TestTypedArrayFromScript(const char* constructor) {
v8::Handle<v8::ArrayBuffer> ab = v8::Handle<v8::ArrayBuffer> ab =
v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab")); v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab"));
Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab); Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
CHECK_EQ(2, CountViews(*iab)); CHECK_EQ(2, CountViews(isolate->heap(), *iab));
for (int j = 1; j <= 3; j++) { for (int j = 1; j <= 3; j++) {
if (j == i) continue; if (j == i) continue;
i::SNPrintF(source, "ta%d", j); i::SNPrintF(source, "ta%d", j);
v8::Handle<TypedArray> ta = v8::Handle<TypedArray> ta =
v8::Handle<TypedArray>::Cast(CompileRun(source.start())); v8::Handle<TypedArray>::Cast(CompileRun(source.start()));
CHECK(HasViewInWeakList(*iab, *v8::Utils::OpenHandle(*ta))); CHECK(HasViewInWeakList(isolate->heap(), *iab,
*v8::Utils::OpenHandle(*ta)));
} }
} }
...@@ -336,7 +363,7 @@ static void TestTypedArrayFromScript(const char* constructor) { ...@@ -336,7 +363,7 @@ static void TestTypedArrayFromScript(const char* constructor) {
v8::Handle<v8::ArrayBuffer> ab = v8::Handle<v8::ArrayBuffer> ab =
v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab")); v8::Handle<v8::ArrayBuffer>::Cast(CompileRun("ab"));
Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab); Handle<JSArrayBuffer> iab = v8::Utils::OpenHandle(*ab);
CHECK_EQ(0, CountViews(*iab)); CHECK_EQ(0, CountViews(isolate->heap(), *iab));
} }
} }
} }
......
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