Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix and enable wasm on xplat #4531

Merged
merged 5 commits into from
Jan 12, 2018
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 2 additions & 2 deletions lib/Backend/JnHelperMethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,10 +194,10 @@ DECLSPEC_GUARDIGNORE _NOINLINE intptr_t GetNonTableMethodAddress(ThreadContextI
return ShiftAddr(context, (void*(*)(void *, void const*, size_t))memcpy);

case HelperDirectMath_FloorFlt:
return ShiftAddr(context, (float(*)(float))floor);
return ShiftAddr(context, (float(*)(float))floorf);

case HelperDirectMath_CeilFlt:
return ShiftAddr(context, (float(*)(float))ceil);
return ShiftAddr(context, (float(*)(float))ceilf);

#if defined(_M_X64)
case HelperDirectMath_Acos:
Expand Down
3 changes: 0 additions & 3 deletions lib/Common/CommonDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -727,15 +727,12 @@
#endif

#if defined(ASMJS_PLAT)
// xplat-todo: once all the wasm tests are passing on xplat, enable it for release builds
#if defined(_WIN32) || (defined(__clang__) && defined(ENABLE_DEBUG_CONFIG_OPTIONS))
#define ENABLE_WASM

#ifdef CAN_BUILD_WABT
#define ENABLE_WABT
#endif

#endif
#endif

#if _M_IX86
Expand Down
5 changes: 0 additions & 5 deletions lib/Common/ConfigFlagsList.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,12 +393,7 @@ PHASE(All)
#endif
#endif // #ifdef ENABLE_SIMDJS

#ifdef _WIN32
#define DEFAULT_CONFIG_Wasm (true)
#else
// Do not enable wasm by default on xplat builds
#define DEFAULT_CONFIG_Wasm (false)
#endif
#define DEFAULT_CONFIG_WasmI64 (false)
#if ENABLE_FAST_ARRAYBUFFER
#define DEFAULT_CONFIG_WasmFastArray (true)
Expand Down
51 changes: 51 additions & 0 deletions lib/Common/Memory/HeapAllocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,57 @@ struct HeapAllocatorData

struct HeapAllocator
{
template<typename T>
struct AutoFree
{
private:
T * obj = nullptr;
public:
~AutoFree()
{
HeapDelete(obj);
}
void Replace(T* obj)
{
this->obj = obj;
}
void Release()
{
this->obj = nullptr;
}
T* Get() const
{
return this->obj;
}
};

template<typename T>
struct AutoFreeArray
{
private:
T* obj = nullptr;
size_t count = 0;
public:
~AutoFreeArray()
{
HeapDeleteArray(count, obj);
}
void Replace(__ecount(count) T* obj, size_t count)
{
this->obj = obj;
this->count = count;
}
void Release()
{
this->obj = nullptr;
this->count = 0;
}
T* Get() const
{
return this->obj;
}
};

static const bool FakeZeroLengthArray = false;

char * Alloc(DECLSPEC_GUARD_OVERFLOW size_t byteSize)
Expand Down
19 changes: 7 additions & 12 deletions lib/Runtime/Language/InterpreterStackFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3000,7 +3000,7 @@ namespace Js
// Move the arguments to the right location
ArgSlot argCount = info->GetArgCount();

#if _M_X64
#if _M_X64 && _WIN32
uint homingAreaSize = 0;
#endif

Expand All @@ -3019,7 +3019,7 @@ namespace Js
uintptr_t argAddress = (uintptr_t)m_inParams;
for (ArgSlot i = 0; i < argCount; i++)
{
#if _M_X64
#if _M_X64 && _WIN32
// 3rd Argument should be at the end of the homing area.
Assert(i != 3 || argAddress == (uintptr_t)m_inParams + homingAreaSize);
if (i < 3)
Expand All @@ -3040,12 +3040,7 @@ namespace Js
// IAT xmm2 spill
// IAT xmm1 spill <- floatSpillAddress for arg1

#ifdef _WIN32
#define FLOAT_SPILL_ADDRESS_OFFSET_WORDS 15
#else
// On Sys V x64 we have 4 words less (4 reg shadow)
#define FLOAT_SPILL_ADDRESS_OFFSET_WORDS 11
#endif
// floats are spilled as xmmwords
uintptr_t floatSpillAddress = (uintptr_t)m_inParams - MachPtr * (FLOAT_SPILL_ADDRESS_OFFSET_WORDS - 2*i);

Expand Down Expand Up @@ -3730,17 +3725,17 @@ namespace Js
AsmJsScriptFunction* scriptFunc = AsmJsScriptFunction::FromVar(function);
AsmJsFunctionInfo* asmInfo = scriptFunc->GetFunctionBody()->GetAsmJsFunctionInfo();
uint alignedArgsSize = ::Math::Align<uint32>(asmInfo->GetArgByteSize(), 16);
#if _M_X64
#if _M_X64 && _WIN32
// convention is to always allocate spill space for rcx,rdx,r8,r9
if (alignedArgsSize < 0x20) alignedArgsSize = 0x20;

// Prepare in advance the possible arguments that will need to be put in register
byte _declspec(align(16)) reg[3 * 16];
uint* argSizes = asmInfo->GetArgsSizesArray();
Assert(asmInfo->GetArgSizeArrayLength() >= 2);
CompileAssert((FunctionBody::MinAsmJsOutParams() * sizeof(Var)) == (sizeof(Var) * 2 + sizeof(reg)));
byte* curOutParams = (byte*)m_outParams + sizeof(Var);
Assert(curOutParams + argSizes[0] + argSizes[1] + 16 <= (byte*)this->m_outParamsEnd);

// Prepare in advance the possible arguments that will need to be put in register
byte _declspec(align(16)) reg[3 * 16];
CompileAssert((FunctionBody::MinAsmJsOutParams() * sizeof(Var)) == (sizeof(Var) * 2 + sizeof(reg)));
js_memcpy_s(reg, 16, curOutParams, 16);
js_memcpy_s(reg + 16, 16, curOutParams + argSizes[0], 16);
js_memcpy_s(reg + 32, 16, curOutParams + argSizes[0] + argSizes[1], 16);
Expand Down
78 changes: 0 additions & 78 deletions lib/Runtime/Language/amd64/amd64_Thunks.S
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,7 @@ NESTED_ENTRY _ZN2Js21InterpreterStackFrame33AsmJsDelayDynamicInterpreterThunkEPN
push r8
push r9

sub rsp, 40h

// spill potential floating point arguments to stack
movaps xmmword ptr [rsp + 00h], xmm0
movaps xmmword ptr [rsp + 10h], xmm1
movaps xmmword ptr [rsp + 20h], xmm2
movaps xmmword ptr [rsp + 30h], xmm3
call C_FUNC(_ZN2Js21InterpreterStackFrame29EnsureDynamicInterpreterThunkEPNS_14ScriptFunctionE)
// restore potential floating point arguments from stack
movaps xmm0, xmmword ptr [rsp + 00h]
movaps xmm1, xmmword ptr [rsp + 10h]
movaps xmm2, xmmword ptr [rsp + 20h]
movaps xmm3, xmmword ptr [rsp + 30h]

add rsp, 40h

pop r9
pop r8
Expand Down Expand Up @@ -190,13 +176,6 @@ NESTED_ENTRY _ZN2Js21InterpreterStackFrame19InterpreterAsmThunkEPNS_20AsmJsCallS

set_cfa_register rbp, (2*8) // Set to compute CFA as: rbp + 16 (sizeof: [rbp] [ReturnAddress])

sub rsp, 40h

// spill potential floating point arguments to stack
movaps xmmword ptr [rsp + 00h], xmm0
movaps xmmword ptr [rsp + 10h], xmm1
movaps xmmword ptr [rsp + 20h], xmm2
movaps xmmword ptr [rsp + 30h], xmm3

// save argument registers used by custom calling convention
push rdi
Expand All @@ -210,7 +189,6 @@ NESTED_ENTRY _ZN2Js21InterpreterStackFrame19InterpreterAsmThunkEPNS_20AsmJsCallS

call rax // call appropriate template

add rsp, 40h
pop_nonvol_reg rbp
ret
NESTED_END _ZN2Js21InterpreterStackFrame19InterpreterAsmThunkEPNS_20AsmJsCallStackLayoutE, _TEXT
Expand Down Expand Up @@ -260,64 +238,8 @@ NESTED_ENTRY _ZN2Js23AsmJsExternalEntryPointEPNS_16RecyclableObjectENS_8CallInfo
call C_FUNC(_ZN2Js19UnboxAsmJsArgumentsEPNS_14ScriptFunctionEPPvPcNS_8CallInfoE)
// rax = target function address

// move first 4 arguments into registers.
// don't know types other than arg0 (which is ScriptFunction *), so put in both xmm and general purpose registers
mov rdi, r12 // arg0: func

// int GetArgsSizesArray(ScriptFunction* func)
// get args sizes of target asmjs function
// rdi has ScriptFunction*
push r13
push rax
push rdi
sub rsp, 8h
call C_FUNC(_ZN2Js17GetArgsSizesArrayEPNS_14ScriptFunctionE)
mov r13, rax // r13: arg size
add rsp, 8h
pop rdi
pop rax

// NOTE: Below xmm usage is non-standard.

// Move 3 args to regs per convention. rdi already has first arg: ScriptFunction*
push r12
// r12->unboxed args
lea r12, [rsp + 18h] // rsp + size of(r12 + r13 + ScriptFunction*)

// r13 is arg size
cmp dword ptr [r13], 10h
je SIMDArg2
mov rsi, [r12] // arg1
movq xmm1, qword ptr [r12] // arg1
add r12, 8h
jmp Arg3
SIMDArg2:
movups xmm1, xmmword ptr[r12]
add r12, 10h
Arg3:
cmp dword ptr [r13 + 4h], 10h
je SIMDArg3
mov rdx, [r12] // arg2
movq xmm2, qword ptr [r12] // arg2
add r12, 8h
jmp Arg4
SIMDArg3:
movups xmm2, xmmword ptr[r12]
add r12, 10h
Arg4:
cmp dword ptr [r13 + 8h], 10h
je SIMDArg4
mov rcx, [r12] // arg3
movq xmm3, qword ptr [r12] // arg3
jmp ArgsDone
SIMDArg4:
movups xmm3, xmmword ptr [r12]

ArgsDone:
pop r12 // r12: func
pop r13 // r13: orig stack pointer

// "home" arg0. other args were read from stack and already homed.
mov [rsp + 00h], rdi

// call entry point
Expand Down
2 changes: 1 addition & 1 deletion lib/Runtime/Library/WasmLibrary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ Js::JavascriptMethod Js::WasmLibrary::WasmDeferredParseEntryPoint(Js::AsmJsScrip
}
catch (Wasm::WasmCompilationException& ex)
{
AutoCleanStr autoCleanExceptionMessage;
AutoFreeExceptionMessage autoCleanExceptionMessage;
char16* exceptionMessage = WebAssemblyModule::FormatExceptionMessage(&ex, &autoCleanExceptionMessage, readerInfo->m_module, body);

JavascriptLibrary *library = scriptContext->GetLibrary();
Expand Down
31 changes: 10 additions & 21 deletions lib/Runtime/Library/WebAssemblyModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ WebAssemblyModule::CreateModule(
Wasm::WasmReaderInfo * readerInfo = nullptr;
Js::FunctionBody * currentBody = nullptr;
char16* exceptionMessage = nullptr;
AutoCleanStr autoCleanExceptionMessage;
AutoFreeExceptionMessage autoCleanExceptionMessage;
try
{
Wasm::WasmModuleGenerator bytecodeGen(scriptContext, src);
Expand Down Expand Up @@ -827,42 +827,31 @@ WebAssemblyModule::GetModuleEnvironmentSize() const
return size;
}

char16* WebAssemblyModule::FormatExceptionMessage(Wasm::WasmCompilationException* ex, AutoCleanStr* autoClean, WebAssemblyModule* wasmModule, FunctionBody* body)
char16* WebAssemblyModule::FormatExceptionMessage(Wasm::WasmCompilationException* ex, AutoFreeExceptionMessage* autoFree, WebAssemblyModule* wasmModule, FunctionBody* body)
{
char16* originalExceptionMessage = ex->GetTempErrorMessageRef();
if (!wasmModule || !body)
{
size_t len = wcslen(originalExceptionMessage) + 1;
autoClean->str = new char16[len];
js_memcpy_s(autoClean->str, len * sizeof(char16), originalExceptionMessage, len * sizeof(char16));
return autoClean->str;
char16* buf = HeapNewArray(char16, len);
autoFree->Replace(buf, len);
js_memcpy_s(buf, len * sizeof(char16), originalExceptionMessage, len * sizeof(char16));
return buf;
}

Wasm::BinaryLocation location = wasmModule->GetReader()->GetCurrentLocation();

const char16* format = _u("function %s at offset %u/%u (0x%x/0x%x): %s");
const char16* funcName = body->GetDisplayName();
char16* buf = HeapNewArray(char16, 2048);
autoFree->Replace(buf, 2048);

uint size = (uint)_scwprintf(format,
_snwprintf_s(buf, 2048, _TRUNCATE, format,
funcName,
location.offset, location.size,
location.offset, location.size,
originalExceptionMessage);

if (size > 2048)
{
// Do not allocate too much for the exception message, just truncate the message past 2048 characters
size = 2047;
}
++size; // Null terminate character
autoClean->str = new char16[size];
int written = _snwprintf_s(autoClean->str, size, _TRUNCATE, format,
funcName,
location.offset, location.size,
location.offset, location.size,
originalExceptionMessage);
Assert((uint)written == size - 1);
return autoClean->str;
return buf;
}

void
Expand Down
13 changes: 2 additions & 11 deletions lib/Runtime/Library/WebAssemblyModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,7 @@ namespace Wasm

namespace Js
{

struct AutoCleanStr
{
char16* str = nullptr;
~AutoCleanStr()
{
delete[] str;
}
};

typedef HeapAllocator::AutoFreeArray<char16> AutoFreeExceptionMessage;

class WebAssemblyModule : public DynamicObject
{
Expand Down Expand Up @@ -160,7 +151,7 @@ class WebAssemblyModule : public DynamicObject

Wasm::WasmBinaryReader* GetReader() const { return m_reader; }

static char16* FormatExceptionMessage(Wasm::WasmCompilationException* ex, AutoCleanStr* autoClean, WebAssemblyModule* wasmModule = nullptr, FunctionBody* body = nullptr);
static char16* FormatExceptionMessage(Wasm::WasmCompilationException* ex, AutoFreeExceptionMessage* autoClean, WebAssemblyModule* wasmModule = nullptr, FunctionBody* body = nullptr);

virtual void Finalize(bool isShutdown) override;
virtual void Dispose(bool isShutdown) override;
Expand Down
12 changes: 0 additions & 12 deletions lib/Runtime/Library/amd64/JavascriptFunctionA.S
Original file line number Diff line number Diff line change
Expand Up @@ -141,19 +141,7 @@ NESTED_ENTRY _ZN2Js18JavascriptFunction17CallAsmJsFunctionIiEET_PNS_16Recyclable
mov rdi, rsp // rdi = arguments destination
rep movsq

// Load 4 first arguments
// First Argument
mov rdi, qword ptr [rsp]
// Review:: Is this really our calling convention on xplat ?
// Second Argument
mov rsi, qword ptr [r8]
movaps xmm1, xmmword ptr [r8]
// Third Argument
mov rdx, qword ptr [r8 + 10h]
movaps xmm2, xmmword ptr [r8 + 10h]
// Fourth Argument
mov rcx, qword ptr [r8 + 20h]
movaps xmm3, xmmword ptr [r8 + 20h]

xor rax, rax // Zero out rax in case r11 expects varags
call r11
Expand Down
2 changes: 2 additions & 0 deletions pal/inc/pal.h
Original file line number Diff line number Diff line change
Expand Up @@ -6358,7 +6358,9 @@ PALIMPORT double __cdecl tanh(double);
PALIMPORT double __cdecl fmod(double, double);
PALIMPORT float __cdecl fmodf(float, float);
PALIMPORT double __cdecl floor(double);
PALIMPORT float __cdecl floorf(float);
PALIMPORT double __cdecl ceil(double);
PALIMPORT float __cdecl ceilf(float);
PALIMPORT float __cdecl fabsf(float);
PALIMPORT double __cdecl modf(double, double *);
PALIMPORT float __cdecl modff(float, float *);
Expand Down
Loading