| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865 |
- //-------------------------------------------------------------------------------------------------------
- // 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, UInt16Math::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 );
- }
- Var AsmJsChangeHeapBuffer(RecyclableObject * function, CallInfo callInfo, ...)
- {
- PROBE_STACK(function->GetScriptContext(), Js::Constants::MinStackDefault);
- ARGUMENTS(args, callInfo);
- ScriptContext* scriptContext = function->GetScriptContext();
- Assert(!(callInfo.Flags & CallFlags_New));
- if (args.Info.Count < 1 || !ArrayBuffer::Is(args[1]))
- {
- JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedArrayBufferObject);
- }
- ArrayBuffer* newArrayBuffer = ArrayBuffer::FromVar(args[1]);
- if (newArrayBuffer->IsDetached() || newArrayBuffer->GetByteLength() & 0xffffff || newArrayBuffer->GetByteLength() <= 0xffffff || newArrayBuffer->GetByteLength() > 0x80000000)
- {
- return JavascriptBoolean::ToVar(FALSE, scriptContext);
- }
- FrameDisplay* frame = ((ScriptFunction*)function)->GetEnvironment();
- Field(Var)* moduleArrayBuffer = (Field(Var)*)frame->GetItem(0) + AsmJsModuleMemory::MemoryTableBeginOffset;
- *moduleArrayBuffer = newArrayBuffer;
- return JavascriptBoolean::ToVar(TRUE, scriptContext);
- }
- #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);
- 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);
- JavascriptOperators::OP_SetProperty(i64Object, lowPropRecord->GetPropertyId(), low, scriptContext);
- JavascriptOperators::OP_SetProperty(i64Object, highPropRecord->GetPropertyId(), 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 = 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;
- }
- 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();
- void* 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
- 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))
- {
- 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
|