/* * Copyright (c) 2021 Huawei Device Co., Ltd. * 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 "ecmascript/js_function.h" #include "ecmascript/base/error_type.h" #include "ecmascript/ecma_macros.h" #include "ecmascript/ecma_runtime_call_info.h" #include "ecmascript/global_env.h" #include "ecmascript/interpreter/interpreter-inl.h" #include "ecmascript/js_hclass.h" #include "ecmascript/js_object.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/jspandafile/class_info_extractor.h" #include "ecmascript/js_handle.h" #include "ecmascript/js_promise.h" #include "ecmascript/js_tagged_value-inl.h" #include "ecmascript/log_wrapper.h" #include "ecmascript/mem/c_containers.h" #include "ecmascript/module/js_module_source_text.h" #include "ecmascript/module/js_shared_module.h" #include "ecmascript/object_factory.h" #include "ecmascript/tagged_array.h" #include "ecmascript/require/js_require_manager.h" namespace panda::ecmascript { void JSFunction::InitializeJSFunction(JSThread *thread, const JSHandle &func, FunctionKind kind) { InitializeWithDefaultValue(thread, func); auto globalConst = thread->GlobalConstants(); if (HasPrototype(kind)) { JSHandle accessor = globalConst->GetHandledFunctionPrototypeAccessor(); if (kind == FunctionKind::BASE_CONSTRUCTOR || kind == FunctionKind::GENERATOR_FUNCTION || kind == FunctionKind::ASYNC_GENERATOR_FUNCTION || kind == FunctionKind::NONE_FUNCTION) { func->SetPropertyInlinedProps(thread, PROTOTYPE_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue()); accessor = globalConst->GetHandledFunctionNameAccessor(); func->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue()); accessor = globalConst->GetHandledFunctionLengthAccessor(); func->SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue()); if (kind == FunctionKind::ASYNC_GENERATOR_FUNCTION) { // Not duplicate codes, it will slow the performace if combining and put outside! JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFun(env->GetObjectFunction()); JSHandle initialGeneratorFuncPrototype = factory->NewJSObjectByConstructor(objFun); JSObject::SetPrototype(thread, initialGeneratorFuncPrototype, env->GetAsyncGeneratorPrototype()); func->SetProtoOrHClass(thread, initialGeneratorFuncPrototype); } if (kind == FunctionKind::GENERATOR_FUNCTION) { // Not duplicate codes, it will slow the performace if combining and put outside! JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle objFun(env->GetObjectFunction()); JSHandle initialGeneratorFuncPrototype = factory->NewJSObjectByConstructor(objFun); JSObject::SetPrototype(thread, initialGeneratorFuncPrototype, env->GetGeneratorPrototype()); func->SetProtoOrHClass(thread, initialGeneratorFuncPrototype); } } else if (!JSFunction::IsClassConstructor(kind)) { // class ctor do nothing PropertyDescriptor desc(thread, accessor, kind != FunctionKind::BUILTIN_CONSTRUCTOR, false, false); [[maybe_unused]] bool success = JSObject::DefineOwnProperty( thread, JSHandle(func), globalConst->GetHandledPrototypeString(), desc, SCheckMode::SKIP); ASSERT(success); } } else if (HasAccessor(kind)) { JSHandle accessor = globalConst->GetHandledFunctionNameAccessor(); func->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue()); accessor = globalConst->GetHandledFunctionLengthAccessor(); func->SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue()); } } void JSFunction::InitializeSFunction(JSThread *thread, const JSHandle &func, FunctionKind kind) { InitializeWithDefaultValue(thread, func); auto globalConst = thread->GlobalConstants(); if (HasAccessor(kind)) { JSHandle accessor = globalConst->GetHandledFunctionNameAccessor(); func->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue()); accessor = globalConst->GetHandledFunctionLengthAccessor(); func->SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue()); } } void JSFunction::InitializeWithDefaultValue(JSThread *thread, const JSHandle &func) { func->SetProtoOrHClass(thread, JSTaggedValue::Hole(), SKIP_BARRIER); func->SetHomeObject(thread, JSTaggedValue::Undefined(), SKIP_BARRIER); func->SetWorkNodePointer(reinterpret_cast(nullptr)); func->SetLexicalEnv(thread, JSTaggedValue::Undefined(), SKIP_BARRIER); func->SetMachineCode(thread, JSTaggedValue::Undefined(), SKIP_BARRIER); func->SetBaselineCode(thread, JSTaggedValue::Undefined(), SKIP_BARRIER); func->SetProfileTypeInfo(thread, JSTaggedValue::Undefined(), SKIP_BARRIER); func->SetMethod(thread, JSTaggedValue::Undefined(), SKIP_BARRIER); func->SetModule(thread, JSTaggedValue::Undefined(), SKIP_BARRIER); func->SetCodeEntry(reinterpret_cast(nullptr)); func->SetTaskConcurrentFuncFlag(0); // 0 : default value } JSHandle JSFunction::NewJSFunctionPrototype(JSThread *thread, const JSHandle &func) { JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle objFun(env->GetObjectFunction()); JSHandle funPro = thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(objFun); SetFunctionPrototypeOrInstanceHClass(thread, func, funPro.GetTaggedValue()); // set "constructor" in prototype JSHandle constructorKey = globalConst->GetHandledConstructorString(); PropertyDescriptor descriptor(thread, JSHandle::Cast(func), true, false, true); JSObject::DefineOwnProperty(thread, funPro, constructorKey, descriptor); return funPro; } JSHClass *JSFunction::GetOrCreateInitialJSHClass(JSThread *thread, const JSHandle &fun) { JSTaggedValue protoOrHClass(fun->GetProtoOrHClass()); if (protoOrHClass.IsJSHClass()) { return reinterpret_cast(protoOrHClass.GetTaggedObject()); } JSHandle proto; if (!fun->HasFunctionPrototype()) { proto = JSHandle::Cast(NewJSFunctionPrototype(thread, fun)); if (thread->GetEcmaVM()->IsEnablePGOProfiler()) { thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(fun.GetTaggedType(), JSTaggedType(proto->GetTaggedObject()->GetClass()), pgo::ProfileType::Kind::PrototypeId); } } else { proto = JSHandle(thread, fun->GetProtoOrHClass()); } ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, proto); fun->SetProtoOrHClass(thread, hclass); if (thread->GetEcmaVM()->IsEnablePGOProfiler()) { thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(fun.GetTaggedType(), hclass.GetTaggedType()); } return *hclass; } JSTaggedValue JSFunction::PrototypeGetter(JSThread *thread, const JSHandle &self) { JSHandle func = JSHandle::Cast(self); if (!func->HasFunctionPrototype()) { JSHandle proto = JSHandle::Cast(NewJSFunctionPrototype(thread, func)); if (thread->GetEcmaVM()->IsEnablePGOProfiler()) { thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(func.GetTaggedType(), JSTaggedType(proto->GetTaggedObject()->GetClass()), pgo::ProfileType::Kind::PrototypeId); } } return JSFunction::Cast(*self)->GetFunctionPrototype(); } bool JSFunction::PrototypeSetter(JSThread *thread, const JSHandle &self, const JSHandle &value, [[maybe_unused]] bool mayThrow) { JSHandle func(self); JSTaggedValue protoOrHClass = func->GetProtoOrHClass(); if (protoOrHClass.IsJSHClass()) { // need transition JSHandle hclass(thread, protoOrHClass); JSHandle newClass = JSHClass::SetPrototypeWithNotification(thread, hclass, value); func->SetProtoOrHClass(thread, newClass); } else { SetFunctionPrototypeOrInstanceHClass(thread, func, value.GetTaggedValue()); } // Since dynamically setting the prototype will cause a transition, // but the HClass of the AOT after the transition cannot be obtained, // in order to avoid subsequent Deopt, PGO gives up collecting this type. if (thread->GetEcmaVM()->IsEnablePGOProfiler()) { EntityId ctorMethodId = Method::Cast(func->GetMethod())->GetMethodId(); thread->GetEcmaVM()->GetPGOProfiler()->InsertSkipCtorMethodId(ctorMethodId); } return true; } void JSFunction::SetFunctionPrototypeOrInstanceHClass(const JSThread *thread, const JSHandle &fun, JSTaggedValue protoOrHClass) { JSHandle protoHandle(thread, protoOrHClass); fun->SetProtoOrHClass(thread, protoHandle.GetTaggedValue()); if (protoHandle->IsJSHClass()) { protoHandle = JSHandle(thread, JSHClass::Cast(protoHandle->GetTaggedObject())->GetPrototype()); } if (protoHandle->IsECMAObject()) { JSHClass::OptimizePrototypeForIC(thread, protoHandle); } } JSTaggedValue JSFunction::NameGetter(JSThread *thread, const JSHandle &self) { if (self->IsBoundFunction()) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle boundFunction(self); JSHandle target(thread, boundFunction->GetBoundTarget()); JSHandle nameKey = globalConst->GetHandledNameString(); JSHandle boundName = thread->GlobalConstants()->GetHandledBoundString(); JSHandle targetName = JSObject::GetProperty(thread, target, nameKey).GetValue(); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle handlePrefixString = JSTaggedValue::ToString(thread, boundName); JSHandle spaceString(globalConst->GetHandledSpaceString()); JSHandle concatString = factory->ConcatFromString(handlePrefixString, spaceString); EcmaString *newString; if (!targetName->IsString()) { JSHandle emptyString = factory->GetEmptyString(); newString = *factory->ConcatFromString(concatString, emptyString); } else { JSHandle functionName = JSHandle::Cast(targetName); newString = *factory->ConcatFromString(concatString, functionName); } return JSTaggedValue(newString); } JSTaggedValue method = JSHandle::Cast(self)->GetMethod(); if (method.IsUndefined()) { return JSTaggedValue::Undefined(); } Method *target = Method::Cast(method.GetTaggedObject()); if (target->IsNativeWithCallField()) { return JSTaggedValue::Undefined(); } std::string funcName = target->ParseFunctionName(); if (funcName.empty()) { return thread->GlobalConstants()->GetEmptyString(); } if (JSHandle::Cast(self)->GetFunctionKind() == FunctionKind::GETTER_FUNCTION) { funcName.insert(0, "get "); } if (JSHandle::Cast(self)->GetFunctionKind() == FunctionKind::SETTER_FUNCTION) { funcName.insert(0, "set "); } ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); return factory->NewFromStdString(funcName).GetTaggedValue(); } JSTaggedValue JSFunction::LengthGetter(JSThread *thread, const JSHandle &self) { // LengthGetter only support BoundFunction if (self->IsBoundFunction()) { JSMutableHandle boundFunction(thread, self.GetTaggedValue()); JSHandle arguments(thread, boundFunction->GetBoundArguments()); uint32_t argsLength = TaggedArray::Cast(arguments->GetTaggedObject())->GetLength(); while (boundFunction->GetBoundTarget().IsBoundFunction()) { boundFunction.Update(boundFunction->GetBoundTarget()); argsLength += TaggedArray::Cast(boundFunction->GetBoundArguments())->GetLength(); } JSHandle target(thread, boundFunction->GetBoundTarget()); JSHandle lengthKey = thread->GlobalConstants()->GetHandledLengthString(); bool targetHasLength = JSTaggedValue::HasOwnProperty(thread, target, lengthKey); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); uint32_t lengthValue = 0; if (targetHasLength) { JSHandle targetLength = JSTaggedValue::GetProperty(thread, target, lengthKey).GetValue(); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); if (targetLength->IsNumber()) { lengthValue = std::max(0u, static_cast(JSTaggedValue::ToNumber(thread, targetLength).GetNumber()) - argsLength); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); } } return JSTaggedValue(lengthValue); } JSHandle func(self); return JSTaggedValue(func->GetLength()); } bool JSFunction::OrdinaryHasInstance(JSThread *thread, const JSHandle &constructor, const JSHandle &obj) { // 1. If IsCallable(C) is false, return false. if (!constructor->IsCallable()) { return false; } // 2. If C has a [[BoundTargetFunction]] internal slot, then // a. Let BC be the value of C's [[BoundTargetFunction]] internal slot. // b. Return InstanceofOperator(O,BC) (see 12.9.4). if (constructor->IsBoundFunction()) { STACK_LIMIT_CHECK(thread, false); JSHandle boundFunction(thread, JSBoundFunction::Cast(constructor->GetTaggedObject())); JSTaggedValue boundTarget = boundFunction->GetBoundTarget(); return JSObject::InstanceOf(thread, obj, JSHandle(thread, boundTarget)); } // 3. If Type(O) is not Object, return false if (!obj->IsECMAObject()) { return false; } // 4. Let P be Get(C, "prototype"). const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle prototypeString = globalConst->GetHandledPrototypeString(); JSMutableHandle constructorPrototype(thread, JSTaggedValue::Undefined()); if (constructor->IsJSFunction()) { JSHandle ctor(thread, constructor->GetTaggedObject()); JSHandle ctorProtoOrHclass(thread, ctor->GetProtoOrHClass()); if (!ctorProtoOrHclass->IsHole()) { if (!ctorProtoOrHclass->IsJSHClass()) { constructorPrototype.Update(ctorProtoOrHclass); } else { JSTaggedValue ctorProto = JSHClass::Cast(ctorProtoOrHclass->GetTaggedObject())->GetProto(); constructorPrototype.Update(ctorProto); } } else { constructorPrototype.Update(JSTaggedValue::GetProperty(thread, constructor, prototypeString).GetValue()); } } else { constructorPrototype.Update(JSTaggedValue::GetProperty(thread, constructor, prototypeString).GetValue()); } // 5. ReturnIfAbrupt(P). // no throw exception, so needn't return RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); // 6. If Type(P) is not Object, throw a TypeError exception. if (!constructorPrototype->IsECMAObject()) { THROW_TYPE_ERROR_AND_RETURN(thread, "HasInstance: is not Object", false); } // 7. Repeat // a.Let O be O.[[GetPrototypeOf]](). // b.ReturnIfAbrupt(O). // c.If O is null, return false. // d.If SameValue(P, O) is true, return true. JSMutableHandle object(thread, obj.GetTaggedValue()); while (!object->IsNull()) { if (JSTaggedValue::SameValue(object, constructorPrototype)) { return true; } object.Update(JSTaggedValue::GetPrototype(thread, object)); RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); } return false; } bool JSFunction::MakeConstructor(JSThread *thread, const JSHandle &func, const JSHandle &proto, bool writable) { ASSERT_PRINT(proto->IsHeapObject() || proto->IsUndefined(), "proto must be JSObject or Undefined"); ASSERT_PRINT(func->IsConstructor(), "func must be Constructor type"); JSHandle env = thread->GetEcmaVM()->GetGlobalEnv(); const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle constructorKey = globalConst->GetHandledConstructorString(); ASSERT_PRINT(func->GetProtoOrHClass().IsHole() && func->IsExtensible(), "function doesn't has proto_type property and is extensible object"); ASSERT_PRINT(JSObject::HasProperty(thread, JSHandle(func), constructorKey), "function must have constructor"); // proto.constructor = func bool status = false; if (proto->IsUndefined()) { // Let prototype be ObjectCreate(%ObjectPrototype%). JSHandle objPrototype = env->GetObjectFunctionPrototype(); PropertyDescriptor constructorDesc(thread, JSHandle::Cast(func), writable, false, true); status = JSTaggedValue::DefinePropertyOrThrow(thread, objPrototype, constructorKey, constructorDesc); } else { PropertyDescriptor constructorDesc(thread, JSHandle::Cast(func), writable, false, true); status = JSTaggedValue::DefinePropertyOrThrow(thread, proto, constructorKey, constructorDesc); } RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false); ASSERT_PRINT(status, "DefineProperty construct failed"); // func.prototype = proto // Let status be DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: // prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false}). SetFunctionPrototypeOrInstanceHClass(thread, func, proto.GetTaggedValue()); ASSERT_PRINT(status, "DefineProperty proto_type failed"); return status; } JSTaggedValue JSFunction::Call(EcmaRuntimeCallInfo *info) { if (info == nullptr) { return JSTaggedValue::Exception(); } JSThread *thread = info->GetThread(); // 1. ReturnIfAbrupt(F). RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); JSHandle func = info->GetFunction(); // 2. If argumentsList was not passed, let argumentsList be a new empty List. // 3. If IsCallable(F) is false, throw a TypeError exception. if (!func->IsCallable()) { RETURN_STACK_BEFORE_THROW_IF_ASM(thread); THROW_TYPE_ERROR_AND_RETURN(thread, "Callable is false", JSTaggedValue::Exception()); } auto *hclass = func->GetTaggedObject()->GetClass(); if (hclass->IsClassConstructor()) { RETURN_STACK_BEFORE_THROW_IF_ASM(thread); THROW_TYPE_ERROR_AND_RETURN(thread, "class constructor cannot call", JSTaggedValue::Exception()); } return EcmaInterpreter::Execute(info); } JSTaggedValue JSFunction::Construct(EcmaRuntimeCallInfo *info) { if (info == nullptr) { return JSTaggedValue::Exception(); } JSThread *thread = info->GetThread(); JSHandle func(info->GetFunction()); JSHandle target = info->GetNewTarget(); if (target->IsUndefined()) { target = func; info->SetNewTarget(target.GetTaggedValue()); } if (!(func->IsConstructor() && target->IsConstructor())) { RETURN_STACK_BEFORE_THROW_IF_ASM(thread); THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception()); } if (func->IsJSFunction()) { return JSFunction::ConstructInternal(info); } else if (func->IsJSProxy()) { return JSProxy::ConstructInternal(info); } else { ASSERT(func->IsBoundFunction()); return JSBoundFunction::ConstructInternal(info); } } JSTaggedValue JSFunction::Invoke(EcmaRuntimeCallInfo *info, const JSHandle &key) { if (info == nullptr) { return JSTaggedValue::Exception(); } ASSERT(JSTaggedValue::IsPropertyKey(key)); JSThread *thread = info->GetThread(); JSHandle thisArg = info->GetThis(); JSHandle func(JSTaggedValue::GetProperty(thread, thisArg, key).GetValue()); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); info->SetFunction(func.GetTaggedValue()); return JSFunction::Call(info); } JSTaggedValue JSFunction::InvokeOptimizedEntrypoint(JSThread *thread, JSHandle mainFunc, JSHandle &thisArg, std::string_view entryPoint, CJSInfo* cjsInfo) { ASSERT(thread->IsInManagedState()); if (mainFunc->IsClassConstructor()) { { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); JSHandle error = factory->GetJSError(ErrorType::TYPE_ERROR, "class constructor cannot called without 'new'"); thread->SetException(error.GetTaggedValue()); } return thread->GetException(); } Method *method = mainFunc->GetCallTarget(); size_t actualNumArgs = method->GetNumArgs(); const JSTaggedType *prevFp = thread->GetLastLeaveFrame(); JSTaggedValue res; std::vector args; #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER RuntimeStubs::StartCallTimer(thread->GetGlueAddr(), mainFunc.GetTaggedType(), true); #endif if (method->IsFastCall()) { // do not modify this log to INFO, this will call many times LOG_ECMA(DEBUG) << "start to execute aot entry: " << entryPoint; args = JSFunction::GetArgsData(true, thisArg, mainFunc, cjsInfo); res = thread->GetEcmaVM()->FastCallAot(actualNumArgs, args.data(), prevFp); } else { args = JSFunction::GetArgsData(false, thisArg, mainFunc, cjsInfo); // do not modify this log to INFO, this will call many times LOG_ECMA(DEBUG) << "start to execute aot entry: " << entryPoint; res = thread->GetCurrentEcmaContext()->ExecuteAot(actualNumArgs, args.data(), prevFp, false); } #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER RuntimeStubs::EndCallTimer(thread->GetGlueAddr(), mainFunc.GetTaggedType()); #endif if (thread->HasPendingException()) { return thread->GetException(); } return res; } std::vector JSFunction::GetArgsData(bool isFastCall, JSHandle &thisArg, JSHandle mainFunc, CJSInfo* cjsInfo) { size_t argsNum; uint32_t mandatoryNum; Method *method = mainFunc->GetCallTarget(); size_t actualNumArgs = method->GetNumArgs(); if (isFastCall) { argsNum = actualNumArgs + NUM_MANDATORY_JSFUNC_ARGS - 1; mandatoryNum = NUM_MANDATORY_JSFUNC_ARGS - 1; } else { argsNum = actualNumArgs + NUM_MANDATORY_JSFUNC_ARGS; mandatoryNum = NUM_MANDATORY_JSFUNC_ARGS; } std::vector args(argsNum, JSTaggedValue::Undefined().GetRawData()); args[0] = mainFunc.GetTaggedValue().GetRawData(); if (isFastCall) { args[1] = thisArg.GetTaggedValue().GetRawData(); // 1: args number } else { args[2] = thisArg.GetTaggedValue().GetRawData(); // 2: args number } if (cjsInfo != nullptr) { args[mandatoryNum++] = cjsInfo->exportsHdl.GetTaggedValue().GetRawData(); args[mandatoryNum++] = cjsInfo->requireHdl.GetTaggedValue().GetRawData(); args[mandatoryNum++] = cjsInfo->moduleHdl.GetTaggedValue().GetRawData(); args[mandatoryNum++] = cjsInfo->filenameHdl.GetTaggedValue().GetRawData(); args[mandatoryNum] = cjsInfo->dirnameHdl.GetTaggedValue().GetRawData(); } return args; } JSTaggedValue JSFunction::InvokeOptimizedEntrypoint(JSThread *thread, JSHandle func, EcmaRuntimeCallInfo *info) { ASSERT(thread->IsInManagedState()); Method *method = func->GetCallTarget(); JSTaggedValue resultValue; uint32_t numArgs = method->GetNumArgsWithCallField(); bool needPushUndefined = numArgs > info->GetArgsNumber(); const JSTaggedType *prevFp = thread->GetLastLeaveFrame(); #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER RuntimeStubs::StartCallTimer(thread->GetGlueAddr(), func.GetTaggedType(), true); #endif if (method->IsFastCall()) { if (needPushUndefined) { info = EcmaInterpreter::ReBuildRuntimeCallInfo(thread, info, numArgs); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); } JSTaggedType *stackArgs = info->GetArgs(); stackArgs[1] = stackArgs[0]; resultValue = thread->GetEcmaVM()->FastCallAot(info->GetArgsNumber(), stackArgs + 1, prevFp); } else { resultValue = thread->GetCurrentEcmaContext()->ExecuteAot(info->GetArgsNumber(), info->GetArgs(), prevFp, needPushUndefined); } #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER RuntimeStubs::EndCallTimer(thread->GetGlueAddr(), func.GetTaggedType()); #endif return resultValue; } // [[Construct]] JSTaggedValue JSFunction::ConstructInternal(EcmaRuntimeCallInfo *info) { ASSERT(info != nullptr); JSThread *thread = info->GetThread(); JSHandle func(info->GetFunction()); JSHandle newTarget(info->GetNewTarget()); ASSERT(newTarget->IsECMAObject()); if (!func->IsConstructor()) { RETURN_STACK_BEFORE_THROW_IF_ASM(thread); THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception()); } JSHandle obj(thread, JSTaggedValue::Undefined()); if (func->IsBase()) { ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); obj = JSHandle(factory->NewJSObjectByConstructor(func, newTarget)); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); } JSTaggedValue resultValue; info->SetThis(obj.GetTaggedValue()); Method *method = func->GetCallTarget(); if (method->IsAotWithCallField() && func->IsClassConstructor()) { resultValue = InvokeOptimizedEntrypoint(thread, func, info); const JSTaggedType *curSp = thread->GetCurrentSPFrame(); InterpretedEntryFrame *entryState = InterpretedEntryFrame::GetFrameFromSp(curSp); JSTaggedType *prevSp = entryState->base.prev; thread->SetCurrentSPFrame(prevSp); } else { method->SetAotCodeBit(false); // if Construct is not ClassConstructor, don't run aot resultValue = EcmaInterpreter::Execute(info); } RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); // 9.3.2 [[Construct]] (argumentsList, newTarget) if (resultValue.IsECMAObject()) { return resultValue; } if (func->IsBase()) { return obj.GetTaggedValue(); } // derived ctor(sub class) return the obj which created by base ctor(parent class) if (func->IsDerivedConstructor()) { if (!resultValue.IsECMAObject() && !resultValue.IsUndefined()) { THROW_TYPE_ERROR_AND_RETURN(thread, "derived class constructor must return an object or undefined", JSTaggedValue::Exception()); } return resultValue; } if (!resultValue.IsUndefined()) { RETURN_STACK_BEFORE_THROW_IF_ASM(thread); THROW_TYPE_ERROR_AND_RETURN(thread, "function is non-constructor", JSTaggedValue::Exception()); } return obj.GetTaggedValue(); } JSHandle JSFunctionBase::GetFunctionName(JSThread *thread, const JSHandle &func) { JSHandle nameKey = thread->GlobalConstants()->GetHandledNameString(); return JSObject::GetProperty(thread, JSHandle(func), nameKey).GetValue(); } bool JSFunctionBase::SetFunctionName(JSThread *thread, const JSHandle &func, const JSHandle &name, const JSHandle &prefix) { ASSERT_PRINT(func->IsExtensible(), "Function must be extensible"); ASSERT_PRINT(name->IsStringOrSymbol(), "name must be string or symbol"); bool needPrefix = false; ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); const GlobalEnvConstants *globalConst = thread->GlobalConstants(); if (!prefix->IsUndefined()) { ASSERT_PRINT(prefix->IsString(), "prefix must be string"); needPrefix = true; } // If Type(name) is Symbol, then // Let description be name’s [[Description]] value. // If description is undefined, let name be the empty String. // Else, let name be the concatenation of "[", description, and "]". JSHandle functionName; if (name->IsSymbol()) { JSTaggedValue description = JSHandle::Cast(name)->GetDescription(); JSHandle descriptionHandle(thread, description); if (description.IsUndefined()) { functionName = factory->GetEmptyString(); } else { JSHandle leftBrackets(globalConst->GetHandledLeftSquareBracketString()); JSHandle rightBrackets(globalConst->GetHandledRightSquareBracketString()); functionName = factory->ConcatFromString(leftBrackets, descriptionHandle); functionName = factory->ConcatFromString(functionName, rightBrackets); } } else { functionName = JSHandle::Cast(name); } EcmaString *newString; if (needPrefix) { JSHandle handlePrefixString = JSTaggedValue::ToString(thread, prefix); JSHandle spaceString(globalConst->GetHandledSpaceString()); JSHandle concatString = factory->ConcatFromString(handlePrefixString, spaceString); newString = *factory->ConcatFromString(concatString, functionName); } else { newString = *functionName; } JSHandle nameHandle(thread, newString); JSHandle nameKey = globalConst->GetHandledNameString(); PropertyDescriptor nameDesc(thread, nameHandle, false, false, true); JSHandle funcHandle(func); return JSTaggedValue::DefinePropertyOrThrow(thread, funcHandle, nameKey, nameDesc); } bool JSFunction::SetFunctionLength(JSThread *thread, const JSHandle &func, JSTaggedValue length, bool cfg) { ASSERT_PRINT(func->IsExtensible(), "Function must be extensible"); ASSERT_PRINT(length.IsInteger(), "length must be integer"); JSHandle lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString(); ASSERT_PRINT(!JSTaggedValue::Less(thread, JSHandle(thread, length), JSHandle(thread, JSTaggedValue(0))), "length must be non negative integer"); PropertyDescriptor lengthDesc(thread, JSHandle(thread, length), false, false, cfg); JSHandle funcHandle(func); return JSTaggedValue::DefinePropertyOrThrow(thread, funcHandle, lengthKeyHandle, lengthDesc); } // 9.4.1.2[[Construct]](argumentsList, newTarget) JSTaggedValue JSBoundFunction::ConstructInternal(EcmaRuntimeCallInfo *info) { JSThread *thread = info->GetThread(); JSHandle func(info->GetFunction()); JSHandle target(thread, func->GetBoundTarget()); if (!target->IsConstructor()) { THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception()); } JSHandle newTarget = info->GetNewTarget(); JSMutableHandle newTargetMutable(thread, newTarget.GetTaggedValue()); if (JSTaggedValue::SameValue(func.GetTaggedValue(), newTarget.GetTaggedValue())) { newTargetMutable.Update(target.GetTaggedValue()); } JSHandle boundArgs(thread, func->GetBoundArguments()); const uint32_t boundLength = boundArgs->GetLength(); const uint32_t argsLength = info->GetArgsNumber() + boundLength; JSHandle undefined = thread->GlobalConstants()->GetHandledUndefined(); uint32_t argc = info->GetArgsNumber(); std::vector argArray(argc); for (uint32_t index = 0; index < argc; ++index) { argArray[index] = info->GetCallArgValue(index).GetRawData(); } JSTaggedType *currentSp = reinterpret_cast(info); InterpretedEntryFrame *currentEntryState = InterpretedEntryFrame::GetFrameFromSp(currentSp); JSTaggedType *prevSp = currentEntryState->base.prev; thread->SetCurrentSPFrame(prevSp); EcmaRuntimeCallInfo *runtimeInfo = EcmaInterpreter::NewRuntimeCallInfo(thread, target, undefined, newTargetMutable, argsLength); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); if (boundLength != 0) { runtimeInfo->SetCallArg(boundLength, boundArgs); } for (uint32_t index = 0; index < argc; index++) { runtimeInfo->SetCallArg(static_cast(index + boundLength), JSTaggedValue(argArray[index])); } return JSFunction::Construct(runtimeInfo); } void JSProxyRevocFunction::ProxyRevocFunctions(const JSThread *thread, const JSHandle &revoker) { // 1.Let p be the value of F’s [[RevocableProxy]] internal slot. JSTaggedValue proxy = revoker->GetRevocableProxy(); // 2.If p is null, return undefined. if (proxy.IsNull()) { return; } // 3.Set the value of F’s [[RevocableProxy]] internal slot to null. revoker->SetRevocableProxy(thread, JSTaggedValue::Null()); // 4.Assert: p is a Proxy object. ASSERT(proxy.IsJSProxy()); JSHandle proxyHandle(thread, proxy); // 5 ~ 6 Set internal slot of p to null. proxyHandle->SetTarget(thread, JSTaggedValue::Null()); proxyHandle->SetHandler(thread, JSTaggedValue::Null()); proxyHandle->SetIsRevoked(true); } JSTaggedValue JSFunction::AccessCallerArgumentsThrowTypeError(EcmaRuntimeCallInfo *argv) { THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "Under strict mode, 'caller' and 'arguments' properties must not be accessed.", JSTaggedValue::Exception()); } JSTaggedValue JSIntlBoundFunction::IntlNameGetter(JSThread *thread, [[maybe_unused]] const JSHandle &self) { return thread->GlobalConstants()->GetEmptyString(); } void JSFunction::SetFunctionNameNoPrefix(JSThread *thread, JSFunction *func, JSTaggedValue name) { ASSERT_PRINT(func->IsExtensible(), "Function must be extensible"); ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); const GlobalEnvConstants *globalConst = thread->GlobalConstants(); JSHandle funcHandle(thread, func); { JSMutableHandle nameHandle(thread, JSTaggedValue::Undefined()); if (!name.IsSymbol()) { nameHandle.Update(name); } else { JSHandle nameBegin(thread, name); JSTaggedValue description = JSSymbol::Cast(name.GetTaggedObject())->GetDescription(); if (description.IsUndefined()) { nameHandle.Update(globalConst->GetEmptyString()); } else { JSHandle leftBrackets(globalConst->GetHandledLeftSquareBracketString()); JSHandle rightBrackets(globalConst->GetHandledRightSquareBracketString()); JSHandle concatName = factory->ConcatFromString(leftBrackets, JSHandle(thread, JSSymbol::Cast(nameBegin->GetTaggedObject())->GetDescription())); concatName = factory->ConcatFromString(concatName, rightBrackets); nameHandle.Update(concatName.GetTaggedValue()); } } PropertyDescriptor nameDesc(thread, nameHandle, false, false, true); JSTaggedValue::DefinePropertyOrThrow(thread, funcHandle, globalConst->GetHandledNameString(), nameDesc); } } JSHandle JSFunction::GetInstanceJSHClass(JSThread *thread, JSHandle constructor, JSHandle newTarget) { JSHandle ctorInitialJSHClass(thread, JSFunction::GetOrCreateInitialJSHClass(thread, constructor)); // newTarget is construct itself if (newTarget.GetTaggedValue() == constructor.GetTaggedValue()) { return ctorInitialJSHClass; } // newTarget is derived-class of constructor if (newTarget->IsJSFunction()) { JSHandle newTargetFunc = JSHandle::Cast(newTarget); if (newTargetFunc->IsDerivedConstructor()) { JSMutableHandle mutableNewTarget(thread, newTarget.GetTaggedValue()); JSMutableHandle mutableNewTargetProto(thread, JSTaggedValue::Undefined()); while (!mutableNewTargetProto->IsNull()) { mutableNewTargetProto.Update(JSTaggedValue::GetPrototype(thread, mutableNewTarget)); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSHClass, thread); if (mutableNewTargetProto.GetTaggedValue() == constructor.GetTaggedValue()) { return GetOrCreateDerivedJSHClass(thread, newTargetFunc, ctorInitialJSHClass); } mutableNewTarget.Update(mutableNewTargetProto.GetTaggedValue()); } } } // ECMA2015 9.1.15 3.Let proto be Get(constructor, "prototype"). JSMutableHandle prototype(thread, JSTaggedValue::Undefined()); if (newTarget->IsJSFunction()) { JSHandle newTargetFunc = JSHandle::Cast(newTarget); FunctionKind kind = newTargetFunc->GetFunctionKind(); if (HasPrototype(kind)) { prototype.Update(PrototypeGetter(thread, JSHandle::Cast(newTargetFunc))); } } else { // Such case: bound function and define a "prototype" property. JSHandle customizePrototype = JSTaggedValue::GetProperty(thread, newTarget, thread->GlobalConstants()->GetHandledPrototypeString()) .GetValue(); RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSHClass, thread); prototype.Update(customizePrototype.GetTaggedValue()); // Reload JSHClass of constructor, where the lookup of 'prototype' property may change it. ctorInitialJSHClass = JSHandle(thread, JSFunction::GetOrCreateInitialJSHClass(thread, constructor)); } if (!prototype->IsECMAObject()) { prototype.Update(constructor->GetFunctionPrototype()); } JSHandle newJSHClass = JSHClass::Clone(thread, ctorInitialJSHClass); newJSHClass->SetElementsKind(ElementsKind::GENERIC); newJSHClass->SetPrototype(thread, prototype); return newJSHClass; } JSHandle JSFunction::GetOrCreateDerivedJSHClass(JSThread *thread, JSHandle derived, JSHandle ctorInitialJSHClass) { JSTaggedValue protoOrHClass(derived->GetProtoOrHClass()); // has cached JSHClass, return directly if (protoOrHClass.IsJSHClass()) { return JSHandle(thread, protoOrHClass); } JSHandle newJSHClass = JSHClass::Clone(thread, ctorInitialJSHClass); newJSHClass->SetElementsKind(ElementsKind::GENERIC); // guarante derived has function prototype JSHandle prototype(thread, derived->GetProtoOrHClass()); ASSERT(!prototype->IsHole()); newJSHClass->SetPrototype(thread, prototype); derived->SetProtoOrHClass(thread, newJSHClass); if (thread->GetEcmaVM()->IsEnablePGOProfiler()) { thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(derived.GetTaggedType(), newJSHClass.GetTaggedType()); } return newJSHClass; } JSTaggedValue JSFunction::GetRecordName() const { JSTaggedValue module = GetModule(); if (module.IsSourceTextModule()) { return SourceTextModule::GetModuleName(module); } if (module.IsString()) { return module; } LOG_INTERPRETER(DEBUG) << "record name is undefined"; return JSTaggedValue::Hole(); } // Those interface below is discarded void JSFunction::InitializeJSFunction(JSThread *thread, [[maybe_unused]] const JSHandle &env, const JSHandle &func, FunctionKind kind) { InitializeJSFunction(thread, func, kind); } bool JSFunction::NameSetter(JSThread *thread, const JSHandle &self, const JSHandle &value, [[maybe_unused]] bool mayThrow) { if (self->IsPropertiesDict()) { // replace setter with value JSHandle nameString = thread->GlobalConstants()->GetHandledNameString(); return self->UpdatePropertyInDictionary(thread, nameString.GetTaggedValue(), value.GetTaggedValue()); } self->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, value.GetTaggedValue()); return true; } void JSFunction::SetFunctionExtraInfo(JSThread *thread, void *nativeFunc, const NativePointerCallback &deleter, void *data, size_t nativeBindingsize, Concurrent isConcurrent) { JSTaggedType hashField = Barriers::GetValue(this, HASH_OFFSET); EcmaVM *vm = thread->GetEcmaVM(); JSHandle value(thread, JSTaggedValue(hashField)); JSHandle obj(thread, this); JSHandle pointer = vm->GetFactory()->NewJSNativePointer(nativeFunc, deleter, data, false, nativeBindingsize, isConcurrent); if (!obj->HasHash()) { Barriers::SetObject(thread, *obj, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); return; } if (value->IsHeapObject()) { if (value->IsJSNativePointer()) { Barriers::SetObject(thread, *obj, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); return; } JSHandle array(value); uint32_t nativeFieldCount = array->GetExtraLength(); if (array->GetLength() >= nativeFieldCount + RESOLVED_MAX_SIZE) { array->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer); } else { JSHandle newArray = vm->GetFactory()->NewTaggedArray(nativeFieldCount + RESOLVED_MAX_SIZE); newArray->SetExtraLength(nativeFieldCount); for (uint32_t i = 0; i < nativeFieldCount; i++) { newArray->Set(thread, i, array->Get(i)); } newArray->Set(thread, nativeFieldCount + HASH_INDEX, array->Get(nativeFieldCount + HASH_INDEX)); newArray->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer); Barriers::SetObject(thread, *obj, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); } } else { JSHandle newArray = vm->GetFactory()->NewTaggedArray(RESOLVED_MAX_SIZE); newArray->SetExtraLength(0); newArray->Set(thread, HASH_INDEX, value); newArray->Set(thread, FUNCTION_EXTRA_INDEX, pointer); Barriers::SetObject(thread, *obj, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); } } void JSFunction::SetSFunctionExtraInfo( JSThread *thread, void *nativeFunc, const NativePointerCallback &deleter, void *data, size_t nativeBindingsize) { JSTaggedType hashField = Barriers::GetValue(this, HASH_OFFSET); EcmaVM *vm = thread->GetEcmaVM(); JSHandle value(thread, JSTaggedValue(hashField)); JSHandle obj(thread, this); JSHandle pointer = vm->GetFactory()->NewSJSNativePointer(nativeFunc, deleter, data, false, nativeBindingsize); if (!obj->HasHash()) { Barriers::SetObject(thread, *obj, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); return; } if (value->IsHeapObject()) { if (value->IsJSNativePointer()) { Barriers::SetObject(thread, *obj, HASH_OFFSET, pointer.GetTaggedValue().GetRawData()); return; } JSHandle array(value); uint32_t nativeFieldCount = array->GetExtraLength(); if (array->GetLength() >= nativeFieldCount + RESOLVED_MAX_SIZE) { array->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer); } else { JSHandle newArray = vm->GetFactory()->NewSTaggedArrayWithoutInit(nativeFieldCount + RESOLVED_MAX_SIZE); newArray->SetExtraLength(nativeFieldCount); for (uint32_t i = 0; i < nativeFieldCount; i++) { newArray->Set(thread, i, array->Get(i)); } newArray->Set(thread, nativeFieldCount + HASH_INDEX, array->Get(nativeFieldCount + HASH_INDEX)); newArray->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer); Barriers::SetObject(thread, *obj, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); } } else { JSHandle newArray = vm->GetFactory()->NewSTaggedArrayWithoutInit(RESOLVED_MAX_SIZE); newArray->SetExtraLength(0); newArray->Set(thread, HASH_INDEX, value); newArray->Set(thread, FUNCTION_EXTRA_INDEX, pointer); Barriers::SetObject(thread, *obj, HASH_OFFSET, newArray.GetTaggedValue().GetRawData()); } } JSTaggedValue JSFunction::GetFunctionExtraInfo() const { JSTaggedType hashField = Barriers::GetValue(this, HASH_OFFSET); JSTaggedValue value(hashField); if (value.IsHeapObject()) { if (value.IsTaggedArray()) { TaggedArray *array = TaggedArray::Cast(value.GetTaggedObject()); uint32_t nativeFieldCount = array->GetExtraLength(); if (array->GetLength() >= nativeFieldCount + RESOLVED_MAX_SIZE) { return array->Get(nativeFieldCount + FUNCTION_EXTRA_INDEX); } } if (value.IsJSNativePointer()) { return value; } LOG_ECMA(FATAL) << "this branch is unreachable"; UNREACHABLE(); } return JSTaggedValue::Undefined(); } JSTaggedValue JSFunction::GetNativeFunctionExtraInfo() const { JSTaggedType hashField = Barriers::GetValue(this, HASH_OFFSET); JSTaggedValue value(hashField); if (value.CheckIsJSNativePointer()) { return value; } return JSTaggedValue::Undefined(); } void JSFunction::InitializeForConcurrentFunction(JSThread *thread) { JSHandle method(thread, this->GetMethod()); const JSPandaFile *jsPandaFile = method->GetJSPandaFile(); if (jsPandaFile == nullptr) { LOG_ECMA(ERROR) << "JSPandaFile is nullptr"; return; } ecmascript::CString moduleName = jsPandaFile->GetJSPandaFileDesc(); ecmascript::CString recordName = method->GetRecordNameStr(); // for debugger, to notify the script loaded and parsed which the concurrent function is in auto *notificationMgr = thread->GetEcmaVM()->GetJsDebuggerManager()->GetNotificationManager(); notificationMgr->LoadModuleEvent(moduleName, recordName); // check ESM or CJS ecmascript::JSRecordInfo recordInfo; bool hasRecord = jsPandaFile->CheckAndGetRecordInfo(recordName, recordInfo); if (!hasRecord) { CString msg = "Cannot find module '" + recordName + "' , which is application Entry Point"; LOG_ECMA(ERROR) << msg; return; } if (!jsPandaFile->IsModule(recordInfo)) { LOG_ECMA(DEBUG) << "Current function is not from ES Module's file."; return; } ecmascript::ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager(); JSHandle moduleRecord; // check compileMode if (jsPandaFile->IsBundlePack()) { LOG_ECMA(DEBUG) << "CompileMode is jsbundle"; moduleRecord = moduleManager->HostResolveImportedModule(moduleName); } else { LOG_ECMA(DEBUG) << "CompileMode is esmodule"; moduleRecord = moduleManager->HostResolveImportedModuleWithMerge(moduleName, recordName); } RETURN_IF_ABRUPT_COMPLETION(thread); ecmascript::SourceTextModule::Instantiate(thread, moduleRecord); JSHandle module = JSHandle::Cast(moduleRecord); module->SetStatus(ecmascript::ModuleStatus::INSTANTIATED); ecmascript::SourceTextModule::EvaluateForConcurrent(thread, module, method); if (this->GetClass()->IsJSSharedFunction()) { JSHandle sendableClassRecord = moduleManager->GenerateSendableFuncModule(moduleRecord); this->SetModule(thread, sendableClassRecord); } else { this->SetModule(thread, moduleRecord); } } void JSFunctionBase::SetCompiledFuncEntry(uintptr_t codeEntry, bool isFastCall) { ASSERT(codeEntry != 0); SetCodeEntry(codeEntry); Method* method = Method::Cast(GetMethod()); method->SetCodeEntryAndMarkAOTWhenBinding(codeEntry); method->SetJitCompiledCode(true); method->SetIsFastCall(isFastCall); MethodLiteral *methodLiteral = method->GetMethodLiteral(); methodLiteral->SetAotCodeBit(true); methodLiteral->SetIsFastCall(isFastCall); } } // namespace panda::ecmascript