Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/Backend/AsmJsJITInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ AsmJsJITInfo::GetWasmSignatureAddr(uint index) const
Assert(index < m_data.wasmSignatureCount);
return m_data.wasmSignaturesBaseAddr + index * sizeof(Wasm::WasmSignature);
}

bool AsmJsJITInfo::IsSharedMemory() const
{
return !!m_data.wasmIsSharedMemory;
}

#endif

bool
Expand Down
1 change: 1 addition & 0 deletions lib/Backend/AsmJsJITInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class AsmJsJITInfo
#ifdef ENABLE_WASM
Wasm::WasmSignature * GetWasmSignature(uint index) const;
intptr_t GetWasmSignatureAddr(uint index) const;
bool IsSharedMemory() const;
#endif

bool UsesHeapBuffer() const;
Expand Down
29 changes: 27 additions & 2 deletions lib/Backend/IRBuilderAsmJs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,9 @@ IRBuilderAsmJs::CreateRelocRecord(IR::BranchInstr * branchInstr, uint32 offset,
void
IRBuilderAsmJs::BuildHeapBufferReload(uint32 offset)
{
IR::RegOpnd* bufferInfoSrc = nullptr;
int bufferOffset = 0;
int bufferLengthOffset = 0;

#ifdef ENABLE_WASM
if(m_func->GetJITFunctionBody()->IsWasmFunction())
Expand All @@ -717,6 +720,21 @@ IRBuilderAsmJs::BuildHeapBufferReload(uint32 offset)
srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::WasmMemoryReg, TyVar), Js::WebAssemblyMemory::GetOffsetOfArrayBuffer(), TyVar, m_func);
instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
AddInstr(instr, offset);

#ifdef ENABLE_WASM_THREADS
if (m_func->GetJITFunctionBody()->GetAsmJsInfo()->IsSharedMemory())
{
// SharedContents
dstOpnd = BuildDstOpnd(AsmJsRegSlots::SharedContents, TyVar);
srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar), Js::SharedArrayBuffer::GetSharedContentsOffset(), TyVar, m_func);
instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
AddInstr(instr, offset);

bufferInfoSrc = BuildSrcOpnd(AsmJsRegSlots::SharedContents, TyVar);
bufferOffset = Js::SharedContents::GetBufferOffset();
bufferLengthOffset = Js::SharedContents::GetBufferLengthOffset();
}
#endif
}
else
#endif
Expand All @@ -727,15 +745,22 @@ IRBuilderAsmJs::BuildHeapBufferReload(uint32 offset)
IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
AddInstr(instr, offset);
}

if (!bufferInfoSrc)
{
bufferInfoSrc = BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar);
bufferOffset = Js::ArrayBuffer::GetBufferOffset();
bufferLengthOffset = Js::ArrayBuffer::GetByteLengthOffset();
}
// ArrayBuffer buffer
IR::RegOpnd * dstOpnd = BuildDstOpnd(AsmJsRegSlots::BufferReg, TyVar);
IR::Opnd * srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar), Js::ArrayBuffer::GetBufferOffset(), TyVar, m_func);
IR::Opnd * srcOpnd = IR::IndirOpnd::New(bufferInfoSrc, bufferOffset, TyVar, m_func);
IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
AddInstr(instr, offset);

// ArrayBuffer length
dstOpnd = BuildDstOpnd(AsmJsRegSlots::LengthReg, TyUint32);
srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar), Js::ArrayBuffer::GetByteLengthOffset(), TyUint32, m_func);
srcOpnd = IR::IndirOpnd::New(bufferInfoSrc, bufferLengthOffset, TyUint32, m_func);
instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
AddInstr(instr, offset);
}
Expand Down
1 change: 1 addition & 0 deletions lib/Backend/IRBuilderAsmJs.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace AsmJsRegSlots
WasmMemoryReg,
BufferReg,
LengthReg,
SharedContents,
RegCount
};
};
Expand Down
5 changes: 5 additions & 0 deletions lib/Backend/JITTimeFunctionBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,11 @@ JITTimeFunctionBody::InitializeJITFunctionData(
#ifdef ENABLE_WASM
if (functionBody->IsWasmFunction())
{
#ifdef ENABLE_WASM_THREADS
jitBody->asmJsData->wasmIsSharedMemory = asmFuncInfo->GetWebAssemblyModule()->IsSharedMemory();
#else
jitBody->asmJsData->wasmIsSharedMemory = false;
#endif
jitBody->asmJsData->wasmSignatureCount = asmFuncInfo->GetWebAssemblyModule()->GetSignatureCount();
jitBody->asmJsData->wasmSignaturesBaseAddr = (intptr_t)asmFuncInfo->GetWebAssemblyModule()->GetSignatures();
jitBody->asmJsData->wasmSignatures = (WasmSignatureIDL*)asmFuncInfo->GetWebAssemblyModule()->GetSignatures();
Expand Down
1 change: 1 addition & 0 deletions lib/Common/CommonDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,7 @@

#if defined(ASMJS_PLAT)
#define ENABLE_WASM
#define ENABLE_WASM_THREADS
#define ENABLE_WASM_SIMD

#ifdef CAN_BUILD_WABT
Expand Down
2 changes: 2 additions & 0 deletions lib/Common/ConfigFlagsList.h
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ PHASE(All)
#else
#define DEFAULT_CONFIG_WasmFastArray (false)
#endif
#define DEFAULT_CONFIG_WasmSharedArrayVirtualBuffer (true)
#define DEFAULT_CONFIG_WasmCheckVersion (true)
#define DEFAULT_CONFIG_WasmIgnoreLimits (false)
#define DEFAULT_CONFIG_WasmFold (true)
Expand Down Expand Up @@ -893,6 +894,7 @@ FLAGNR(Boolean, AsmJsEdge , "Enable asm.js features which may have b
FLAGNR(Boolean, Wasm , "Enable WebAssembly", DEFAULT_CONFIG_Wasm)
FLAGNR(Boolean, WasmI64 , "Enable Int64 testing for WebAssembly. ArgIns can be [number,string,{low:number,high:number}]. Return values will be {low:number,high:number}", DEFAULT_CONFIG_WasmI64)
FLAGNR(Boolean, WasmFastArray , "Enable fast array implementation for WebAssembly", DEFAULT_CONFIG_WasmFastArray)
FLAGNR(Boolean, WasmSharedArrayVirtualBuffer, "Use Virtual allocation for WebAssemblySharedArrayBuffer (Windows only)", DEFAULT_CONFIG_WasmSharedArrayVirtualBuffer)
FLAGNR(Boolean, WasmMathExFilter , "Enable Math exception filter for WebAssembly", DEFAULT_CONFIG_WasmMathExFilter)
FLAGNR(Boolean, WasmCheckVersion , "Check the binary version for WebAssembly", DEFAULT_CONFIG_WasmCheckVersion)
FLAGNR(Boolean, WasmIgnoreLimits , "Ignore the WebAssembly binary limits ", DEFAULT_CONFIG_WasmIgnoreLimits)
Expand Down
2 changes: 1 addition & 1 deletion lib/JITIDL/JITTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ typedef struct TypedSlotInfo
typedef struct AsmJsDataIDL
{
boolean usesHeapBuffer;
IDL_PAD1(0)
boolean wasmIsSharedMemory;
unsigned short argByteSize;
unsigned short argCount;
IDL_PAD2(1)
Expand Down
6 changes: 4 additions & 2 deletions lib/Parser/rterrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -403,8 +403,10 @@ RT_ERROR_MSG(WASMERR_NeedInstanceObject, 7025, "%s is not a WebAssembly.Instance
RT_ERROR_MSG(WASMERR_InvalidImportModule, 7026, "Import module '%s' is invalid", "Import module is invalid", kjstTypeError, 0)
RT_ERROR_MSG(WASMERR_InvalidImport, 7027, "Import '%s.%s' is invalid. Expected type %s", "Import is invalid", kjstTypeError, 0)
RT_ERROR_MSG(WASMERR_InvalidInitialSize, 7028, "Imported %s initial size (%u) is smaller than declared (%u)", "Invalid initial size", kjstWebAssemblyLinkError, 0)
RT_ERROR_MSG(WASMERR_InvalidMaximumSize, 7029, "Imported %s maximum size (%u) is larger than declared (%u)", "Invalid initial size", kjstWebAssemblyLinkError, 0)
RT_ERROR_MSG(WASMERR_UnalignedAtomicAccess, 7030, "", "Atomic memory access is unaligned", kjstWebAssemblyRuntimeError, 0)
RT_ERROR_MSG(WASMERR_InvalidMaximumSize, 7029, "Imported %s maximum size (%u) is larger than declared (%u)", "Invalid maximum size", kjstWebAssemblyLinkError, 0)
RT_ERROR_MSG(WASMERR_InvalidMemoryType, 7030, "Imported %s type is %s, expected %s", "Invalid memory type", kjstWebAssemblyLinkError, 0)
RT_ERROR_MSG(WASMERR_UnalignedAtomicAccess, 7031, "", "Atomic memory access is unaligned", kjstWebAssemblyRuntimeError, 0)
RT_ERROR_MSG(WASMERR_SharedNoMaximum, 7032, "", "Shared memory must have a maximum size", kjstTypeError, 0)

// Wabt Errors
RT_ERROR_MSG(WABTERR_WabtError, 7200, "%s", "Wabt Error.", kjstTypeError, 0)
1 change: 1 addition & 0 deletions lib/Runtime/Base/JnDirectFields.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ ENTRY(imports)
ENTRY(customSections)
ENTRY(initial)
ENTRY(maximum)
ENTRY(shared)
ENTRY(element)
ENTRY(low)
ENTRY(high)
Expand Down
4 changes: 2 additions & 2 deletions lib/Runtime/ByteCode/ByteCodeCacheReleaseFileVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
//-------------------------------------------------------------------------------------------------------
// NOTE: If there is a merge conflict the correct fix is to make a new GUID.

// {552D65CC-09D7-4FCE-A631-C46FDF7F4A0A}
// {790F966D-646F-4CBF-86C2-6C8FECA645EA}
const GUID byteCodeCacheReleaseFileVersion =
{ 0x552D65CC, 0x09D7, 0x4FCE, { 0xA6, 0x31, 0xC4, 0x6F, 0xDF, 0x7F, 0x4A, 0x0A } };
{ 0x790F966D, 0x646F, 0x4CBF, { 0x86, 0xC2, 0x6C, 0x8F, 0xEC, 0xA6, 0x45, 0xEA } };
16 changes: 8 additions & 8 deletions lib/Runtime/Language/InterpreterStackFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7879,7 +7879,7 @@ const byte * InterpreterStackFrame::OP_ProfiledLoopBodyStart(uint loopId)
Assert(playout->ViewType < Js::ArrayBufferView::TYPE_COUNT);
const uint64 index = ((uint64)(uint32)GetRegRawInt(playout->SlotIndex) + playout->Offset /* WASM only */) & (int64)(int)ArrayBufferView::ViewMask[playout->ViewType];

JavascriptArrayBuffer* arr =
ArrayBufferBase* arr =
#ifdef ENABLE_WASM_SIMD
(m_functionBody->IsWasmFunction()) ?
m_wasmMemory->GetBuffer() :
Expand Down Expand Up @@ -7927,7 +7927,7 @@ const byte * InterpreterStackFrame::OP_ProfiledLoopBodyStart(uint loopId)
Assert(playout->ViewType < Js::ArrayBufferView::TYPE_COUNT);
const uint64 index = ((uint64)(uint32)GetRegRawInt(playout->SlotIndex) + playout->Offset /* WASM only */) & (int64)(int)ArrayBufferView::ViewMask[playout->ViewType];

JavascriptArrayBuffer* arr =
ArrayBufferBase* arr =
#ifdef ENABLE_WASM_SIMD
(m_functionBody->IsWasmFunction()) ?
m_wasmMemory->GetBuffer() :
Expand Down Expand Up @@ -8602,7 +8602,7 @@ const byte * InterpreterStackFrame::OP_ProfiledLoopBodyStart(uint loopId)
#ifdef ENABLE_WASM
Assert(playout->ViewType < Js::ArrayBufferView::TYPE_COUNT);
const uint64 index = playout->Offset + (uint64)(uint32)GetRegRawInt(playout->SlotIndex);
WebAssemblyArrayBuffer* arr = GetWebAssemblyMemory()->GetBuffer();
ArrayBufferBase* arr = GetWebAssemblyMemory()->GetBuffer();

uint32 byteLength = arr->GetByteLength();
BYTE* buffer = arr->GetBuffer();
Expand All @@ -8625,10 +8625,10 @@ const byte * InterpreterStackFrame::OP_ProfiledLoopBodyStart(uint loopId)
void InterpreterStackFrame::OP_LdArrAtomic(const unaligned T* playout)
{
#ifdef ENABLE_WASM
Assert(CONFIG_FLAG(WasmThreads));
Assert(Wasm::Threads::IsEnabled());
Assert(playout->ViewType < Js::ArrayBufferView::TYPE_COUNT);
const uint64 index = playout->Offset + (uint64)(uint32)GetRegRawInt(playout->SlotIndex);
WebAssemblyArrayBuffer* arr = GetWebAssemblyMemory()->GetBuffer();
ArrayBufferBase* arr = GetWebAssemblyMemory()->GetBuffer();

uint32 byteLength = arr->GetByteLength();
BYTE* buffer = arr->GetBuffer();
Expand All @@ -8653,10 +8653,10 @@ const byte * InterpreterStackFrame::OP_ProfiledLoopBodyStart(uint loopId)
void InterpreterStackFrame::OP_StArrAtomic(const unaligned T* playout)
{
#ifdef ENABLE_WASM
Assert(CONFIG_FLAG(WasmThreads));
Assert(Wasm::Threads::IsEnabled());
Assert(playout->ViewType < Js::ArrayBufferView::TYPE_COUNT);
const uint64 index = playout->Offset + (uint64)(uint32)GetRegRawInt(playout->SlotIndex);
WebAssemblyArrayBuffer* arr = GetWebAssemblyMemory()->GetBuffer();
ArrayBufferBase* arr = GetWebAssemblyMemory()->GetBuffer();

uint32 byteLength = arr->GetByteLength();
BYTE* buffer = arr->GetBuffer();
Expand Down Expand Up @@ -8711,7 +8711,7 @@ const byte * InterpreterStackFrame::OP_ProfiledLoopBodyStart(uint loopId)
#ifdef ENABLE_WASM
Assert(playout->ViewType < Js::ArrayBufferView::TYPE_COUNT);
const uint64 index = playout->Offset + (uint64)(uint32)GetRegRawInt(playout->SlotIndex);
WebAssemblyArrayBuffer* arr = GetWebAssemblyMemory()->GetBuffer();
ArrayBufferBase* arr = GetWebAssemblyMemory()->GetBuffer();

uint32 byteLength = arr->GetByteLength();
BYTE* buffer = arr->GetBuffer();
Expand Down
23 changes: 12 additions & 11 deletions lib/Runtime/Library/ArrayBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -804,17 +804,6 @@ namespace Js
/* See JavascriptArrayBuffer::Finalize */
}

// Same as realloc but zero newly allocated portion if newSize > oldSize
static BYTE* ReallocZero(BYTE* ptr, size_t oldSize, size_t newSize)
{
BYTE* ptrNew = (BYTE*)realloc(ptr, newSize);
if (ptrNew && newSize > oldSize)
{
ZeroMemory(ptrNew + oldSize, newSize - oldSize);
}
return ptrNew;
}

#if ENABLE_TTD
TTD::NSSnapObjects::SnapObjectType JavascriptArrayBuffer::GetSnapTag_TTD() const
{
Expand All @@ -840,6 +829,17 @@ namespace Js
}
#endif

#ifdef ENABLE_WASM
// Same as realloc but zero newly allocated portion if newSize > oldSize
static BYTE* ReallocZero(BYTE* ptr, size_t oldSize, size_t newSize)
{
BYTE* ptrNew = (BYTE*)realloc(ptr, newSize);
if (ptrNew && newSize > oldSize)
{
ZeroMemory(ptrNew + oldSize, newSize - oldSize);
}
return ptrNew;
}

template<typename Allocator>
Js::WebAssemblyArrayBuffer::WebAssemblyArrayBuffer(uint32 length, DynamicType * type, Allocator allocator):
Expand Down Expand Up @@ -996,6 +996,7 @@ namespace Js
return newArrayBuffer;
}
}
#endif

ProjectionArrayBuffer::ProjectionArrayBuffer(uint32 length, DynamicType * type) :
ArrayBuffer(length, type, CoTaskMemAlloc)
Expand Down
29 changes: 22 additions & 7 deletions lib/Runtime/Library/ArrayBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Js
class ArrayBufferParent;
class ArrayBuffer;
class SharedArrayBuffer;

class ArrayBufferBase : public DynamicObject
{
protected:
Expand All @@ -20,8 +21,17 @@ namespace Js
typedef void*(*AllocWrapperType)(size_t);
#define AsmJsVirtualAllocator ((AllocWrapperType)Js::ArrayBuffer::AllocWrapper<MAX_ASMJS_ARRAYBUFFER_LENGTH>)
#define WasmVirtualAllocator ((AllocWrapperType)Js::ArrayBuffer::AllocWrapper<MAX_WASM__ARRAYBUFFER_LENGTH>)
template<size_t MaxVirtualSize = MAX_ASMJS_ARRAYBUFFER_LENGTH>
static void* __cdecl AllocWrapper(DECLSPEC_GUARD_OVERFLOW size_t length)
#else
#define AsmJsVirtualAllocator Js::ArrayBuffer::BadAllocCall
#define WasmVirtualAllocator Js::ArrayBuffer::BadAllocCall
static void* __cdecl BadAllocCall(DECLSPEC_GUARD_OVERFLOW size_t length)
{
// This allocator should never be used
Js::Throw::FatalInternalError();
}
#endif
#ifdef _WIN32
static void* __cdecl AllocWrapper(DECLSPEC_GUARD_OVERFLOW size_t length, size_t MaxVirtualSize)
{
LPVOID address = VirtualAlloc(nullptr, MaxVirtualSize, MEM_RESERVE, PAGE_NOACCESS);
//throw out of memory
Expand All @@ -43,20 +53,23 @@ namespace Js
}
return arrayAddress;
}
template<size_t MaxVirtualSize>
static void* __cdecl AllocWrapper(DECLSPEC_GUARD_OVERFLOW size_t length)
{
return AllocWrapper(length, MaxVirtualSize);
}

static void FreeMemAlloc(Var ptr)
{
BOOL fSuccess = VirtualFree((LPVOID)ptr, 0, MEM_RELEASE);
Assert(fSuccess);
}
#else
static void* __cdecl AllocWrapper(DECLSPEC_GUARD_OVERFLOW size_t length)
static void FreeMemAlloc(Var ptr)
{
// This allocator should never be used
// This free function should never be used
Js::Throw::FatalInternalError();
}
#define AsmJsVirtualAllocator Js::ArrayBuffer::AllocWrapper
#define WasmVirtualAllocator Js::ArrayBuffer::AllocWrapper
#endif
public:
DEFINE_VTABLE_CTOR_ABSTRACT(ArrayBufferBase, DynamicObject);
Expand Down Expand Up @@ -271,6 +284,7 @@ namespace Js
#endif
};

#ifdef ENABLE_WASM
class WebAssemblyArrayBuffer : public JavascriptArrayBuffer
{
template<typename Allocator>
Expand All @@ -282,14 +296,15 @@ namespace Js
DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(WebAssemblyArrayBuffer);
public:
static WebAssemblyArrayBuffer* Create(byte* buffer, DECLSPEC_GUARD_OVERFLOW uint32 length, DynamicType * type);
WebAssemblyArrayBuffer* GrowMemory(DECLSPEC_GUARD_OVERFLOW uint32 newBufferLength);
WebAssemblyArrayBuffer* GrowMemory(uint32 newBufferLength);

virtual bool IsValidVirtualBufferLength(uint length) const override;
virtual bool IsWebAssemblyArrayBuffer() override { return true; }

protected:
virtual ArrayBufferDetachedStateBase* CreateDetachedState(BYTE* buffer, DECLSPEC_GUARD_OVERFLOW uint32 bufferLength) override;
};
#endif

// the memory must be allocated via CoTaskMemAlloc.
class ProjectionArrayBuffer : public ArrayBuffer
Expand Down
6 changes: 1 addition & 5 deletions lib/Runtime/Library/AtomicsObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,7 @@ namespace Js

TypedArrayBase *typedArrayBase = TypedArrayBase::UnsafeFromVar(typedArray);
ArrayBufferBase* arrayBuffer = typedArrayBase->GetArrayBuffer();

// todo:: Allow WebAssemblySharedArrayBuffer
// Since WebAssemblySharedArrayBuffer can be detached (through grow_memory), we need to revalidate the buffer
// after JavascriptConversion on index and values, because {valueOf} can detach the buffer
if (arrayBuffer == nullptr || !ArrayBufferBase::Is(arrayBuffer) || !arrayBuffer->IsSharedArrayBuffer() || arrayBuffer->IsWebAssemblyArrayBuffer())
if (arrayBuffer == nullptr || !ArrayBufferBase::Is(arrayBuffer) || !arrayBuffer->IsSharedArrayBuffer())
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedSharedArrayBufferObject);
}
Expand Down
Loading