From 5ae083a05a6743d6cb91585f449539f7846a5d8c Mon Sep 17 00:00:00 2001 From: jochen Date: Wed, 22 Apr 2015 02:19:38 -0700 Subject: [PATCH] Remove the weak list of views from array buffers Instead, views have to check their array buffer for whether it's neutered or not. BUG=v8:3996 R=hpayer@chromium.org,dslomov@chromium.org,verwaest@chromium.org LOG=n Review URL: https://codereview.chromium.org/1094863002 Cr-Commit-Position: refs/heads/master@{#27995} --- src/accessors.cc | 22 --- src/elements.cc | 36 ++-- src/elements.h | 3 +- src/factory.cc | 97 +++++++-- src/factory.h | 6 + src/heap-snapshot-generator.cc | 5 - src/heap/heap.cc | 30 +-- src/heap/heap.h | 32 --- src/heap/objects-visiting-inl.h | 28 +-- src/heap/objects-visiting.cc | 79 -------- src/hydrogen-instructions.h | 15 +- src/hydrogen.cc | 87 +++++--- src/hydrogen.h | 3 + src/objects-debug.cc | 18 +- src/objects-inl.h | 98 +++++++-- src/objects.cc | 256 ++++++++++++------------ src/objects.h | 98 +++++---- src/runtime/runtime-typedarray.cc | 62 ------ src/snapshot/serialize.cc | 2 - test/cctest/test-api.cc | 14 +- test/cctest/test-heap-profiler.cc | 3 - test/cctest/test-weaktypedarrays.cc | 295 ---------------------------- 22 files changed, 450 insertions(+), 839 deletions(-) diff --git a/src/accessors.cc b/src/accessors.cc index 5ef8bf15f7..df981dc151 100644 --- a/src/accessors.cc +++ b/src/accessors.cc @@ -78,32 +78,10 @@ bool Accessors::IsJSObjectFieldAccessor(Handle map, Handle name, return CheckForName(name, isolate->factory()->length_string(), JSArray::kLengthOffset, object_offset); - case JS_TYPED_ARRAY_TYPE: - // %TypedArray%.prototype is non-configurable, and so are the following - // named properties on %TypedArray%.prototype, so we can directly inline - // the field-load for typed array maps that still use their - // %TypedArray%.prototype. - if (JSFunction::cast(map->GetConstructor())->prototype() != - map->prototype()) { - return false; - } - return - CheckForName(name, isolate->factory()->length_string(), - JSTypedArray::kLengthOffset, object_offset) || - CheckForName(name, isolate->factory()->byte_length_string(), - JSTypedArray::kByteLengthOffset, object_offset) || - CheckForName(name, isolate->factory()->byte_offset_string(), - JSTypedArray::kByteOffsetOffset, object_offset); case JS_ARRAY_BUFFER_TYPE: return CheckForName(name, isolate->factory()->byte_length_string(), JSArrayBuffer::kByteLengthOffset, object_offset); - case JS_DATA_VIEW_TYPE: - return - CheckForName(name, isolate->factory()->byte_length_string(), - JSDataView::kByteLengthOffset, object_offset) || - CheckForName(name, isolate->factory()->byte_offset_string(), - JSDataView::kByteOffsetOffset, object_offset); default: if (map->instance_type() < FIRST_NONSTRING_TYPE) { return CheckForName(name, isolate->factory()->length_string(), diff --git a/src/elements.cc b/src/elements.cc index a00cd249e7..ac63b75888 100644 --- a/src/elements.cc +++ b/src/elements.cc @@ -620,7 +620,7 @@ class ElementsAccessorBase : public ElementsAccessor { Handle obj, uint32_t key, Handle backing_store) { - if (key < ElementsAccessorSubclass::GetCapacityImpl(backing_store)) { + if (key < ElementsAccessorSubclass::GetCapacityImpl(obj, backing_store)) { return BackingStore::get(Handle::cast(backing_store), key); } else { return backing_store->GetIsolate()->factory()->the_hole_value(); @@ -638,7 +638,7 @@ class ElementsAccessorBase : public ElementsAccessor { Handle obj, uint32_t key, Handle backing_store) { - if (key >= ElementsAccessorSubclass::GetCapacityImpl(backing_store)) { + if (key >= ElementsAccessorSubclass::GetCapacityImpl(obj, backing_store)) { return ABSENT; } return @@ -751,7 +751,7 @@ class ElementsAccessorBase : public ElementsAccessor { // Optimize if 'other' is empty. // We cannot optimize if 'this' is empty, as other may have holes. - uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(from); + uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(holder, from); if (len1 == 0) return to; Isolate* isolate = from->GetIsolate(); @@ -817,12 +817,14 @@ class ElementsAccessorBase : public ElementsAccessor { } protected: - static uint32_t GetCapacityImpl(Handle backing_store) { + static uint32_t GetCapacityImpl(Handle holder, + Handle backing_store) { return backing_store->length(); } - uint32_t GetCapacity(Handle backing_store) final { - return ElementsAccessorSubclass::GetCapacityImpl(backing_store); + uint32_t GetCapacity(Handle holder, + Handle backing_store) final { + return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store); } static uint32_t GetKeyForIndexImpl(Handle backing_store, @@ -1260,7 +1262,7 @@ class TypedElementsAccessor Handle obj, uint32_t key, Handle backing_store) { - if (key < AccessorClass::GetCapacityImpl(backing_store)) { + if (key < AccessorClass::GetCapacityImpl(obj, backing_store)) { return BackingStore::get(Handle::cast(backing_store), key); } else { return backing_store->GetIsolate()->factory()->undefined_value(); @@ -1271,9 +1273,8 @@ class TypedElementsAccessor Handle obj, uint32_t key, Handle backing_store) { - return - key < AccessorClass::GetCapacityImpl(backing_store) - ? NONE : ABSENT; + return key < AccessorClass::GetCapacityImpl(obj, backing_store) ? NONE + : ABSENT; } MUST_USE_RESULT static MaybeHandle SetLengthImpl( @@ -1293,10 +1294,16 @@ class TypedElementsAccessor static bool HasElementImpl(Handle holder, uint32_t key, Handle backing_store) { - uint32_t capacity = - AccessorClass::GetCapacityImpl(backing_store); + uint32_t capacity = AccessorClass::GetCapacityImpl(holder, backing_store); return key < capacity; } + + static uint32_t GetCapacityImpl(Handle holder, + Handle backing_store) { + Handle view = Handle::cast(holder); + if (view->WasNeutered()) return 0; + return backing_store->length(); + } }; @@ -1632,12 +1639,13 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase< UNREACHABLE(); } - static uint32_t GetCapacityImpl(Handle backing_store) { + static uint32_t GetCapacityImpl(Handle holder, + Handle backing_store) { Handle parameter_map = Handle::cast(backing_store); Handle arguments( FixedArrayBase::cast(parameter_map->get(1))); return Max(static_cast(parameter_map->length() - 2), - ForArray(arguments)->GetCapacity(arguments)); + ForArray(arguments)->GetCapacity(holder, arguments)); } static uint32_t GetKeyForIndexImpl(Handle dict, diff --git a/src/elements.h b/src/elements.h index 1d80b25891..e743849ff7 100644 --- a/src/elements.h +++ b/src/elements.h @@ -183,7 +183,8 @@ class ElementsAccessor { protected: friend class SloppyArgumentsElementsAccessor; - virtual uint32_t GetCapacity(Handle backing_store) = 0; + virtual uint32_t GetCapacity(Handle holder, + Handle backing_store) = 0; // Element handlers distinguish between indexes and keys when they manipulate // elements. Indexes refer to elements in terms of their location in the diff --git a/src/factory.cc b/src/factory.cc index eda7cdda84..d2a8d79dcf 100644 --- a/src/factory.cc +++ b/src/factory.cc @@ -1825,9 +1825,38 @@ size_t GetExternalArrayElementSize(ExternalArrayType type) { case kExternal##Type##Array: \ return size; TYPED_ARRAYS(TYPED_ARRAY_CASE) + default: + UNREACHABLE(); + return 0; + } +#undef TYPED_ARRAY_CASE +} + + +size_t GetFixedTypedArraysElementSize(ElementsKind kind) { + switch (kind) { +#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ + case TYPE##_ELEMENTS: \ + return size; + TYPED_ARRAYS(TYPED_ARRAY_CASE) + default: + UNREACHABLE(); + return 0; + } +#undef TYPED_ARRAY_CASE +} + + +ExternalArrayType GetArrayTypeFromElementsKind(ElementsKind kind) { + switch (kind) { +#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ + case TYPE##_ELEMENTS: \ + return kExternal##Type##Array; + TYPED_ARRAYS(TYPED_ARRAY_CASE) + default: + UNREACHABLE(); + return kExternalInt8Array; } - UNREACHABLE(); - return 0; #undef TYPED_ARRAY_CASE } @@ -1849,6 +1878,23 @@ JSFunction* GetTypedArrayFun(ExternalArrayType type, Isolate* isolate) { } +JSFunction* GetTypedArrayFun(ElementsKind elements_kind, Isolate* isolate) { + Context* native_context = isolate->context()->native_context(); + switch (elements_kind) { +#define TYPED_ARRAY_FUN(Type, type, TYPE, ctype, size) \ + case TYPE##_ELEMENTS: \ + return native_context->type##_array_fun(); + + TYPED_ARRAYS(TYPED_ARRAY_FUN) +#undef TYPED_ARRAY_FUN + + default: + UNREACHABLE(); + return NULL; + } +} + + void SetupArrayBufferView(i::Isolate* isolate, i::Handle obj, i::Handle buffer, @@ -1858,15 +1904,6 @@ void SetupArrayBufferView(i::Isolate* isolate, obj->set_buffer(*buffer); - Heap* heap = isolate->heap(); - 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 byte_offset_object = isolate->factory()->NewNumberFromSize(byte_offset); obj->set_byte_offset(*byte_offset_object); @@ -1890,6 +1927,16 @@ Handle Factory::NewJSTypedArray(ExternalArrayType type) { } +Handle Factory::NewJSTypedArray(ElementsKind elements_kind) { + Handle typed_array_fun_handle( + GetTypedArrayFun(elements_kind, isolate())); + + CALL_HEAP_FUNCTION( + isolate(), isolate()->heap()->AllocateJSObject(*typed_array_fun_handle), + JSTypedArray); +} + + Handle Factory::NewJSTypedArray(ExternalArrayType type, Handle buffer, size_t byte_offset, @@ -1918,6 +1965,34 @@ Handle Factory::NewJSTypedArray(ExternalArrayType type, } +Handle Factory::NewJSTypedArray(ElementsKind elements_kind, + size_t number_of_elements) { + Handle obj = NewJSTypedArray(elements_kind); + + size_t element_size = GetFixedTypedArraysElementSize(elements_kind); + ExternalArrayType array_type = GetArrayTypeFromElementsKind(elements_kind); + + CHECK(number_of_elements <= + (std::numeric_limits::max() / element_size)); + CHECK(number_of_elements <= static_cast(Smi::kMaxValue)); + size_t byte_length = number_of_elements * element_size; + + obj->set_byte_offset(Smi::FromInt(0)); + i::Handle byte_length_object = + isolate()->factory()->NewNumberFromSize(byte_length); + obj->set_byte_length(*byte_length_object); + Handle length_object = NewNumberFromSize(number_of_elements); + obj->set_length(*length_object); + + obj->set_buffer(Smi::FromInt(0)); + Handle elements = + isolate()->factory()->NewFixedTypedArray( + static_cast(number_of_elements), array_type); + obj->set_elements(*elements); + return obj; +} + + Handle Factory::NewJSDataView(Handle buffer, size_t byte_offset, size_t byte_length) { diff --git a/src/factory.h b/src/factory.h index 87ec2e6e70..72991d9bf0 100644 --- a/src/factory.h +++ b/src/factory.h @@ -448,11 +448,17 @@ class Factory final { Handle NewJSTypedArray(ExternalArrayType type); + Handle NewJSTypedArray(ElementsKind elements_kind); + // Creates a new JSTypedArray with the specified buffer. Handle NewJSTypedArray(ExternalArrayType type, Handle buffer, size_t byte_offset, size_t length); + // Creates a new on-heap JSTypedArray. + Handle NewJSTypedArray(ElementsKind elements_kind, + size_t number_of_elements); + Handle NewJSDataView(); Handle NewJSDataView(Handle buffer, size_t byte_offset, size_t byte_length); diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc index 92149a2e86..bae364cae7 100644 --- a/src/heap-snapshot-generator.cc +++ b/src/heap-snapshot-generator.cc @@ -1175,8 +1175,6 @@ void V8HeapExplorer::ExtractJSObjectReferences( JSArrayBufferView* view = JSArrayBufferView::cast(obj); SetInternalReference(view, entry, "buffer", view->buffer(), JSArrayBufferView::kBufferOffset); - SetWeakReference(view, entry, "weak_next", view->weak_next(), - JSArrayBufferView::kWeakNextOffset); } TagObject(js_obj->properties(), "(object properties)"); SetInternalReference(obj, entry, @@ -1570,9 +1568,6 @@ void V8HeapExplorer::ExtractJSArrayBufferReferences( int entry, JSArrayBuffer* buffer) { SetWeakReference(buffer, entry, "weak_next", buffer->weak_next(), JSArrayBuffer::kWeakNextOffset); - SetWeakReference(buffer, entry, - "weak_first_view", buffer->weak_first_view(), - JSArrayBuffer::kWeakFirstViewOffset); // Setup a reference to a native memory backing_store object. if (!buffer->backing_store()) return; diff --git a/src/heap/heap.cc b/src/heap/heap.cc index ecf8be101a..84d383bfa2 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -141,9 +141,7 @@ Heap::Heap() chunks_queued_for_free_(NULL), gc_callbacks_depth_(0), deserialization_complete_(false), - concurrent_sweeping_enabled_(false), - migration_failure_(false), - previous_migration_failure_(false) { + concurrent_sweeping_enabled_(false) { // 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. @@ -705,13 +703,6 @@ void Heap::GarbageCollectionEpilogue() { // Remember the last top pointer so that we can later find out // whether we allocated in new space since the last GC. 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); } @@ -1686,7 +1677,6 @@ void Heap::UpdateReferencesInExternalStringTable( void Heap::ProcessAllWeakReferences(WeakObjectRetainer* retainer) { ProcessArrayBuffers(retainer, false); - ProcessNewArrayBufferViews(retainer); ProcessNativeContexts(retainer); ProcessAllocationSites(retainer); } @@ -1694,7 +1684,6 @@ void Heap::ProcessAllWeakReferences(WeakObjectRetainer* retainer) { void Heap::ProcessYoungWeakReferences(WeakObjectRetainer* retainer) { ProcessArrayBuffers(retainer, true); - ProcessNewArrayBufferViews(retainer); ProcessNativeContexts(retainer); } @@ -1721,7 +1710,6 @@ void Heap::ProcessArrayBuffers(WeakObjectRetainer* retainer, 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); @@ -1732,20 +1720,6 @@ void Heap::ProcessArrayBuffers(WeakObjectRetainer* retainer, } -void Heap::ProcessNewArrayBufferViews(WeakObjectRetainer* retainer) { - // Retain the list of new space views. - Object* typed_array_obj = VisitWeakList( - this, new_array_buffer_views_list_, retainer, false, NULL); - 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); -} - - void Heap::TearDownArrayBuffers() { Object* undefined = undefined_value(); for (Object* o = array_buffers_list(); o != undefined;) { @@ -2177,7 +2151,6 @@ class ScavengingVisitor : public StaticVisitorBase { if (SemiSpaceCopyObject(map, slot, object, object_size)) { return; } - heap->set_migration_failure(true); } if (PromoteObject(map, slot, object, @@ -5402,7 +5375,6 @@ bool Heap::CreateHeapObjects() { set_native_contexts_list(undefined_value()); set_array_buffers_list(undefined_value()); set_last_array_buffer_in_list(undefined_value()); - set_new_array_buffer_views_list(undefined_value()); set_allocation_sites_list(undefined_value()); return true; } diff --git a/src/heap/heap.h b/src/heap/heap.h index fcec005695..7573c676aa 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -882,13 +882,6 @@ class Heap { return last_array_buffer_in_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) { allocation_sites_list_ = object; } @@ -1495,18 +1488,6 @@ class Heap { 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: // Methods made available to tests. @@ -1681,11 +1662,6 @@ class Heap { Object* last_array_buffer_in_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 // marking. It is initialized during marking, destroyed after marking and // contains Smi(0) while marking is not active. @@ -2016,7 +1992,6 @@ class Heap { void ProcessNativeContexts(WeakObjectRetainer* retainer); void ProcessArrayBuffers(WeakObjectRetainer* retainer, bool stop_after_young); - void ProcessNewArrayBufferViews(WeakObjectRetainer* retainer); void ProcessAllocationSites(WeakObjectRetainer* retainer); // Deopts all code that contains allocation instruction which are tenured or @@ -2176,13 +2151,6 @@ class Heap { 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 Deserializer; friend class Factory; diff --git a/src/heap/objects-visiting-inl.h b/src/heap/objects-visiting-inl.h index 06fa10ef04..39803b1a2c 100644 --- a/src/heap/objects-visiting-inl.h +++ b/src/heap/objects-visiting-inl.h @@ -80,14 +80,12 @@ int StaticNewSpaceVisitor::VisitJSArrayBuffer( Map* map, HeapObject* object) { Heap* heap = map->GetHeap(); - STATIC_ASSERT(JSArrayBuffer::kWeakFirstViewOffset == - JSArrayBuffer::kWeakNextOffset + kPointerSize); VisitPointers(heap, HeapObject::RawField( object, JSArrayBuffer::BodyDescriptor::kStartOffset), HeapObject::RawField(object, JSArrayBuffer::kWeakNextOffset)); VisitPointers( - heap, HeapObject::RawField( - object, JSArrayBuffer::kWeakNextOffset + 2 * kPointerSize), + heap, HeapObject::RawField(object, + JSArrayBuffer::kWeakNextOffset + kPointerSize), HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields)); return JSArrayBuffer::kSizeWithInternalFields; } @@ -99,10 +97,6 @@ int StaticNewSpaceVisitor::VisitJSTypedArray( VisitPointers( map->GetHeap(), HeapObject::RawField(object, JSTypedArray::BodyDescriptor::kStartOffset), - HeapObject::RawField(object, JSTypedArray::kWeakNextOffset)); - VisitPointers( - map->GetHeap(), HeapObject::RawField( - object, JSTypedArray::kWeakNextOffset + kPointerSize), HeapObject::RawField(object, JSTypedArray::kSizeWithInternalFields)); return JSTypedArray::kSizeWithInternalFields; } @@ -114,10 +108,6 @@ int StaticNewSpaceVisitor::VisitJSDataView(Map* map, VisitPointers( map->GetHeap(), HeapObject::RawField(object, JSDataView::BodyDescriptor::kStartOffset), - HeapObject::RawField(object, JSDataView::kWeakNextOffset)); - VisitPointers( - map->GetHeap(), - HeapObject::RawField(object, JSDataView::kWeakNextOffset + kPointerSize), HeapObject::RawField(object, JSDataView::kSizeWithInternalFields)); return JSDataView::kSizeWithInternalFields; } @@ -540,15 +530,13 @@ void StaticMarkingVisitor::VisitJSArrayBuffer( Map* map, HeapObject* object) { Heap* heap = map->GetHeap(); - STATIC_ASSERT(JSArrayBuffer::kWeakFirstViewOffset == - JSArrayBuffer::kWeakNextOffset + kPointerSize); StaticVisitor::VisitPointers( heap, HeapObject::RawField(object, JSArrayBuffer::BodyDescriptor::kStartOffset), HeapObject::RawField(object, JSArrayBuffer::kWeakNextOffset)); StaticVisitor::VisitPointers( - heap, HeapObject::RawField( - object, JSArrayBuffer::kWeakNextOffset + 2 * kPointerSize), + heap, HeapObject::RawField(object, + JSArrayBuffer::kWeakNextOffset + kPointerSize), HeapObject::RawField(object, JSArrayBuffer::kSizeWithInternalFields)); } @@ -559,10 +547,6 @@ void StaticMarkingVisitor::VisitJSTypedArray( StaticVisitor::VisitPointers( map->GetHeap(), HeapObject::RawField(object, JSTypedArray::BodyDescriptor::kStartOffset), - HeapObject::RawField(object, JSTypedArray::kWeakNextOffset)); - StaticVisitor::VisitPointers( - map->GetHeap(), HeapObject::RawField( - object, JSTypedArray::kWeakNextOffset + kPointerSize), HeapObject::RawField(object, JSTypedArray::kSizeWithInternalFields)); } @@ -573,10 +557,6 @@ void StaticMarkingVisitor::VisitJSDataView(Map* map, StaticVisitor::VisitPointers( map->GetHeap(), HeapObject::RawField(object, JSDataView::BodyDescriptor::kStartOffset), - HeapObject::RawField(object, JSDataView::kWeakNextOffset)); - StaticVisitor::VisitPointers( - map->GetHeap(), - HeapObject::RawField(object, JSDataView::kWeakNextOffset + kPointerSize), HeapObject::RawField(object, JSDataView::kSizeWithInternalFields)); } diff --git a/src/heap/objects-visiting.cc b/src/heap/objects-visiting.cc index cf71fb2bda..8c2f198754 100644 --- a/src/heap/objects-visiting.cc +++ b/src/heap/objects-visiting.cc @@ -243,56 +243,6 @@ 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 static void ClearWeakList(Heap* heap, Object* list) { Object* undefined = heap->undefined_value(); @@ -394,22 +344,6 @@ struct WeakListVisitor { }; -template <> -struct WeakListVisitor { - static void SetWeakNext(JSArrayBufferView* obj, Object* next) { - obj->set_weak_next(next); - } - - static Object* WeakNext(JSArrayBufferView* obj) { return obj->weak_next(); } - - static int WeakNextOffset() { return JSArrayBufferView::kWeakNextOffset; } - - static void VisitLiveObject(Heap*, JSArrayBufferView*, WeakObjectRetainer*) {} - - static void VisitPhantomObject(Heap*, JSArrayBufferView*) {} -}; - - template <> struct WeakListVisitor { static void SetWeakNext(JSArrayBuffer* obj, Object* next) { @@ -422,14 +356,6 @@ struct WeakListVisitor { static void VisitLiveObject(Heap* heap, JSArrayBuffer* array_buffer, WeakObjectRetainer* retainer) { - Object* typed_array_obj = VisitWeakList( - heap, array_buffer->weak_first_view(), retainer, false, NULL); - array_buffer->set_weak_first_view(typed_array_obj); - if (typed_array_obj != heap->undefined_value() && MustRecordSlots(heap)) { - Object** slot = HeapObject::RawField(array_buffer, - JSArrayBuffer::kWeakFirstViewOffset); - heap->mark_compact_collector()->RecordSlot(slot, slot, typed_array_obj); - } } static void VisitPhantomObject(Heap* heap, JSArrayBuffer* phantom) { @@ -465,11 +391,6 @@ template Object* VisitWeakList(Heap* heap, Object* list, bool stop_after_young, Object** list_tail); -template Object* VisitWeakList(Heap* heap, Object* list, - WeakObjectRetainer* retainer, - bool stop_after_young, - Object** list_tail); - template Object* VisitWeakList(Heap* heap, Object* list, WeakObjectRetainer* retainer, bool stop_after_young, diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index 0434a13407..0e84a6e959 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -6097,21 +6097,16 @@ class HObjectAccess final { JSArrayBuffer::kByteLengthOffset, Representation::Tagged()); } + static HObjectAccess ForJSArrayBufferFlag() { + return HObjectAccess::ForObservableJSObjectOffset( + JSArrayBuffer::kFlagOffset, Representation::Smi()); + } + static HObjectAccess ForExternalArrayExternalPointer() { return HObjectAccess::ForObservableJSObjectOffset( ExternalArray::kExternalPointerOffset, Representation::External()); } - static HObjectAccess ForJSArrayBufferViewWeakNext() { - return HObjectAccess::ForObservableJSObjectOffset( - JSArrayBufferView::kWeakNextOffset); - } - - static HObjectAccess ForJSArrayBufferWeakFirstView() { - return HObjectAccess::ForObservableJSObjectOffset( - JSArrayBuffer::kWeakFirstViewOffset); - } - static HObjectAccess ForJSArrayBufferViewBuffer() { return HObjectAccess::ForObservableJSObjectOffset( JSArrayBufferView::kBufferOffset); diff --git a/src/hydrogen.cc b/src/hydrogen.cc index e7621d4d0f..74434cd528 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -2427,6 +2427,22 @@ HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess( IsFixedTypedArrayElementsKind(elements_kind)) { HValue* backing_store; if (IsExternalArrayElementsKind(elements_kind)) { + NoObservableSideEffectsScope no_effects(this); + HInstruction* buffer = Add( + checked_object, nullptr, HObjectAccess::ForJSArrayBufferViewBuffer()); + HInstruction* flags = Add( + buffer, nullptr, HObjectAccess::ForJSArrayBufferFlag()); + HValue* was_neutered_mask = + Add(1 << JSArrayBuffer::kWasNeuteredBit); + HValue* was_neutered_test = + AddUncasted(Token::BIT_AND, flags, was_neutered_mask); + + IfBuilder if_was_neutered(this); + if_was_neutered.If( + was_neutered_test, graph()->GetConstant0(), Token::NE); + if_was_neutered.ThenDeopt(Deoptimizer::kOutOfBounds); + if_was_neutered.End(); + backing_store = Add( elements, nullptr, HObjectAccess::ForExternalArrayExternalPointer()); } else { @@ -9613,20 +9629,11 @@ void HGraphBuilder::BuildArrayBufferViewInitialization( Add( obj, HObjectAccess::ForJSArrayBufferViewBuffer(), buffer); - HObjectAccess weak_first_view_access = - HObjectAccess::ForJSArrayBufferWeakFirstView(); - Add( - obj, HObjectAccess::ForJSArrayBufferViewWeakNext(), - Add(buffer, nullptr, weak_first_view_access)); - Add(buffer, weak_first_view_access, obj); } else { Add( obj, HObjectAccess::ForJSArrayBufferViewBuffer(), Add(static_cast(0))); - Add(obj, - HObjectAccess::ForJSArrayBufferViewWeakNext(), - graph()->GetConstantUndefined()); } } @@ -9920,36 +9927,62 @@ void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength( } -void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength( - CallRuntime* expr) { +void HOptimizedGraphBuilder::GenerateArrayBufferViewIndirectAccessor( + CallRuntime* expr, HObjectAccess access) { + NoObservableSideEffectsScope scope(this); DCHECK(expr->arguments()->length() == 1); CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); - HValue* buffer = Pop(); - HInstruction* result = New( - buffer, nullptr, HObjectAccess::ForJSArrayBufferViewByteLength()); - return ast_context()->ReturnInstruction(result, expr->id()); + HValue* view = Pop(); + HInstruction* buffer = Add( + view, nullptr, HObjectAccess::ForJSArrayBufferViewBuffer()); + HInstruction* field = Add(view, nullptr, access); + + IfBuilder if_has_buffer(this); + if_has_buffer.IfNot(buffer); + if_has_buffer.Then(); + { + HInstruction* flags = Add( + buffer, nullptr, HObjectAccess::ForJSArrayBufferFlag()); + HValue* was_neutered_mask = + Add(1 << JSArrayBuffer::kWasNeuteredBit); + HValue* was_neutered_test = + AddUncasted(Token::BIT_AND, flags, was_neutered_mask); + + IfBuilder if_was_neutered(this); + if_was_neutered.If( + was_neutered_test, graph()->GetConstant0(), Token::NE); + if_was_neutered.Then(); + Push(graph()->GetConstant0()); + if_was_neutered.Else(); + Push(field); + if_was_neutered.End(); + } + if_has_buffer.Else(); + Push(field); + if_has_buffer.End(); + + return ast_context()->ReturnValue(Pop()); +} + + +void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength( + CallRuntime* expr) { + return GenerateArrayBufferViewIndirectAccessor( + expr, HObjectAccess::ForJSArrayBufferViewByteLength()); } void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset( CallRuntime* expr) { - DCHECK(expr->arguments()->length() == 1); - CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); - HValue* buffer = Pop(); - HInstruction* result = New( - buffer, nullptr, HObjectAccess::ForJSArrayBufferViewByteOffset()); - return ast_context()->ReturnInstruction(result, expr->id()); + return GenerateArrayBufferViewIndirectAccessor( + expr, HObjectAccess::ForJSArrayBufferViewByteOffset()); } void HOptimizedGraphBuilder::GenerateTypedArrayGetLength( CallRuntime* expr) { - DCHECK(expr->arguments()->length() == 1); - CHECK_ALIVE(VisitForValue(expr->arguments()->at(0))); - HValue* buffer = Pop(); - HInstruction* result = New( - buffer, nullptr, HObjectAccess::ForJSTypedArrayLength()); - return ast_context()->ReturnInstruction(result, expr->id()); + return GenerateArrayBufferViewIndirectAccessor( + expr, HObjectAccess::ForJSTypedArrayLength()); } diff --git a/src/hydrogen.h b/src/hydrogen.h index 8617d38534..b11d856361 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -2244,6 +2244,9 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { FOR_EACH_HYDROGEN_INTRINSIC(GENERATOR_DECLARATION) #undef GENERATOR_DECLARATION + void GenerateArrayBufferViewIndirectAccessor(CallRuntime* call, + HObjectAccess access); + void VisitDelete(UnaryOperation* expr); void VisitVoid(UnaryOperation* expr); void VisitTypeof(UnaryOperation* expr); diff --git a/src/objects-debug.cc b/src/objects-debug.cc index 3495ad65a6..eebf00bcda 100644 --- a/src/objects-debug.cc +++ b/src/objects-debug.cc @@ -841,22 +841,22 @@ void JSArrayBufferView::JSArrayBufferViewVerify() { CHECK(buffer()->IsJSArrayBuffer() || buffer()->IsUndefined() || buffer() == Smi::FromInt(0)); - VerifyPointer(byte_offset()); - CHECK(byte_offset()->IsSmi() || byte_offset()->IsHeapNumber() - || byte_offset()->IsUndefined()); + VerifyPointer(raw_byte_offset()); + CHECK(raw_byte_offset()->IsSmi() || raw_byte_offset()->IsHeapNumber() || + raw_byte_offset()->IsUndefined()); - VerifyPointer(byte_length()); - CHECK(byte_length()->IsSmi() || byte_length()->IsHeapNumber() - || byte_length()->IsUndefined()); + VerifyPointer(raw_byte_length()); + CHECK(raw_byte_length()->IsSmi() || raw_byte_length()->IsHeapNumber() || + raw_byte_length()->IsUndefined()); } void JSTypedArray::JSTypedArrayVerify() { CHECK(IsJSTypedArray()); JSArrayBufferViewVerify(); - VerifyPointer(length()); - CHECK(length()->IsSmi() || length()->IsHeapNumber() - || length()->IsUndefined()); + VerifyPointer(raw_length()); + CHECK(raw_length()->IsSmi() || raw_length()->IsHeapNumber() || + raw_length()->IsUndefined()); VerifyPointer(elements()); } diff --git a/src/objects-inl.h b/src/objects-inl.h index 5f3d0747e6..8a5a327c75 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -4377,23 +4377,25 @@ Handle FixedTypedArray::get( template Handle FixedTypedArray::SetValue( - Handle > array, - uint32_t index, - Handle value) { + Handle holder, Handle > array, + uint32_t index, Handle value) { ElementType cast_value = Traits::defaultValue(); - if (index < static_cast(array->length())) { - if (value->IsSmi()) { - int int_value = Handle::cast(value)->value(); - cast_value = from_int(int_value); - } else if (value->IsHeapNumber()) { - double double_value = Handle::cast(value)->value(); - cast_value = from_double(double_value); - } else { - // Clamp undefined to the default value. All other types have been - // converted to a number type further up in the call chain. - DCHECK(value->IsUndefined()); + Handle view = Handle::cast(holder); + if (!view->WasNeutered()) { + if (index < static_cast(array->length())) { + if (value->IsSmi()) { + int int_value = Handle::cast(value)->value(); + cast_value = from_int(int_value); + } else if (value->IsHeapNumber()) { + double double_value = Handle::cast(value)->value(); + cast_value = from_double(double_value); + } else { + // Clamp undefined to the default value. All other types have been + // converted to a number type further up in the call chain. + DCHECK(value->IsUndefined()); + } + array->set(index, cast_value); } - array->set(index, cast_value); } return Traits::ToHandle(array->GetIsolate(), cast_value); } @@ -6455,15 +6457,71 @@ void JSArrayBuffer::set_is_neuterable(bool value) { } +bool JSArrayBuffer::was_neutered() { + return BooleanBit::get(flag(), kWasNeuteredBit); +} + + +void JSArrayBuffer::set_was_neutered(bool value) { + set_flag(BooleanBit::set(flag(), kWasNeuteredBit, value)); +} + + ACCESSORS(JSArrayBuffer, weak_next, Object, kWeakNextOffset) -ACCESSORS(JSArrayBuffer, weak_first_view, Object, kWeakFirstViewOffset) + + +Object* JSArrayBufferView::byte_offset() const { + if (WasNeutered()) return Smi::FromInt(0); + return Object::cast(READ_FIELD(this, kByteOffsetOffset)); +} + + +void JSArrayBufferView::set_byte_offset(Object* value, WriteBarrierMode mode) { + WRITE_FIELD(this, kByteOffsetOffset, value); + CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kByteOffsetOffset, value, mode); +} + + +Object* JSArrayBufferView::byte_length() const { + if (WasNeutered()) return Smi::FromInt(0); + return Object::cast(READ_FIELD(this, kByteLengthOffset)); +} + + +void JSArrayBufferView::set_byte_length(Object* value, WriteBarrierMode mode) { + WRITE_FIELD(this, kByteLengthOffset, value); + CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kByteLengthOffset, value, mode); +} ACCESSORS(JSArrayBufferView, buffer, Object, kBufferOffset) -ACCESSORS(JSArrayBufferView, byte_offset, Object, kByteOffsetOffset) -ACCESSORS(JSArrayBufferView, byte_length, Object, kByteLengthOffset) -ACCESSORS(JSArrayBufferView, weak_next, Object, kWeakNextOffset) -ACCESSORS(JSTypedArray, length, Object, kLengthOffset) +#ifdef VERIFY_HEAP +ACCESSORS(JSArrayBufferView, raw_byte_offset, Object, kByteOffsetOffset) +ACCESSORS(JSArrayBufferView, raw_byte_length, Object, kByteLengthOffset) +#endif + + +bool JSArrayBufferView::WasNeutered() const { + return !buffer()->IsSmi() && JSArrayBuffer::cast(buffer())->was_neutered(); +} + + +Object* JSTypedArray::length() const { + if (WasNeutered()) return Smi::FromInt(0); + return Object::cast(READ_FIELD(this, kLengthOffset)); +} + + +void JSTypedArray::set_length(Object* value, WriteBarrierMode mode) { + WRITE_FIELD(this, kLengthOffset, value); + CONDITIONAL_WRITE_BARRIER(GetHeap(), this, kLengthOffset, value, mode); +} + + +#ifdef VERIFY_HEAP +ACCESSORS(JSTypedArray, raw_length, Object, kLengthOffset) +#endif + ACCESSORS(JSRegExp, data, Object, kDataOffset) diff --git a/src/objects.cc b/src/objects.cc index fa158fa946..76e97b1b22 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -13317,17 +13317,17 @@ MaybeHandle JSObject::SetElementWithoutInterceptor( return SetFastDoubleElement(object, index, value, language_mode, check_prototype); -#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ - case EXTERNAL_##TYPE##_ELEMENTS: { \ - Handle array( \ - External##Type##Array::cast(object->elements())); \ - return External##Type##Array::SetValue(array, index, value); \ - } \ - case TYPE##_ELEMENTS: { \ - Handle array( \ - Fixed##Type##Array::cast(object->elements())); \ - return Fixed##Type##Array::SetValue(array, index, value); \ - } +#define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ + case EXTERNAL_##TYPE##_ELEMENTS: { \ + Handle array( \ + External##Type##Array::cast(object->elements())); \ + return External##Type##Array::SetValue(object, array, index, value); \ + } \ + case TYPE##_ELEMENTS: { \ + Handle array( \ + Fixed##Type##Array::cast(object->elements())); \ + return Fixed##Type##Array::SetValue(object, array, index, value); \ + } TYPED_ARRAYS(TYPED_ARRAY_CASE) @@ -15193,168 +15193,183 @@ size_t JSTypedArray::element_size() { Handle ExternalUint8ClampedArray::SetValue( - Handle array, - uint32_t index, - Handle value) { + Handle holder, Handle array, + uint32_t index, Handle value) { uint8_t clamped_value = 0; - if (index < static_cast(array->length())) { - if (value->IsSmi()) { - int int_value = Handle::cast(value)->value(); - if (int_value < 0) { - clamped_value = 0; - } else if (int_value > 255) { - clamped_value = 255; + Handle view = Handle::cast(holder); + if (!view->WasNeutered()) { + if (index < static_cast(array->length())) { + if (value->IsSmi()) { + int int_value = Handle::cast(value)->value(); + if (int_value < 0) { + clamped_value = 0; + } else if (int_value > 255) { + clamped_value = 255; + } else { + clamped_value = static_cast(int_value); + } + } else if (value->IsHeapNumber()) { + double double_value = Handle::cast(value)->value(); + if (!(double_value > 0)) { + // NaN and less than zero clamp to zero. + clamped_value = 0; + } else if (double_value > 255) { + // Greater than 255 clamp to 255. + clamped_value = 255; + } else { + // Other doubles are rounded to the nearest integer. + clamped_value = static_cast(lrint(double_value)); + } } else { - clamped_value = static_cast(int_value); + // Clamp undefined to zero (default). All other types have been + // converted to a number type further up in the call chain. + DCHECK(value->IsUndefined()); } - } else if (value->IsHeapNumber()) { - double double_value = Handle::cast(value)->value(); - if (!(double_value > 0)) { - // NaN and less than zero clamp to zero. - clamped_value = 0; - } else if (double_value > 255) { - // Greater than 255 clamp to 255. - clamped_value = 255; - } else { - // Other doubles are rounded to the nearest integer. - clamped_value = static_cast(lrint(double_value)); - } - } else { - // Clamp undefined to zero (default). All other types have been - // converted to a number type further up in the call chain. - DCHECK(value->IsUndefined()); + array->set(index, clamped_value); } - array->set(index, clamped_value); } return handle(Smi::FromInt(clamped_value), array->GetIsolate()); } -template +template static Handle ExternalArrayIntSetter( - Isolate* isolate, - Handle receiver, - uint32_t index, - Handle value) { + Isolate* isolate, Handle holder, + Handle receiver, uint32_t index, Handle value) { ValueType cast_value = 0; - if (index < static_cast(receiver->length())) { - if (value->IsSmi()) { - int int_value = Handle::cast(value)->value(); - cast_value = static_cast(int_value); - } else if (value->IsHeapNumber()) { - double double_value = Handle::cast(value)->value(); - cast_value = static_cast(DoubleToInt32(double_value)); - } else { - // Clamp undefined to zero (default). All other types have been - // converted to a number type further up in the call chain. - DCHECK(value->IsUndefined()); + Handle view = Handle::cast(holder); + if (!view->WasNeutered()) { + if (index < static_cast(receiver->length())) { + if (value->IsSmi()) { + int int_value = Handle::cast(value)->value(); + cast_value = static_cast(int_value); + } else if (value->IsHeapNumber()) { + double double_value = Handle::cast(value)->value(); + cast_value = static_cast(DoubleToInt32(double_value)); + } else { + // Clamp undefined to zero (default). All other types have been + // converted to a number type further up in the call chain. + DCHECK(value->IsUndefined()); + } + receiver->set(index, cast_value); } - receiver->set(index, cast_value); } return isolate->factory()->NewNumberFromInt(cast_value); } -Handle ExternalInt8Array::SetValue(Handle array, +Handle ExternalInt8Array::SetValue(Handle holder, + Handle array, uint32_t index, Handle value) { return ExternalArrayIntSetter( - array->GetIsolate(), array, index, value); + array->GetIsolate(), holder, array, index, value); } -Handle ExternalUint8Array::SetValue(Handle array, +Handle ExternalUint8Array::SetValue(Handle holder, + Handle array, uint32_t index, Handle value) { return ExternalArrayIntSetter( - array->GetIsolate(), array, index, value); + array->GetIsolate(), holder, array, index, value); } -Handle ExternalInt16Array::SetValue(Handle array, +Handle ExternalInt16Array::SetValue(Handle holder, + Handle array, uint32_t index, Handle value) { return ExternalArrayIntSetter( - array->GetIsolate(), array, index, value); + array->GetIsolate(), holder, array, index, value); } -Handle ExternalUint16Array::SetValue(Handle array, +Handle ExternalUint16Array::SetValue(Handle holder, + Handle array, uint32_t index, Handle value) { return ExternalArrayIntSetter( - array->GetIsolate(), array, index, value); + array->GetIsolate(), holder, array, index, value); } -Handle ExternalInt32Array::SetValue(Handle array, +Handle ExternalInt32Array::SetValue(Handle holder, + Handle array, uint32_t index, Handle value) { return ExternalArrayIntSetter( - array->GetIsolate(), array, index, value); + array->GetIsolate(), holder, array, index, value); } -Handle ExternalUint32Array::SetValue( - Handle array, - uint32_t index, - Handle value) { +Handle ExternalUint32Array::SetValue(Handle holder, + Handle array, + uint32_t index, + Handle value) { uint32_t cast_value = 0; - if (index < static_cast(array->length())) { - if (value->IsSmi()) { - int int_value = Handle::cast(value)->value(); - cast_value = static_cast(int_value); - } else if (value->IsHeapNumber()) { - double double_value = Handle::cast(value)->value(); - cast_value = static_cast(DoubleToUint32(double_value)); - } else { - // Clamp undefined to zero (default). All other types have been - // converted to a number type further up in the call chain. - DCHECK(value->IsUndefined()); + Handle view = Handle::cast(holder); + if (!view->WasNeutered()) { + if (index < static_cast(array->length())) { + if (value->IsSmi()) { + int int_value = Handle::cast(value)->value(); + cast_value = static_cast(int_value); + } else if (value->IsHeapNumber()) { + double double_value = Handle::cast(value)->value(); + cast_value = static_cast(DoubleToUint32(double_value)); + } else { + // Clamp undefined to zero (default). All other types have been + // converted to a number type further up in the call chain. + DCHECK(value->IsUndefined()); + } + array->set(index, cast_value); } - array->set(index, cast_value); } return array->GetIsolate()->factory()->NewNumberFromUint(cast_value); } Handle ExternalFloat32Array::SetValue( - Handle array, - uint32_t index, + Handle holder, Handle array, uint32_t index, Handle value) { float cast_value = std::numeric_limits::quiet_NaN(); - if (index < static_cast(array->length())) { - if (value->IsSmi()) { - int int_value = Handle::cast(value)->value(); - cast_value = static_cast(int_value); - } else if (value->IsHeapNumber()) { - double double_value = Handle::cast(value)->value(); - cast_value = static_cast(double_value); - } else { - // Clamp undefined to NaN (default). All other types have been - // converted to a number type further up in the call chain. - DCHECK(value->IsUndefined()); + Handle view = Handle::cast(holder); + if (!view->WasNeutered()) { + if (index < static_cast(array->length())) { + if (value->IsSmi()) { + int int_value = Handle::cast(value)->value(); + cast_value = static_cast(int_value); + } else if (value->IsHeapNumber()) { + double double_value = Handle::cast(value)->value(); + cast_value = static_cast(double_value); + } else { + // Clamp undefined to NaN (default). All other types have been + // converted to a number type further up in the call chain. + DCHECK(value->IsUndefined()); + } + array->set(index, cast_value); } - array->set(index, cast_value); } return array->GetIsolate()->factory()->NewNumber(cast_value); } Handle ExternalFloat64Array::SetValue( - Handle array, - uint32_t index, + Handle holder, Handle array, uint32_t index, Handle value) { double double_value = std::numeric_limits::quiet_NaN(); - if (index < static_cast(array->length())) { - if (value->IsNumber()) { - double_value = value->Number(); - } else { - // Clamp undefined to NaN (default). All other types have been - // converted to a number type further up in the call chain. - DCHECK(value->IsUndefined()); + Handle view = Handle::cast(holder); + if (!view->WasNeutered()) { + if (index < static_cast(array->length())) { + if (value->IsNumber()) { + double_value = value->Number(); + } else { + // Clamp undefined to NaN (default). All other types have been + // converted to a number type further up in the call chain. + DCHECK(value->IsUndefined()); + } + array->set(index, double_value); } - array->set(index, double_value); } return array->GetIsolate()->factory()->NewNumber(double_value); } @@ -16916,25 +16931,7 @@ void JSArrayBuffer::Neuter() { CHECK(is_external()); set_backing_store(NULL); set_byte_length(Smi::FromInt(0)); -} - - -void JSArrayBufferView::NeuterView() { - CHECK(JSArrayBuffer::cast(buffer())->is_neuterable()); - set_byte_offset(Smi::FromInt(0)); - set_byte_length(Smi::FromInt(0)); -} - - -void JSDataView::Neuter() { - NeuterView(); -} - - -void JSTypedArray::Neuter() { - NeuterView(); - set_length(Smi::FromInt(0)); - set_elements(GetHeap()->EmptyExternalArrayForMap(map())); + set_was_neutered(true); } @@ -16978,15 +16975,6 @@ Handle JSTypedArray::MaterializeArrayBuffer( fixed_typed_array->length(), typed_array->type(), static_cast(buffer->backing_store())); - Heap* heap = isolate->heap(); - 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); JSObject::SetMapAndElements(typed_array, new_map, new_elements); diff --git a/src/objects.h b/src/objects.h index e873187002..d6fbaee932 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4652,9 +4652,9 @@ class ExternalUint8ClampedArray: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined and clamps the converted value between 0 and 255. - static Handle SetValue(Handle array, - uint32_t index, - Handle value); + static Handle SetValue(Handle holder, + Handle array, + uint32_t index, Handle value); DECLARE_CAST(ExternalUint8ClampedArray) @@ -4676,9 +4676,9 @@ class ExternalInt8Array: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - static Handle SetValue(Handle array, - uint32_t index, - Handle value); + static Handle SetValue(Handle holder, + Handle array, + uint32_t index, Handle value); DECLARE_CAST(ExternalInt8Array) @@ -4700,9 +4700,9 @@ class ExternalUint8Array: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - static Handle SetValue(Handle array, - uint32_t index, - Handle value); + static Handle SetValue(Handle holder, + Handle array, + uint32_t index, Handle value); DECLARE_CAST(ExternalUint8Array) @@ -4724,9 +4724,9 @@ class ExternalInt16Array: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - static Handle SetValue(Handle array, - uint32_t index, - Handle value); + static Handle SetValue(Handle holder, + Handle array, + uint32_t index, Handle value); DECLARE_CAST(ExternalInt16Array) @@ -4749,9 +4749,9 @@ class ExternalUint16Array: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - static Handle SetValue(Handle array, - uint32_t index, - Handle value); + static Handle SetValue(Handle holder, + Handle array, + uint32_t index, Handle value); DECLARE_CAST(ExternalUint16Array) @@ -4773,9 +4773,9 @@ class ExternalInt32Array: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - static Handle SetValue(Handle array, - uint32_t index, - Handle value); + static Handle SetValue(Handle holder, + Handle array, + uint32_t index, Handle value); DECLARE_CAST(ExternalInt32Array) @@ -4798,9 +4798,9 @@ class ExternalUint32Array: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - static Handle SetValue(Handle array, - uint32_t index, - Handle value); + static Handle SetValue(Handle holder, + Handle array, + uint32_t index, Handle value); DECLARE_CAST(ExternalUint32Array) @@ -4823,9 +4823,9 @@ class ExternalFloat32Array: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - static Handle SetValue(Handle array, - uint32_t index, - Handle value); + static Handle SetValue(Handle holder, + Handle array, + uint32_t index, Handle value); DECLARE_CAST(ExternalFloat32Array) @@ -4848,9 +4848,9 @@ class ExternalFloat64Array: public ExternalArray { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - static Handle SetValue(Handle array, - uint32_t index, - Handle value); + static Handle SetValue(Handle holder, + Handle array, + uint32_t index, Handle value); DECLARE_CAST(ExternalFloat64Array) @@ -4913,9 +4913,9 @@ class FixedTypedArray: public FixedTypedArrayBase { // This accessor applies the correct conversion from Smi, HeapNumber // and undefined. - static Handle SetValue(Handle > array, - uint32_t index, - Handle value); + static Handle SetValue(Handle holder, + Handle > array, + uint32_t index, Handle value); DECLARE_PRINTER(FixedTypedArray) DECLARE_VERIFIER(FixedTypedArray) @@ -10236,15 +10236,14 @@ class JSArrayBuffer: public JSObject { inline bool is_neuterable(); inline void set_is_neuterable(bool value); + inline bool was_neutered(); + inline void set_was_neutered(bool value); + // [weak_next]: linked list of array buffers. DECL_ACCESSORS(weak_next, Object) - // [weak_first_array]: weak linked list of views. - DECL_ACCESSORS(weak_first_view, Object) - DECLARE_CAST(JSArrayBuffer) - // Neutering. Only neuters the buffer, not associated typed arrays. void Neuter(); // Dispatched behavior. @@ -10255,18 +10254,18 @@ class JSArrayBuffer: public JSObject { static const int kByteLengthOffset = kBackingStoreOffset + kPointerSize; static const int kFlagOffset = kByteLengthOffset + kPointerSize; static const int kWeakNextOffset = kFlagOffset + kPointerSize; - static const int kWeakFirstViewOffset = kWeakNextOffset + kPointerSize; - static const int kSize = kWeakFirstViewOffset + kPointerSize; + static const int kSize = kWeakNextOffset + kPointerSize; static const int kSizeWithInternalFields = kSize + v8::ArrayBuffer::kInternalFieldCount * kPointerSize; - private: // Bit position in a flag static const int kIsExternalBit = 0; static const int kShouldBeFreed = 1; static const int kIsNeuterableBit = 2; + static const int kWasNeuteredBit = 3; + private: DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayBuffer); }; @@ -10282,23 +10281,23 @@ class JSArrayBufferView: public JSObject { // [byte_length]: length of typed array in bytes. DECL_ACCESSORS(byte_length, Object) - // [weak_next]: linked list of typed arrays over the same array buffer. - DECL_ACCESSORS(weak_next, Object) - DECLARE_CAST(JSArrayBufferView) DECLARE_VERIFIER(JSArrayBufferView) + inline bool WasNeutered() const; + static const int kBufferOffset = JSObject::kHeaderSize; static const int kByteOffsetOffset = kBufferOffset + kPointerSize; static const int kByteLengthOffset = kByteOffsetOffset + kPointerSize; - static const int kWeakNextOffset = kByteLengthOffset + kPointerSize; - static const int kViewSize = kWeakNextOffset + kPointerSize; - - protected: - void NeuterView(); + static const int kViewSize = kByteLengthOffset + kPointerSize; private: +#ifdef VERIFY_HEAP + DECL_ACCESSORS(raw_byte_offset, Object) + DECL_ACCESSORS(raw_byte_length, Object) +#endif + DISALLOW_IMPLICIT_CONSTRUCTORS(JSArrayBufferView); }; @@ -10308,9 +10307,6 @@ class JSTypedArray: public JSArrayBufferView { // [length]: length of typed array in elements. DECL_ACCESSORS(length, Object) - // Neutering. Only neuters this typed array. - void Neuter(); - DECLARE_CAST(JSTypedArray) ExternalArrayType type(); @@ -10331,6 +10327,9 @@ class JSTypedArray: public JSArrayBufferView { private: static Handle MaterializeArrayBuffer( Handle typed_array); +#ifdef VERIFY_HEAP + DECL_ACCESSORS(raw_length, Object) +#endif DISALLOW_IMPLICIT_CONSTRUCTORS(JSTypedArray); }; @@ -10338,9 +10337,6 @@ class JSTypedArray: public JSArrayBufferView { class JSDataView: public JSArrayBufferView { public: - // Only neuters this DataView - void Neuter(); - DECLARE_CAST(JSDataView) // Dispatched behavior. diff --git a/src/runtime/runtime-typedarray.cc b/src/runtime/runtime-typedarray.cc index a1aacd7aa8..02b5579bf8 100644 --- a/src/runtime/runtime-typedarray.cc +++ b/src/runtime/runtime-typedarray.cc @@ -63,7 +63,6 @@ void Runtime::SetupArrayBuffer(Isolate* isolate, ->set_weak_next(*array_buffer); isolate->heap()->set_last_array_buffer_in_list(*array_buffer); } - array_buffer->set_weak_first_view(isolate->heap()->undefined_value()); } @@ -97,39 +96,6 @@ bool Runtime::SetupArrayBufferAllocatingData(Isolate* isolate, void Runtime::NeuterArrayBuffer(Handle array_buffer) { - Isolate* isolate = array_buffer->GetIsolate(); - // Firstly, iterate over the views which are referenced directly by the array - // buffer. - for (Handle view_obj(array_buffer->weak_first_view(), isolate); - !view_obj->IsUndefined();) { - Handle view(JSArrayBufferView::cast(*view_obj)); - if (view->IsJSTypedArray()) { - JSTypedArray::cast(*view)->Neuter(); - } else if (view->IsJSDataView()) { - JSDataView::cast(*view)->Neuter(); - } else { - UNREACHABLE(); - } - 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 view_obj(heap->new_array_buffer_views_list(), isolate); - !view_obj->IsUndefined();) { - Handle 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(); } @@ -295,19 +261,10 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) { holder->set_byte_offset(*byte_offset_object); holder->set_byte_length(*byte_length_object); - Heap* heap = isolate->heap(); if (!maybe_buffer->IsNull()) { Handle buffer = Handle::cast(maybe_buffer); holder->set_buffer(*buffer); - 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 elements = isolate->factory()->NewExternalArray( static_cast(length), array_type, static_cast(buffer->backing_store()) + byte_offset); @@ -317,7 +274,6 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitialize) { DCHECK(IsExternalArrayElementsKind(holder->map()->elements_kind())); } else { holder->set_buffer(Smi::FromInt(0)); - holder->set_weak_next(isolate->heap()->undefined_value()); Handle elements = isolate->factory()->NewFixedTypedArray(static_cast(length), array_type); @@ -405,15 +361,6 @@ RUNTIME_FUNCTION(Runtime_TypedArrayInitializeFromArrayLike) { holder->set_byte_length(*byte_length_obj); holder->set_length(*length_obj); - 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 elements = isolate->factory()->NewExternalArray( static_cast(length), array_type, static_cast(buffer->backing_store())); @@ -586,15 +533,6 @@ RUNTIME_FUNCTION(Runtime_DataViewInitialize) { holder->set_byte_offset(*byte_offset); holder->set_byte_length(*byte_length); - 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); - } - return isolate->heap()->undefined_value(); } diff --git a/src/snapshot/serialize.cc b/src/snapshot/serialize.cc index bf0a4eb347..26f8da3af8 100644 --- a/src/snapshot/serialize.cc +++ b/src/snapshot/serialize.cc @@ -567,8 +567,6 @@ void Deserializer::Deserialize(Isolate* isolate) { isolate_->heap()->undefined_value()); isolate_->heap()->set_last_array_buffer_in_list( 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 // were encountered then it needs to be initialized to undefined. diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 88c49ce83f..7954598c60 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -13833,9 +13833,10 @@ static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type, i::Factory* factory = isolate->factory(); v8::HandleScope scope(context->GetIsolate()); const int kElementCount = 260; - i::Handle fixed_array = - i::Handle::cast( - factory->NewFixedTypedArray(kElementCount, array_type)); + i::Handle jsobj = + factory->NewJSTypedArray(elements_kind, kElementCount); + i::Handle fixed_array( + FixedTypedArrayClass::cast(jsobj->elements())); CHECK_EQ(FixedTypedArrayClass::kInstanceType, fixed_array->map()->instance_type()); CHECK_EQ(kElementCount, fixed_array->length()); @@ -13849,12 +13850,7 @@ static void FixedTypedArrayTestHelper(i::ExternalArrayType array_type, CHECK_EQ(static_cast(static_cast(i)), static_cast(fixed_array->get_scalar(i))); } - v8::Handle obj = v8::Object::New(CcTest::isolate()); - i::Handle jsobj = v8::Utils::OpenHandle(*obj); - i::Handle fixed_array_map = - i::JSObject::GetElementsTransitionMap(jsobj, elements_kind); - jsobj->set_map(*fixed_array_map); - jsobj->set_elements(*fixed_array); + v8::Handle obj = v8::Utils::ToLocal(jsobj); ObjectWithExternalArrayTestHelper( context.local(), obj, kElementCount, array_type, diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index f461eff949..0a255b69b5 100644 --- a/test/cctest/test-heap-profiler.cc +++ b/test/cctest/test-heap-profiler.cc @@ -2577,9 +2577,6 @@ TEST(ArrayBufferAndArrayBufferView) { const v8::HeapGraphNode* arr1_buffer = GetProperty(arr1_obj, v8::HeapGraphEdge::kInternal, "buffer"); CHECK(arr1_buffer); - const v8::HeapGraphNode* first_view = - GetProperty(arr1_buffer, v8::HeapGraphEdge::kWeak, "weak_first_view"); - CHECK(first_view); const v8::HeapGraphNode* backing_store = GetProperty(arr1_buffer, v8::HeapGraphEdge::kInternal, "backing_store"); CHECK(backing_store); diff --git a/test/cctest/test-weaktypedarrays.cc b/test/cctest/test-weaktypedarrays.cc index c1f59de45a..aa3e432ca8 100644 --- a/test/cctest/test-weaktypedarrays.cc +++ b/test/cctest/test-weaktypedarrays.cc @@ -62,87 +62,6 @@ static bool HasArrayBufferInWeakList(Heap* heap, JSArrayBuffer* ab) { } -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; - for (Object* o = array_buffer->weak_first_view(); - !o->IsUndefined(); - o = JSArrayBufferView::cast(o)->weak_next()) { - count++; - } - - return count + CountViewsInNewSpaceList(heap, 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) { - for (Object* o = array_buffer->weak_first_view(); - !o->IsUndefined(); - o = JSArrayBufferView::cast(o)->weak_next()) { - if (ta == o) return true; - } - return HasViewInNewSpaceList(heap, ta); -} - - -TEST(WeakArrayBuffersFromApi) { - v8::V8::Initialize(); - LocalContext context; - Isolate* isolate = GetIsolateFrom(&context); - - int start = CountArrayBuffersInWeakList(isolate->heap()); - { - v8::HandleScope s1(context->GetIsolate()); - v8::Handle ab1 = - v8::ArrayBuffer::New(context->GetIsolate(), 256); - { - v8::HandleScope s2(context->GetIsolate()); - v8::Handle ab2 = - v8::ArrayBuffer::New(context->GetIsolate(), 128); - - Handle iab1 = v8::Utils::OpenHandle(*ab1); - Handle iab2 = v8::Utils::OpenHandle(*ab2); - CHECK_EQ(2, CountArrayBuffersInWeakList(isolate->heap()) - start); - CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab1)); - CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab2)); - } - isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); - CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start); - { - HandleScope scope2(isolate); - Handle iab1 = v8::Utils::OpenHandle(*ab1); - - CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab1)); - } - } - - isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); - CHECK_EQ(start, CountArrayBuffersInWeakList(isolate->heap())); -} - - TEST(WeakArrayBuffersFromScript) { v8::V8::Initialize(); LocalContext context; @@ -203,217 +122,3 @@ TEST(WeakArrayBuffersFromScript) { CHECK_EQ(start, CountArrayBuffersInWeakList(isolate->heap())); } } - -template -void TestViewFromApi() { - v8::V8::Initialize(); - LocalContext context; - Isolate* isolate = GetIsolateFrom(&context); - - v8::HandleScope s1(context->GetIsolate()); - v8::Handle ab = - v8::ArrayBuffer::New(context->GetIsolate(), 2048); - Handle iab = v8::Utils::OpenHandle(*ab); - { - v8::HandleScope s2(context->GetIsolate()); - v8::Handle ta1 = View::New(ab, 0, 256); - { - v8::HandleScope s3(context->GetIsolate()); - v8::Handle ta2 = View::New(ab, 0, 128); - - Handle ita1 = v8::Utils::OpenHandle(*ta1); - Handle ita2 = v8::Utils::OpenHandle(*ta2); - CHECK_EQ(2, CountViews(isolate->heap(), *iab)); - CHECK(HasViewInWeakList(isolate->heap(), *iab, *ita1)); - CHECK(HasViewInWeakList(isolate->heap(), *iab, *ita2)); - } - isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); - CHECK_EQ(1, CountViews(isolate->heap(), *iab)); - Handle ita1 = v8::Utils::OpenHandle(*ta1); - CHECK(HasViewInWeakList(isolate->heap(), *iab, *ita1)); - } - isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); - - CHECK_EQ(0, CountViews(isolate->heap(), *iab)); -} - - -TEST(Uint8ArrayFromApi) { - TestViewFromApi(); -} - - -TEST(Int8ArrayFromApi) { - TestViewFromApi(); -} - - -TEST(Uint16ArrayFromApi) { - TestViewFromApi(); -} - - -TEST(Int16ArrayFromApi) { - TestViewFromApi(); -} - - -TEST(Uint32ArrayFromApi) { - TestViewFromApi(); -} - - -TEST(Int32ArrayFromApi) { - TestViewFromApi(); -} - - -TEST(Float32ArrayFromApi) { - TestViewFromApi(); -} - - -TEST(Float64ArrayFromApi) { - TestViewFromApi(); -} - - -TEST(Uint8ClampedArrayFromApi) { - TestViewFromApi(); -} - - -TEST(DataViewFromApi) { - TestViewFromApi(); -} - -template -static void TestTypedArrayFromScript(const char* constructor) { - v8::V8::Initialize(); - LocalContext context; - Isolate* isolate = GetIsolateFrom(&context); - v8::HandleScope scope(context->GetIsolate()); - int start = CountArrayBuffersInWeakList(isolate->heap()); - CompileRun("var ab = new ArrayBuffer(2048);"); - for (int i = 1; i <= 3; i++) { - // Create 3 typed arrays, make i-th of them garbage, - // validate correct state of typed array weak list. - v8::HandleScope s0(context->GetIsolate()); - i::ScopedVector source(2048); - - CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start); - - { - v8::HandleScope s1(context->GetIsolate()); - i::SNPrintF(source, - "var ta1 = new %s(ab);" - "var ta2 = new %s(ab);" - "var ta3 = new %s(ab)", - constructor, constructor, constructor); - - CompileRun(source.start()); - v8::Handle ab = - v8::Handle::Cast(CompileRun("ab")); - v8::Handle ta1 = - v8::Handle::Cast(CompileRun("ta1")); - v8::Handle ta2 = - v8::Handle::Cast(CompileRun("ta2")); - v8::Handle ta3 = - v8::Handle::Cast(CompileRun("ta3")); - CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start); - Handle iab = v8::Utils::OpenHandle(*ab); - CHECK_EQ(3, CountViews(isolate->heap(), *iab)); - CHECK(HasViewInWeakList(isolate->heap(), *iab, - *v8::Utils::OpenHandle(*ta1))); - 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); - CompileRun(source.start()); - isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); - - CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start); - - { - v8::HandleScope s2(context->GetIsolate()); - v8::Handle ab = - v8::Handle::Cast(CompileRun("ab")); - Handle iab = v8::Utils::OpenHandle(*ab); - CHECK_EQ(2, CountViews(isolate->heap(), *iab)); - for (int j = 1; j <= 3; j++) { - if (j == i) continue; - i::SNPrintF(source, "ta%d", j); - v8::Handle ta = - v8::Handle::Cast(CompileRun(source.start())); - CHECK(HasViewInWeakList(isolate->heap(), *iab, - *v8::Utils::OpenHandle(*ta))); - } - } - - CompileRun("ta1 = null; ta2 = null; ta3 = null;"); - isolate->heap()->CollectAllGarbage(Heap::kAbortIncrementalMarkingMask); - - CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start); - - { - v8::HandleScope s3(context->GetIsolate()); - v8::Handle ab = - v8::Handle::Cast(CompileRun("ab")); - Handle iab = v8::Utils::OpenHandle(*ab); - CHECK_EQ(0, CountViews(isolate->heap(), *iab)); - } - } -} - - -TEST(Uint8ArrayFromScript) { - TestTypedArrayFromScript("Uint8Array"); -} - - -TEST(Int8ArrayFromScript) { - TestTypedArrayFromScript("Int8Array"); -} - - -TEST(Uint16ArrayFromScript) { - TestTypedArrayFromScript("Uint16Array"); -} - - -TEST(Int16ArrayFromScript) { - TestTypedArrayFromScript("Int16Array"); -} - - -TEST(Uint32ArrayFromScript) { - TestTypedArrayFromScript("Uint32Array"); -} - - -TEST(Int32ArrayFromScript) { - TestTypedArrayFromScript("Int32Array"); -} - - -TEST(Float32ArrayFromScript) { - TestTypedArrayFromScript("Float32Array"); -} - - -TEST(Float64ArrayFromScript) { - TestTypedArrayFromScript("Float64Array"); -} - - -TEST(Uint8ClampedArrayFromScript) { - TestTypedArrayFromScript("Uint8ClampedArray"); -} - - -TEST(DataViewFromScript) { - TestTypedArrayFromScript("DataView"); -}