blob: 7b38aec187b0b825308bcf039cc31b2aab5af92f [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
// Portions of this file are copyright 2014 Mozilla Foundation, available under the Apache 2.0 license.
//-------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------
// Copyright 2014 Mozilla Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http ://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeLanguagePch.h"
#ifdef ASMJS_PLAT
namespace Js
{
bool ParserWrapper::ParseVarOrConstStatement( AsmJSParser &parser, ParseNode **var )
{
Assert( parser );
*var = nullptr;
ParseNode *body = parser->sxFnc.pnodeBody;
if( body )
{
ParseNode* lhs = GetBinaryLeft( body );
ParseNode* rhs = GetBinaryRight( body );
if( rhs && rhs->nop == knopList )
{
AssertMsg( lhs->nop == knopStr, "this should be use asm" );
*var = rhs;
return true;
}
}
return false;
}
bool ParserWrapper::IsDefinition( ParseNode *arg )
{
//TODO, eliminate duplicates
return true;
}
ParseNode* ParserWrapper::NextInList( ParseNode *node )
{
Assert( node->nop == knopList );
return node->sxBin.pnode2;
}
ParseNode* ParserWrapper::NextVar( ParseNode *node )
{
return node->sxVar.pnodeNext;
}
ParseNode* ParserWrapper::FunctionArgsList( ParseNode *node, ArgSlot &numformals )
{
Assert( node->nop == knopFncDecl );
PnFnc func = node->sxFnc;
ParseNode* first = func.pnodeParams;
// throws OOM on uint16 overflow
for( ParseNode* pnode = first; pnode; pnode = pnode->sxVar.pnodeNext, ArgSlotMath::Inc(numformals));
return first;
}
PropertyName ParserWrapper::VariableName( ParseNode *node )
{
return node->name();
}
PropertyName ParserWrapper::FunctionName( ParseNode *node )
{
if( node->nop == knopFncDecl )
{
PnFnc function = node->sxFnc;
if( function.pnodeName && function.pnodeName->nop == knopVarDecl )
{
return function.pnodeName->sxVar.pid;
}
}
return nullptr;
}
ParseNode * ParserWrapper::GetVarDeclList( ParseNode * pnode )
{
ParseNode* varNode = pnode;
while (varNode->nop == knopList)
{
ParseNode * var = GetBinaryLeft(varNode);
if (var->nop == knopVarDecl)
{
return var;
}
else if (var->nop == knopList)
{
var = GetBinaryLeft(var);
if (var->nop == knopVarDecl)
{
return var;
}
}
varNode = GetBinaryRight(varNode);
}
return nullptr;
}
void ParserWrapper::ReachEndVarDeclList( ParseNode** outNode )
{
ParseNode* pnode = *outNode;
// moving down to the last var declaration
while( pnode->nop == knopList )
{
ParseNode* var = GetBinaryLeft( pnode );
if (var->nop == knopVarDecl)
{
pnode = GetBinaryRight( pnode );
continue;
}
else if (var->nop == knopList)
{
var = GetBinaryLeft( var );
if (var->nop == knopVarDecl)
{
pnode = GetBinaryRight( pnode );
continue;
}
}
break;
}
*outNode = pnode;
}
AsmJsCompilationException::AsmJsCompilationException( const char16* _msg, ... )
{
va_list arglist;
va_start( arglist, _msg );
vswprintf_s( msg_, _msg, arglist );
}
#if ENABLE_DEBUG_CONFIG_OPTIONS
int64 ConvertStringToInt64(Var string, ScriptContext* scriptContext)
{
JavascriptString* str = JavascriptString::FromVar(string);
charcount_t length = str->GetLength();
const char16* buf = str->GetString();
int radix = 10;
if (length >= 2 && buf[0] == '0' && buf[1] == 'x')
{
radix = 16;
}
return (int64)_wcstoui64(buf, nullptr, radix);
}
Var CreateI64ReturnObject(int64 val, ScriptContext* scriptContext)
{
Js::Var i64Object = JavascriptOperators::NewJavascriptObjectNoArg(scriptContext);
Var low = JavascriptNumber::ToVar((uint)val, scriptContext);
Var high = JavascriptNumber::ToVar(val >> 32, scriptContext);
JavascriptOperators::OP_SetProperty(i64Object, PropertyIds::low, low, scriptContext);
JavascriptOperators::OP_SetProperty(i64Object, PropertyIds::high, high, scriptContext);
return i64Object;
}
#endif
void * UnboxAsmJsArguments(ScriptFunction* func, Var * origArgs, char * argDst, CallInfo callInfo)
{
void * address = reinterpret_cast<void*>(func->GetEntryPointInfo()->jsMethod);
Assert(address);
AsmJsFunctionInfo* info = func->GetFunctionBody()->GetAsmJsFunctionInfo();
ScriptContext* scriptContext = func->GetScriptContext();
#if ENABLE_DEBUG_CONFIG_OPTIONS
bool allowTestInputs = CONFIG_FLAG(WasmI64);
#endif
AsmJsModuleInfo::EnsureHeapAttached(func);
ArgumentReader reader(&callInfo, origArgs);
uint actualArgCount = reader.Info.Count - 1; // -1 for ScriptFunction
argDst = argDst + MachPtr; // add one first so as to skip the ScriptFunction argument
for (ArgSlot i = 0; i < info->GetArgCount(); i++)
{
if (info->GetArgType(i).isInt())
{
int32 intVal;
if (i < actualArgCount)
{
#if ENABLE_DEBUG_CONFIG_OPTIONS
if (allowTestInputs && JavascriptString::Is(*origArgs))
{
intVal = (int32)ConvertStringToInt64(*origArgs, scriptContext);
}
else
#endif
intVal = JavascriptMath::ToInt32(*origArgs, scriptContext);
}
else
{
intVal = 0;
}
#if TARGET_64
*(int64*)(argDst) = 0;
#endif
*(int32*)argDst = intVal;
argDst = argDst + MachPtr;
}
else if (info->GetArgType(i).isInt64())
{
#if ENABLE_DEBUG_CONFIG_OPTIONS
if (!allowTestInputs)
#endif
{
JavascriptError::ThrowTypeError(scriptContext, WASMERR_InvalidTypeConversion);
}
#if ENABLE_DEBUG_CONFIG_OPTIONS
int64 val;
if (i < actualArgCount)
{
if (JavascriptString::Is(*origArgs))
{
val = ConvertStringToInt64(*origArgs, scriptContext);
}
else if (JavascriptObject::Is(*origArgs))
{
RecyclableObject* object = RecyclableObject::FromVar(*origArgs);
PropertyRecord const * lowPropRecord = nullptr;
PropertyRecord const * highPropRecord = nullptr;
scriptContext->GetOrAddPropertyRecord(_u("low"), (int)wcslen(_u("low")), &lowPropRecord);
scriptContext->GetOrAddPropertyRecord(_u("high"), (int)wcslen(_u("high")), &highPropRecord);
Var low = JavascriptOperators::OP_GetProperty(object, lowPropRecord->GetPropertyId(), scriptContext);
Var high = JavascriptOperators::OP_GetProperty(object, highPropRecord->GetPropertyId(), scriptContext);
uint64 lowVal = JavascriptMath::ToInt32(low, scriptContext);
uint64 highVal = JavascriptMath::ToInt32(high, scriptContext);
val = (highVal << 32) | (lowVal & 0xFFFFFFFF);
}
else
{
int32 intVal = JavascriptMath::ToInt32(*origArgs, scriptContext);
val = (int64)intVal;
}
}
else
{
val = 0;
}
*(int64*)(argDst) = val;
argDst += sizeof(int64);
#endif
}
else if (info->GetArgType(i).isFloat())
{
float floatVal;
if (i < actualArgCount)
{
#if ENABLE_DEBUG_CONFIG_OPTIONS
if (allowTestInputs && JavascriptString::Is(*origArgs))
{
int32 val = (int32)ConvertStringToInt64(*origArgs, scriptContext);
floatVal = *(float*)&val;
}
else
#endif
floatVal = (float)(JavascriptConversion::ToNumber(*origArgs, scriptContext));
}
else
{
floatVal = (float)(JavascriptNumber::NaN);
}
#if TARGET_64
*(int64*)(argDst) = 0;
#endif
*(float*)argDst = floatVal;
argDst = argDst + MachPtr;
}
else if (info->GetArgType(i).isDouble())
{
double doubleVal;
if (i < actualArgCount)
{
#if ENABLE_DEBUG_CONFIG_OPTIONS
if (allowTestInputs && JavascriptString::Is(*origArgs))
{
int64 val = ConvertStringToInt64(*origArgs, scriptContext);
doubleVal = *(double*)&val;
}
else
#endif
doubleVal = JavascriptConversion::ToNumber(*origArgs, scriptContext);
}
else
{
doubleVal = JavascriptNumber::NaN;
}
*(double*)argDst = doubleVal;
argDst = argDst + sizeof(double);
}
else if (info->GetArgType(i).isSIMD())
{
AsmJsVarType argType = info->GetArgType(i);
AsmJsSIMDValue simdVal = {0, 0, 0, 0};
// SIMD values are copied unaligned.
// SIMD values cannot be implicitly coerced from/to other types. If the SIMD parameter is missing (i.e. Undefined), we throw type error since there is not equivalent SIMD value to coerce to.
switch (argType.which())
{
case AsmJsType::Int32x4:
if (!JavascriptSIMDInt32x4::Is(*origArgs))
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdInt32x4TypeMismatch, _u("Int32x4"));
}
simdVal = ((JavascriptSIMDInt32x4*)(*origArgs))->GetValue();
break;
case AsmJsType::Bool32x4:
if (!JavascriptSIMDBool32x4::Is(*origArgs))
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdBool32x4TypeMismatch, _u("Bool32x4"));
}
simdVal = ((JavascriptSIMDBool32x4*)(*origArgs))->GetValue();
break;
case AsmJsType::Bool16x8:
if (!JavascriptSIMDBool16x8::Is(*origArgs))
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdBool16x8TypeMismatch, _u("Bool16x8"));
}
simdVal = ((JavascriptSIMDBool16x8*)(*origArgs))->GetValue();
break;
case AsmJsType::Bool8x16:
if (!JavascriptSIMDBool8x16::Is(*origArgs))
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdBool8x16TypeMismatch, _u("Bool8x16"));
}
simdVal = ((JavascriptSIMDBool8x16*)(*origArgs))->GetValue();
break;
case AsmJsType::Float32x4:
if (!JavascriptSIMDFloat32x4::Is(*origArgs))
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdFloat32x4TypeMismatch, _u("Float32x4"));
}
simdVal = ((JavascriptSIMDFloat32x4*)(*origArgs))->GetValue();
break;
case AsmJsType::Float64x2:
if (!JavascriptSIMDFloat64x2::Is(*origArgs))
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdFloat64x2TypeMismatch, _u("Float64x2"));
}
simdVal = ((JavascriptSIMDFloat64x2*)(*origArgs))->GetValue();
break;
case AsmJsType::Int16x8:
if (!JavascriptSIMDInt16x8::Is(*origArgs))
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdInt16x8TypeMismatch, _u("Int16x8"));
}
simdVal = ((JavascriptSIMDInt16x8*)(*origArgs))->GetValue();
break;
case AsmJsType::Int8x16:
if (!JavascriptSIMDInt8x16::Is(*origArgs))
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdInt8x16TypeMismatch, _u("Int8x16"));
}
simdVal = ((JavascriptSIMDInt8x16*)(*origArgs))->GetValue();
break;
case AsmJsType::Uint32x4:
if (!JavascriptSIMDUint32x4::Is(*origArgs))
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdUint32x4TypeMismatch, _u("Uint32x4"));
}
simdVal = ((JavascriptSIMDUint32x4*)(*origArgs))->GetValue();
break;
case AsmJsType::Uint16x8:
if (!JavascriptSIMDUint16x8::Is(*origArgs))
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdUint16x8TypeMismatch, _u("Uint16x8"));
}
simdVal = ((JavascriptSIMDUint16x8*)(*origArgs))->GetValue();
break;
case AsmJsType::Uint8x16:
if (!JavascriptSIMDUint8x16::Is(*origArgs))
{
JavascriptError::ThrowTypeError(scriptContext, JSERR_SimdUint8x16TypeMismatch, _u("Uint8x16"));
}
simdVal = ((JavascriptSIMDUint8x16*)(*origArgs))->GetValue();
break;
default:
Assert(UNREACHED);
}
*(AsmJsSIMDValue*)argDst = simdVal;
argDst = argDst + sizeof(AsmJsSIMDValue);
}
else
{
Assert(UNREACHED);
}
++origArgs;
}
// for convenience, lets take the opportunity to return the asm.js entrypoint address
return address;
}
#if _M_X64
// returns an array containing the size of each argument
uint *GetArgsSizesArray(ScriptFunction* func)
{
AsmJsFunctionInfo* info = func->GetFunctionBody()->GetAsmJsFunctionInfo();
return info->GetArgsSizesArray();
}
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 BoxAsmJsReturnValue(ScriptFunction* func, int64 intRetVal, double doubleRetVal, float floatRetVal, __m128 simdRetVal)
{
// ExternalEntryPoint doesn't know the return value, so it will send garbage for everything except actual return type
Var returnValue = nullptr;
// make call and convert primitive type back to Var
AsmJsFunctionInfo* info = func->GetFunctionBody()->GetAsmJsFunctionInfo();
ScriptContext* scriptContext = func->GetScriptContext();
switch (info->GetReturnType().which())
{
case AsmJsRetType::Void:
returnValue = JavascriptOperators::OP_LdUndef(scriptContext);
break;
case AsmJsRetType::Signed:
{
returnValue = JavascriptNumber::ToVar((int)intRetVal, scriptContext);
break;
}
case AsmJsRetType::Int64:
{
#if ENABLE_DEBUG_CONFIG_OPTIONS
if (CONFIG_FLAG(WasmI64))
{
returnValue = CreateI64ReturnObject(intRetVal, scriptContext);
break;
}
#endif
JavascriptError::ThrowTypeError(scriptContext, WASMERR_InvalidTypeConversion);
}
case AsmJsRetType::Double:
{
returnValue = JavascriptNumber::NewWithCheck(doubleRetVal, scriptContext);
break;
}
case AsmJsRetType::Float:
{
returnValue = JavascriptNumber::NewWithCheck(floatRetVal, scriptContext);
break;
}
case AsmJsRetType::Float32x4:
{
X86SIMDValue simdVal;
simdVal.m128_value = simdRetVal;
returnValue = JavascriptSIMDFloat32x4::New(&X86SIMDValue::ToSIMDValue(simdVal), scriptContext);
break;
}
case AsmJsRetType::Int32x4:
{
X86SIMDValue simdVal;
simdVal.m128_value = simdRetVal;
returnValue = JavascriptSIMDInt32x4::New(&X86SIMDValue::ToSIMDValue(simdVal), scriptContext);
break;
}
case AsmJsRetType::Bool32x4:
{
X86SIMDValue simdVal;
simdVal.m128_value = simdRetVal;
returnValue = JavascriptSIMDBool32x4::New(&X86SIMDValue::ToSIMDValue(simdVal), scriptContext);
break;
}
case AsmJsRetType::Bool16x8:
{
X86SIMDValue simdVal;
simdVal.m128_value = simdRetVal;
returnValue = JavascriptSIMDBool16x8::New(&X86SIMDValue::ToSIMDValue(simdVal), scriptContext);
break;
}
case AsmJsRetType::Bool8x16:
{
X86SIMDValue simdVal;
simdVal.m128_value = simdRetVal;
returnValue = JavascriptSIMDBool8x16::New(&X86SIMDValue::ToSIMDValue(simdVal), scriptContext);
break;
}
case AsmJsRetType::Float64x2:
{
X86SIMDValue simdVal;
simdVal.m128_value = simdRetVal;
returnValue = JavascriptSIMDFloat64x2::New(&X86SIMDValue::ToSIMDValue(simdVal), scriptContext);
break;
}
case AsmJsRetType::Int16x8:
{
X86SIMDValue simdVal;
simdVal.m128_value = simdRetVal;
returnValue = JavascriptSIMDInt16x8::New(&X86SIMDValue::ToSIMDValue(simdVal), scriptContext);
break;
}
case AsmJsRetType::Int8x16:
{
X86SIMDValue simdVal;
simdVal.m128_value = simdRetVal;
returnValue = JavascriptSIMDInt8x16::New(&X86SIMDValue::ToSIMDValue(simdVal), scriptContext);
break;
}
case AsmJsRetType::Uint32x4:
{
X86SIMDValue simdVal;
simdVal.m128_value = simdRetVal;
returnValue = JavascriptSIMDUint32x4::New(&X86SIMDValue::ToSIMDValue(simdVal), scriptContext);
break;
}
case AsmJsRetType::Uint16x8:
{
X86SIMDValue simdVal;
simdVal.m128_value = simdRetVal;
returnValue = JavascriptSIMDUint16x8::New(&X86SIMDValue::ToSIMDValue(simdVal), scriptContext);
break;
}
case AsmJsRetType::Uint8x16:
{
X86SIMDValue simdVal;
simdVal.m128_value = simdRetVal;
returnValue = JavascriptSIMDUint8x16::New(&X86SIMDValue::ToSIMDValue(simdVal), scriptContext);
break;
}
default:
Assume(UNREACHED);
}
return returnValue;
}
#elif _M_IX86
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();
char* dst;
Var returnValue = 0;
// TODO (michhol): wasm, heap should not ever be detached
AsmJsModuleInfo::EnsureHeapAttached(func);
argSize = ::Math::Align<int32>(argSize, 8);
// Allocate stack space for args
__asm
{
sub esp, argSize
mov dst, esp
};
const void * asmJSEntryPoint = UnboxAsmJsArguments(func, args.Values + 1, 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))
{
returnValue = CreateI64ReturnObject((int64)iLow | ((int64)iHigh << 32), 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;
}
case AsmJsRetType::Int32x4:
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
}
returnValue = JavascriptSIMDInt32x4::New(&simdVal, func->GetScriptContext());
break;
case AsmJsRetType::Bool32x4:
simdVal.Zero();
__asm
{
mov ecx, asmJSEntryPoint
#ifdef _CONTROL_FLOW_GUARD
call[__guard_check_icall_fptr]
#endif
push func
call ecx
movups simdVal, xmm0
}
returnValue = JavascriptSIMDBool32x4::New(&simdVal, func->GetScriptContext());
break;
case AsmJsRetType::Bool16x8:
simdVal.Zero();
__asm
{
mov ecx, asmJSEntryPoint
#ifdef _CONTROL_FLOW_GUARD
call[__guard_check_icall_fptr]
#endif
push func
call ecx
movups simdVal, xmm0
}
returnValue = JavascriptSIMDBool16x8::New(&simdVal, func->GetScriptContext());
break;
case AsmJsRetType::Bool8x16:
simdVal.Zero();
__asm
{
mov ecx, asmJSEntryPoint
#ifdef _CONTROL_FLOW_GUARD
call[__guard_check_icall_fptr]
#endif
push func
call ecx
movups simdVal, xmm0
}
returnValue = JavascriptSIMDBool8x16::New(&simdVal, func->GetScriptContext());
break;
case AsmJsRetType::Float32x4:
simdVal.Zero();
__asm
{
mov ecx, asmJSEntryPoint
#ifdef _CONTROL_FLOW_GUARD
call[__guard_check_icall_fptr]
#endif
push func
call ecx
movups simdVal, xmm0
}
returnValue = JavascriptSIMDFloat32x4::New(&simdVal, func->GetScriptContext());
break;
case AsmJsRetType::Float64x2:
simdVal.Zero();
__asm
{
mov ecx, asmJSEntryPoint
#ifdef _CONTROL_FLOW_GUARD
call[__guard_check_icall_fptr]
#endif
push func
call ecx
movups simdVal, xmm0
}
returnValue = JavascriptSIMDFloat64x2::New(&simdVal, func->GetScriptContext());
break;
case AsmJsRetType::Int16x8:
simdVal.Zero();
__asm
{
mov ecx, asmJSEntryPoint
#ifdef _CONTROL_FLOW_GUARD
call[__guard_check_icall_fptr]
#endif
push func
call ecx
movups simdVal, xmm0
}
returnValue = JavascriptSIMDInt16x8::New(&simdVal, func->GetScriptContext());
break;
case AsmJsRetType::Int8x16:
simdVal.Zero();
__asm
{
mov ecx, asmJSEntryPoint
#ifdef _CONTROL_FLOW_GUARD
call[__guard_check_icall_fptr]
#endif
push func
call ecx
movups simdVal, xmm0
}
returnValue = JavascriptSIMDInt8x16::New(&simdVal, func->GetScriptContext());
break;
case AsmJsRetType::Uint32x4:
simdVal.Zero();
__asm
{
mov ecx, asmJSEntryPoint
#ifdef _CONTROL_FLOW_GUARD
call[__guard_check_icall_fptr]
#endif
push func
call ecx
movups simdVal, xmm0
}
returnValue = JavascriptSIMDUint32x4::New(&simdVal, func->GetScriptContext());
break;
case AsmJsRetType::Uint16x8:
simdVal.Zero();
__asm
{
mov ecx, asmJSEntryPoint
#ifdef _CONTROL_FLOW_GUARD
call[__guard_check_icall_fptr]
#endif
push func
call ecx
movups simdVal, xmm0
}
returnValue = JavascriptSIMDUint16x8::New(&simdVal, func->GetScriptContext());
break;
case AsmJsRetType::Uint8x16:
simdVal.Zero();
__asm
{
mov ecx, asmJSEntryPoint
#ifdef _CONTROL_FLOW_GUARD
call[__guard_check_icall_fptr]
#endif
push func
call ecx
movups simdVal, xmm0
}
returnValue = JavascriptSIMDUint8x16::New(&simdVal, func->GetScriptContext());
break;
default:
Assume(UNREACHED);
}
return returnValue;
}
#endif
}
#endif