int GetStackSizeForAsmJsUnboxing(ScriptFunction* func) { AsmJsFunctionInfo* info = func->GetFunctionBody()->GetAsmJsFunctionInfo(); int argSize = info->GetArgByteSize() + MachPtr; argSize = ::Math::Align<int32>(argSize, 16); if (argSize < 32) { argSize = 32; // convention is to always allocate spill space for rcx,rdx,r8,r9 } PROBE_STACK_CALL(func->GetScriptContext(), func, argSize + Js::Constants::MinStackDefault); return argSize; }
int GetStackSizeForAsmJsUnboxing(ScriptFunction* func) { AsmJsFunctionInfo* info = func->GetFunctionBody()->GetAsmJsFunctionInfo(); int argSize = MachPtr; for (ArgSlot i = 0; i < info->GetArgCount(); i++) { if (info->GetArgType(i).isSIMD()) { argSize += sizeof(AsmJsSIMDValue); } else { argSize += MachPtr; } } argSize = ::Math::Align<int32>(argSize, 16); if (argSize < 32) { argSize = 32; // convention is to always allocate spill space for rcx,rdx,r8,r9 } PROBE_STACK_CALL(func->GetScriptContext(), func, argSize); return argSize; }
Var AsmJsExternalEntryPoint(RecyclableObject* entryObject, CallInfo callInfo, ...) { ARGUMENTS(args, callInfo); ScriptFunction* func = (ScriptFunction*)entryObject; FunctionBody* body = func->GetFunctionBody(); AsmJsFunctionInfo* info = body->GetAsmJsFunctionInfo(); int argSize = info->GetArgByteSize(); void* dst; Var returnValue = 0; argSize = ::Math::Align<int32>(argSize, 8); // Allocate stack space for args PROBE_STACK_CALL(func->GetScriptContext(), func, argSize + Js::Constants::MinStackDefault); dst = _alloca(argSize); const void * asmJSEntryPoint = UnboxAsmJsArguments(func, args.Values + 1, ((char*)dst) - MachPtr, callInfo); // make call and convert primitive type back to Var switch (info->GetReturnType().which()) { case AsmJsRetType::Void: __asm { mov ecx, asmJSEntryPoint #ifdef _CONTROL_FLOW_GUARD call[__guard_check_icall_fptr] #endif push func call ecx } returnValue = JavascriptOperators::OP_LdUndef(func->GetScriptContext()); break; case AsmJsRetType::Signed:{ int32 ival = 0; __asm { mov ecx, asmJSEntryPoint #ifdef _CONTROL_FLOW_GUARD call[__guard_check_icall_fptr] #endif push func call ecx mov ival, eax } returnValue = JavascriptNumber::ToVar(ival, func->GetScriptContext()); break; } case AsmJsRetType::Int64: { int32 iLow = 0, iHigh = 0; __asm { mov ecx, asmJSEntryPoint #ifdef _CONTROL_FLOW_GUARD call[__guard_check_icall_fptr] #endif push func call ecx mov iLow, eax; mov iHigh, edx; } #if ENABLE_DEBUG_CONFIG_OPTIONS if (CONFIG_FLAG(WasmI64)) { uint64 lHigh = ((uint64)iHigh) << 32; uint64 lLow = (uint64)(uint32)iLow; returnValue = CreateI64ReturnObject((int64)(lHigh | lLow), func->GetScriptContext()); break; } #endif JavascriptError::ThrowTypeError(func->GetScriptContext(), WASMERR_InvalidTypeConversion); } case AsmJsRetType::Double:{ double dval = 0; __asm { mov ecx, asmJSEntryPoint #ifdef _CONTROL_FLOW_GUARD call[__guard_check_icall_fptr] #endif push func call ecx movsd dval, xmm0 } returnValue = JavascriptNumber::NewWithCheck(dval, func->GetScriptContext()); break; } case AsmJsRetType::Float:{ float fval = 0; __asm { mov ecx, asmJSEntryPoint #ifdef _CONTROL_FLOW_GUARD call[__guard_check_icall_fptr] #endif push func call ecx movss fval, xmm0 } returnValue = JavascriptNumber::NewWithCheck((double)fval, func->GetScriptContext()); break; } #ifdef ENABLE_WASM_SIMD case AsmJsRetType::Bool32x4: case AsmJsRetType::Bool16x8: case AsmJsRetType::Bool8x16: case AsmJsRetType::Float32x4: case AsmJsRetType::Float64x2: case AsmJsRetType::Int64x2: case AsmJsRetType::Int32x4: case AsmJsRetType::Int16x8: case AsmJsRetType::Int8x16: case AsmJsRetType::Uint32x4: case AsmJsRetType::Uint16x8: case AsmJsRetType::Uint8x16: AsmJsSIMDValue simdVal; simdVal.Zero(); __asm { mov ecx, asmJSEntryPoint #ifdef _CONTROL_FLOW_GUARD call[__guard_check_icall_fptr] #endif push func call ecx movups simdVal, xmm0 } // Todo:: support test return object (like int64) for wasm.simd JavascriptError::ThrowTypeError(func->GetScriptContext(), WASMERR_InvalidTypeConversion); break; #endif default: Assume(UNREACHED); JavascriptError::ThrowTypeError(func->GetScriptContext(), WASMERR_InvalidTypeConversion); } return returnValue; }