|
|
@@ -950,32 +950,42 @@ namespace Js
|
|
|
#endif
|
|
|
|
|
|
|
|
|
-
|
|
|
- WebAssemblyArrayBuffer::WebAssemblyArrayBuffer(uint32 length, DynamicType * type) :
|
|
|
-#ifndef ENABLE_FAST_ARRAYBUFFER
|
|
|
- // Treat as a normal JavascriptArrayBuffer
|
|
|
- JavascriptArrayBuffer(length, type) {}
|
|
|
-#else
|
|
|
- JavascriptArrayBuffer(length, type, WasmVirtualAllocator)
|
|
|
+ template<typename Allocator>
|
|
|
+ Js::WebAssemblyArrayBuffer::WebAssemblyArrayBuffer(uint32 length, DynamicType * type, Allocator allocator):
|
|
|
+ JavascriptArrayBuffer(length, type, allocator)
|
|
|
{
|
|
|
+#ifndef ENABLE_FAST_ARRAYBUFFER
|
|
|
+ CompileAssert(UNREACHED);
|
|
|
+#endif
|
|
|
+ Assert(allocator == WasmVirtualAllocator);
|
|
|
// Make sure we always have a buffer even if the length is 0
|
|
|
if (buffer == nullptr)
|
|
|
{
|
|
|
// We want to allocate an empty buffer using virtual memory
|
|
|
Assert(length == 0);
|
|
|
- buffer = (BYTE*)WasmVirtualAllocator(0);
|
|
|
+ buffer = (BYTE*)allocator(0);
|
|
|
if (buffer == nullptr)
|
|
|
{
|
|
|
JavascriptError::ThrowOutOfMemoryError(GetScriptContext());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-#endif
|
|
|
+
|
|
|
+ // Treat as a normal JavascriptArrayBuffer
|
|
|
+ WebAssemblyArrayBuffer::WebAssemblyArrayBuffer(uint32 length, DynamicType * type) :
|
|
|
+ JavascriptArrayBuffer(length, type, malloc)
|
|
|
+ {
|
|
|
+ }
|
|
|
|
|
|
WebAssemblyArrayBuffer::WebAssemblyArrayBuffer(byte* buffer, uint32 length, DynamicType * type):
|
|
|
JavascriptArrayBuffer(buffer, length, type)
|
|
|
{
|
|
|
-
|
|
|
+#if ENABLE_FAST_ARRAYBUFFER
|
|
|
+ if (CONFIG_FLAG(WasmFastArray) && buffer == nullptr)
|
|
|
+ {
|
|
|
+ JavascriptError::ThrowOutOfMemoryError(GetScriptContext());
|
|
|
+ }
|
|
|
+#endif
|
|
|
}
|
|
|
|
|
|
WebAssemblyArrayBuffer* WebAssemblyArrayBuffer::Create(byte* buffer, uint32 length, DynamicType * type)
|
|
|
@@ -988,7 +998,16 @@ namespace Js
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- result = RecyclerNewFinalized(recycler, WebAssemblyArrayBuffer, length, type);
|
|
|
+#if ENABLE_FAST_ARRAYBUFFER
|
|
|
+ if (CONFIG_FLAG(WasmFastArray))
|
|
|
+ {
|
|
|
+ result = RecyclerNewFinalized(recycler, WebAssemblyArrayBuffer, length, type, WasmVirtualAllocator);
|
|
|
+ }
|
|
|
+ else
|
|
|
+#endif
|
|
|
+ {
|
|
|
+ result = RecyclerNewFinalized(recycler, WebAssemblyArrayBuffer, length, type);
|
|
|
+ }
|
|
|
}
|
|
|
Assert(result);
|
|
|
recycler->AddExternalMemoryUsage(length);
|
|
|
@@ -998,21 +1017,26 @@ namespace Js
|
|
|
bool WebAssemblyArrayBuffer::IsValidVirtualBufferLength(uint length) const
|
|
|
{
|
|
|
#if ENABLE_FAST_ARRAYBUFFER
|
|
|
- return true;
|
|
|
+ return CONFIG_FLAG(WasmFastArray);
|
|
|
#else
|
|
|
return false;
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
- ArrayBuffer * WebAssemblyArrayBuffer::TransferInternal(uint32 newBufferLength)
|
|
|
+ WebAssemblyArrayBuffer* WebAssemblyArrayBuffer::GrowMemory(uint32 newBufferLength)
|
|
|
{
|
|
|
-#if ENABLE_FAST_ARRAYBUFFER
|
|
|
- ReportDifferentialAllocation(newBufferLength);
|
|
|
- Assert(this->buffer);
|
|
|
+ if (newBufferLength <= this->bufferLength)
|
|
|
+ {
|
|
|
+ JavascriptError::ThrowTypeError(GetScriptContext(), WASMERR_BufferGrowOnly);
|
|
|
+ }
|
|
|
|
|
|
- AssertMsg(newBufferLength > this->bufferLength, "The only supported scenario in WebAssembly is to grow the memory");
|
|
|
- if (newBufferLength > this->bufferLength)
|
|
|
+ WebAssemblyArrayBuffer* newArrayBuffer = nullptr;
|
|
|
+#if ENABLE_FAST_ARRAYBUFFER
|
|
|
+ if (CONFIG_FLAG(WasmFastArray))
|
|
|
{
|
|
|
+ ReportDifferentialAllocation(newBufferLength);
|
|
|
+ AssertOrFailFast(this->buffer);
|
|
|
+
|
|
|
LPVOID newMem = VirtualAlloc(this->buffer + this->bufferLength, newBufferLength - this->bufferLength, MEM_COMMIT, PAGE_READWRITE);
|
|
|
if (!newMem)
|
|
|
{
|
|
|
@@ -1020,16 +1044,43 @@ namespace Js
|
|
|
recycler->ReportExternalMemoryFailure(newBufferLength);
|
|
|
JavascriptError::ThrowOutOfMemoryError(GetScriptContext());
|
|
|
}
|
|
|
+ newArrayBuffer = GetLibrary()->CreateWebAssemblyArrayBuffer(this->buffer, newBufferLength);
|
|
|
+ }
|
|
|
+ else
|
|
|
+#endif
|
|
|
+ if (this->GetByteLength() == 0)
|
|
|
+ {
|
|
|
+ newArrayBuffer = GetLibrary()->CreateWebAssemblyArrayBuffer(newBufferLength);
|
|
|
+ if (!newArrayBuffer->GetByteLength())
|
|
|
+ {
|
|
|
+ JavascriptError::ThrowOutOfMemoryError(GetScriptContext());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ ReportDifferentialAllocation(newBufferLength);
|
|
|
+ byte* newBuffer = ReallocZero(this->buffer, this->bufferLength, newBufferLength);
|
|
|
+ if (!newBuffer)
|
|
|
+ {
|
|
|
+ this->GetRecycler()->ReportExternalMemoryFailure(newBufferLength - this->bufferLength);
|
|
|
+ JavascriptError::ThrowOutOfMemoryError(GetScriptContext());
|
|
|
+ }
|
|
|
+ newArrayBuffer = GetLibrary()->CreateWebAssemblyArrayBuffer(newBuffer, newBufferLength);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!newArrayBuffer)
|
|
|
+ {
|
|
|
+ JavascriptError::ThrowOutOfMemoryError(GetScriptContext());
|
|
|
}
|
|
|
- ArrayBuffer* newArrayBuffer = GetLibrary()->CreateWebAssemblyArrayBuffer(this->buffer, newBufferLength);
|
|
|
|
|
|
AutoDiscardPTR<Js::ArrayBufferDetachedStateBase> state(DetachAndGetState());
|
|
|
state->MarkAsClaimed();
|
|
|
-
|
|
|
return newArrayBuffer;
|
|
|
-#else
|
|
|
- return JavascriptArrayBuffer::TransferInternal(newBufferLength);
|
|
|
-#endif
|
|
|
+ }
|
|
|
+
|
|
|
+ ArrayBuffer * WebAssemblyArrayBuffer::TransferInternal(uint32 newBufferLength)
|
|
|
+ {
|
|
|
+ JavascriptError::ThrowTypeError(GetScriptContext(), WASMERR_CantDetach);
|
|
|
}
|
|
|
|
|
|
ProjectionArrayBuffer::ProjectionArrayBuffer(uint32 length, DynamicType * type) :
|