_Must_inspect_result_ bool WebAssemblySharedArrayBuffer::GrowMemory(uint32 newBufferLength) { uint32 bufferLength = sharedContents->bufferLength; BYTE* buffer = sharedContents->buffer; if (newBufferLength < bufferLength || newBufferLength > sharedContents->maxBufferLength) { AssertMsg(newBufferLength <= sharedContents->maxBufferLength, "This shouldn't happen"); Assert(UNREACHED); JavascriptError::ThrowTypeError(GetScriptContext(), WASMERR_BufferGrowOnly); } uint32 growSize = newBufferLength - bufferLength; // We're not growing the buffer, do nothing if (growSize == 0) { return true; } AssertOrFailFast(buffer); if (IsValidVirtualBufferLength(newBufferLength)) { auto virtualAllocFunc = [=] { return !!VirtualAlloc(buffer + bufferLength, growSize, MEM_COMMIT, PAGE_READWRITE); }; if (!this->GetRecycler()->DoExternalAllocation(growSize, virtualAllocFunc)) { return false; } this->GetRecycler()->AddExternalMemoryUsage(growSize); } else { // We have already allocated maxLength in the heap if we're not using virtual alloc } ZeroMemory(buffer + bufferLength, growSize); sharedContents->bufferLength = newBufferLength; ValidateBuffer(); return true; }
void WebAssemblySharedArrayBuffer::FreeBuffer(BYTE* buffer, uint32 length, uint32 maxLength) { if (IsValidVirtualBufferLength(length)) { FreeMemAlloc(buffer); } else { HeapDeleteArray(maxLength, buffer); AssertOrFailFast(maxLength >= length); // JavascriptSharedArrayBuffer::Finalize will only report freeing `length`, we have to take care of the balance uint32 additionalSize = maxLength - length; if (additionalSize > 0) { Recycler* recycler = GetType()->GetLibrary()->GetRecycler(); recycler->ReportExternalMemoryFree(additionalSize); } } }
void JavascriptSharedArrayBuffer::Finalize(bool isShutdown) { if (sharedContents == nullptr) { return; } uint ref = InterlockedDecrement(&sharedContents->refCount); if (ref == 0) { #if _WIN64 //AsmJS Virtual Free //TOD - see if isBufferCleared need to be added for free too if (IsValidVirtualBufferLength(sharedContents->bufferLength) && !sharedContents->isBufferCleared) { LPVOID startBuffer = (LPVOID)((uint64)sharedContents->buffer); BOOL fSuccess = VirtualFree((LPVOID)startBuffer, 0, MEM_RELEASE); Assert(fSuccess); sharedContents->isBufferCleared = true; } else { free(sharedContents->buffer); } #else free(sharedContents->buffer); #endif Recycler* recycler = GetType()->GetLibrary()->GetRecycler(); recycler->ReportExternalMemoryFree(sharedContents->bufferLength); sharedContents->Cleanup(); HeapDelete(sharedContents); } sharedContents = nullptr; }
JavascriptSharedArrayBuffer::JavascriptSharedArrayBuffer(uint32 length, DynamicType * type) : SharedArrayBuffer(length, type, (IsValidVirtualBufferLength(length)) ? AllocWrapper : malloc) { }