| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "RuntimeLibraryPch.h"
- #ifdef ENABLE_WASM
- namespace Js
- {
- WebAssemblyMemory::WebAssemblyMemory(WebAssemblyArrayBuffer* buffer, uint32 initial, uint32 maximum, DynamicType * type) :
- DynamicObject(type),
- m_buffer(buffer),
- m_initial(initial),
- m_maximum(maximum)
- {
- }
- /* static */
- bool
- WebAssemblyMemory::Is(Var value)
- {
- return JavascriptOperators::GetTypeId(value) == TypeIds_WebAssemblyMemory;
- }
- /* static */
- WebAssemblyMemory *
- WebAssemblyMemory::FromVar(Var value)
- {
- Assert(WebAssemblyMemory::Is(value));
- return static_cast<WebAssemblyMemory*>(value);
- }
- Var
- WebAssemblyMemory::NewInstance(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
- Var newTarget = callInfo.Flags & CallFlags_NewTarget ? args.Values[args.Info.Count] : args[0];
- bool isCtorSuperCall = (callInfo.Flags & CallFlags_New) && newTarget != nullptr && !JavascriptOperators::IsUndefined(newTarget);
- Assert(isCtorSuperCall || !(callInfo.Flags & CallFlags_New) || args[0] == nullptr);
- if (!(callInfo.Flags & CallFlags_New) || (newTarget && JavascriptOperators::IsUndefinedObject(newTarget)))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_ClassConstructorCannotBeCalledWithoutNew, _u("WebAssembly.Memory"));
- }
- if (args.Info.Count < 2 || !JavascriptOperators::IsObject(args[1]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedObject, _u("memoryDescriptor"));
- }
- DynamicObject * memoryDescriptor = JavascriptObject::FromVar(args[1]);
- Var initVar = JavascriptOperators::OP_GetProperty(memoryDescriptor, PropertyIds::initial, scriptContext);
- uint32 initial = WebAssembly::ToNonWrappingUint32(initVar, scriptContext);
- uint32 maximum = UINT_MAX;
- if (JavascriptOperators::OP_HasProperty(memoryDescriptor, PropertyIds::maximum, scriptContext))
- {
- Var maxVar = JavascriptOperators::OP_GetProperty(memoryDescriptor, PropertyIds::maximum, scriptContext);
- maximum = WebAssembly::ToNonWrappingUint32(maxVar, scriptContext);
- }
- return CreateMemoryObject(initial, maximum, scriptContext);
- }
- Var
- WebAssemblyMemory::EntryGrow(RecyclableObject* function, CallInfo callInfo, ...)
- {
- ScriptContext* scriptContext = function->GetScriptContext();
- PROBE_STACK(scriptContext, Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'");
- Assert(!(callInfo.Flags & CallFlags_New));
- if (!WebAssemblyMemory::Is(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, WASMERR_NeedMemoryObject);
- }
- WebAssemblyMemory* memory = WebAssemblyMemory::FromVar(args[0]);
- Assert(ArrayBuffer::Is(memory->m_buffer));
- if (memory->m_buffer->IsDetached())
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray);
- }
- Var deltaVar = scriptContext->GetLibrary()->GetUndefined();
- if (args.Info.Count >= 2)
- {
- deltaVar = args[1];
- }
- uint32 deltaPages = WebAssembly::ToNonWrappingUint32(deltaVar, scriptContext);
- int32 oldPageCount = memory->GrowInternal(deltaPages);
- if (oldPageCount == -1)
- {
- JavascriptError::ThrowRangeError(scriptContext, JSERR_ArgumentOutOfRange);
- }
- return JavascriptNumber::ToVar(oldPageCount, scriptContext);
- }
- int32
- WebAssemblyMemory::GrowInternal(uint32 deltaPages)
- {
- const uint64 deltaBytes = (uint64)deltaPages * WebAssembly::PageSize;
- if (deltaBytes > ArrayBuffer::MaxArrayBufferLength)
- {
- return -1;
- }
- const uint32 oldBytes = m_buffer->GetByteLength();
- const uint64 newBytesLong = deltaBytes + oldBytes;
- if (newBytesLong > ArrayBuffer::MaxArrayBufferLength)
- {
- return -1;
- }
- CompileAssert(ArrayBuffer::MaxArrayBufferLength <= UINT32_MAX);
- const uint32 newBytes = (uint32)newBytesLong;
- const uint32 oldPageCount = oldBytes / WebAssembly::PageSize;
- Assert(oldBytes % WebAssembly::PageSize == 0);
- if (deltaBytes == 0)
- {
- return (int32)oldPageCount;
- }
- const uint32 newPageCount = oldPageCount + deltaPages;
- if (newPageCount > m_maximum)
- {
- return -1;
- }
- WebAssemblyArrayBuffer * newBuffer = nullptr;
- JavascriptExceptionObject* caughtExceptionObject = nullptr;
- try
- {
- newBuffer = m_buffer->GrowMemory(newBytes);
- }
- catch (const JavascriptException& err)
- {
- caughtExceptionObject = err.GetAndClear();
- Assert(caughtExceptionObject && caughtExceptionObject == ThreadContext::GetContextForCurrentThread()->GetPendingOOMErrorObject());
- return -1;
- }
- AssertOrFailFast(newBuffer);
- m_buffer = newBuffer;
- CompileAssert(ArrayBuffer::MaxArrayBufferLength / WebAssembly::PageSize <= INT32_MAX);
- return (int32)oldPageCount;
- }
- int32
- WebAssemblyMemory::GrowHelper(WebAssemblyMemory * mem, uint32 deltaPages)
- {
- return mem->GrowInternal(deltaPages);
- }
- Var
- WebAssemblyMemory::EntryGetterBuffer(RecyclableObject* function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count == 0 || !WebAssemblyMemory::Is(args[0]))
- {
- JavascriptError::ThrowTypeError(scriptContext, WASMERR_NeedMemoryObject);
- }
- WebAssemblyMemory* memory = WebAssemblyMemory::FromVar(args[0]);
- Assert(ArrayBuffer::Is(memory->m_buffer));
- return memory->m_buffer;
- }
- WebAssemblyMemory *
- WebAssemblyMemory::CreateMemoryObject(uint32 initial, uint32 maximum, ScriptContext * scriptContext)
- {
- uint32 byteLength = UInt32Math::Mul<WebAssembly::PageSize>(initial);
- WebAssemblyArrayBuffer* buffer = scriptContext->GetLibrary()->CreateWebAssemblyArrayBuffer(byteLength);
- return RecyclerNewFinalized(scriptContext->GetRecycler(), WebAssemblyMemory, buffer, initial, maximum, scriptContext->GetLibrary()->GetWebAssemblyMemoryType());
- }
- WebAssemblyArrayBuffer*
- WebAssemblyMemory::GetBuffer() const
- {
- return m_buffer;
- }
- uint
- WebAssemblyMemory::GetInitialLength() const
- {
- return m_initial;
- }
- uint
- WebAssemblyMemory::GetMaximumLength() const
- {
- return m_maximum;
- }
- } // namespace Js
- #endif // ENABLE_WASM
|