From 655b04637e9da2749f53c866bca8f5f6abb05a3f Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 23 Apr 2015 06:02:53 -0700 Subject: [PATCH] Reland "Remove the weak list of views from array buffers" Original description: > 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 BUG=v8:3996 R=hpayer@chromium.org,dslomov@chromium.org,verwaest@chromium.org LOG=n Review URL: https://codereview.chromium.org/1093183004 Cr-Commit-Position: refs/heads/master@{#28029} --- src/accessors.cc | 54 ++--- src/accessors.h | 8 + src/code-stubs-hydrogen.cc | 12 ++ src/code-stubs.h | 27 +++ 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 | 177 ++++++++++++----- src/hydrogen.h | 41 ++-- src/ic/ic.cc | 6 + 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 ---------------------------- 26 files changed, 621 insertions(+), 881 deletions(-) diff --git a/src/accessors.cc b/src/accessors.cc index 5ef8bf15f7..f220b829bf 100644 --- a/src/accessors.cc +++ b/src/accessors.cc @@ -78,6 +78,26 @@ bool Accessors::IsJSObjectFieldAccessor(Handle map, Handle name, return CheckForName(name, isolate->factory()->length_string(), JSArray::kLengthOffset, object_offset); + case JS_ARRAY_BUFFER_TYPE: + return CheckForName(name, isolate->factory()->byte_length_string(), + JSArrayBuffer::kByteLengthOffset, object_offset); + default: + if (map->instance_type() < FIRST_NONSTRING_TYPE) { + return CheckForName(name, isolate->factory()->length_string(), + String::kLengthOffset, object_offset); + } + + return false; + } +} + + +bool Accessors::IsJSArrayBufferViewFieldAccessor(Handle map, + Handle name, + int* object_offset) { + Isolate* isolate = name->GetIsolate(); + + switch (map->instance_type()) { 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 @@ -87,29 +107,19 @@ bool Accessors::IsJSObjectFieldAccessor(Handle map, Handle name, 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(), - String::kLengthOffset, object_offset); - } + 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_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: return false; } } diff --git a/src/accessors.h b/src/accessors.h index 6b586a0dc7..d37b6b770c 100644 --- a/src/accessors.h +++ b/src/accessors.h @@ -80,6 +80,14 @@ class Accessors : public AllStatic { static bool IsJSObjectFieldAccessor(Handle map, Handle name, int* object_offset); + // Returns true for properties that are accessors to ArrayBufferView and + // derived classes fields. If true, *object_offset contains offset of + // object field. The caller still has to check whether the underlying + // buffer was neutered. + static bool IsJSArrayBufferViewFieldAccessor(Handle map, + Handle name, + int* object_offset); + static Handle MakeAccessor( Isolate* isolate, Handle name, diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc index 3ca301ca6c..47e7ddb826 100644 --- a/src/code-stubs-hydrogen.cc +++ b/src/code-stubs-hydrogen.cc @@ -624,6 +624,18 @@ Handle LoadFieldStub::GenerateCode() { } +template <> +HValue* CodeStubGraphBuilder::BuildCodeStub() { + return BuildArrayBufferViewFieldAccessor(GetParameter(0), nullptr, + casted_stub()->index()); +} + + +Handle ArrayBufferViewLoadFieldStub::GenerateCode() { + return DoGenerateCode(this); +} + + template <> HValue* CodeStubGraphBuilder::BuildCodeStub() { HValue* map = AddLoadMap(GetParameter(0), NULL); diff --git a/src/code-stubs.h b/src/code-stubs.h index 424026f40b..6ce369dd08 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -88,6 +88,7 @@ namespace internal { V(VectorRawKeyedLoad) \ V(VectorRawLoad) \ /* IC Handler stubs */ \ + V(ArrayBufferViewLoadField) \ V(LoadConstant) \ V(LoadField) \ V(KeyedLoadSloppyArguments) \ @@ -973,6 +974,32 @@ class LoadFieldStub: public HandlerStub { }; +class ArrayBufferViewLoadFieldStub : public HandlerStub { + public: + ArrayBufferViewLoadFieldStub(Isolate* isolate, FieldIndex index) + : HandlerStub(isolate) { + int property_index_key = index.GetFieldAccessStubKey(); + set_sub_minor_key( + ArrayBufferViewLoadFieldByIndexBits::encode(property_index_key)); + } + + FieldIndex index() const { + int property_index_key = + ArrayBufferViewLoadFieldByIndexBits::decode(sub_minor_key()); + return FieldIndex::FromFieldAccessStubKey(property_index_key); + } + + protected: + Code::Kind kind() const override { return Code::LOAD_IC; } + Code::StubType GetStubType() const override { return Code::FAST; } + + private: + class ArrayBufferViewLoadFieldByIndexBits : public BitField {}; + + DEFINE_HANDLER_CODE_STUB(ArrayBufferViewLoadField, HandlerStub); +}; + + class KeyedLoadSloppyArgumentsStub : public HandlerStub { public: explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate) 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 63cdae87b7..985d1f6788 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); } @@ -1687,7 +1678,6 @@ void Heap::UpdateReferencesInExternalStringTable( void Heap::ProcessAllWeakReferences(WeakObjectRetainer* retainer) { ProcessArrayBuffers(retainer, false); - ProcessNewArrayBufferViews(retainer); ProcessNativeContexts(retainer); ProcessAllocationSites(retainer); } @@ -1695,7 +1685,6 @@ void Heap::ProcessAllWeakReferences(WeakObjectRetainer* retainer) { void Heap::ProcessYoungWeakReferences(WeakObjectRetainer* retainer) { ProcessArrayBuffers(retainer, true); - ProcessNewArrayBufferViews(retainer); ProcessNativeContexts(retainer); } @@ -1722,7 +1711,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); @@ -1733,20 +1721,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;) { @@ -2178,7 +2152,6 @@ class ScavengingVisitor : public StaticVisitorBase { if (SemiSpaceCopyObject(map, slot, object, object_size)) { return; } - heap->set_migration_failure(true); } if (PromoteObject(map, slot, object, @@ -5403,7 +5376,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 d60a3f079b..dcf7bdea0a 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -883,13 +883,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; } @@ -1496,18 +1489,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. @@ -1682,11 +1663,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. @@ -2017,7 +1993,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 @@ -2177,13 +2152,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 1e28ceace2..e48b170ef2 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 { @@ -3155,6 +3171,44 @@ HInstruction* HGraphBuilder::BuildGetArrayFunction() { } +HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object, + HValue* checked_object, + FieldIndex index) { + NoObservableSideEffectsScope scope(this); + HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset( + index.offset(), Representation::Tagged()); + HInstruction* buffer = Add( + object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer()); + HInstruction* field = Add(object, checked_object, access); + + IfBuilder if_has_buffer(this); + HValue* has_buffer = if_has_buffer.IfNot(buffer); + if_has_buffer.Then(); + { + HInstruction* flags = Add( + buffer, has_buffer, 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 Pop(); +} + + HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder, ElementsKind kind, HValue* allocation_site_payload, @@ -5654,7 +5708,7 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { Handle map = property->GetReceiverType(); Handle name = key->AsPropertyName(); - HInstruction* store; + HValue* store; if (map.is_null()) { // If we don't know the monomorphic type, do a generic store. CHECK_ALIVE(store = BuildNamedGeneric( @@ -5672,7 +5726,9 @@ void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { STORE, NULL, literal, name, value)); } } - AddInstruction(store); + if (store->IsInstruction()) { + AddInstruction(HInstruction::cast(store)); + } DCHECK(store->HasObservableSideEffects()); Add(key->id(), REMOVABLE_SIMULATE); } else { @@ -6133,6 +6189,7 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() { bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() { if (!CanInlinePropertyAccess(map_)) return false; if (IsJSObjectFieldAccessor()) return IsLoad(); + if (IsJSArrayBufferViewFieldAccessor()) return IsLoad(); if (map_->function_with_prototype() && !map_->has_non_instance_prototype() && name_.is_identical_to(isolate()->factory()->prototype_string())) { return IsLoad(); @@ -6181,6 +6238,18 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic( return true; } + if (GetJSArrayBufferViewFieldAccess(&access)) { + for (int i = 1; i < maps->length(); ++i) { + PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_); + HObjectAccess test_access = HObjectAccess::ForMap(); // bogus default + if (!test_info.GetJSArrayBufferViewFieldAccess(&test_access)) { + return false; + } + if (!access.Equals(test_access)) return false; + } + return true; + } + // Currently only handle numbers as a polymorphic case. // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber // instruction. @@ -6220,21 +6289,22 @@ bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor( } -HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess( - PropertyAccessInfo* info, - HValue* object, - HValue* checked_object, - HValue* value, - BailoutId ast_id, - BailoutId return_id, +HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess( + PropertyAccessInfo* info, HValue* object, HValue* checked_object, + HValue* value, BailoutId ast_id, BailoutId return_id, bool can_inline_accessor) { - HObjectAccess access = HObjectAccess::ForMap(); // bogus default if (info->GetJSObjectFieldAccess(&access)) { DCHECK(info->IsLoad()); return New(object, checked_object, access); } + if (info->GetJSArrayBufferViewFieldAccess(&access)) { + DCHECK(info->IsLoad()); + return BuildArrayBufferViewFieldAccessor( + object, checked_object, FieldIndex::ForInObjectOffset(access.offset())); + } + if (info->name().is_identical_to(isolate()->factory()->prototype_string()) && info->map()->function_with_prototype()) { DCHECK(!info->map()->has_non_instance_prototype()); @@ -6384,9 +6454,9 @@ void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( set_current_block(if_true); - HInstruction* access = BuildMonomorphicAccess( - &info, object, dependency, value, ast_id, - return_id, FLAG_polymorphic_inlining); + HValue* access = + BuildMonomorphicAccess(&info, object, dependency, value, ast_id, + return_id, FLAG_polymorphic_inlining); HValue* result = NULL; switch (access_type) { @@ -6401,7 +6471,10 @@ void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess( if (access == NULL) { if (HasStackOverflow()) return; } else { - if (!access->IsLinked()) AddInstruction(access); + if (access->IsInstruction()) { + HInstruction* instr = HInstruction::cast(access); + if (!instr->IsLinked()) AddInstruction(instr); + } if (!ast_context()->IsEffect()) Push(result); } @@ -6495,13 +6568,13 @@ void HOptimizedGraphBuilder::BuildStore(Expression* expr, Handle name = Handle::cast(key->value()); DCHECK(!name.is_null()); - HInstruction* instr = BuildNamedAccess(STORE, ast_id, return_id, expr, - object, name, value, is_uninitialized); - if (instr == NULL) return; + HValue* access = BuildNamedAccess(STORE, ast_id, return_id, expr, object, + name, value, is_uninitialized); + if (access == NULL) return; if (!ast_context()->IsEffect()) Push(value); - AddInstruction(instr); - if (instr->HasObservableSideEffects()) { + if (access->IsInstruction()) AddInstruction(HInstruction::cast(access)); + if (access->HasObservableSideEffects()) { Add(ast_id, REMOVABLE_SIMULATE); } if (!ast_context()->IsEffect()) Drop(1); @@ -7250,16 +7323,18 @@ HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess( constant = isolate()->factory()->InternalizeString( Handle::cast(constant)); } - HInstruction* instr = + HValue* access = BuildNamedAccess(access_type, ast_id, return_id, expr, obj, Handle::cast(constant), val, false); - if (instr == NULL || instr->IsLinked()) { + if (access == NULL || access->IsPhi() || + HInstruction::cast(access)->IsLinked()) { *has_side_effects = false; } else { + HInstruction* instr = HInstruction::cast(access); AddInstruction(instr); *has_side_effects = instr->HasObservableSideEffects(); } - return instr; + return access; } } @@ -7418,14 +7493,9 @@ bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) { } -HInstruction* HOptimizedGraphBuilder::BuildNamedAccess( - PropertyAccessType access, - BailoutId ast_id, - BailoutId return_id, - Expression* expr, - HValue* object, - Handle name, - HValue* value, +HValue* HOptimizedGraphBuilder::BuildNamedAccess( + PropertyAccessType access, BailoutId ast_id, BailoutId return_id, + Expression* expr, HValue* object, Handle name, HValue* value, bool is_uninitialized) { SmallMapList* maps; ComputeReceiverTypes(expr, object, &maps, zone()); @@ -7481,9 +7551,11 @@ void HOptimizedGraphBuilder::BuildLoad(Property* expr, Handle name = expr->key()->AsLiteral()->AsPropertyName(); HValue* object = Pop(); - instr = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr, - object, name, NULL, expr->IsUninitialized()); - if (instr == NULL) return; + HValue* value = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr, object, + name, NULL, expr->IsUninitialized()); + if (value == NULL) return; + if (value->IsPhi()) return ast_context()->ReturnValue(value); + instr = HInstruction::cast(value); if (instr->IsLinked()) return ast_context()->ReturnValue(instr); } else { @@ -9617,20 +9689,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()); } } @@ -9926,34 +9989,40 @@ void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength( void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength( CallRuntime* expr) { + 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(); + + return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor( + view, nullptr, + FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteLengthOffset))); } void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset( CallRuntime* expr) { + NoObservableSideEffectsScope scope(this); 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()); + HValue* view = Pop(); + + return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor( + view, nullptr, + FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteOffsetOffset))); } void HOptimizedGraphBuilder::GenerateTypedArrayGetLength( CallRuntime* expr) { + NoObservableSideEffectsScope scope(this); 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()); + HValue* view = Pop(); + + return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor( + view, nullptr, + FieldIndex::ForInObjectOffset(JSTypedArray::kLengthOffset))); } diff --git a/src/hydrogen.h b/src/hydrogen.h index 8617d38534..01f71075af 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -1862,6 +1862,10 @@ class HGraphBuilder { HInstruction* BuildGetNativeContext(); HInstruction* BuildGetScriptContext(int context_index); HInstruction* BuildGetArrayFunction(); + HValue* BuildArrayBufferViewFieldAccessor(HValue* object, + HValue* checked_object, + FieldIndex index); + protected: void SetSourcePosition(int position) { @@ -2554,6 +2558,20 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { return false; } + bool IsJSArrayBufferViewFieldAccessor() { + int offset; // unused + return Accessors::IsJSArrayBufferViewFieldAccessor(map_, name_, &offset); + } + + bool GetJSArrayBufferViewFieldAccess(HObjectAccess* access) { + int offset; + if (Accessors::IsJSArrayBufferViewFieldAccessor(map_, name_, &offset)) { + *access = HObjectAccess::ForMapAndOffset(map_, offset); + return true; + } + return false; + } + bool has_holder() { return !holder_.is_null(); } bool IsLoad() const { return access_type_ == LOAD; } @@ -2678,22 +2696,15 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor { PropertyDetails details_; }; - HInstruction* BuildMonomorphicAccess(PropertyAccessInfo* info, - HValue* object, - HValue* checked_object, - HValue* value, - BailoutId ast_id, - BailoutId return_id, - bool can_inline_accessor = true); + HValue* BuildMonomorphicAccess(PropertyAccessInfo* info, HValue* object, + HValue* checked_object, HValue* value, + BailoutId ast_id, BailoutId return_id, + bool can_inline_accessor = true); - HInstruction* BuildNamedAccess(PropertyAccessType access, - BailoutId ast_id, - BailoutId reutrn_id, - Expression* expr, - HValue* object, - Handle name, - HValue* value, - bool is_uninitialized = false); + HValue* BuildNamedAccess(PropertyAccessType access, BailoutId ast_id, + BailoutId reutrn_id, Expression* expr, + HValue* object, Handle name, HValue* value, + bool is_uninitialized = false); void HandlePolymorphicCallNamed(Call* expr, HValue* receiver, diff --git a/src/ic/ic.cc b/src/ic/ic.cc index a6ae92a892..699e90f75b 100644 --- a/src/ic/ic.cc +++ b/src/ic/ic.cc @@ -1227,6 +1227,12 @@ Handle LoadIC::CompileHandler(LookupIterator* lookup, FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); return SimpleFieldLoad(index); } + if (Accessors::IsJSArrayBufferViewFieldAccessor(map, lookup->name(), + &object_offset)) { + FieldIndex index = FieldIndex::ForInObjectOffset(object_offset, *map); + ArrayBufferViewLoadFieldStub stub(isolate(), index); + return stub.GetCode(); + } Handle accessors = lookup->GetAccessors(); if (accessors->IsExecutableAccessorInfo()) { 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 e9db3c5736..2e77f92927 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 6880a0175c..9a7dcb0d11 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -13330,17 +13330,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) @@ -15206,168 +15206,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); } @@ -16929,25 +16944,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); } @@ -16991,15 +16988,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 bfec772678..68db075981 100644 --- a/src/objects.h +++ b/src/objects.h @@ -4660,9 +4660,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) @@ -4684,9 +4684,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) @@ -4708,9 +4708,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) @@ -4732,9 +4732,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) @@ -4757,9 +4757,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) @@ -4781,9 +4781,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) @@ -4806,9 +4806,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) @@ -4831,9 +4831,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) @@ -4856,9 +4856,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) @@ -4921,9 +4921,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) @@ -10244,15 +10244,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. @@ -10263,18 +10262,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); }; @@ -10290,23 +10289,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); }; @@ -10316,9 +10315,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(); @@ -10339,6 +10335,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); }; @@ -10346,9 +10345,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 0635e9e094..9ad8281df5 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -13831,9 +13831,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()); @@ -13847,12 +13848,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 4b78644b50..1d998d1f45 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 8c5459a8f1..c0d2950432 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(); - CHECK_EQ(1, CountArrayBuffersInWeakList(isolate->heap()) - start); - { - HandleScope scope2(isolate); - Handle iab1 = v8::Utils::OpenHandle(*ab1); - - CHECK(HasArrayBufferInWeakList(isolate->heap(), *iab1)); - } - } - - isolate->heap()->CollectAllGarbage(); - 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(); - CHECK_EQ(1, CountViews(isolate->heap(), *iab)); - Handle ita1 = v8::Utils::OpenHandle(*ta1); - CHECK(HasViewInWeakList(isolate->heap(), *iab, *ita1)); - } - isolate->heap()->CollectAllGarbage(); - - 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(); - - 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(); - - 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"); -}