diff --git a/lib/Runtime/Library/ArrayBuffer.cpp b/lib/Runtime/Library/ArrayBuffer.cpp index 1dbf195c55f..aed7980559f 100644 --- a/lib/Runtime/Library/ArrayBuffer.cpp +++ b/lib/Runtime/Library/ArrayBuffer.cpp @@ -38,7 +38,7 @@ namespace Js return toReturn; } - void ArrayBuffer::ClearParentsLength(ArrayBufferParent* parent) + void ArrayBuffer::DetachBufferFromParent(ArrayBufferParent* parent) { if (parent == nullptr) { @@ -48,23 +48,158 @@ namespace Js switch (JavascriptOperators::GetTypeId(parent)) { case TypeIds_Int8Array: + if (Int8VirtualArray::Is(parent)) + { + if (VirtualTableInfo::HasVirtualTable(parent)) + { + VirtualTableInfo::SetVirtualTable(parent); + } + else + { + Assert(VirtualTableInfo>::HasVirtualTable(parent)); + VirtualTableInfo>::SetVirtualTable(parent); + } + } + TypedArrayBase::FromVar(parent)->ClearLengthAndBufferOnDetach(); + break; + case TypeIds_Uint8Array: + if (Uint8VirtualArray::Is(parent)) + { + if (VirtualTableInfo::HasVirtualTable(parent)) + { + VirtualTableInfo::SetVirtualTable(parent); + } + else + { + Assert(VirtualTableInfo>::HasVirtualTable(parent)); + VirtualTableInfo>::SetVirtualTable(parent); + } + } + TypedArrayBase::FromVar(parent)->ClearLengthAndBufferOnDetach(); + break; + case TypeIds_Uint8ClampedArray: + if (Uint8ClampedVirtualArray::Is(parent)) + { + if (VirtualTableInfo::HasVirtualTable(parent)) + { + VirtualTableInfo::SetVirtualTable(parent); + } + else + { + Assert(VirtualTableInfo>::HasVirtualTable(parent)); + VirtualTableInfo>::SetVirtualTable(parent); + } + } + TypedArrayBase::FromVar(parent)->ClearLengthAndBufferOnDetach(); + break; + case TypeIds_Int16Array: + if (Int16VirtualArray::Is(parent)) + { + if (VirtualTableInfo::HasVirtualTable(parent)) + { + VirtualTableInfo::SetVirtualTable(parent); + } + else + { + Assert(VirtualTableInfo>::HasVirtualTable(parent)); + VirtualTableInfo>::SetVirtualTable(parent); + } + } + TypedArrayBase::FromVar(parent)->ClearLengthAndBufferOnDetach(); + break; + case TypeIds_Uint16Array: + if (Uint16VirtualArray::Is(parent)) + { + if (VirtualTableInfo::HasVirtualTable(parent)) + { + VirtualTableInfo::SetVirtualTable(parent); + } + else + { + Assert(VirtualTableInfo>::HasVirtualTable(parent)); + VirtualTableInfo>::SetVirtualTable(parent); + } + } + TypedArrayBase::FromVar(parent)->ClearLengthAndBufferOnDetach(); + break; + case TypeIds_Int32Array: + if (Int32VirtualArray::Is(parent)) + { + if (VirtualTableInfo::HasVirtualTable(parent)) + { + VirtualTableInfo::SetVirtualTable(parent); + } + else + { + Assert(VirtualTableInfo>::HasVirtualTable(parent)); + VirtualTableInfo>::SetVirtualTable(parent); + } + } + TypedArrayBase::FromVar(parent)->ClearLengthAndBufferOnDetach(); + break; + case TypeIds_Uint32Array: + if (Uint32VirtualArray::Is(parent)) + { + if (VirtualTableInfo::HasVirtualTable(parent)) + { + VirtualTableInfo::SetVirtualTable(parent); + } + else + { + Assert(VirtualTableInfo>::HasVirtualTable(parent)); + VirtualTableInfo>::SetVirtualTable(parent); + } + } + TypedArrayBase::FromVar(parent)->ClearLengthAndBufferOnDetach(); + break; + case TypeIds_Float32Array: + if (Float32VirtualArray::Is(parent)) + { + if (VirtualTableInfo::HasVirtualTable(parent)) + { + VirtualTableInfo::SetVirtualTable(parent); + } + else + { + Assert(VirtualTableInfo>::HasVirtualTable(parent)); + VirtualTableInfo>::SetVirtualTable(parent); + } + } + TypedArrayBase::FromVar(parent)->ClearLengthAndBufferOnDetach(); + break; + case TypeIds_Float64Array: + if (Float64VirtualArray::Is(parent)) + { + if (VirtualTableInfo::HasVirtualTable(parent)) + { + VirtualTableInfo::SetVirtualTable(parent); + } + else + { + Assert(VirtualTableInfo>::HasVirtualTable(parent)); + VirtualTableInfo>::SetVirtualTable(parent); + } + } + TypedArrayBase::FromVar(parent)->ClearLengthAndBufferOnDetach(); + break; + case TypeIds_Int64Array: case TypeIds_Uint64Array: case TypeIds_CharArray: case TypeIds_BoolArray: - TypedArrayBase::FromVar(parent)->length = 0; + TypedArrayBase::FromVar(parent)->ClearLengthAndBufferOnDetach(); break; case TypeIds_DataView: - DataView::FromVar(parent)->length = 0; + DataView::FromVar(parent)->ClearLengthAndBufferOnDetach(); break; default: @@ -90,14 +225,14 @@ namespace Js if (this->primaryParent != nullptr) { - this->ClearParentsLength(this->primaryParent->Get()); + this->DetachBufferFromParent(this->primaryParent->Get()); } if (this->otherParents != nullptr) { this->otherParents->Map([&](RecyclerWeakReference* item) { - this->ClearParentsLength(item->Get()); + this->DetachBufferFromParent(item->Get()); }); } diff --git a/lib/Runtime/Library/ArrayBuffer.h b/lib/Runtime/Library/ArrayBuffer.h index 04d03e6384d..70bf4845b50 100644 --- a/lib/Runtime/Library/ArrayBuffer.h +++ b/lib/Runtime/Library/ArrayBuffer.h @@ -50,7 +50,7 @@ namespace Js DEFINE_VTABLE_CTOR_ABSTRACT(ArrayBuffer, ArrayBufferBase); #define MAX_ASMJS_ARRAYBUFFER_LENGTH 0x100000000 //4GB private: - void ClearParentsLength(ArrayBufferParent* parent); + void DetachBufferFromParent(ArrayBufferParent* parent); public: template class ArrayBufferDetachedState : public ArrayBufferDetachedStateBase diff --git a/lib/Runtime/Library/DataView.cpp b/lib/Runtime/Library/DataView.cpp index e16286e8c7e..ba2c0b7a088 100644 --- a/lib/Runtime/Library/DataView.cpp +++ b/lib/Runtime/Library/DataView.cpp @@ -666,6 +666,14 @@ namespace Js return FALSE; } + void DataView::ClearLengthAndBufferOnDetach() + { + AssertMsg(this->GetArrayBuffer()->IsDetached(), "Array buffer should be detached if we're calling this method"); + + this->length = 0; + this->buffer = nullptr; + } + #ifdef _M_ARM // Provide template specialization (only) for memory access at unaligned float/double address which causes data alignment exception otherwise. template<> diff --git a/lib/Runtime/Library/DataView.h b/lib/Runtime/Library/DataView.h index c7b6fab50e2..711cafd3253 100644 --- a/lib/Runtime/Library/DataView.h +++ b/lib/Runtime/Library/DataView.h @@ -50,6 +50,7 @@ namespace Js } uint32 GetByteOffset() const { return byteOffset; } + void ClearLengthAndBufferOnDetach(); static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...); static Var EntryGetInt8(RecyclableObject* function, CallInfo callInfo, ...); diff --git a/lib/Runtime/Library/TypedArray.cpp b/lib/Runtime/Library/TypedArray.cpp index 6e7ec0efbd9..951df220cf7 100644 --- a/lib/Runtime/Library/TypedArray.cpp +++ b/lib/Runtime/Library/TypedArray.cpp @@ -1117,6 +1117,14 @@ namespace Js } + void TypedArrayBase::ClearLengthAndBufferOnDetach() + { + AssertMsg(IsDetachedBuffer(), "Array buffer should be detached if we're calling this method"); + + this->length = 0; + this->buffer = nullptr; + } + Var TypedArrayBase::EntryGetterBuffer(RecyclableObject* function, CallInfo callInfo, ...) { PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault); diff --git a/lib/Runtime/Library/TypedArray.h b/lib/Runtime/Library/TypedArray.h index ac767cd48cf..966c9e0cbe6 100644 --- a/lib/Runtime/Library/TypedArray.h +++ b/lib/Runtime/Library/TypedArray.h @@ -157,6 +157,7 @@ namespace Js uint32 GetBytesPerElement() const { return BYTES_PER_ELEMENT; } byte* GetByteBuffer() const { return buffer; }; bool IsDetachedBuffer() const { return this->GetArrayBuffer()->IsDetached(); } + void ClearLengthAndBufferOnDetach(); static Var CommonSet(Arguments& args); static Var CommonSubarray(Arguments& args);