• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/js_function.h"
17 
18 #include "ecmascript/debugger/js_debugger_manager.h"
19 #include "ecmascript/ecma_context.h"
20 #include "ecmascript/global_env.h"
21 #include "ecmascript/interpreter/interpreter.h"
22 #include "ecmascript/js_object-inl.h"
23 #include "ecmascript/module/module_resolver.h"
24 #include "ecmascript/object_factory-inl.h"
25 #include "ecmascript/pgo_profiler/pgo_profiler.h"
26 #include "ecmascript/require/js_require_manager.h"
27 #include "ecmascript/ic/profile_type_info.h"
28 
29 namespace panda::ecmascript {
InitializeJSFunction(JSThread * thread,const JSHandle<JSFunction> & func,FunctionKind kind)30 void JSFunction::InitializeJSFunction(JSThread *thread, const JSHandle<JSFunction> &func, FunctionKind kind)
31 {
32     InitializeWithDefaultValue(thread, func);
33     auto globalConst = thread->GlobalConstants();
34     if (HasPrototype(kind)) {
35         JSHandle<JSTaggedValue> accessor = globalConst->GetHandledFunctionPrototypeAccessor();
36         if (kind == FunctionKind::BASE_CONSTRUCTOR || kind == FunctionKind::GENERATOR_FUNCTION ||
37             kind == FunctionKind::ASYNC_GENERATOR_FUNCTION || kind == FunctionKind::NONE_FUNCTION) {
38             func->SetPropertyInlinedProps(thread, PROTOTYPE_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
39             accessor = globalConst->GetHandledFunctionNameAccessor();
40             func->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
41             accessor = globalConst->GetHandledFunctionLengthAccessor();
42             func->SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
43             if (kind == FunctionKind::ASYNC_GENERATOR_FUNCTION) {
44                 // Not duplicate codes, it will slow the performace if combining and put outside!
45                 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
46                 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
47                 JSHandle<JSFunction> objFun(env->GetObjectFunction());
48                 JSHandle<JSObject> initialGeneratorFuncPrototype = factory->NewJSObjectByConstructor(objFun);
49                 JSObject::SetPrototype(thread, initialGeneratorFuncPrototype, env->GetAsyncGeneratorPrototype());
50                 func->SetProtoOrHClass(thread, initialGeneratorFuncPrototype);
51             }
52             if (kind == FunctionKind::GENERATOR_FUNCTION) {
53                 // Not duplicate codes, it will slow the performace if combining and put outside!
54                 JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
55                 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
56                 JSHandle<JSFunction> objFun(env->GetObjectFunction());
57                 JSHandle<JSObject> initialGeneratorFuncPrototype = factory->NewJSObjectByConstructor(objFun);
58                 JSObject::SetPrototype(thread, initialGeneratorFuncPrototype, env->GetGeneratorPrototype());
59                 func->SetProtoOrHClass(thread, initialGeneratorFuncPrototype);
60             }
61         } else if (!JSFunction::IsClassConstructor(kind)) {  // class ctor do nothing
62             PropertyDescriptor desc(thread, accessor, kind != FunctionKind::BUILTIN_CONSTRUCTOR, false, false);
63             [[maybe_unused]] bool success = JSObject::DefineOwnProperty(
64                 thread, JSHandle<JSObject>(func), globalConst->GetHandledPrototypeString(), desc, SCheckMode::SKIP);
65             ASSERT(success);
66         }
67     } else if (HasAccessor(kind)) {
68         JSHandle<JSTaggedValue> accessor = globalConst->GetHandledFunctionNameAccessor();
69         func->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
70         accessor = globalConst->GetHandledFunctionLengthAccessor();
71         func->SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
72     }
73 }
74 
InitializeSFunction(JSThread * thread,const JSHandle<JSFunction> & func,FunctionKind kind)75 void JSFunction::InitializeSFunction(JSThread *thread, const JSHandle<JSFunction> &func, FunctionKind kind)
76 {
77     InitializeWithDefaultValue(thread, func);
78     auto globalConst = thread->GlobalConstants();
79     JSHandle<JSTaggedValue> accessor = globalConst->GetHandledFunctionPrototypeAccessor();
80     if (HasAccessor(kind) || IsBaseConstructorKind(kind)) {
81         if (IsBaseConstructorKind(kind)) {
82             func->SetPropertyInlinedProps(thread, PROTOTYPE_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
83         }
84         accessor = globalConst->GetHandledFunctionNameAccessor();
85         func->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
86         accessor = globalConst->GetHandledFunctionLengthAccessor();
87         func->SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, accessor.GetTaggedValue());
88     }
89 }
90 
InitializeWithDefaultValue(JSThread * thread,const JSHandle<JSFunction> & func)91 void JSFunction::InitializeWithDefaultValue(JSThread *thread, const JSHandle<JSFunction> &func)
92 {
93     func->SetProtoOrHClass(thread, JSTaggedValue::Hole(), SKIP_BARRIER);
94     func->SetHomeObject(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
95     func->SetWorkNodePointer(reinterpret_cast<uintptr_t>(nullptr));
96     func->SetLexicalEnv(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
97     func->SetMachineCode(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
98     func->SetBaselineCode(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
99     func->SetRawProfileTypeInfo(thread, thread->GlobalConstants()->GetEmptyProfileTypeInfoCell(), SKIP_BARRIER);
100     func->SetMethod(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
101     func->SetModule(thread, JSTaggedValue::Undefined(), SKIP_BARRIER);
102     func->SetCodeEntry(reinterpret_cast<uintptr_t>(nullptr));
103     func->ClearCompiledCodeFlags();
104     func->SetTaskConcurrentFuncFlag(0); // 0 : default value
105     func->SetCallNapi(false);
106 }
107 
NewJSFunctionPrototype(JSThread * thread,const JSHandle<JSFunction> & func)108 JSHandle<JSObject> JSFunction::NewJSFunctionPrototype(JSThread *thread, const JSHandle<JSFunction> &func)
109 {
110     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
111     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
112     JSHandle<JSFunction> objFun;
113     if (func->IsSharedFunction()) {
114         objFun = JSHandle<JSFunction>(env->GetSObjectFunction());
115     } else {
116         objFun = JSHandle<JSFunction>(env->GetObjectFunction());
117     }
118     JSHandle<JSObject> funPro = thread->GetEcmaVM()->GetFactory()->NewJSObjectByConstructor(objFun);
119     SetFunctionPrototypeOrInstanceHClass(thread, func, funPro.GetTaggedValue());
120 
121     // set "constructor" in prototype
122     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
123     PropertyDescriptor descriptor(thread, JSHandle<JSTaggedValue>::Cast(func), true, false, true);
124     JSObject::DefineOwnProperty(thread, funPro, constructorKey, descriptor);
125 
126     return funPro;
127 }
128 
GetOrCreateInitialJSHClass(JSThread * thread,const JSHandle<JSFunction> & fun)129 JSHClass *JSFunction::GetOrCreateInitialJSHClass(JSThread *thread, const JSHandle<JSFunction> &fun)
130 {
131     JSTaggedValue protoOrHClass(fun->GetProtoOrHClass());
132     if (protoOrHClass.IsJSHClass()) {
133         return reinterpret_cast<JSHClass *>(protoOrHClass.GetTaggedObject());
134     }
135 
136     JSHandle<JSTaggedValue> proto;
137     bool needProfileTransition = false;
138     if (!fun->HasFunctionPrototype()) {
139         proto = JSHandle<JSTaggedValue>::Cast(NewJSFunctionPrototype(thread, fun));
140         if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
141             thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(fun.GetTaggedType(),
142                 JSTaggedType(proto->GetTaggedObject()->GetClass()), pgo::ProfileType::Kind::PrototypeId);
143         }
144     } else {
145         proto = JSHandle<JSTaggedValue>(thread, fun->GetProtoOrHClass());
146         needProfileTransition = proto->IsECMAObject();
147     }
148 
149     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
150     JSHandle<JSHClass> hclass;
151     if (thread->GetEcmaVM()->GetJSOptions().IsEnableInlinePropertyOptimization()) {
152         bool isStartObjSizeTracking = true;
153         uint32_t expectedOfProperties = JSFunction::CalcuExpotedOfProperties(fun, &isStartObjSizeTracking);
154         hclass = factory->NewEcmaHClass(JSObject::SIZE, expectedOfProperties, JSType::JS_OBJECT, proto);
155         if (isStartObjSizeTracking) {
156             hclass->StartObjSizeTracking();
157         }
158     } else {
159         hclass = factory->NewEcmaHClass(JSObject::SIZE, JSType::JS_OBJECT, proto);
160     }
161     fun->SetProtoOrHClass(thread, hclass);
162     if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
163         if (!needProfileTransition) {
164             thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(fun.GetTaggedType(), hclass.GetTaggedType());
165         } else {
166             thread->GetEcmaVM()->GetPGOProfiler()->ProfileProtoTransitionClass(fun, hclass, proto);
167         }
168     }
169     return *hclass;
170 }
171 
CalcuExpotedOfProperties(const JSHandle<JSFunction> & fun,bool * isStartObjSizeTracking)172 uint32_t JSFunction::CalcuExpotedOfProperties(const JSHandle<JSFunction> &fun, bool *isStartObjSizeTracking)
173 {
174     JSTaggedValue prototype = fun.GetTaggedValue();
175     uint32_t expectedPropertyCount = 0;
176     while (prototype.IsJSFunction()) {
177         JSTaggedValue method = JSFunction::Cast(prototype.GetTaggedObject())->GetMethod();
178         uint32_t count = Method::Cast(method.GetTaggedObject())->GetExpectedPropertyCount();
179         prototype = JSObject::GetPrototype(prototype);
180         // if equal MAX_EXPECTED_PROPERTY_COUNT means none expectedProperty in method
181         if (count == MethodLiteral::MAX_EXPECTED_PROPERTY_COUNT) {
182             continue;
183         }
184         expectedPropertyCount += count;
185     }
186     expectedPropertyCount += JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS;
187     // if equal DEFAULT_CAPACITY_OF_IN_OBJECTS mean none expectedProperty in func
188     if (expectedPropertyCount == JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS) {
189         *isStartObjSizeTracking = false;
190         return expectedPropertyCount;
191     }
192     if (expectedPropertyCount > PropertyAttributes::MAX_FAST_PROPS_CAPACITY) {
193         return PropertyAttributes::MAX_FAST_PROPS_CAPACITY;
194     }
195     return expectedPropertyCount;
196 }
197 
PrototypeGetter(JSThread * thread,const JSHandle<JSObject> & self)198 JSTaggedValue JSFunction::PrototypeGetter(JSThread *thread, const JSHandle<JSObject> &self)
199 {
200     JSHandle<JSFunction> func = JSHandle<JSFunction>::Cast(self);
201     if (!func->HasFunctionPrototype()) {
202         JSHandle<JSTaggedValue> proto = JSHandle<JSTaggedValue>::Cast(NewJSFunctionPrototype(thread, func));
203         if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
204             thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(func.GetTaggedType(),
205                 JSTaggedType(proto->GetTaggedObject()->GetClass()), pgo::ProfileType::Kind::PrototypeId);
206         }
207     }
208     return JSFunction::Cast(*self)->GetFunctionPrototype();
209 }
210 
PrototypeSetter(JSThread * thread,const JSHandle<JSObject> & self,const JSHandle<JSTaggedValue> & value,bool mayThrow)211 bool JSFunction::PrototypeSetter(JSThread *thread, const JSHandle<JSObject> &self, const JSHandle<JSTaggedValue> &value,
212                                  [[maybe_unused]] bool mayThrow)
213 {
214     JSHandle<JSFunction> func(self);
215     JSTaggedValue protoOrHClass = func->GetProtoOrHClass();
216     if (protoOrHClass.IsJSHClass()) {
217         // need transition
218         JSHandle<JSHClass> hclass(thread, JSHClass::Cast(protoOrHClass.GetTaggedObject()));
219         hclass->CompleteObjSizeTracking();
220         JSHandle<JSHClass> newClass = JSHClass::SetPrototypeWithNotification(thread, hclass, value);
221         func->SetProtoOrHClass(thread, newClass);
222         // Forbide to profile for changing the function prototype after an instance of the function has been created
223         if (!hclass->IsAOT() && thread->GetEcmaVM()->IsEnablePGOProfiler()) {
224             EntityId ctorMethodId = Method::Cast(func->GetMethod().GetTaggedObject())->GetMethodId();
225             thread->GetEcmaVM()->GetPGOProfiler()->InsertSkipCtorMethodIdSafe(ctorMethodId);
226         }
227     } else {
228         if (!value->IsECMAObject()) {
229             func->SetProtoOrHClass(thread, value.GetTaggedValue());
230             return true;
231         }
232 
233         bool enablePgo = thread->GetEcmaVM()->IsEnablePGOProfiler();
234         JSMutableHandle<JSTaggedValue> oldPrototype(thread, func->GetProtoOrHClass());
235         // For pgo, we need the oldPrototype to record the old ihc and phc.
236         if (enablePgo && oldPrototype->IsHole()) {
237             oldPrototype.Update(JSHandle<JSTaggedValue>::Cast(NewJSFunctionPrototype(thread, func)));
238         }
239         JSHandle<JSTaggedValue> baseIhc(thread, value->GetTaggedObject()->GetClass());
240         func->SetProtoOrHClass(thread, value.GetTaggedValue());
241         JSHClass::OptimizePrototypeForIC(thread, value, true);
242         if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
243             thread->GetEcmaVM()->GetPGOProfiler()->ProfileProtoTransitionPrototype(func, value, oldPrototype, baseIhc);
244         }
245     }
246     return true;
247 }
248 
SetFunctionPrototypeOrInstanceHClass(const JSThread * thread,const JSHandle<JSFunction> & fun,JSTaggedValue protoOrHClass)249 void JSFunction::SetFunctionPrototypeOrInstanceHClass(const JSThread *thread, const JSHandle<JSFunction> &fun,
250                                                       JSTaggedValue protoOrHClass)
251 {
252     JSHandle<JSTaggedValue> protoHandle(thread, protoOrHClass);
253     fun->SetProtoOrHClass(thread, protoHandle.GetTaggedValue());
254     if (protoHandle->IsJSHClass()) {
255         protoHandle = JSHandle<JSTaggedValue>(thread,
256                                               JSHClass::Cast(protoHandle->GetTaggedObject())->GetPrototype());
257     }
258     if (protoHandle->IsECMAObject()) {
259         JSHClass::OptimizePrototypeForIC(thread, protoHandle);
260     }
261 }
262 
GetFunctionNameString(ObjectFactory * factory,JSHandle<EcmaString> concatString,JSHandle<JSTaggedValue> target)263 EcmaString* JSFunction::GetFunctionNameString(ObjectFactory *factory, JSHandle<EcmaString> concatString,
264                                               JSHandle<JSTaggedValue> target)
265 {
266     if (target->IsJSFunction()) {
267         JSTaggedValue method = JSHandle<JSFunction>::Cast(target)->GetMethod();
268         if (!method.IsUndefined()) {
269             std::string funcName = Method::Cast(method.GetTaggedObject())->ParseFunctionName();
270             if (!funcName.empty()) {
271                 return *factory->ConcatFromString(concatString, factory->NewFromStdString(funcName));
272             }
273         }
274     }
275     return *concatString;
276 }
277 
NameGetter(JSThread * thread,const JSHandle<JSObject> & self)278 JSTaggedValue JSFunction::NameGetter(JSThread *thread, const JSHandle<JSObject> &self)
279 {
280     if (self->IsBoundFunction()) {
281         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
282         const GlobalEnvConstants *globalConst = thread->GlobalConstants();
283         JSHandle<JSBoundFunction> boundFunction(self);
284         JSHandle<JSTaggedValue> target(thread, boundFunction->GetBoundTarget());
285 
286         JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
287         JSHandle<JSTaggedValue> boundName = thread->GlobalConstants()->GetHandledBoundString();
288         JSHandle<JSTaggedValue> targetName = JSObject::GetProperty(thread, target, nameKey).GetValue();
289         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
290 
291         JSHandle<EcmaString> handlePrefixString = JSTaggedValue::ToString(thread, boundName);
292         JSHandle<EcmaString> spaceString(globalConst->GetHandledSpaceString());
293         JSHandle<EcmaString> concatString = factory->ConcatFromString(handlePrefixString, spaceString);
294 
295         EcmaString *newString;
296         if (!targetName->IsString()) {
297             newString = GetFunctionNameString(factory, concatString, target);
298         } else {
299             JSHandle<EcmaString> functionName = JSHandle<EcmaString>::Cast(targetName);
300             newString = *factory->ConcatFromString(concatString, functionName);
301         }
302 
303         return JSTaggedValue(newString);
304     }
305 
306     JSTaggedValue method = JSHandle<JSFunction>::Cast(self)->GetMethod();
307     if (method.IsUndefined()) {
308         return JSTaggedValue::Undefined();
309     }
310     Method *target = Method::Cast(method.GetTaggedObject());
311     if (target->IsNativeWithCallField()) {
312         return JSTaggedValue::Undefined();
313     }
314     auto [funcName, isASCII] = target->ParseFunctionNameView();
315     if (funcName.empty()) {
316         return thread->GlobalConstants()->GetEmptyString();
317     }
318     ObjectFactory* factory = thread->GetEcmaVM()->GetFactory();
319     const JSHandle<EcmaString> nameHdl = factory->NewFromUtf8(funcName, isASCII);
320     if (JSHandle<JSFunction>::Cast(self)->GetFunctionKind() == FunctionKind::GETTER_FUNCTION) {
321         return factory->ConcatFromString(
322             JSHandle<EcmaString>(thread->GlobalConstants()->GetHandledGetWithSpaceString()), nameHdl).GetTaggedValue();
323     }
324     if (JSHandle<JSFunction>::Cast(self)->GetFunctionKind() == FunctionKind::SETTER_FUNCTION) {
325         return factory->ConcatFromString(
326             JSHandle<EcmaString>(thread->GlobalConstants()->GetHandledSetWithSpaceString()), nameHdl).GetTaggedValue();
327     }
328     return nameHdl.GetTaggedValue();
329 }
330 
LengthGetter(JSThread * thread,const JSHandle<JSObject> & self)331 JSTaggedValue JSFunction::LengthGetter(JSThread *thread, const JSHandle<JSObject> &self)
332 {
333     // LengthGetter only support BoundFunction
334     if (self->IsBoundFunction()) {
335         JSMutableHandle<JSBoundFunction> boundFunction(thread, self.GetTaggedValue());
336         JSHandle<JSTaggedValue> arguments(thread, boundFunction->GetBoundArguments());
337         uint32_t argsLength = TaggedArray::Cast(arguments->GetTaggedObject())->GetLength();
338         while (boundFunction->GetBoundTarget().IsBoundFunction()) {
339             boundFunction.Update(boundFunction->GetBoundTarget());
340             argsLength += TaggedArray::Cast(boundFunction->GetBoundArguments())->GetLength();
341         }
342 
343         JSHandle<JSTaggedValue> target(thread, boundFunction->GetBoundTarget());
344         JSHandle<JSTaggedValue> lengthKey = thread->GlobalConstants()->GetHandledLengthString();
345 
346         bool targetHasLength =
347             JSTaggedValue::HasOwnProperty(thread, target, lengthKey);
348         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
349         uint32_t lengthValue = 0;
350         if (targetHasLength) {
351             JSHandle<JSTaggedValue> targetLength = JSTaggedValue::GetProperty(thread, target, lengthKey).GetValue();
352             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
353             if (targetLength->IsNumber()) {
354                 lengthValue =
355                     std::max(0.0, JSTaggedValue::ToNumber(thread, targetLength).GetNumber() -
356                              static_cast<double>(argsLength));
357                 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
358             }
359         }
360         return JSTaggedValue(lengthValue);
361     }
362 
363     JSHandle<JSFunction> func(self);
364     return JSTaggedValue(func->GetLength());
365 }
366 
OrdinaryHasInstance(JSThread * thread,const JSHandle<JSTaggedValue> & constructor,const JSHandle<JSTaggedValue> & obj)367 bool JSFunction::OrdinaryHasInstance(JSThread *thread, const JSHandle<JSTaggedValue> &constructor,
368                                      const JSHandle<JSTaggedValue> &obj)
369 {
370     // 1. If IsCallable(C) is false, return false.
371     if (!constructor->IsCallable()) {
372         return false;
373     }
374 
375     // 2. If C has a [[BoundTargetFunction]] internal slot, then
376     //    a. Let BC be the value of C's [[BoundTargetFunction]] internal slot.
377     //    b. Return InstanceofOperator(O,BC)  (see 12.9.4).
378     if (constructor->IsBoundFunction()) {
379         STACK_LIMIT_CHECK(thread, false);
380         JSHandle<JSBoundFunction> boundFunction(thread, JSBoundFunction::Cast(constructor->GetTaggedObject()));
381         JSTaggedValue boundTarget = boundFunction->GetBoundTarget();
382         return JSObject::InstanceOf(thread, obj, JSHandle<JSTaggedValue>(thread, boundTarget));
383     }
384     // 3. If Type(O) is not Object, return false
385     if (!obj->IsECMAObject()) {
386         return false;
387     }
388 
389     // 4. Let P be Get(C, "prototype").
390     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
391     JSHandle<JSTaggedValue> prototypeString = globalConst->GetHandledPrototypeString();
392     JSMutableHandle<JSTaggedValue> constructorPrototype(thread, JSTaggedValue::Undefined());
393     if (constructor->IsJSFunction()) {
394         JSHandle<JSFunction> ctor(thread, constructor->GetTaggedObject());
395         JSHandle<JSTaggedValue> ctorProtoOrHclass(thread, ctor->GetProtoOrHClass());
396         if (!ctorProtoOrHclass->IsHole()) {
397             if (!ctorProtoOrHclass->IsJSHClass()) {
398                 constructorPrototype.Update(ctorProtoOrHclass);
399             } else {
400                 JSTaggedValue ctorProto = JSHClass::Cast(ctorProtoOrHclass->GetTaggedObject())->GetProto();
401                 constructorPrototype.Update(ctorProto);
402             }
403         } else {
404             constructorPrototype.Update(JSTaggedValue::GetProperty(thread, constructor, prototypeString).GetValue());
405         }
406     } else {
407         constructorPrototype.Update(JSTaggedValue::GetProperty(thread, constructor, prototypeString).GetValue());
408     }
409 
410     // 5. ReturnIfAbrupt(P).
411     // no throw exception, so needn't return
412     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
413 
414     // 6. If Type(P) is not Object, throw a TypeError exception.
415     if (!constructorPrototype->IsECMAObject()) {
416         THROW_TYPE_ERROR_AND_RETURN(thread, "HasInstance: is not Object", false);
417     }
418 
419     // 7. Repeat
420     //    a.Let O be O.[[GetPrototypeOf]]().
421     //    b.ReturnIfAbrupt(O).
422     //    c.If O is null, return false.
423     //    d.If SameValue(P, O) is true, return true.
424     JSMutableHandle<JSTaggedValue> object(thread, obj.GetTaggedValue());
425     while (!object->IsNull()) {
426         object.Update(JSTaggedValue::GetPrototype(thread, object));
427         RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
428         if (JSTaggedValue::SameValue(object, constructorPrototype)) {
429             return true;
430         }
431     }
432     return false;
433 }
434 
MakeConstructor(JSThread * thread,const JSHandle<JSFunction> & func,const JSHandle<JSTaggedValue> & proto,bool writable)435 bool JSFunction::MakeConstructor(JSThread *thread, const JSHandle<JSFunction> &func,
436                                  const JSHandle<JSTaggedValue> &proto, bool writable)
437 {
438     ASSERT_PRINT(proto->IsHeapObject() || proto->IsUndefined(), "proto must be JSObject or Undefined");
439     ASSERT_PRINT(func->IsConstructor(), "func must be Constructor type");
440     JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
441     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
442     JSHandle<JSTaggedValue> constructorKey = globalConst->GetHandledConstructorString();
443 
444     ASSERT_PRINT(func->GetProtoOrHClass().IsHole() && func->IsExtensible(),
445                  "function doesn't has proto_type property and is extensible object");
446     ASSERT_PRINT(JSObject::HasProperty(thread, JSHandle<JSObject>(func), constructorKey),
447                  "function must have constructor");
448 
449     // proto.constructor = func
450     bool status = false;
451     if (proto->IsUndefined()) {
452         // Let prototype be ObjectCreate(%ObjectPrototype%).
453         JSHandle<JSTaggedValue> objPrototype = env->GetObjectFunctionPrototype();
454         PropertyDescriptor constructorDesc(thread, JSHandle<JSTaggedValue>::Cast(func), writable, false, true);
455         status = JSTaggedValue::DefinePropertyOrThrow(thread, objPrototype, constructorKey, constructorDesc);
456     } else {
457         PropertyDescriptor constructorDesc(thread, JSHandle<JSTaggedValue>::Cast(func), writable, false, true);
458         status = JSTaggedValue::DefinePropertyOrThrow(thread, proto, constructorKey, constructorDesc);
459     }
460     RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
461 
462     ASSERT_PRINT(status, "DefineProperty construct failed");
463     // func.prototype = proto
464     // Let status be DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]:
465     // prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false}).
466     SetFunctionPrototypeOrInstanceHClass(thread, func, proto.GetTaggedValue());
467 
468     ASSERT_PRINT(status, "DefineProperty proto_type failed");
469     return status;
470 }
471 
Call(EcmaRuntimeCallInfo * info)472 JSTaggedValue JSFunction::Call(EcmaRuntimeCallInfo *info)
473 {
474     if (info == nullptr) {
475         return JSTaggedValue::Exception();
476     }
477 
478     JSThread *thread = info->GetThread();
479     // 1. ReturnIfAbrupt(F).
480     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
481     JSHandle<JSTaggedValue> func = info->GetFunction();
482     // 2. If argumentsList was not passed, let argumentsList be a new empty List.
483     // 3. If IsCallable(F) is false, throw a TypeError exception.
484     if (!func->IsCallable()) {
485         RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
486         THROW_TYPE_ERROR_AND_RETURN(thread, "Callable is false", JSTaggedValue::Exception());
487     }
488 
489     auto *hclass = func->GetTaggedObject()->GetClass();
490     if (hclass->IsClassConstructor()) {
491         RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
492         THROW_TYPE_ERROR_AND_RETURN(thread, "class constructor cannot call", JSTaggedValue::Exception());
493     }
494     return EcmaInterpreter::Execute(info);
495 }
496 
Construct(EcmaRuntimeCallInfo * info)497 JSTaggedValue JSFunction::Construct(EcmaRuntimeCallInfo *info)
498 {
499     if (info == nullptr) {
500         return JSTaggedValue::Exception();
501     }
502 
503     JSThread *thread = info->GetThread();
504     JSHandle<JSTaggedValue> func(info->GetFunction());
505     JSHandle<JSTaggedValue> target = info->GetNewTarget();
506     if (target->IsUndefined()) {
507         target = func;
508         info->SetNewTarget(target.GetTaggedValue());
509     }
510     if (!(func->IsConstructor() && target->IsConstructor())) {
511         RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
512         THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
513     }
514 
515     if (func->IsJSFunction()) {
516         return JSFunction::ConstructInternal(info);
517     } else if (func->IsJSProxy()) {
518         return JSProxy::ConstructInternal(info);
519     } else {
520         ASSERT(func->IsBoundFunction());
521         return JSBoundFunction::ConstructInternal(info);
522     }
523 }
524 
Invoke(EcmaRuntimeCallInfo * info,const JSHandle<JSTaggedValue> & key)525 JSTaggedValue JSFunction::Invoke(EcmaRuntimeCallInfo *info, const JSHandle<JSTaggedValue> &key)
526 {
527     if (info == nullptr) {
528         return JSTaggedValue::Exception();
529     }
530 
531     ASSERT(JSTaggedValue::IsPropertyKey(key));
532     JSThread *thread = info->GetThread();
533     JSHandle<JSTaggedValue> thisArg = info->GetThis();
534     JSHandle<JSTaggedValue> func(JSTaggedValue::GetProperty(thread, thisArg, key).GetValue());
535     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
536     info->SetFunction(func.GetTaggedValue());
537     return JSFunction::Call(info);
538 }
539 
InvokeOptimizedEntrypoint(JSThread * thread,JSHandle<JSFunction> mainFunc,JSHandle<JSTaggedValue> & thisArg,CJSInfo * cjsInfo)540 JSTaggedValue JSFunction::InvokeOptimizedEntrypoint(JSThread *thread, JSHandle<JSFunction> mainFunc,
541     JSHandle<JSTaggedValue> &thisArg, CJSInfo* cjsInfo)
542 {
543     ASSERT(thread->IsInManagedState());
544     if (mainFunc->IsClassConstructor()) {
545         {
546             ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
547             JSHandle<JSObject> error = factory->GetJSError(ErrorType::TYPE_ERROR,
548                 "class constructor cannot called without 'new'", StackCheck::NO);
549             thread->SetException(error.GetTaggedValue());
550         }
551         return thread->GetException();
552     }
553     Method *method = mainFunc->GetCallTarget();
554     size_t actualNumArgs = method->GetNumArgs();
555     const JSTaggedType *prevFp = thread->GetLastLeaveFrame();
556     JSTaggedValue res;
557     std::vector<JSTaggedType> args;
558 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
559     RuntimeStubs::StartCallTimer(thread->GetGlueAddr(), mainFunc.GetTaggedType(), true);
560 #endif
561     if (mainFunc->IsCompiledFastCall()) {
562         // entry of aot
563         args = JSFunction::GetArgsData(true, thisArg, mainFunc, cjsInfo);
564         res = thread->GetEcmaVM()->FastCallAot(actualNumArgs, args.data(), prevFp);
565     } else {
566         args = JSFunction::GetArgsData(false, thisArg, mainFunc, cjsInfo);
567         // entry of aot
568         res = thread->GetCurrentEcmaContext()->ExecuteAot(actualNumArgs, args.data(), prevFp, false);
569     }
570 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
571     RuntimeStubs::EndCallTimer(thread->GetGlueAddr(), mainFunc.GetTaggedType());
572 #endif
573     if (thread->HasPendingException()) {
574         return thread->GetException();
575     }
576     return res;
577 }
578 
GetArgsData(bool isFastCall,JSHandle<JSTaggedValue> & thisArg,JSHandle<JSFunction> mainFunc,CJSInfo * cjsInfo)579 std::vector<JSTaggedType> JSFunction::GetArgsData(bool isFastCall, JSHandle<JSTaggedValue> &thisArg,
580     JSHandle<JSFunction> mainFunc, CJSInfo* cjsInfo)
581 {
582     size_t argsNum;
583     uint32_t mandatoryNum;
584     Method *method = mainFunc->GetCallTarget();
585     size_t actualNumArgs = method->GetNumArgs();
586     if (isFastCall) {
587         argsNum = actualNumArgs + NUM_MANDATORY_JSFUNC_ARGS - 1;
588         mandatoryNum = NUM_MANDATORY_JSFUNC_ARGS - 1;
589     } else {
590         argsNum = actualNumArgs + NUM_MANDATORY_JSFUNC_ARGS;
591         mandatoryNum = NUM_MANDATORY_JSFUNC_ARGS;
592     }
593     std::vector<JSTaggedType> args(argsNum, JSTaggedValue::Undefined().GetRawData());
594     args[0] = mainFunc.GetTaggedValue().GetRawData();
595     if (isFastCall) {
596         args[1] = thisArg.GetTaggedValue().GetRawData(); // 1: args number
597     } else {
598         args[2] = thisArg.GetTaggedValue().GetRawData(); // 2: args number
599     }
600     if (cjsInfo != nullptr) {
601         args[mandatoryNum++] = cjsInfo->exportsHdl.GetTaggedValue().GetRawData();
602         args[mandatoryNum++] = cjsInfo->requireHdl.GetTaggedValue().GetRawData();
603         args[mandatoryNum++] = cjsInfo->moduleHdl.GetTaggedValue().GetRawData();
604         args[mandatoryNum++] = cjsInfo->filenameHdl.GetTaggedValue().GetRawData();
605         args[mandatoryNum] = cjsInfo->dirnameHdl.GetTaggedValue().GetRawData();
606     }
607     return args;
608 }
609 
InvokeOptimizedEntrypoint(JSThread * thread,JSHandle<JSFunction> func,EcmaRuntimeCallInfo * info)610 JSTaggedValue JSFunction::InvokeOptimizedEntrypoint(JSThread *thread, JSHandle<JSFunction> func,
611     EcmaRuntimeCallInfo *info)
612 {
613     ASSERT(thread->IsInManagedState());
614     Method *method = func->GetCallTarget();
615     JSTaggedValue resultValue;
616     size_t numArgs = method->GetNumArgsWithCallField();
617     bool needPushArgv = numArgs > info->GetArgsNumber();
618     const JSTaggedType *prevFp = thread->GetLastLeaveFrame();
619 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
620     RuntimeStubs::StartCallTimer(thread->GetGlueAddr(), func.GetTaggedType(), true);
621 #endif
622     if (func->IsCompiledFastCall()) {
623         if (needPushArgv) {
624             info = EcmaInterpreter::ReBuildRuntimeCallInfo(thread, info, numArgs);
625             RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
626         }
627         JSTaggedType *stackArgs = info->GetArgs();
628         stackArgs[1] = stackArgs[0];
629         resultValue = thread->GetEcmaVM()->FastCallAot(info->GetArgsNumber(), stackArgs + 1, prevFp);
630     } else {
631         resultValue = thread->GetCurrentEcmaContext()->ExecuteAot(info->GetArgsNumber(),
632             info->GetArgs(), prevFp, needPushArgv);
633     }
634 #if ECMASCRIPT_ENABLE_FUNCTION_CALL_TIMER
635     RuntimeStubs::EndCallTimer(thread->GetGlueAddr(), func.GetTaggedType());
636 #endif
637     return resultValue;
638 }
639 
640 // [[Construct]]
ConstructInternal(EcmaRuntimeCallInfo * info)641 JSTaggedValue JSFunction::ConstructInternal(EcmaRuntimeCallInfo *info)
642 {
643     ASSERT(info != nullptr);
644     JSThread *thread = info->GetThread();
645     // func need to create a new handle, because optimized EcmaRuntimeCallInfo may overwrite this position.
646     JSHandle<JSFunction> func(thread, info->GetFunction().GetTaggedValue());
647     JSHandle<JSTaggedValue> newTarget(info->GetNewTarget());
648     ASSERT(newTarget->IsECMAObject());
649     if (!func->IsConstructor()) {
650         RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
651         THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
652     }
653 
654     JSHandle<JSTaggedValue> obj(thread, JSTaggedValue::Undefined());
655     if (func->IsBase()) {
656         ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
657         obj = JSHandle<JSTaggedValue>(factory->NewJSObjectByConstructor(func, newTarget));
658         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
659     }
660 
661     JSTaggedValue resultValue;
662     info->SetThis(obj.GetTaggedValue());
663     if (func->IsCompiledCode()) {
664         resultValue = InvokeOptimizedEntrypoint(thread, func, info);
665         const JSTaggedType *curSp = thread->GetCurrentSPFrame();
666         InterpretedEntryFrame *entryState = InterpretedEntryFrame::GetFrameFromSp(curSp);
667         JSTaggedType *prevSp = entryState->base.prev;
668         thread->SetCurrentSPFrame(prevSp);
669     } else {
670         resultValue = EcmaInterpreter::Execute(info);
671     }
672     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
673     // 9.3.2 [[Construct]] (argumentsList, newTarget)
674     if (resultValue.IsECMAObject()) {
675         return resultValue;
676     }
677     if (func->IsBase()) {
678         return obj.GetTaggedValue();
679     }
680     // derived ctor(sub class) return the obj which created by base ctor(parent class)
681     if (func->IsDerivedConstructor()) {
682         if (!resultValue.IsECMAObject() && !resultValue.IsUndefined()) {
683             THROW_TYPE_ERROR_AND_RETURN(thread,
684                 "derived class constructor must return an object or undefined", JSTaggedValue::Exception());
685         }
686         return resultValue;
687     }
688     if (!resultValue.IsUndefined()) {
689         RETURN_STACK_BEFORE_THROW_IF_ASM(thread);
690         THROW_TYPE_ERROR_AND_RETURN(thread, "function is non-constructor", JSTaggedValue::Exception());
691     }
692     return obj.GetTaggedValue();
693 }
694 
GetFunctionName(JSThread * thread,const JSHandle<JSFunctionBase> & func)695 JSHandle<JSTaggedValue> JSFunctionBase::GetFunctionName(JSThread *thread, const JSHandle<JSFunctionBase> &func)
696 {
697     JSHandle<JSTaggedValue> nameKey = thread->GlobalConstants()->GetHandledNameString();
698 
699     return JSObject::GetProperty(thread, JSHandle<JSTaggedValue>(func), nameKey).GetValue();
700 }
701 
SetFunctionName(JSThread * thread,const JSHandle<JSFunctionBase> & func,const JSHandle<JSTaggedValue> & name,const JSHandle<JSTaggedValue> & prefix)702 bool JSFunctionBase::SetFunctionName(JSThread *thread, const JSHandle<JSFunctionBase> &func,
703                                      const JSHandle<JSTaggedValue> &name, const JSHandle<JSTaggedValue> &prefix)
704 {
705     ASSERT_PRINT(func->IsExtensible(), "Function must be extensible");
706     ASSERT_PRINT(name->IsStringOrSymbol(), "name must be string or symbol");
707     bool needPrefix = false;
708     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
709     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
710     if (!prefix->IsUndefined()) {
711         ASSERT_PRINT(prefix->IsString(), "prefix must be string");
712         needPrefix = true;
713     }
714     // If Type(name) is Symbol, then
715     // Let description be name’s [[Description]] value.
716     // If description is undefined, let name be the empty String.
717     // Else, let name be the concatenation of "[", description, and "]".
718     JSHandle<EcmaString> functionName;
719     if (name->IsSymbol()) {
720         JSTaggedValue description = JSHandle<JSSymbol>::Cast(name)->GetDescription();
721         JSHandle<EcmaString> descriptionHandle(thread, description);
722         if (description.IsUndefined()) {
723             functionName = factory->GetEmptyString();
724         } else {
725             JSHandle<EcmaString> leftBrackets(globalConst->GetHandledLeftSquareBracketString());
726             JSHandle<EcmaString> rightBrackets(globalConst->GetHandledRightSquareBracketString());
727             functionName = factory->ConcatFromString(leftBrackets, descriptionHandle);
728             functionName = factory->ConcatFromString(functionName, rightBrackets);
729         }
730     } else {
731         functionName = JSHandle<EcmaString>::Cast(name);
732     }
733     EcmaString *newString;
734     if (needPrefix) {
735         JSHandle<EcmaString> handlePrefixString = JSTaggedValue::ToString(thread, prefix);
736         JSHandle<EcmaString> spaceString(globalConst->GetHandledSpaceString());
737         JSHandle<EcmaString> concatString = factory->ConcatFromString(handlePrefixString, spaceString);
738         newString = *factory->ConcatFromString(concatString, functionName);
739     } else {
740         newString = *functionName;
741     }
742     JSHandle<JSTaggedValue> nameHandle(thread, newString);
743     // String.prototype.trimLeft.name shoud be trimStart
744     if (!nameHandle.IsEmpty()
745         && nameHandle.GetTaggedValue() == globalConst->GetHandledTrimLeftString().GetTaggedValue()) {
746         nameHandle = globalConst->GetHandledTrimStartString();
747     }
748     // String.prototype.trimRight.name shoud be trimEnd
749     if (!nameHandle.IsEmpty()
750         && nameHandle.GetTaggedValue() == globalConst->GetHandledTrimRightString().GetTaggedValue()) {
751         nameHandle = globalConst->GetHandledTrimEndString();
752     }
753     JSHandle<JSTaggedValue> nameKey = globalConst->GetHandledNameString();
754     PropertyDescriptor nameDesc(thread, nameHandle, false, false, true);
755     JSHandle<JSTaggedValue> funcHandle(func);
756     return JSTaggedValue::DefinePropertyOrThrow(thread, funcHandle, nameKey, nameDesc);
757 }
758 
SetFunctionLength(JSThread * thread,const JSHandle<JSFunction> & func,JSTaggedValue length,bool cfg)759 bool JSFunction::SetFunctionLength(JSThread *thread, const JSHandle<JSFunction> &func, JSTaggedValue length, bool cfg)
760 {
761     ASSERT_PRINT(func->IsExtensible(), "Function must be extensible");
762     ASSERT_PRINT(length.IsInteger(), "length must be integer");
763     JSHandle<JSTaggedValue> lengthKeyHandle = thread->GlobalConstants()->GetHandledLengthString();
764     ASSERT_PRINT(!JSTaggedValue::Less(thread, JSHandle<JSTaggedValue>(thread, length),
765                                       JSHandle<JSTaggedValue>(thread, JSTaggedValue(0))),
766                  "length must be non negative integer");
767     PropertyDescriptor lengthDesc(thread, JSHandle<JSTaggedValue>(thread, length), false, false, cfg);
768     JSHandle<JSTaggedValue> funcHandle(func);
769     return JSTaggedValue::DefinePropertyOrThrow(thread, funcHandle, lengthKeyHandle, lengthDesc);
770 }
771 
772 // 9.4.1.2[[Construct]](argumentsList, newTarget)
ConstructInternal(EcmaRuntimeCallInfo * info)773 JSTaggedValue JSBoundFunction::ConstructInternal(EcmaRuntimeCallInfo *info)
774 {
775     JSThread *thread = info->GetThread();
776     JSHandle<JSBoundFunction> func(info->GetFunction());
777     JSHandle<JSTaggedValue> target(thread, func->GetBoundTarget());
778     if (!target->IsConstructor()) {
779         THROW_TYPE_ERROR_AND_RETURN(thread, "Constructor is false", JSTaggedValue::Exception());
780     }
781     JSHandle<JSTaggedValue> newTarget = info->GetNewTarget();
782     JSMutableHandle<JSTaggedValue> newTargetMutable(thread, newTarget.GetTaggedValue());
783     if (JSTaggedValue::SameValue(func.GetTaggedValue(), newTarget.GetTaggedValue())) {
784         newTargetMutable.Update(target.GetTaggedValue());
785     }
786 
787     JSHandle<TaggedArray> boundArgs(thread, func->GetBoundArguments());
788     const uint32_t boundLength = boundArgs->GetLength();
789     const uint32_t argsLength = info->GetArgsNumber() + boundLength;
790     JSHandle<JSTaggedValue> undefined = thread->GlobalConstants()->GetHandledUndefined();
791     uint32_t argc = info->GetArgsNumber();
792     std::vector<JSTaggedType> argArray(argc);
793     for (uint32_t index = 0; index < argc; ++index) {
794         argArray[index] = info->GetCallArgValue(index).GetRawData();
795     }
796     JSTaggedType *currentSp = reinterpret_cast<JSTaggedType *>(info);
797     InterpretedEntryFrame *currentEntryState = InterpretedEntryFrame::GetFrameFromSp(currentSp);
798     JSTaggedType *prevSp = currentEntryState->base.prev;
799     thread->SetCurrentSPFrame(prevSp);
800     EcmaRuntimeCallInfo *runtimeInfo =
801         EcmaInterpreter::NewRuntimeCallInfo(thread, target, undefined, newTargetMutable, argsLength);
802     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
803     if (boundLength != 0) {
804         runtimeInfo->SetCallArg(boundLength, boundArgs);
805     }
806     for (uint32_t index = 0; index < argc; index++) {
807         runtimeInfo->SetCallArg(static_cast<uint32_t>(index + boundLength), JSTaggedValue(argArray[index]));
808     }
809     return JSFunction::Construct(runtimeInfo);
810 }
811 
ProxyRevocFunctions(const JSThread * thread,const JSHandle<JSProxyRevocFunction> & revoker)812 void JSProxyRevocFunction::ProxyRevocFunctions(const JSThread *thread, const JSHandle<JSProxyRevocFunction> &revoker)
813 {
814     // 1.Let p be the value of F’s [[RevocableProxy]] internal slot.
815     JSTaggedValue proxy = revoker->GetRevocableProxy();
816     // 2.If p is null, return undefined.
817     if (proxy.IsNull()) {
818         return;
819     }
820 
821     // 3.Set the value of F’s [[RevocableProxy]] internal slot to null.
822     revoker->SetRevocableProxy(thread, JSTaggedValue::Null());
823 
824     // 4.Assert: p is a Proxy object.
825     ASSERT(proxy.IsJSProxy());
826     JSHandle<JSProxy> proxyHandle(thread, proxy);
827 
828     // 5 ~ 6 Set internal slot of p to null.
829     proxyHandle->SetTarget(thread, JSTaggedValue::Null());
830     proxyHandle->SetHandler(thread, JSTaggedValue::Null());
831     proxyHandle->SetIsRevoked(true);
832 }
833 
AccessCallerArgumentsThrowTypeError(EcmaRuntimeCallInfo * argv)834 JSTaggedValue JSFunction::AccessCallerArgumentsThrowTypeError(EcmaRuntimeCallInfo *argv)
835 {
836     THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(),
837                                 "Under strict mode, 'caller' and 'arguments' properties must not be accessed.",
838                                 JSTaggedValue::Exception());
839 }
840 
IntlNameGetter(JSThread * thread,const JSHandle<JSObject> & self)841 JSTaggedValue JSIntlBoundFunction::IntlNameGetter(JSThread *thread, [[maybe_unused]] const JSHandle<JSObject> &self)
842 {
843     return thread->GlobalConstants()->GetEmptyString();
844 }
845 
SetFunctionNameNoPrefix(JSThread * thread,JSFunction * func,JSTaggedValue name)846 void JSFunction::SetFunctionNameNoPrefix(JSThread *thread, JSFunction *func, JSTaggedValue name)
847 {
848     ASSERT_PRINT(func->IsExtensible(), "Function must be extensible");
849     ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
850     const GlobalEnvConstants *globalConst = thread->GlobalConstants();
851 
852     JSHandle<JSTaggedValue> funcHandle(thread, func);
853     {
854         JSMutableHandle<JSTaggedValue> nameHandle(thread, JSTaggedValue::Undefined());
855         if (!name.IsSymbol()) {
856             nameHandle.Update(name);
857         } else {
858             JSHandle<JSTaggedValue> nameBegin(thread, name);
859             JSTaggedValue description = JSSymbol::Cast(name.GetTaggedObject())->GetDescription();
860             if (description.IsUndefined()) {
861                 nameHandle.Update(globalConst->GetEmptyString());
862             } else {
863                 JSHandle<EcmaString> leftBrackets(globalConst->GetHandledLeftSquareBracketString());
864                 JSHandle<EcmaString> rightBrackets(globalConst->GetHandledRightSquareBracketString());
865                 JSHandle<EcmaString> concatName = factory->ConcatFromString(leftBrackets,
866                     JSHandle<EcmaString>(thread, JSSymbol::Cast(nameBegin->GetTaggedObject())->GetDescription()));
867                 concatName = factory->ConcatFromString(concatName, rightBrackets);
868                 nameHandle.Update(concatName.GetTaggedValue());
869             }
870         }
871         PropertyDescriptor nameDesc(thread, nameHandle, false, false, true);
872         JSTaggedValue::DefinePropertyOrThrow(thread, funcHandle, globalConst->GetHandledNameString(), nameDesc);
873     }
874 }
875 
GetInstanceJSHClass(JSThread * thread,JSHandle<JSFunction> constructor,JSHandle<JSTaggedValue> newTarget)876 JSHandle<JSHClass> JSFunction::GetInstanceJSHClass(JSThread *thread, JSHandle<JSFunction> constructor,
877                                                    JSHandle<JSTaggedValue> newTarget)
878 {
879     JSHandle<JSHClass> ctorInitialJSHClass(thread, JSFunction::GetOrCreateInitialJSHClass(thread, constructor));
880     // newTarget is construct itself
881     if (newTarget.GetTaggedValue() == constructor.GetTaggedValue()) {
882         return ctorInitialJSHClass;
883     }
884 
885     // newTarget is derived-class of constructor
886     if (newTarget->IsJSFunction()) {
887         JSHandle<JSFunction> newTargetFunc = JSHandle<JSFunction>::Cast(newTarget);
888         if (newTargetFunc->IsDerivedConstructor()) {
889             JSMutableHandle<JSTaggedValue> mutableNewTarget(thread, newTarget.GetTaggedValue());
890             JSMutableHandle<JSTaggedValue> mutableNewTargetProto(thread, JSTaggedValue::Undefined());
891             while (!mutableNewTargetProto->IsNull()) {
892                 mutableNewTargetProto.Update(JSTaggedValue::GetPrototype(thread, mutableNewTarget));
893                 RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSHClass, thread);
894                 if (mutableNewTargetProto.GetTaggedValue() == constructor.GetTaggedValue()) {
895                     return GetOrCreateDerivedJSHClass(thread, newTargetFunc, ctorInitialJSHClass);
896                 }
897                 mutableNewTarget.Update(mutableNewTargetProto.GetTaggedValue());
898             }
899         }
900     }
901 
902     // ECMA2015 9.1.15 3.Let proto be Get(constructor, "prototype").
903     JSMutableHandle<JSTaggedValue> prototype(thread, JSTaggedValue::Undefined());
904     if (newTarget->IsJSFunction()) {
905         JSHandle<JSFunction> newTargetFunc = JSHandle<JSFunction>::Cast(newTarget);
906         FunctionKind kind = newTargetFunc->GetFunctionKind();
907         if (HasPrototype(kind)) {
908             prototype.Update(PrototypeGetter(thread, JSHandle<JSObject>::Cast(newTargetFunc)));
909         }
910     } else {
911         // Such case: bound function and define a "prototype" property.
912         JSHandle<JSTaggedValue> customizePrototype =
913             JSTaggedValue::GetProperty(thread, newTarget, thread->GlobalConstants()->GetHandledPrototypeString())
914                 .GetValue();
915         RETURN_HANDLE_IF_ABRUPT_COMPLETION(JSHClass, thread);
916         prototype.Update(customizePrototype.GetTaggedValue());
917         // Reload JSHClass of constructor, where the lookup of 'prototype' property may change it.
918         ctorInitialJSHClass = JSHandle<JSHClass>(thread, JSFunction::GetOrCreateInitialJSHClass(thread, constructor));
919     }
920 
921     if (!prototype->IsECMAObject()) {
922         prototype.Update(constructor->GetFunctionPrototype());
923     }
924 
925     JSHandle<JSHClass> newJSHClass = JSHClass::Clone(thread, ctorInitialJSHClass);
926     newJSHClass->SetElementsKind(ElementsKind::GENERIC);
927     newJSHClass->SetPrototype(thread, prototype);
928 
929     return newJSHClass;
930 }
931 
GetOrCreateDerivedJSHClass(JSThread * thread,JSHandle<JSFunction> derived,JSHandle<JSHClass> ctorInitialJSHClass)932 JSHandle<JSHClass> JSFunction::GetOrCreateDerivedJSHClass(JSThread *thread, JSHandle<JSFunction> derived,
933                                                           JSHandle<JSHClass> ctorInitialJSHClass)
934 {
935     JSTaggedValue protoOrHClass(derived->GetProtoOrHClass());
936     // has cached JSHClass, return directly
937     if (protoOrHClass.IsJSHClass()) {
938         return JSHandle<JSHClass>(thread, protoOrHClass);
939     }
940     JSHandle<JSHClass> newJSHClass;
941     if (thread->GetEcmaVM()->GetJSOptions().IsEnableInlinePropertyOptimization()) {
942         bool isStartObjSizeTracking = true;
943         uint32_t expectedOfProperties = CalcuExpotedOfProperties(derived, &isStartObjSizeTracking);
944         if (isStartObjSizeTracking) {
945             newJSHClass = JSHClass::CloneAndIncInlinedProperties(thread, ctorInitialJSHClass, expectedOfProperties);
946             newJSHClass->StartObjSizeTracking();
947         } else {
948             newJSHClass = JSHClass::Clone(thread, ctorInitialJSHClass);
949         }
950     } else {
951         newJSHClass = JSHClass::Clone(thread, ctorInitialJSHClass);
952     }
953     newJSHClass->SetElementsKind(ElementsKind::GENERIC);
954     // guarante derived has function prototype
955     JSHandle<JSTaggedValue> prototype(thread, derived->GetProtoOrHClass());
956     ASSERT(!prototype->IsHole());
957     newJSHClass->SetPrototype(thread, prototype);
958     derived->SetProtoOrHClass(thread, newJSHClass);
959 
960     if (thread->GetEcmaVM()->IsEnablePGOProfiler()) {
961         thread->GetEcmaVM()->GetPGOProfiler()->ProfileClassRootHClass(derived.GetTaggedType(),
962             newJSHClass.GetTaggedType());
963     }
964 
965     return newJSHClass;
966 }
967 
GetRecordName() const968 CString JSFunction::GetRecordName() const
969 {
970     JSTaggedValue module = GetModule();
971     if (module.IsSourceTextModule()) {
972         return SourceTextModule::GetModuleName(module);
973     }
974     if (module.IsString()) {
975         return ConvertToString(module);
976     }
977     LOG_INTERPRETER(DEBUG) << "record name is undefined";
978     return "";
979 }
980 
981 // Those interface below is discarded
InitializeJSFunction(JSThread * thread,const JSHandle<GlobalEnv> & env,const JSHandle<JSFunction> & func,FunctionKind kind)982 void JSFunction::InitializeJSFunction(JSThread *thread, [[maybe_unused]] const JSHandle<GlobalEnv> &env,
983                                       const JSHandle<JSFunction> &func, FunctionKind kind)
984 {
985     InitializeJSFunction(thread, func, kind);
986 }
987 
NameSetter(JSThread * thread,const JSHandle<JSObject> & self,const JSHandle<JSTaggedValue> & value,bool mayThrow)988 bool JSFunction::NameSetter(JSThread *thread, const JSHandle<JSObject> &self, const JSHandle<JSTaggedValue> &value,
989                             [[maybe_unused]] bool mayThrow)
990 {
991     if (self->IsPropertiesDict()) {
992         // replace setter with value
993         JSHandle<JSTaggedValue> nameString = thread->GlobalConstants()->GetHandledNameString();
994         return self->UpdatePropertyInDictionary(thread, nameString.GetTaggedValue(), value.GetTaggedValue());
995     }
996     self->SetPropertyInlinedProps(thread, NAME_INLINE_PROPERTY_INDEX, value.GetTaggedValue());
997     return true;
998 }
999 
1000 // NOTE: move to INL file?
SetFunctionLength(const JSThread * thread,JSTaggedValue length)1001 void JSFunction::SetFunctionLength(const JSThread *thread, JSTaggedValue length)
1002 {
1003     ASSERT(!IsPropertiesDict());
1004     SetPropertyInlinedProps(thread, LENGTH_INLINE_PROPERTY_INDEX, length);
1005 }
1006 
1007 // static
SetFunctionExtraInfo(JSThread * thread,const JSHandle<JSFunction> & func,void * nativeFunc,const NativePointerCallback & deleter,void * data,size_t nativeBindingsize,Concurrent isConcurrent)1008 void JSFunction::SetFunctionExtraInfo(JSThread *thread, const JSHandle<JSFunction> &func, void *nativeFunc,
1009                                       const NativePointerCallback &deleter, void *data, size_t nativeBindingsize,
1010                                       Concurrent isConcurrent)
1011 {
1012     JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(*func, HASH_OFFSET);
1013     EcmaVM *vm = thread->GetEcmaVM();
1014     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(hashField));
1015     JSHandle<JSNativePointer> pointer = vm->GetFactory()->NewJSNativePointer(nativeFunc, deleter, data,
1016         false, nativeBindingsize, isConcurrent);
1017     if (!func->HasHash()) {
1018         Barriers::SetObject<true>(thread, *func, HASH_OFFSET, pointer.GetTaggedValue().GetRawData());
1019         return;
1020     }
1021     if (value->IsHeapObject()) {
1022         if (value->IsJSNativePointer()) {
1023             Barriers::SetObject<true>(thread, *func, HASH_OFFSET, pointer.GetTaggedValue().GetRawData());
1024             return;
1025         }
1026         JSHandle<TaggedArray> array(value);
1027 
1028         uint32_t nativeFieldCount = array->GetExtraLength();
1029         if (array->GetLength() >= nativeFieldCount + RESOLVED_MAX_SIZE) {
1030             array->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer);
1031         } else {
1032             JSHandle<TaggedArray> newArray = vm->GetFactory()->NewTaggedArray(nativeFieldCount + RESOLVED_MAX_SIZE);
1033             newArray->SetExtraLength(nativeFieldCount);
1034             for (uint32_t i = 0; i < nativeFieldCount; i++) {
1035                 newArray->Set(thread, i, array->Get(i));
1036             }
1037             newArray->Set(thread, nativeFieldCount + HASH_INDEX, array->Get(nativeFieldCount + HASH_INDEX));
1038             newArray->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer);
1039             Barriers::SetObject<true>(thread, *func, HASH_OFFSET, newArray.GetTaggedValue().GetRawData());
1040         }
1041     } else {
1042         JSHandle<TaggedArray> newArray = vm->GetFactory()->NewTaggedArray(RESOLVED_MAX_SIZE);
1043         newArray->SetExtraLength(0);
1044         newArray->Set(thread, HASH_INDEX, value);
1045         newArray->Set(thread, FUNCTION_EXTRA_INDEX, pointer);
1046         Barriers::SetObject<true>(thread, *func, HASH_OFFSET, newArray.GetTaggedValue().GetRawData());
1047     }
1048 }
1049 
1050 // static
SetSFunctionExtraInfo(JSThread * thread,const JSHandle<JSFunction> & func,void * nativeFunc,const NativePointerCallback & deleter,void * data,size_t nativeBindingsize)1051 void JSFunction::SetSFunctionExtraInfo(JSThread *thread, const JSHandle<JSFunction> &func, void *nativeFunc,
1052                                        const NativePointerCallback &deleter, void *data, size_t nativeBindingsize)
1053 {
1054     JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(*func, HASH_OFFSET);
1055     EcmaVM *vm = thread->GetEcmaVM();
1056     JSHandle<JSTaggedValue> value(thread, JSTaggedValue(hashField));
1057     JSHandle<JSNativePointer> pointer =
1058         vm->GetFactory()->NewSJSNativePointer(nativeFunc, deleter, data, false, nativeBindingsize);
1059     if (!func->HasHash()) {
1060         Barriers::SetObject<true>(thread, *func, HASH_OFFSET, pointer.GetTaggedValue().GetRawData());
1061         return;
1062     }
1063     if (value->IsHeapObject()) {
1064         if (value->IsJSNativePointer()) {
1065             Barriers::SetObject<true>(thread, *func, HASH_OFFSET, pointer.GetTaggedValue().GetRawData());
1066             return;
1067         }
1068         JSHandle<TaggedArray> array(value);
1069 
1070         uint32_t nativeFieldCount = array->GetExtraLength();
1071         if (array->GetLength() >= nativeFieldCount + RESOLVED_MAX_SIZE) {
1072             array->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer);
1073         } else {
1074             JSHandle<TaggedArray> newArray =
1075                 vm->GetFactory()->NewSTaggedArrayWithoutInit(nativeFieldCount + RESOLVED_MAX_SIZE);
1076             newArray->SetExtraLength(nativeFieldCount);
1077             for (uint32_t i = 0; i < nativeFieldCount; i++) {
1078                 newArray->Set(thread, i, array->Get(i));
1079             }
1080             newArray->Set(thread, nativeFieldCount + HASH_INDEX, array->Get(nativeFieldCount + HASH_INDEX));
1081             newArray->Set(thread, nativeFieldCount + FUNCTION_EXTRA_INDEX, pointer);
1082             Barriers::SetObject<true>(thread, *func, HASH_OFFSET, newArray.GetTaggedValue().GetRawData());
1083         }
1084     } else {
1085         JSHandle<TaggedArray> newArray = vm->GetFactory()->NewSTaggedArrayWithoutInit(RESOLVED_MAX_SIZE);
1086         newArray->SetExtraLength(0);
1087         newArray->Set(thread, HASH_INDEX, value);
1088         newArray->Set(thread, FUNCTION_EXTRA_INDEX, pointer);
1089         Barriers::SetObject<true>(thread, *func, HASH_OFFSET, newArray.GetTaggedValue().GetRawData());
1090     }
1091 }
1092 
SetProfileTypeInfo(const JSThread * thread,const JSHandle<JSFunction> & func,const JSHandle<JSTaggedValue> & value,BarrierMode mode)1093 void JSFunction::SetProfileTypeInfo(const JSThread *thread, const JSHandle<JSFunction> &func,
1094                                     const JSHandle<JSTaggedValue> &value, BarrierMode mode)
1095 {
1096     JSHandle<ProfileTypeInfoCell> handleRaw(thread, func->GetRawProfileTypeInfo());
1097     if (handleRaw->IsEmptyProfileTypeInfoCell(thread)) {
1098         JSHandle<ProfileTypeInfoCell> handleProfileTypeInfoCell =
1099             thread->GetEcmaVM()->GetFactory()->NewProfileTypeInfoCell(value);
1100         func->SetRawProfileTypeInfo(thread, handleProfileTypeInfoCell, WRITE_BARRIER);
1101         return;
1102     }
1103     handleRaw->SetValue(thread, value, mode);
1104 }
1105 
UpdateProfileTypeInfoCell(JSThread * thread,JSHandle<FunctionTemplate> literalFunc,JSHandle<JSFunction> targetFunc)1106 void JSFunction::UpdateProfileTypeInfoCell(JSThread *thread, JSHandle<FunctionTemplate> literalFunc,
1107                                            JSHandle<JSFunction> targetFunc)
1108 {
1109     auto profileTypeInfoCellVal = literalFunc->GetRawProfileTypeInfo();
1110     ASSERT(profileTypeInfoCellVal.IsProfileTypeInfoCell());
1111     auto profileTypeInfoCell = ProfileTypeInfoCell::Cast(profileTypeInfoCellVal);
1112     if (profileTypeInfoCell->IsEmptyProfileTypeInfoCell(thread)) {
1113         JSHandle<JSTaggedValue> handleUndefined(thread, JSTaggedValue::Undefined());
1114         JSHandle<ProfileTypeInfoCell> newProfileTypeInfoCell =
1115             thread->GetEcmaVM()->GetFactory()->NewProfileTypeInfoCell(handleUndefined);
1116         literalFunc->SetRawProfileTypeInfo(thread, newProfileTypeInfoCell);
1117         targetFunc->SetRawProfileTypeInfo(thread, newProfileTypeInfoCell);
1118     } else {
1119         ProfileTypeInfoCell::Cast(profileTypeInfoCell)->UpdateProfileTypeInfoCellType(thread);
1120         targetFunc->SetRawProfileTypeInfo(thread, profileTypeInfoCellVal);
1121     }
1122 }
1123 
SetJitMachineCodeCache(const JSThread * thread,const JSHandle<MachineCode> & machineCode)1124 void JSFunction::SetJitMachineCodeCache(const JSThread *thread, const JSHandle<MachineCode> &machineCode)
1125 {
1126     JSHandle<ProfileTypeInfoCell> handleRaw(thread, GetRawProfileTypeInfo());
1127     ASSERT(!handleRaw->IsEmptyProfileTypeInfoCell(thread));
1128     handleRaw->SetMachineCode(thread, machineCode.GetTaggedValue().CreateAndGetWeakRef(), WRITE_BARRIER);
1129 }
1130 
SetBaselineJitCodeCache(const JSThread * thread,const JSHandle<MachineCode> & machineCode)1131 void JSFunction::SetBaselineJitCodeCache(const JSThread *thread, const JSHandle<MachineCode> &machineCode)
1132 {
1133     JSHandle<ProfileTypeInfoCell> handleRaw(thread, GetRawProfileTypeInfo());
1134     if (handleRaw->IsEmptyProfileTypeInfoCell(thread)) {
1135         LOG_BASELINEJIT(ERROR) << "skip set baselinejit cache, as profileTypeInfoCell is empty.";
1136         return;
1137     }
1138     handleRaw->SetBaselineCode(thread, machineCode.GetTaggedValue().CreateAndGetWeakRef(), WRITE_BARRIER);
1139 }
1140 
GetFunctionExtraInfo() const1141 JSTaggedValue JSFunctionBase::GetFunctionExtraInfo() const
1142 {
1143     JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(this, HASH_OFFSET);
1144     JSTaggedValue value(hashField);
1145     if (value.IsHeapObject()) {
1146         if (value.IsTaggedArray()) {
1147             TaggedArray *array = TaggedArray::Cast(value.GetTaggedObject());
1148             uint32_t nativeFieldCount = array->GetExtraLength();
1149             if (array->GetLength() >= nativeFieldCount + RESOLVED_MAX_SIZE) {
1150                 return array->Get(nativeFieldCount + FUNCTION_EXTRA_INDEX);
1151             }
1152         }
1153         if (value.IsJSNativePointer()) {
1154             return value;
1155         }
1156         JSType valueType = value.GetTaggedObject()->GetClass()->GetObjectType();
1157         JSType thisType = this->GetClass()->GetObjectType();
1158         LOG_ECMA(FATAL) << "this branch is unreachable, thisType is " << static_cast<uint8_t>(thisType)
1159                         << ", value type is " << static_cast<uint8_t>(valueType);
1160         UNREACHABLE();
1161     }
1162     return JSTaggedValue::Undefined();
1163 }
1164 
GetNativeFunctionExtraInfo() const1165 JSTaggedValue JSFunction::GetNativeFunctionExtraInfo() const
1166 {
1167     JSTaggedType hashField = Barriers::GetValue<JSTaggedType>(this, HASH_OFFSET);
1168     JSTaggedValue value(hashField);
1169     if (value.CheckIsJSNativePointer()) {
1170         return value;
1171     }
1172     return JSTaggedValue::Undefined();
1173 }
1174 
InitializeForConcurrentFunction(JSThread * thread,JSHandle<JSFunction> & func)1175 void JSFunction::InitializeForConcurrentFunction(JSThread *thread, JSHandle<JSFunction> &func)
1176 {
1177     JSHandle<Method> method(thread, func->GetMethod());
1178     JSMutableHandle<JSTaggedValue> sendableEnv(thread, JSTaggedValue::Undefined());
1179     if (func->IsSharedFunction() && !func->GetModule().IsUndefined()) {
1180         sendableEnv.Update(SourceTextModule::Cast(func->GetModule())->GetSendableEnv());
1181     }
1182     const JSPandaFile *jsPandaFile = method->GetJSPandaFile();
1183     if (jsPandaFile == nullptr) {
1184         LOG_ECMA(ERROR) << "JSPandaFile is nullptr";
1185         return;
1186     }
1187     ecmascript::CString moduleName = jsPandaFile->GetJSPandaFileDesc();
1188     ecmascript::CString recordName = method->GetRecordNameStr();
1189 
1190     // check ESM or CJS
1191     ecmascript::JSRecordInfo *recordInfo = jsPandaFile->CheckAndGetRecordInfo(recordName);
1192     if (recordInfo == nullptr) {
1193         CString msg = "Cannot find module '" + recordName + "' , which is application Entry Point";
1194         LOG_ECMA(ERROR) << msg;
1195         return;
1196     }
1197 
1198     if (!jsPandaFile->IsModule(recordInfo)) {
1199         LOG_ECMA(DEBUG) << "Current function is not from ES Module's file.";
1200         return;
1201     }
1202     ecmascript::ModuleManager *moduleManager = thread->GetCurrentEcmaContext()->GetModuleManager();
1203     LOG_ECMA(DEBUG) << "CompileMode is " << (jsPandaFile->IsBundlePack() ? "jsbundle" : "esmodule");
1204     JSHandle<ecmascript::JSTaggedValue> moduleRecord =
1205         ModuleResolver::HostResolveImportedModule(thread, moduleName, recordName);
1206     RETURN_IF_ABRUPT_COMPLETION(thread);
1207     ecmascript::SourceTextModule::Instantiate(thread, moduleRecord);
1208     RETURN_IF_ABRUPT_COMPLETION(thread);
1209     JSHandle<ecmascript::SourceTextModule> module = JSHandle<ecmascript::SourceTextModule>::Cast(moduleRecord);
1210     module->SetStatus(ecmascript::ModuleStatus::INSTANTIATED);
1211     ecmascript::SourceTextModule::EvaluateForConcurrent(thread, module, method);
1212     RETURN_IF_ABRUPT_COMPLETION(thread);
1213     if (!jsPandaFile->IsBundlePack() && func->IsSharedFunction()) {
1214         JSHandle<JSTaggedValue> sendableClassRecord = moduleManager->GenerateSendableFuncModule(moduleRecord);
1215         SourceTextModule::Cast(sendableClassRecord.GetTaggedValue())->SetSendableEnv(thread, sendableEnv);
1216         func->SetModule(thread, sendableClassRecord);
1217     } else {
1218         func->SetModule(thread, moduleRecord);
1219     }
1220 
1221     // for debugger, to notify the script loaded and parsed which the concurrent function is in
1222     auto *notificationMgr = thread->GetEcmaVM()->GetJsDebuggerManager()->GetNotificationManager();
1223     notificationMgr->LoadModuleEvent(moduleName, recordName);
1224 }
1225 
IsSendableOrConcurrentFunction() const1226 bool JSFunction::IsSendableOrConcurrentFunction() const
1227 {
1228     if (this->GetClass()->IsJSSharedFunction() || this->GetClass()->IsJSSharedAsyncFunction() ||
1229         this->GetFunctionKind() == ecmascript::FunctionKind::CONCURRENT_FUNCTION) {
1230         return true;
1231     }
1232     return false;
1233 }
1234 
IsSharedFunction() const1235 bool JSFunction::IsSharedFunction() const
1236 {
1237     if (this->GetClass()->IsJSSharedFunction() || this->GetClass()->IsJSSharedAsyncFunction()) {
1238         return true;
1239     }
1240     return false;
1241 }
1242 
SetCompiledFuncEntry(uintptr_t codeEntry,bool isFastCall)1243 void JSFunctionBase::SetCompiledFuncEntry(uintptr_t codeEntry, bool isFastCall)
1244 {
1245     ASSERT(codeEntry != 0);
1246     SetCodeEntry(codeEntry);
1247     SetIsCompiledFastCall(isFastCall);
1248     SetCompiledCodeBit(true);
1249 }
1250 
SetJitCompiledFuncEntry(JSThread * thread,JSHandle<MachineCode> & machineCode,bool isFastCall)1251 void JSFunction::SetJitCompiledFuncEntry(JSThread *thread, JSHandle<MachineCode> &machineCode, bool isFastCall)
1252 {
1253     uintptr_t codeEntry = machineCode->GetFuncAddr();
1254     ASSERT(codeEntry != 0);
1255 
1256     SetMachineCode(thread, machineCode);
1257     SetCompiledFuncEntry(codeEntry, isFastCall);
1258 }
1259 
SetJitHotnessCnt(uint16_t cnt)1260 void JSFunction::SetJitHotnessCnt(uint16_t cnt)
1261 {
1262     JSTaggedValue profileTypeInfoVal = GetProfileTypeInfo();
1263     if (!profileTypeInfoVal.IsUndefined()) {
1264         ProfileTypeInfo *profileTypeInfo = ProfileTypeInfo::Cast(profileTypeInfoVal.GetTaggedObject());
1265         profileTypeInfo->SetJitHotnessCnt(cnt);
1266     }
1267 }
1268 
ClearCompiledCodeFlags()1269 void JSFunctionBase::ClearCompiledCodeFlags()
1270 {
1271     SetCompiledCodeBit(false);
1272     SetIsCompiledFastCall(false);
1273 }
1274 
ClearMachineCode(const JSThread * thread)1275 void JSFunction::ClearMachineCode(const JSThread *thread)
1276 {
1277     SetMachineCode(thread, JSTaggedValue::Undefined());
1278 }
1279 }  // namespace panda::ecmascript
1280