Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_RegisterChakraLibraryFunction(RecyclableObject* function, CallInfo callInfo, ...) { EngineInterfaceObject_CommonFunctionProlog(function, callInfo); AssertOrFailFast(args.Info.Count >= 3 && JavascriptString::Is(args.Values[1]) && JavascriptFunction::Is(args.Values[2])); JavascriptLibrary * library = scriptContext->GetLibrary(); // retrieves arguments JavascriptString* methodName = JavascriptString::FromVar(args.Values[1]); JavascriptFunction* func = JavascriptFunction::FromVar(args.Values[2]); // Set the function's display name, as the function we pass in argument are anonym. func->GetFunctionProxy()->SetIsPublicLibraryCode(); func->GetFunctionProxy()->EnsureDeserialized()->SetDisplayName(methodName->GetString(), methodName->GetLength(), 0); DynamicObject* chakraLibraryObject = GetPrototypeFromName(PropertyIds::__chakraLibrary, scriptContext); PropertyIds functionIdentifier = JavascriptOperators::GetPropertyId(methodName, scriptContext); // Link the function to __chakraLibrary. ScriptFunction* scriptFunction = library->CreateScriptFunction(func->GetFunctionProxy()); scriptFunction->GetFunctionProxy()->SetIsJsBuiltInCode(); Assert(scriptFunction->HasFunctionBody()); scriptFunction->GetFunctionBody()->SetJsBuiltInForceInline(); scriptFunction->SetPropertyWithAttributes(PropertyIds::name, methodName, PropertyConfigurable, nullptr); library->AddMember(chakraLibraryObject, functionIdentifier, scriptFunction); //Don't need to return anything return library->GetUndefined(); }
Var EngineInterfaceObject::Entry_TagPublicLibraryCode(RecyclableObject *function, CallInfo callInfo, ...) { EngineInterfaceObject_CommonFunctionProlog(function, callInfo); if (callInfo.Count >= 2 && JavascriptFunction::Is(args.Values[1])) { JavascriptFunction* func = JavascriptFunction::FromVar(args.Values[1]); func->GetFunctionProxy()->SetIsPublicLibraryCode(); if (callInfo.Count >= 3 && JavascriptString::Is(args.Values[2])) { JavascriptString* customFunctionName = JavascriptString::FromVar(args.Values[2]); // tagPublicFunction("Intl.Collator", Collator); in Intl.js calls TagPublicLibraryCode the expected name is Collator so we need to calculate the offset const wchar_t * shortName = wcsrchr(customFunctionName->GetString(), L'.'); uint shortNameOffset = 0; if (shortName != nullptr) { // JavascriptString length is bounded by uint max shortName++; shortNameOffset = static_cast<uint>(shortName - customFunctionName->GetString()); } func->GetFunctionProxy()->EnsureDeserialized()->SetDisplayName(customFunctionName->GetString(), customFunctionName->GetLength(), shortNameOffset); } return func; } return scriptContext->GetLibrary()->GetUndefined(); }
void CrossSite::MarshalDynamicObject(ScriptContext * scriptContext, DynamicObject * object) { Assert(!object->IsExternal() && !object->IsCrossSiteObject()); TTD_XSITE_LOG(scriptContext, "MarshalDynamicObject", object); object->MarshalToScriptContext(scriptContext); if (object->GetTypeId() == TypeIds_Function) { AssertMsg(object != object->GetScriptContext()->GetLibrary()->GetDefaultAccessorFunction(), "default accessor marshalled"); JavascriptFunction * function = JavascriptFunction::FromVar(object); //TODO: this may be too aggressive and create x-site thunks that are't technically needed -- see uglify-2js test. // See if this function is one that the host needs to handle HostScriptContext * hostScriptContext = scriptContext->GetHostScriptContext(); if (!hostScriptContext || !hostScriptContext->SetCrossSiteForFunctionType(function)) { if (function->GetDynamicType()->GetIsLocked()) { TTD_XSITE_LOG(scriptContext, "SetCrossSiteForLockedFunctionType ", object); function->GetLibrary()->SetCrossSiteForLockedFunctionType(function); } else { TTD_XSITE_LOG(scriptContext, "setEntryPoint->CurrentCrossSiteThunk ", object); function->SetEntryPoint(function->GetScriptContext()->CurrentCrossSiteThunk); } } } else if (object->GetTypeId() == TypeIds_Proxy) { RecyclableObject * target = JavascriptProxy::FromVar(object)->GetTarget(); if (JavascriptConversion::IsCallable(target)) { Assert(JavascriptProxy::FunctionCallTrap == object->GetEntryPoint()); TTD_XSITE_LOG(scriptContext, "setEntryPoint->CrossSiteProxyCallTrap ", object); object->GetDynamicType()->SetEntryPoint(CrossSite::CrossSiteProxyCallTrap); } } }
void CrossSite::MarshalCrossSite_TTDInflate(DynamicObject* obj) { obj->MarshalCrossSite_TTDInflate(); if(obj->GetTypeId() == TypeIds_Function) { AssertMsg(obj != obj->GetScriptContext()->GetLibrary()->GetDefaultAccessorFunction(), "default accessor marshalled -- I don't think this should ever happen as it is marshalled in a special case?"); JavascriptFunction * function = JavascriptFunction::FromVar(obj); // //TODO: what happens if the gaurd in marshal (MarshalDynamicObject) isn't true? // if(function->GetTypeHandler()->GetIsLocked()) { function->GetLibrary()->SetCrossSiteForLockedFunctionType(function); } else { function->SetEntryPoint(function->GetScriptContext()->CurrentCrossSiteThunk); } } }
Var CrossSite::ProfileThunk(RecyclableObject* callable, CallInfo callInfo, ...) { JavascriptFunction* function = JavascriptFunction::FromVar(callable); Assert(function->GetTypeId() == TypeIds_Function); Assert(function->GetEntryPoint() == CrossSite::ProfileThunk); RUNTIME_ARGUMENTS(args, callInfo); ScriptContext * scriptContext = function->GetScriptContext(); // It is not safe to access the function body if the script context is not alive. scriptContext->VerifyAliveWithHostContext(!function->IsExternal(), scriptContext->GetThreadContext()->GetPreviousHostScriptContext()); JavascriptMethod entryPoint; FunctionInfo *funcInfo = function->GetFunctionInfo(); TTD_XSITE_LOG(callable->GetScriptContext(), "DefaultOrProfileThunk", callable); #ifdef ENABLE_WASM if (WasmScriptFunction::Is(function)) { AsmJsFunctionInfo* asmInfo = funcInfo->GetFunctionBody()->GetAsmJsFunctionInfo(); Assert(asmInfo); if (asmInfo->IsWasmDeferredParse()) { entryPoint = WasmLibrary::WasmDeferredParseExternalThunk; } else { entryPoint = Js::AsmJsExternalEntryPoint; } } else #endif if (funcInfo->HasBody()) { #if ENABLE_DEBUG_CONFIG_OPTIONS char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE]; #endif entryPoint = ScriptFunction::FromVar(function)->GetEntryPointInfo()->jsMethod; if (funcInfo->IsDeferred() && scriptContext->IsProfiling()) { // if the current entrypoint is deferred parse we need to update it appropriately for the profiler mode. entryPoint = Js::ScriptContext::GetProfileModeThunk(entryPoint); } OUTPUT_TRACE(Js::ScriptProfilerPhase, _u("CrossSite::ProfileThunk FunctionNumber : %s, Entrypoint : 0x%08X\n"), funcInfo->GetFunctionProxy()->GetDebugNumberSet(debugStringBuffer), entryPoint); } else { entryPoint = ProfileEntryThunk; } return CommonThunk(function, entryPoint, args); }
Var CrossSite::DefaultThunk(RecyclableObject* callable, CallInfo callInfo, ...) { JavascriptFunction* function = JavascriptFunction::FromVar(callable); Assert(function->GetTypeId() == TypeIds_Function); Assert(function->GetEntryPoint() == CrossSite::DefaultThunk); RUNTIME_ARGUMENTS(args, callInfo); // It is not safe to access the function body if the script context is not alive. function->GetScriptContext()->VerifyAliveWithHostContext(!function->IsExternal(), ThreadContext::GetContextForCurrentThread()->GetPreviousHostScriptContext()); JavascriptMethod entryPoint; FunctionInfo *funcInfo = function->GetFunctionInfo(); TTD_XSITE_LOG(callable->GetScriptContext(), "DefaultOrProfileThunk", callable); if (funcInfo->HasBody()) { #ifdef ASMJS_PLAT if (funcInfo->GetFunctionProxy()->IsFunctionBody() && funcInfo->GetFunctionBody()->GetIsAsmJsFunction()) { #ifdef ENABLE_WASM AsmJsFunctionInfo* asmInfo = funcInfo->GetFunctionBody()->GetAsmJsFunctionInfo(); if (asmInfo && asmInfo->IsWasmDeferredParse()) { entryPoint = WasmLibrary::WasmDeferredParseExternalThunk; } else #endif { entryPoint = Js::AsmJsExternalEntryPoint; } } else #endif { entryPoint = ScriptFunction::FromVar(function)->GetEntryPointInfo()->jsMethod; } } else { entryPoint = funcInfo->GetOriginalEntryPoint(); } return CommonThunk(function, entryPoint, args); }
void JavascriptExternalFunction::PrepareExternalCall(Js::Arguments * args) { ScriptContext * scriptContext = this->type->GetScriptContext(); Assert(!scriptContext->GetThreadContext()->IsDisableImplicitException()); scriptContext->VerifyAlive(); Assert(scriptContext->GetThreadContext()->IsScriptActive()); if (args->Info.Count == 0) { JavascriptError::ThrowTypeError(scriptContext, JSERR_This_NullOrUndefined); } Var &thisVar = args->Values[0]; Js::TypeId typeId = Js::JavascriptOperators::GetTypeId(thisVar); this->callCount++; if (IS_JS_ETW(EventEnabledJSCRIPT_HOSTING_EXTERNAL_FUNCTION_CALL_START())) { JavascriptFunction* caller = nullptr; // Lot the caller function if the call count of the external function pass certain threshold (randomly pick 256) // we don't want to call stackwalk too often. The threshold can be adjusted as needed. if (callCount >= ETW_MIN_COUNT_FOR_CALLER && ((callCount % ETW_MIN_COUNT_FOR_CALLER) == 0)) { Js::JavascriptStackWalker stackWalker(scriptContext); bool foundScriptCaller = false; while(stackWalker.GetCaller(&caller)) { if(caller != nullptr && Js::ScriptFunction::Is(caller)) { foundScriptCaller = true; break; } } if(foundScriptCaller) { Var sourceString = caller->EnsureSourceString(); Assert(JavascriptString::Is(sourceString)); const char16* callerString = Js::JavascriptString::FromVar(sourceString)->GetSz(); char16* outString = (char16*)callerString; int length = 0; if (wcschr(callerString, _u('\n')) != NULL || wcschr(callerString, _u('\n')) != NULL) { length = Js::JavascriptString::FromVar(sourceString)->GetLength(); outString = HeapNewArray(char16, length+1); int j = 0; for (int i = 0; i < length; i++) { if (callerString[i] != _u('\n') && callerString[i] != L'\r') { outString[j++] = callerString[i]; } } outString[j] = L'\0'; } JS_ETW(EventWriteJSCRIPT_HOSTING_CALLER_TO_EXTERNAL(scriptContext, this, typeId, outString, callCount)); if (outString != callerString) { HeapDeleteArray(length+1, outString); } #if DBG_DUMP if (Js::Configuration::Global.flags.Trace.IsEnabled(Js::HostPhase)) { Output::Print(_u("Large number of Call to trampoline: methodAddr= %p, Object typeid= %d, caller method= %s, callcount= %d\n"), this, typeId, callerString, callCount); } #endif } } JS_ETW(EventWriteJSCRIPT_HOSTING_EXTERNAL_FUNCTION_CALL_START(scriptContext, this, typeId)); #if DBG_DUMP if (Js::Configuration::Global.flags.Trace.IsEnabled(Js::HostPhase)) { Output::Print(_u("Call to trampoline: methodAddr= %p, Object typeid= %d\n"), this, typeId); } #endif } Js::RecyclableObject* directHostObject = nullptr; switch(typeId) { case TypeIds_Integer: #if FLOATVAR case TypeIds_Number: #endif // FLOATVAR Assert(!Js::RecyclableObject::Is(thisVar)); break; default: { Assert(Js::RecyclableObject::Is(thisVar)); ScriptContext* scriptContextThisVar = Js::RecyclableObject::FromVar(thisVar)->GetScriptContext(); // We need to verify "this" pointer is active as well. The problem is that DOM prototype functions are // the same across multiple frames, and caller can do function.call(closedthis) Assert(!scriptContext->GetThreadContext()->IsDisableImplicitException()); scriptContextThisVar->VerifyAlive(); // translate direct host for fastDOM. switch(typeId) { case Js::TypeIds_GlobalObject: { Js::GlobalObject* srcGlobalObject = static_cast<Js::GlobalObject*>(thisVar); directHostObject = srcGlobalObject->GetDirectHostObject(); // For jsrt, direct host object can be null. If thats the case don't change it. if (directHostObject != nullptr) { thisVar = directHostObject; } } break; case Js::TypeIds_Undefined: case Js::TypeIds_Null: { // Call to DOM function with this as "undefined" or "null" // This should be converted to Global object Js::GlobalObject* srcGlobalObject = scriptContextThisVar->GetGlobalObject() ; directHostObject = srcGlobalObject->GetDirectHostObject(); // For jsrt, direct host object can be null. If thats the case don't change it. if (directHostObject != nullptr) { thisVar = directHostObject; } } break; } } break; } }
Var JsBuiltInEngineInterfaceExtensionObject::EntryJsBuiltIn_RegisterFunction(RecyclableObject* function, CallInfo callInfo, ...) { EngineInterfaceObject_CommonFunctionProlog(function, callInfo); AssertOrFailFast(args.Info.Count >= 3 && JavascriptObject::Is(args.Values[1]) && JavascriptFunction::Is(args.Values[2])); JavascriptLibrary * library = scriptContext->GetLibrary(); // retrieves arguments RecyclableObject* funcInfo = nullptr; if (!JavascriptConversion::ToObject(args.Values[1], scriptContext, &funcInfo)) { JavascriptError::ThrowTypeError(scriptContext, JSERR_FunctionArgument_NeedObject, _u("Object.assign")); } Var classNameProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::className, scriptContext); Var methodNameProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::methodName, scriptContext); Var argumentsCountProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::argumentsCount, scriptContext); Var forceInlineProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::forceInline, scriptContext); Var aliasProperty = JavascriptOperators::OP_GetProperty(funcInfo, Js::PropertyIds::alias, scriptContext); Assert(JavascriptString::Is(classNameProperty)); Assert(JavascriptString::Is(methodNameProperty)); Assert(TaggedInt::Is(argumentsCountProperty)); JavascriptString* className = JavascriptString::FromVar(classNameProperty); JavascriptString* methodName = JavascriptString::FromVar(methodNameProperty); int argumentsCount = TaggedInt::ToInt32(argumentsCountProperty); BOOL forceInline = JavascriptConversion::ToBoolean(forceInlineProperty, scriptContext); JavascriptFunction* func = JavascriptFunction::FromVar(args.Values[2]); // Set the function's display name, as the function we pass in argument are anonym. func->GetFunctionProxy()->SetIsPublicLibraryCode(); func->GetFunctionProxy()->EnsureDeserialized()->SetDisplayName(methodName->GetString(), methodName->GetLength(), 0); DynamicObject* prototype = GetPrototypeFromName(JavascriptOperators::GetPropertyId(className, scriptContext), scriptContext); PropertyIds functionIdentifier = methodName->BufferEquals(_u("Symbol.iterator"), 15)? PropertyIds::_symbolIterator : JavascriptOperators::GetPropertyId(methodName, scriptContext); // Link the function to the prototype. ScriptFunction* scriptFunction = library->CreateScriptFunction(func->GetFunctionProxy()); scriptFunction->GetFunctionProxy()->SetIsJsBuiltInCode(); if (forceInline) { Assert(scriptFunction->HasFunctionBody()); scriptFunction->GetFunctionBody()->SetJsBuiltInForceInline(); } scriptFunction->SetPropertyWithAttributes(PropertyIds::length, TaggedInt::ToVarUnchecked(argumentsCount), PropertyConfigurable, nullptr); scriptFunction->SetConfigurable(PropertyIds::prototype, true); scriptFunction->DeleteProperty(PropertyIds::prototype, Js::PropertyOperationFlags::PropertyOperation_None); scriptFunction->SetPropertyWithAttributes(PropertyIds::name, methodName, PropertyConfigurable, nullptr); library->AddMember(prototype, functionIdentifier, scriptFunction); RecordCommonNativeInterfaceBuiltIns(functionIdentifier, scriptContext, scriptFunction); if (!JavascriptOperators::IsUndefinedOrNull(aliasProperty)) { JavascriptString * alias = JavascriptConversion::ToString(aliasProperty, scriptContext); // Cannot do a string to property id search here, Symbol.* have different hashing mechanism, so resort to this str compare PropertyIds aliasFunctionIdentifier = alias->BufferEquals(_u("Symbol.iterator"), 15) ? PropertyIds::_symbolIterator : JavascriptOperators::GetPropertyId(alias, scriptContext); library->AddMember(prototype, aliasFunctionIdentifier, scriptFunction); } if (prototype == library->arrayPrototype) { RecordDefaultIteratorFunctions(functionIdentifier, scriptContext, scriptFunction); } //Don't need to return anything return library->GetUndefined(); }
bool ASMLink::CheckMathLibraryMethod(ScriptContext* scriptContext, const Var asmMathObject, const AsmJSMathBuiltinFunction mathLibMethod) { Var mathFuncObj; switch (mathLibMethod) { case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_sin: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::sin, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Sin)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_cos: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::cos, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Cos)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_tan: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::tan, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Tan)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_asin: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::asin, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Asin)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_acos: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::acos, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Acos)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_atan: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::atan, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Atan)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_ceil: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::ceil, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Ceil)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_floor: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::floor, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Floor)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_exp: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::exp, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Exp)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_log: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::log, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Log)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_pow: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::pow, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Pow)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_sqrt: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::sqrt, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Sqrt)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_abs: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::abs, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Abs)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_atan2: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::atan2, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Atan2)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_imul: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::imul, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Imul)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_clz32: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::clz32, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Clz32)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_min: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::min, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Min)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_max: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::max, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Max)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_fround: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::fround, scriptContext); if (JavascriptFunction::Is(mathFuncObj)) { JavascriptFunction* mathLibFunc = (JavascriptFunction*)mathFuncObj; if (mathLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Math::EntryInfo::Fround)->GetOriginalEntryPoint()) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_e: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::E, scriptContext); if (JavascriptNumber::Is(mathFuncObj)) { JavascriptNumber* mathConstNumber = (JavascriptNumber*)mathFuncObj; if (JavascriptNumber::GetValue(mathConstNumber) == (Math::E)) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_ln10: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::LN10, scriptContext); if (JavascriptNumber::Is(mathFuncObj)) { JavascriptNumber* mathConstNumber = (JavascriptNumber*)mathFuncObj; if (JavascriptNumber::GetValue(mathConstNumber) == (Math::LN10)) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_ln2: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::LN2, scriptContext); if (JavascriptNumber::Is(mathFuncObj)) { JavascriptNumber* mathConstNumber = (JavascriptNumber*)mathFuncObj; if (JavascriptNumber::GetValue(mathConstNumber) == (Math::LN2)) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_log2e: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::LOG2E, scriptContext); if (JavascriptNumber::Is(mathFuncObj)) { JavascriptNumber* mathConstNumber = (JavascriptNumber*)mathFuncObj; if (JavascriptNumber::GetValue(mathConstNumber) == (Math::LOG2E)) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_log10e: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::LOG10E, scriptContext); if (JavascriptNumber::Is(mathFuncObj)) { JavascriptNumber* mathConstNumber = (JavascriptNumber*)mathFuncObj; if (JavascriptNumber::GetValue(mathConstNumber) == (Math::LOG10E)) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_pi: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::PI, scriptContext); if (JavascriptNumber::Is(mathFuncObj)) { JavascriptNumber* mathConstNumber = (JavascriptNumber*)mathFuncObj; if (JavascriptNumber::GetValue(mathConstNumber) == (Math::PI)) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_sqrt1_2: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::SQRT1_2, scriptContext); if (JavascriptNumber::Is(mathFuncObj)) { JavascriptNumber* mathConstNumber = (JavascriptNumber*)mathFuncObj; if (JavascriptNumber::GetValue(mathConstNumber) == (Math::SQRT1_2)) { return true; } } break; case AsmJSMathBuiltinFunction::AsmJSMathBuiltin_sqrt2: mathFuncObj = JavascriptOperators::OP_GetProperty(asmMathObject, PropertyIds::SQRT2, scriptContext); if (JavascriptNumber::Is(mathFuncObj)) { JavascriptNumber* mathConstNumber = (JavascriptNumber*)mathFuncObj; if (JavascriptNumber::GetValue(mathConstNumber) == (Math::SQRT2)) { return true; } } break; default: Assume(UNREACHED); } return false; }
bool ASMLink::CheckArrayLibraryMethod(ScriptContext* scriptContext, const Var stdlib, const AsmJSTypedArrayBuiltinFunction arrayLibMethod) { Var arrayFuncObj; switch (arrayLibMethod) { case AsmJSTypedArrayBuiltinFunction::AsmJSTypedArrayBuiltin_byteLength: arrayFuncObj = JavascriptOperators::OP_GetProperty(stdlib, PropertyIds::byteLength, scriptContext); if (JavascriptFunction::Is(arrayFuncObj)) { JavascriptFunction* arrayLibFunc = (JavascriptFunction*)arrayFuncObj; if (arrayLibFunc->IsBoundFunction()) { BoundFunction* boundFunc = (BoundFunction*)arrayLibFunc; RecyclableObject* thisObj = boundFunc->GetBoundThis(); if (JavascriptFunction::Is(thisObj)) { JavascriptFunction * thisFunc = (JavascriptFunction*)thisObj; if (thisFunc->GetFunctionInfo()->GetOriginalEntryPoint() != (&ArrayBuffer::EntryInfo::GetterByteLength)->GetOriginalEntryPoint()) { return false; } } JavascriptFunction* targetFunc = boundFunc->GetTargetFunction(); return targetFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&JavascriptFunction::EntryInfo::Call)->GetOriginalEntryPoint(); } } break; case AsmJSTypedArrayBuiltinFunction::AsmJSTypedArrayBuiltin_Int8Array: arrayFuncObj = JavascriptOperators::OP_GetProperty(stdlib, PropertyIds::Int8Array, scriptContext); if (JavascriptFunction::Is(arrayFuncObj)) { JavascriptFunction* arrayLibFunc = (JavascriptFunction*)arrayFuncObj; return arrayLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Int8Array::EntryInfo::NewInstance)->GetOriginalEntryPoint(); } break; case AsmJSTypedArrayBuiltinFunction::AsmJSTypedArrayBuiltin_Uint8Array: arrayFuncObj = JavascriptOperators::OP_GetProperty(stdlib, PropertyIds::Uint8Array, scriptContext); if (JavascriptFunction::Is(arrayFuncObj)) { JavascriptFunction* arrayLibFunc = (JavascriptFunction*)arrayFuncObj; return arrayLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Uint8Array::EntryInfo::NewInstance)->GetOriginalEntryPoint(); } break; case AsmJSTypedArrayBuiltinFunction::AsmJSTypedArrayBuiltin_Int16Array: arrayFuncObj = JavascriptOperators::OP_GetProperty(stdlib, PropertyIds::Int16Array, scriptContext); if (JavascriptFunction::Is(arrayFuncObj)) { JavascriptFunction* arrayLibFunc = (JavascriptFunction*)arrayFuncObj; return arrayLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Int16Array::EntryInfo::NewInstance)->GetOriginalEntryPoint(); } break; case AsmJSTypedArrayBuiltinFunction::AsmJSTypedArrayBuiltin_Uint16Array: arrayFuncObj = JavascriptOperators::OP_GetProperty(stdlib, PropertyIds::Uint16Array, scriptContext); if (JavascriptFunction::Is(arrayFuncObj)) { JavascriptFunction* arrayLibFunc = (JavascriptFunction*)arrayFuncObj; return arrayLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Uint16Array::EntryInfo::NewInstance)->GetOriginalEntryPoint(); } break; case AsmJSTypedArrayBuiltinFunction::AsmJSTypedArrayBuiltin_Int32Array: arrayFuncObj = JavascriptOperators::OP_GetProperty(stdlib, PropertyIds::Int32Array, scriptContext); if (JavascriptFunction::Is(arrayFuncObj)) { JavascriptFunction* arrayLibFunc = (JavascriptFunction*)arrayFuncObj; return arrayLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Int32Array::EntryInfo::NewInstance)->GetOriginalEntryPoint(); } break; case AsmJSTypedArrayBuiltinFunction::AsmJSTypedArrayBuiltin_Uint32Array: arrayFuncObj = JavascriptOperators::OP_GetProperty(stdlib, PropertyIds::Uint32Array, scriptContext); if (JavascriptFunction::Is(arrayFuncObj)) { JavascriptFunction* arrayLibFunc = (JavascriptFunction*)arrayFuncObj; return arrayLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Uint32Array::EntryInfo::NewInstance)->GetOriginalEntryPoint(); } break; case AsmJSTypedArrayBuiltinFunction::AsmJSTypedArrayBuiltin_Float32Array: arrayFuncObj = JavascriptOperators::OP_GetProperty(stdlib, PropertyIds::Float32Array, scriptContext); if (JavascriptFunction::Is(arrayFuncObj)) { JavascriptFunction* arrayLibFunc = (JavascriptFunction*)arrayFuncObj; return arrayLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Float32Array::EntryInfo::NewInstance)->GetOriginalEntryPoint(); } break; case AsmJSTypedArrayBuiltinFunction::AsmJSTypedArrayBuiltin_Float64Array: arrayFuncObj = JavascriptOperators::OP_GetProperty(stdlib, PropertyIds::Float64Array, scriptContext); if (JavascriptFunction::Is(arrayFuncObj)) { JavascriptFunction* arrayLibFunc = (JavascriptFunction*)arrayFuncObj; return arrayLibFunc->GetFunctionInfo()->GetOriginalEntryPoint() == (&Float64Array::EntryInfo::NewInstance)->GetOriginalEntryPoint(); } break; default: Assume(UNREACHED); } return false; }