Skip to content

Commit b5cf4ec

Browse files
committed
[MERGE #4531 @MikeHolman] fix and enable wasm on xplat
Merge pull request #4531 from MikeHolman:fixwasmxplat fix issues with calling convention: we are using stack based calling convention, so we can cleanup a lot of code that was complicated by xmm registers. fix issue where JIT was calling wrong method for floorf and ceilf Resolves #3561
2 parents 6b6a96b + 0ab89e1 commit b5cf4ec

20 files changed

Lines changed: 120 additions & 200 deletions

lib/Backend/JnHelperMethod.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,10 @@ DECLSPEC_GUARDIGNORE _NOINLINE intptr_t GetNonTableMethodAddress(ThreadContextI
194194
return ShiftAddr(context, (void*(*)(void *, void const*, size_t))memcpy);
195195

196196
case HelperDirectMath_FloorFlt:
197-
return ShiftAddr(context, (float(*)(float))floor);
197+
return ShiftAddr(context, (float(*)(float))floorf);
198198

199199
case HelperDirectMath_CeilFlt:
200-
return ShiftAddr(context, (float(*)(float))ceil);
200+
return ShiftAddr(context, (float(*)(float))ceilf);
201201

202202
#if defined(_M_X64)
203203
case HelperDirectMath_Acos:

lib/Common/CommonDefines.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -727,15 +727,12 @@
727727
#endif
728728

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

734732
#ifdef CAN_BUILD_WABT
735733
#define ENABLE_WABT
736734
#endif
737735

738-
#endif
739736
#endif
740737

741738
#if _M_IX86

lib/Common/ConfigFlagsList.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -393,12 +393,7 @@ PHASE(All)
393393
#endif
394394
#endif // #ifdef ENABLE_SIMDJS
395395

396-
#ifdef _WIN32
397396
#define DEFAULT_CONFIG_Wasm (true)
398-
#else
399-
// Do not enable wasm by default on xplat builds
400-
#define DEFAULT_CONFIG_Wasm (false)
401-
#endif
402397
#define DEFAULT_CONFIG_WasmI64 (false)
403398
#if ENABLE_FAST_ARRAYBUFFER
404399
#define DEFAULT_CONFIG_WasmFastArray (true)

lib/Common/Memory/HeapAllocator.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,57 @@ struct HeapAllocatorData
9393

9494
struct HeapAllocator
9595
{
96+
template<typename T>
97+
struct AutoFree
98+
{
99+
private:
100+
T * obj = nullptr;
101+
public:
102+
~AutoFree()
103+
{
104+
HeapDelete(obj);
105+
}
106+
void Replace(T* obj)
107+
{
108+
this->obj = obj;
109+
}
110+
void Release()
111+
{
112+
this->obj = nullptr;
113+
}
114+
T* Get() const
115+
{
116+
return this->obj;
117+
}
118+
};
119+
120+
template<typename T>
121+
struct AutoFreeArray
122+
{
123+
private:
124+
T* obj = nullptr;
125+
size_t count = 0;
126+
public:
127+
~AutoFreeArray()
128+
{
129+
HeapDeleteArray(count, obj);
130+
}
131+
void Replace(__ecount(count) T* obj, size_t count)
132+
{
133+
this->obj = obj;
134+
this->count = count;
135+
}
136+
void Release()
137+
{
138+
this->obj = nullptr;
139+
this->count = 0;
140+
}
141+
T* Get() const
142+
{
143+
return this->obj;
144+
}
145+
};
146+
96147
static const bool FakeZeroLengthArray = false;
97148

98149
char * Alloc(DECLSPEC_GUARD_OVERFLOW size_t byteSize)

lib/Runtime/Language/InterpreterStackFrame.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3000,7 +3000,7 @@ namespace Js
30003000
// Move the arguments to the right location
30013001
ArgSlot argCount = info->GetArgCount();
30023002

3003-
#if _M_X64
3003+
#if _M_X64 && _WIN32
30043004
uint homingAreaSize = 0;
30053005
#endif
30063006

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

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

@@ -3730,17 +3725,17 @@ namespace Js
37303725
AsmJsScriptFunction* scriptFunc = AsmJsScriptFunction::FromVar(function);
37313726
AsmJsFunctionInfo* asmInfo = scriptFunc->GetFunctionBody()->GetAsmJsFunctionInfo();
37323727
uint alignedArgsSize = ::Math::Align<uint32>(asmInfo->GetArgByteSize(), 16);
3733-
#if _M_X64
3728+
#if _M_X64 && _WIN32
37343729
// convention is to always allocate spill space for rcx,rdx,r8,r9
37353730
if (alignedArgsSize < 0x20) alignedArgsSize = 0x20;
3736-
3737-
// Prepare in advance the possible arguments that will need to be put in register
3738-
byte _declspec(align(16)) reg[3 * 16];
37393731
uint* argSizes = asmInfo->GetArgsSizesArray();
37403732
Assert(asmInfo->GetArgSizeArrayLength() >= 2);
3741-
CompileAssert((FunctionBody::MinAsmJsOutParams() * sizeof(Var)) == (sizeof(Var) * 2 + sizeof(reg)));
37423733
byte* curOutParams = (byte*)m_outParams + sizeof(Var);
37433734
Assert(curOutParams + argSizes[0] + argSizes[1] + 16 <= (byte*)this->m_outParamsEnd);
3735+
3736+
// Prepare in advance the possible arguments that will need to be put in register
3737+
byte _declspec(align(16)) reg[3 * 16];
3738+
CompileAssert((FunctionBody::MinAsmJsOutParams() * sizeof(Var)) == (sizeof(Var) * 2 + sizeof(reg)));
37443739
js_memcpy_s(reg, 16, curOutParams, 16);
37453740
js_memcpy_s(reg + 16, 16, curOutParams + argSizes[0], 16);
37463741
js_memcpy_s(reg + 32, 16, curOutParams + argSizes[0] + argSizes[1], 16);

lib/Runtime/Language/amd64/amd64_Thunks.S

Lines changed: 0 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -62,21 +62,7 @@ NESTED_ENTRY _ZN2Js21InterpreterStackFrame33AsmJsDelayDynamicInterpreterThunkEPN
6262
push r8
6363
push r9
6464

65-
sub rsp, 40h
66-
67-
// spill potential floating point arguments to stack
68-
movaps xmmword ptr [rsp + 00h], xmm0
69-
movaps xmmword ptr [rsp + 10h], xmm1
70-
movaps xmmword ptr [rsp + 20h], xmm2
71-
movaps xmmword ptr [rsp + 30h], xmm3
7265
call C_FUNC(_ZN2Js21InterpreterStackFrame29EnsureDynamicInterpreterThunkEPNS_14ScriptFunctionE)
73-
// restore potential floating point arguments from stack
74-
movaps xmm0, xmmword ptr [rsp + 00h]
75-
movaps xmm1, xmmword ptr [rsp + 10h]
76-
movaps xmm2, xmmword ptr [rsp + 20h]
77-
movaps xmm3, xmmword ptr [rsp + 30h]
78-
79-
add rsp, 40h
8066

8167
pop r9
8268
pop r8
@@ -190,13 +176,6 @@ NESTED_ENTRY _ZN2Js21InterpreterStackFrame19InterpreterAsmThunkEPNS_20AsmJsCallS
190176

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

193-
sub rsp, 40h
194-
195-
// spill potential floating point arguments to stack
196-
movaps xmmword ptr [rsp + 00h], xmm0
197-
movaps xmmword ptr [rsp + 10h], xmm1
198-
movaps xmmword ptr [rsp + 20h], xmm2
199-
movaps xmmword ptr [rsp + 30h], xmm3
200179

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

211190
call rax // call appropriate template
212191

213-
add rsp, 40h
214192
pop_nonvol_reg rbp
215193
ret
216194
NESTED_END _ZN2Js21InterpreterStackFrame19InterpreterAsmThunkEPNS_20AsmJsCallStackLayoutE, _TEXT
@@ -260,64 +238,8 @@ NESTED_ENTRY _ZN2Js23AsmJsExternalEntryPointEPNS_16RecyclableObjectENS_8CallInfo
260238
call C_FUNC(_ZN2Js19UnboxAsmJsArgumentsEPNS_14ScriptFunctionEPPvPcNS_8CallInfoE)
261239
// rax = target function address
262240

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

267-
// int GetArgsSizesArray(ScriptFunction* func)
268-
// get args sizes of target asmjs function
269-
// rdi has ScriptFunction*
270-
push r13
271-
push rax
272-
push rdi
273-
sub rsp, 8h
274-
call C_FUNC(_ZN2Js17GetArgsSizesArrayEPNS_14ScriptFunctionE)
275-
mov r13, rax // r13: arg size
276-
add rsp, 8h
277-
pop rdi
278-
pop rax
279-
280-
// NOTE: Below xmm usage is non-standard.
281-
282-
// Move 3 args to regs per convention. rdi already has first arg: ScriptFunction*
283-
push r12
284-
// r12->unboxed args
285-
lea r12, [rsp + 18h] // rsp + size of(r12 + r13 + ScriptFunction*)
286-
287-
// r13 is arg size
288-
cmp dword ptr [r13], 10h
289-
je SIMDArg2
290-
mov rsi, [r12] // arg1
291-
movq xmm1, qword ptr [r12] // arg1
292-
add r12, 8h
293-
jmp Arg3
294-
SIMDArg2:
295-
movups xmm1, xmmword ptr[r12]
296-
add r12, 10h
297-
Arg3:
298-
cmp dword ptr [r13 + 4h], 10h
299-
je SIMDArg3
300-
mov rdx, [r12] // arg2
301-
movq xmm2, qword ptr [r12] // arg2
302-
add r12, 8h
303-
jmp Arg4
304-
SIMDArg3:
305-
movups xmm2, xmmword ptr[r12]
306-
add r12, 10h
307-
Arg4:
308-
cmp dword ptr [r13 + 8h], 10h
309-
je SIMDArg4
310-
mov rcx, [r12] // arg3
311-
movq xmm3, qword ptr [r12] // arg3
312-
jmp ArgsDone
313-
SIMDArg4:
314-
movups xmm3, xmmword ptr [r12]
315-
316-
ArgsDone:
317-
pop r12 // r12: func
318-
pop r13 // r13: orig stack pointer
319-
320-
// "home" arg0. other args were read from stack and already homed.
321243
mov [rsp + 00h], rdi
322244

323245
// call entry point

lib/Runtime/Library/WasmLibrary.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ Js::JavascriptMethod Js::WasmLibrary::WasmDeferredParseEntryPoint(Js::AsmJsScrip
107107
}
108108
catch (Wasm::WasmCompilationException& ex)
109109
{
110-
AutoCleanStr autoCleanExceptionMessage;
110+
AutoFreeExceptionMessage autoCleanExceptionMessage;
111111
char16* exceptionMessage = WebAssemblyModule::FormatExceptionMessage(&ex, &autoCleanExceptionMessage, readerInfo->m_module, body);
112112

113113
JavascriptLibrary *library = scriptContext->GetLibrary();

lib/Runtime/Library/WebAssemblyModule.cpp

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ WebAssemblyModule::CreateModule(
227227
Wasm::WasmReaderInfo * readerInfo = nullptr;
228228
Js::FunctionBody * currentBody = nullptr;
229229
char16* exceptionMessage = nullptr;
230-
AutoCleanStr autoCleanExceptionMessage;
230+
AutoFreeExceptionMessage autoCleanExceptionMessage;
231231
try
232232
{
233233
Wasm::WasmModuleGenerator bytecodeGen(scriptContext, src);
@@ -827,42 +827,31 @@ WebAssemblyModule::GetModuleEnvironmentSize() const
827827
return size;
828828
}
829829

830-
char16* WebAssemblyModule::FormatExceptionMessage(Wasm::WasmCompilationException* ex, AutoCleanStr* autoClean, WebAssemblyModule* wasmModule, FunctionBody* body)
830+
char16* WebAssemblyModule::FormatExceptionMessage(Wasm::WasmCompilationException* ex, AutoFreeExceptionMessage* autoFree, WebAssemblyModule* wasmModule, FunctionBody* body)
831831
{
832832
char16* originalExceptionMessage = ex->GetTempErrorMessageRef();
833833
if (!wasmModule || !body)
834834
{
835835
size_t len = wcslen(originalExceptionMessage) + 1;
836-
autoClean->str = new char16[len];
837-
js_memcpy_s(autoClean->str, len * sizeof(char16), originalExceptionMessage, len * sizeof(char16));
838-
return autoClean->str;
836+
char16* buf = HeapNewArray(char16, len);
837+
autoFree->Replace(buf, len);
838+
js_memcpy_s(buf, len * sizeof(char16), originalExceptionMessage, len * sizeof(char16));
839+
return buf;
839840
}
840841

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

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

846-
uint size = (uint)_scwprintf(format,
849+
_snwprintf_s(buf, 2048, _TRUNCATE, format,
847850
funcName,
848851
location.offset, location.size,
849852
location.offset, location.size,
850853
originalExceptionMessage);
851-
852-
if (size > 2048)
853-
{
854-
// Do not allocate too much for the exception message, just truncate the message past 2048 characters
855-
size = 2047;
856-
}
857-
++size; // Null terminate character
858-
autoClean->str = new char16[size];
859-
int written = _snwprintf_s(autoClean->str, size, _TRUNCATE, format,
860-
funcName,
861-
location.offset, location.size,
862-
location.offset, location.size,
863-
originalExceptionMessage);
864-
Assert((uint)written == size - 1);
865-
return autoClean->str;
854+
return buf;
866855
}
867856

868857
void

lib/Runtime/Library/WebAssemblyModule.h

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,7 @@ namespace Wasm
2323

2424
namespace Js
2525
{
26-
27-
struct AutoCleanStr
28-
{
29-
char16* str = nullptr;
30-
~AutoCleanStr()
31-
{
32-
delete[] str;
33-
}
34-
};
35-
26+
typedef HeapAllocator::AutoFreeArray<char16> AutoFreeExceptionMessage;
3627

3728
class WebAssemblyModule : public DynamicObject
3829
{
@@ -160,7 +151,7 @@ class WebAssemblyModule : public DynamicObject
160151

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

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

165156
virtual void Finalize(bool isShutdown) override;
166157
virtual void Dispose(bool isShutdown) override;

lib/Runtime/Library/amd64/JavascriptFunctionA.S

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -141,19 +141,7 @@ NESTED_ENTRY _ZN2Js18JavascriptFunction17CallAsmJsFunctionIiEET_PNS_16Recyclable
141141
mov rdi, rsp // rdi = arguments destination
142142
rep movsq
143143

144-
// Load 4 first arguments
145-
// First Argument
146144
mov rdi, qword ptr [rsp]
147-
// Review:: Is this really our calling convention on xplat ?
148-
// Second Argument
149-
mov rsi, qword ptr [r8]
150-
movaps xmm1, xmmword ptr [r8]
151-
// Third Argument
152-
mov rdx, qword ptr [r8 + 10h]
153-
movaps xmm2, xmmword ptr [r8 + 10h]
154-
// Fourth Argument
155-
mov rcx, qword ptr [r8 + 20h]
156-
movaps xmm3, xmmword ptr [r8 + 20h]
157145

158146
xor rax, rax // Zero out rax in case r11 expects varags
159147
call r11

0 commit comments

Comments
 (0)