• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 #ifndef ECMASCRIPT_JSFUNCTION_H
17 #define ECMASCRIPT_JSFUNCTION_H
18 
19 #include "ecmascript/accessor_data.h"
20 #include "ecmascript/ecma_macros.h"
21 #include "ecmascript/ic/profile_type_info_cell.h"
22 #include "ecmascript/js_object.h"
23 #include "ecmascript/js_proxy.h"
24 
25 namespace panda::ecmascript {
26 class JSThread;
27 struct EcmaRuntimeCallInfo;
28 struct CJSInfo;
29 
30 class JSFunctionBase : public JSObject {
31 public:
32     CAST_CHECK(JSFunctionBase, IsJSFunctionBase);
33 
SetConstructor(bool flag)34     inline void SetConstructor(bool flag)
35     {
36         JSHClass *hclass = GetJSHClass();
37         hclass->SetConstructor(flag);
38     }
39 
40     static bool SetFunctionName(JSThread *thread, const JSHandle<JSFunctionBase> &func,
41                                 const JSHandle<JSTaggedValue> &name, const JSHandle<JSTaggedValue> &prefix);
42     static JSHandle<JSTaggedValue> GetFunctionName(JSThread *thread, const JSHandle<JSFunctionBase> &func);
43 
InitBitField()44     void InitBitField()
45     {
46         SetBitField(static_cast<uint32_t>(0));
47     }
48 
SetCallNapi(bool isCallNapi)49     void SetCallNapi(bool isCallNapi)
50     {
51         uint32_t bitField = GetBitField();
52         uint32_t newValue = IsCallNapiBit::Update(bitField, isCallNapi);
53         SetBitField(newValue);
54     }
55 
IsCallNapi()56     bool IsCallNapi() const
57     {
58         uint32_t bitField = GetBitField();
59         return IsCallNapiBit::Decode(bitField);
60     }
61 
GetFunctionKind(const JSThread * thread)62     FunctionKind GetFunctionKind(const JSThread *thread) const
63     {
64         JSTaggedValue method = GetMethod(thread);
65         return Method::ConstCast(method.GetTaggedObject())->GetFunctionKind();
66     }
67 
68     void SetCompiledFuncEntry(uintptr_t codeEntry, bool isFastCall);
69 
SetIsCompiledFastCall(bool isFastCall)70     void SetIsCompiledFastCall(bool isFastCall)
71     {
72         uint32_t bitField = GetBitField();
73         uint32_t newValue = IsFastCallBit::Update(bitField, isFastCall);
74         SetBitField(newValue);
75     }
76 
IsCompiledFastCall()77     bool IsCompiledFastCall() const
78     {
79         uint32_t bitField = GetBitField();
80         return IsFastCallBit::Decode(bitField);
81     }
82 
IsCompiledCodeFromCallTarget(const JSThread * thread,JSTaggedValue callTarget)83     static bool IsCompiledCodeFromCallTarget(const JSThread *thread, JSTaggedValue callTarget)
84     {
85         if (callTarget.IsJSFunction()) {
86             return Cast(callTarget.GetTaggedObject())->IsCompiledCode();
87         } else {
88             ECMAObject *target = reinterpret_cast<ECMAObject*>(callTarget.GetTaggedObject());
89             ASSERT(target != nullptr);
90             Method *method = target->GetCallTarget(thread);
91             return method->IsAotWithCallField();
92         }
93     }
94 
IsFastCallFromCallTarget(const JSThread * thread,JSTaggedValue callTarget)95     static bool IsFastCallFromCallTarget(const JSThread *thread, JSTaggedValue callTarget)
96     {
97         if (callTarget.IsJSFunction()) {
98             return Cast(callTarget.GetTaggedObject())->IsCompiledFastCall();
99         } else {
100             ECMAObject *target = reinterpret_cast<ECMAObject*>(callTarget.GetTaggedObject());
101             ASSERT(target != nullptr);
102             Method *method = target->GetCallTarget(thread);
103             return method->IsFastCall();
104         }
105     }
106 
SetCompiledCodeBit(bool isCompiled)107     void SetCompiledCodeBit(bool isCompiled)
108     {
109         uint32_t bitField = GetBitField();
110         uint32_t newValue = IsCompiledCodeBit::Update(bitField, isCompiled);
111         SetBitField(newValue);
112     }
113 
IsCompiledCode()114     bool IsCompiledCode() const
115     {
116         uint32_t bitField = GetBitField();
117         return IsCompiledCodeBit::Decode(bitField);
118     }
119 
120     void ClearCompiledCodeFlags();
121 
SetTaskConcurrentFuncFlag(bool value)122     void SetTaskConcurrentFuncFlag(bool value)
123     {
124         uint32_t bitField = GetBitField();
125         uint32_t newValue = TaskConcurrentFuncFlagBit::Update(bitField, value);
126         SetBitField(newValue);
127     }
128 
GetTaskConcurrentFuncFlag()129     bool GetTaskConcurrentFuncFlag() const
130     {
131         uint32_t bitField = GetBitField();
132         return TaskConcurrentFuncFlagBit::Decode(bitField);
133     }
134 
SetJitCompilingFlag(bool value)135     void SetJitCompilingFlag(bool value)
136     {
137         uint32_t bitField = GetBitField();
138         uint32_t newValue = JitCompilingFlagBit::Update(bitField, value);
139         SetBitField(newValue);
140     }
141 
IsJitCompiling()142     bool IsJitCompiling() const
143     {
144         uint32_t bitField = GetBitField();
145         return JitCompilingFlagBit::Decode(bitField);
146     }
147 
SetBaselinejitCompilingFlag(bool value)148     void SetBaselinejitCompilingFlag(bool value)
149     {
150         uint32_t bitField = GetBitField();
151         uint32_t newValue = BaselinejitCompilingFlagBit::Update(bitField, value);
152         SetBitField(newValue);
153     }
154 
IsBaselinejitCompiling()155     bool IsBaselinejitCompiling() const
156     {
157         uint32_t bitField = GetBitField();
158         return BaselinejitCompilingFlagBit::Decode(bitField);
159     }
160 
GetCodeEntry()161     uintptr_t GetCodeEntry() const
162     {
163         return GetCodeEntryOrNativePointer();
164     }
165 
SetCodeEntry(uintptr_t codeEntry)166     void SetCodeEntry(uintptr_t codeEntry)
167     {
168         SetCodeEntryOrNativePointer(codeEntry);
169     }
170 
GetNativePointer()171     void *GetNativePointer() const
172     {
173         return reinterpret_cast<void *>(GetCodeEntryOrNativePointer());
174     }
175 
SetNativePointer(void * nativePointer)176     void SetNativePointer(void *nativePointer)
177     {
178         SetCodeEntryOrNativePointer(ToUintPtr(nativePointer));
179     }
180 
181     JSTaggedValue GetFunctionExtraInfo(const JSThread *thread) const;
182 
183     /* compiled code flag field */
184     using IsCompiledCodeBit = BitField<bool, 0, 1>;        // offset 0
185     using IsFastCallBit = IsCompiledCodeBit::NextFlag;     // offset 1
186     static constexpr uint32_t COMPILED_CODE_FASTCALL_BITS = 0x3; // 0x3U: compiled code and fastcall bit field
187 
188     using TaskConcurrentFuncFlagBit = IsFastCallBit::NextFlag;     // offset 2
189     using JitCompilingFlagBit = TaskConcurrentFuncFlagBit::NextFlag; // offset 3
190     using BaselinejitCompilingFlagBit = JitCompilingFlagBit::NextFlag; // offset 4
191     using IsCallNapiBit = BaselinejitCompilingFlagBit::NextFlag; // offset 5
192 
193     static constexpr size_t METHOD_OFFSET = JSObject::SIZE;
194     ACCESSORS(Method, METHOD_OFFSET, CODE_ENTRY_OFFSET)
195     ACCESSORS_PRIMITIVE_FIELD(CodeEntryOrNativePointer, uintptr_t, CODE_ENTRY_OFFSET, LENGTH_OFFSET)
196     ACCESSORS_PRIMITIVE_FIELD(Length, uint32_t, LENGTH_OFFSET, BIT_FIELD_OFFSET)
197     ACCESSORS_PRIMITIVE_FIELD(BitField, uint32_t, BIT_FIELD_OFFSET, LAST_OFFSET)
198     DEFINE_ALIGN_SIZE(LAST_OFFSET);
199 
200     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSObject, METHOD_OFFSET, CODE_ENTRY_OFFSET)
201     DECL_DUMP()
202 };
203 
204 static_assert((JSFunctionBase::SIZE % static_cast<uint8_t>(MemAlignment::MEM_ALIGN_OBJECT)) == 0);
205 static_assert(JSFunctionBase::METHOD_OFFSET == JSProxy::METHOD_OFFSET);
206 
207 class JSFunction : public JSFunctionBase {
208 public:
209     static constexpr int LENGTH_OF_INLINE_PROPERTIES = 3;
210     static constexpr int LENGTH_INLINE_PROPERTY_INDEX = 0;
211     static constexpr int NAME_INLINE_PROPERTY_INDEX = 1;
212     static constexpr int PROTOTYPE_INLINE_PROPERTY_INDEX = 2;
213     static constexpr int CLASS_PROTOTYPE_INLINE_PROPERTY_INDEX = 1;
214 
215     CAST_CHECK(JSFunction, IsJSFunction);
216 
217     static void InitializeJSFunction(JSThread *thread, const JSHandle<GlobalEnv> &env, const JSHandle<JSFunction> &func,
218                                      FunctionKind kind = FunctionKind::NORMAL_FUNCTION);
219     // ecma6 7.3
220     static bool OrdinaryHasInstance(JSThread *thread, const JSHandle<JSTaggedValue> &constructor,
221                                     const JSHandle<JSTaggedValue> &obj);
222 
223     static JSTaggedValue SpeciesConstructor(const JSHandle<JSFunction> &func,
224                                             const JSHandle<JSFunction> &defaultConstructor);
225 
226     // ecma6 9.2
227     // 7.3.12 Call(F, V, argumentsList)
228 
229     static JSTaggedValue Call(EcmaRuntimeCallInfo *info);
230 
231     static JSTaggedValue Construct(EcmaRuntimeCallInfo *info);
232     static JSTaggedValue Invoke(EcmaRuntimeCallInfo *info, const JSHandle<JSTaggedValue> &key);
233     static JSTaggedValue InvokeOptimizedEntrypoint(JSThread *thread, JSHandle<JSFunction> mainFunc,
234         JSHandle<JSTaggedValue> &thisArg, CJSInfo* cjsInfo);
235     static JSTaggedValue InvokeOptimizedEntrypoint(JSThread *thread, JSHandle<JSFunction> func,
236         EcmaRuntimeCallInfo *info);
237     // 9.2.2[[Construct]](argumentsList, newTarget)
238     // 9.3.2[[Construct]](argumentsList, newTarget)
239     static JSTaggedValue ConstructInternal(EcmaRuntimeCallInfo *info);
240 
241     static bool AddRestrictedFunctionProperties(const JSHandle<JSFunction> &func, const JSHandle<JSTaggedValue> &realm);
242     static bool MakeConstructor(JSThread *thread, const JSHandle<JSFunction> &func,
243                                 const JSHandle<JSTaggedValue> &proto, bool writable = true);
244     static bool SetFunctionLength(JSThread *thread, const JSHandle<JSFunction> &func, JSTaggedValue length,
245                                   bool cfg = true);
246     static JSHandle<JSObject> NewJSFunctionPrototype(JSThread *thread, const JSHandle<JSFunction> &func);
247     static JSTaggedValue AccessCallerArgumentsThrowTypeError(EcmaRuntimeCallInfo *argv);
248     static JSTaggedValue PrototypeGetter(JSThread *thread, const JSHandle<JSObject> &self);
249     static bool PrototypeSetter(JSThread *thread, const JSHandle<JSObject> &self, const JSHandle<JSTaggedValue> &value,
250                                 bool mayThrow);
251     static JSTaggedValue NameGetter(JSThread *thread, const JSHandle<JSObject> &self);
252     static JSTaggedValue LengthGetter(JSThread *thread, const JSHandle<JSObject> &self);
253     static bool NameSetter(JSThread *thread, const JSHandle<JSObject> &self, const JSHandle<JSTaggedValue> &value,
254                            bool mayThrow);
255     static void SetFunctionNameNoPrefix(JSThread *thread, JSFunction *func, JSTaggedValue name);
GetFunctionPrototype(const JSThread * thread)256     inline JSTaggedValue GetFunctionPrototype(const JSThread *thread) const
257     {
258         ASSERT(HasFunctionPrototype(thread));
259         JSTaggedValue protoOrHClass = GetProtoOrHClass(thread);
260         if (protoOrHClass.IsJSHClass()) {
261             return JSHClass::Cast(protoOrHClass.GetTaggedObject())->GetPrototype(thread);
262         }
263 
264         return protoOrHClass;
265     }
266 
267     static void SetFunctionPrototypeOrInstanceHClass(const JSThread *thread, const JSHandle<JSFunction> &fun,
268                                                      JSTaggedValue protoOrHClass);
269 
270     static EcmaString *GetFunctionNameString(const JSThread *thread, ObjectFactory *factory,
271                                              JSHandle<EcmaString> concatString, JSHandle<JSTaggedValue> target);
272 
HasInitialClass(const JSThread * thread)273     inline bool HasInitialClass(const JSThread *thread) const
274     {
275         JSTaggedValue protoOrHClass = GetProtoOrHClass(thread);
276         return protoOrHClass.IsJSHClass();
277     }
278 
HasFunctionPrototype(const JSThread * thread)279     inline bool HasFunctionPrototype(const JSThread *thread) const
280     {
281         JSTaggedValue protoOrHClass = GetProtoOrHClass(thread);
282         return !protoOrHClass.IsHole();
283     }
284 
285     void SetFunctionLength(const JSThread *thread, JSTaggedValue length);
286 
IsGetterOrSetter(const JSThread * thread)287     inline bool IsGetterOrSetter(const JSThread *thread) const
288     {
289         FunctionKind kind = GetFunctionKind(thread);
290         return kind == FunctionKind::GETTER_FUNCTION || kind == FunctionKind::SETTER_FUNCTION;
291     }
292 
IsGetter(const JSThread * thread)293     inline bool IsGetter(const JSThread *thread) const
294     {
295         FunctionKind kind = GetFunctionKind(thread);
296         return kind == FunctionKind::GETTER_FUNCTION;
297     }
298 
IsBase(const JSThread * thread)299     inline bool IsBase(const JSThread *thread) const
300     {
301         FunctionKind kind = GetFunctionKind(thread);
302         return kind <= FunctionKind::CLASS_CONSTRUCTOR;
303     }
304 
IsDerivedConstructor(const JSThread * thread)305     inline bool IsDerivedConstructor(const JSThread *thread) const
306     {
307         FunctionKind kind = GetFunctionKind(thread);
308         return kind == FunctionKind::DERIVED_CONSTRUCTOR;
309     }
310 
IsArrowFunction(FunctionKind kind)311     inline static bool IsArrowFunction(FunctionKind kind)
312     {
313         return (kind >= FunctionKind::ARROW_FUNCTION) && (kind <= FunctionKind::ASYNC_ARROW_FUNCTION);
314     }
315 
IsClassConstructor(FunctionKind kind)316     inline static bool IsClassConstructor(FunctionKind kind)
317     {
318         return (kind == FunctionKind::CLASS_CONSTRUCTOR) || (kind == FunctionKind::DERIVED_CONSTRUCTOR);
319     }
320 
IsConstructorKind(FunctionKind kind)321     inline static bool IsConstructorKind(FunctionKind kind)
322     {
323         return (kind >= FunctionKind::BASE_CONSTRUCTOR) && (kind <= FunctionKind::DERIVED_CONSTRUCTOR);
324     }
325 
IsBuiltinConstructor(const JSThread * thread)326     inline bool IsBuiltinConstructor(const JSThread *thread)
327     {
328         FunctionKind kind = GetFunctionKind(thread);
329         return kind >= FunctionKind::BUILTIN_PROXY_CONSTRUCTOR && kind <= FunctionKind::BUILTIN_CONSTRUCTOR;
330     }
331 
HasPrototype(FunctionKind kind)332     inline static bool HasPrototype(FunctionKind kind)
333     {
334         return (kind >= FunctionKind::BASE_CONSTRUCTOR) && (kind <= FunctionKind::ASYNC_GENERATOR_FUNCTION) &&
335             (kind != FunctionKind::BUILTIN_PROXY_CONSTRUCTOR);
336     }
337 
IsNormalFunctionAndCanSkipWbWhenInitialization(FunctionKind kind)338     inline static bool IsNormalFunctionAndCanSkipWbWhenInitialization(FunctionKind kind)
339     {
340         return kind != FunctionKind::LAST_FUNCTION_KIND;
341     }
342 
HasAccessor(FunctionKind kind)343     inline static bool HasAccessor(FunctionKind kind)
344     {
345         return kind >= FunctionKind::NORMAL_FUNCTION && kind <= FunctionKind::ASYNC_FUNCTION;
346     }
347 
IsBaseConstructorKind(FunctionKind kind)348     inline static bool IsBaseConstructorKind(FunctionKind kind)
349     {
350         return kind == FunctionKind::BASE_CONSTRUCTOR;
351     }
352 
IsClassConstructor()353     inline bool IsClassConstructor() const
354     {
355         return GetClass()->IsClassConstructor();
356     }
357 
SetClassConstructor(bool flag)358     inline void SetClassConstructor(bool flag)
359     {
360         GetClass()->SetClassConstructor(flag);
361     }
362 
HasProfileTypeInfo(const JSThread * thread)363     inline bool HasProfileTypeInfo(const JSThread *thread) const
364     {
365         return GetRawProfileTypeInfo(thread).IsProfileTypeInfoCell() &&
366                !ProfileTypeInfoCell::Cast(GetRawProfileTypeInfo(thread))->IsEmptyProfileTypeInfoCell(thread) &&
367                !ProfileTypeInfoCell::Cast(GetRawProfileTypeInfo(thread))->GetValue(thread).IsUndefined();
368     }
369 
370     static void SetFunctionExtraInfo(JSThread *thread, const JSHandle<JSFunction> &func, void *nativeFunc,
371                                      const NativePointerCallback &deleter, void *data, size_t nativeBindingsize = 0,
372                                      Concurrent isConcurrent = Concurrent::NO);
373     static void SetSFunctionExtraInfo(JSThread *thread, const JSHandle<JSFunction> &func, void *nativeFunc,
374                                       const NativePointerCallback &deleter, void *data, size_t nativeBindingsize = 0);
375     static void SetProfileTypeInfo(const JSThread *thread, const JSHandle<JSFunction> &func,
376                                    const JSHandle<JSTaggedValue> &value);
377     static void UpdateProfileTypeInfoCell(JSThread *thread, JSHandle<FunctionTemplate> literalFunc,
378                                           JSHandle<JSFunction> targetFunc);
379     void SetJitMachineCodeCache(const JSThread *thread, const JSHandle<MachineCode> &machineCode);
380     void ClearMachineCode(const JSThread *thread);
381 
382     JSTaggedValue GetNativeFunctionExtraInfo(const JSThread *thread) const;
383     CString GetRecordName(const JSThread *thread) const;
GetProfileTypeInfo(const JSThread * thread)384     JSTaggedValue GetProfileTypeInfo(const JSThread *thread) const
385     {
386         JSTaggedValue raw = GetRawProfileTypeInfo(thread);
387         return ProfileTypeInfoCell::Cast(raw.GetTaggedObject())->GetValue(thread);
388     }
389 
390     void SetJitCompiledFuncEntry(JSThread *thread, JSHandle<MachineCode> &machineCode, bool isFastCall);
391     void SetJitHotnessCnt(const JSThread *thread, uint16_t cnt);
392     uint16_t GetJitHotnessCnt(const JSThread *thread) const;
393 
394     static void InitializeForConcurrentFunction(JSThread *thread, JSHandle<JSFunction> &func);
395 
396     static void ReplaceFunctionForHook(const JSThread *thread, JSHandle<JSFunction> &oldFunc,
397                                 const JSHandle<JSFunction> &newFunc);
398 
399     bool IsSendableOrConcurrentFunction(JSThread *thread) const;
400     bool IsSharedFunction() const;
401 
402     static uint32_t CalcuExpotedOfProperties(JSThread *thread, const JSHandle<JSFunction> &fun,
403                                              bool *isStartSlackTracking);
404     static void InitializeJSFunctionCommon(JSThread *thread, const JSHandle<JSFunction> &func, FunctionKind kind);
405     static void InitializeJSFunction(JSThread *thread, const JSHandle<JSFunction> &func,
406                                      FunctionKind kind = FunctionKind::NORMAL_FUNCTION);
407     static void InitializeJSBuiltinFunction(JSThread *thread, const JSHandle<GlobalEnv> &env,
408                                             const JSHandle<JSFunction> &func,
409                                             FunctionKind kind = FunctionKind::NORMAL_FUNCTION);
410     static void InitializeSFunction(JSThread *thread, const JSHandle<JSFunction> &func,
411                                     FunctionKind kind = FunctionKind::NORMAL_FUNCTION);
412     static void InitializeWithDefaultValueCommon(JSThread *thread, const JSHandle<JSFunction> &func);
413     static void InitializeWithDefaultValue(JSThread *thread, const JSHandle<JSFunction> &func);
414     static void InitializeBuiltinWithDefaultValue(JSThread *thread, const JSHandle<GlobalEnv> &env,
415                                                   const JSHandle<JSFunction> &func);
416     static void InitClassFunction(JSThread *thread, JSHandle<JSFunction> &func, bool callNapi);
417     static void InitClassFunctionWithClsPrototype(JSThread *thread, JSHandle<JSFunction> &func, bool callNapi,
418                                                   JSHandle<JSObject> &clsPrototype);
419     static JSHClass *PUBLIC_API GetOrCreateInitialJSHClass(JSThread *thread, const JSHandle<JSFunction> &fun);
420     static JSHandle<JSHClass> GetInstanceJSHClass(JSThread *thread, JSHandle<JSFunction> constructor,
421                                                   JSHandle<JSTaggedValue> newTarget);
422 
GetInlinedPropertyOffset(uint32_t index)423     static constexpr uint32_t GetInlinedPropertyOffset(uint32_t index)
424     {
425         return JSFunction::SIZE + index * JSTaggedValue::TaggedTypeSize();
426     }
427 
428     static constexpr size_t PROTO_OR_DYNCLASS_OFFSET = JSFunctionBase::SIZE;
429     ACCESSORS(ProtoOrHClass, PROTO_OR_DYNCLASS_OFFSET, LEXICAL_ENV_OFFSET)
430     // For runtime native function, the LexicalEnv field is used to store GlobalEnv, such as RegExp's native function
431     ACCESSORS(LexicalEnv, LEXICAL_ENV_OFFSET, MACHINECODE_OFFSET)
432     ACCESSORS(MachineCode, MACHINECODE_OFFSET, BASELINECODE_OFFSET)
433     ACCESSORS(BaselineCode, BASELINECODE_OFFSET, RAW_PROFILE_TYPE_INFO_OFFSET)
434     ACCESSORS(RawProfileTypeInfo, RAW_PROFILE_TYPE_INFO_OFFSET, HOME_OBJECT_OFFSET)
435     ACCESSORS(HomeObject, HOME_OBJECT_OFFSET, ECMA_MODULE_OFFSET)
436     ACCESSORS(Module, ECMA_MODULE_OFFSET, WORK_NODE_POINTER_OFFSET)
437     ACCESSORS_PRIMITIVE_FIELD(WorkNodePointer, uintptr_t, WORK_NODE_POINTER_OFFSET, LAST_OFFSET)
438     DEFINE_ALIGN_SIZE(LAST_OFFSET);
439 
440     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunctionBase, PROTO_OR_DYNCLASS_OFFSET, WORK_NODE_POINTER_OFFSET)
441     DECL_DUMP()
442 
443 private:
444     static JSHandle<JSHClass> GetOrCreateDerivedJSHClass(JSThread *thread, JSHandle<JSFunction> derived,
445                                                          JSHandle<JSHClass> ctorInitialClass);
446     static std::vector<JSTaggedType> GetArgsData(JSThread *thread, bool isFastCall, JSHandle<JSTaggedValue> &thisArg,
447                                                  JSHandle<JSFunction> mainFunc,  CJSInfo* cjsInfo);
448 };
449 
450 class JSGeneratorFunction : public JSFunction {
451 public:
452     CAST_CHECK(JSGeneratorFunction, IsGeneratorFunction);
453 
454     static constexpr size_t SIZE = JSFunction::SIZE;
455 
456     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, SIZE, SIZE)
457 
458     DECL_DUMP()
459 };
460 
461 class JSBoundFunction : public JSFunctionBase {
462 public:
463     CAST_CHECK(JSBoundFunction, IsBoundFunction);
464 
465     // 9.4.1.2[[Construct]](argumentsList, newTarget)
466     static JSTaggedValue ConstructInternal(EcmaRuntimeCallInfo *info);
467 
GetInlinedPropertyOffset(uint32_t index)468     static constexpr uint32_t GetInlinedPropertyOffset(uint32_t index)
469     {
470         return JSBoundFunction::SIZE + index * JSTaggedValue::TaggedTypeSize();
471     }
472 
473     static constexpr size_t BOUND_TARGET_OFFSET = JSFunctionBase::SIZE;
474     ACCESSORS(BoundTarget, BOUND_TARGET_OFFSET, BOUND_THIS_OFFSET);
475     ACCESSORS(BoundThis, BOUND_THIS_OFFSET, BOUND_ARGUMENTS_OFFSET);
476     ACCESSORS(BoundArguments, BOUND_ARGUMENTS_OFFSET, SIZE);
477 
478     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunctionBase, BOUND_TARGET_OFFSET, SIZE)
479 
480     DECL_DUMP()
481 };
482 
483 class JSProxyRevocFunction : public JSFunction {
484 public:
485     CAST_CHECK(JSProxyRevocFunction, IsProxyRevocFunction);
486 
487     static void ProxyRevocFunctions(const JSThread *thread, const JSHandle<JSProxyRevocFunction> &revoker);
488 
489     static constexpr size_t REVOCABLE_PROXY_OFFSET = JSFunction::SIZE;
490     ACCESSORS(RevocableProxy, REVOCABLE_PROXY_OFFSET, SIZE);
491 
492     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, REVOCABLE_PROXY_OFFSET, SIZE)
493 
494     DECL_DUMP()
495 };
496 
497 // ResolveFunction/RejectFunction
498 class JSPromiseReactionsFunction : public JSFunction {
499 public:
500     CAST_CHECK(JSPromiseReactionsFunction, IsJSPromiseReactionFunction);
501 
502     static constexpr size_t PROMISE_OFFSET = JSFunction::SIZE;
503     ACCESSORS(Promise, PROMISE_OFFSET, ALREADY_RESOLVED_OFFSET);
504     ACCESSORS(AlreadyResolved, ALREADY_RESOLVED_OFFSET, SIZE);
505 
506     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, PROMISE_OFFSET, SIZE)
507 
508     DECL_DUMP()
509 };
510 
511 // ExecutorFunction
512 class JSPromiseExecutorFunction : public JSFunction {
513 public:
514     CAST_CHECK(JSPromiseExecutorFunction, IsJSPromiseExecutorFunction);
515 
516     static constexpr size_t CAPABILITY_OFFSET = JSFunction::SIZE;
517     ACCESSORS(Capability, CAPABILITY_OFFSET, SIZE);
518 
519     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, CAPABILITY_OFFSET, SIZE)
520 
521     DECL_DUMP()
522 };
523 
524 class JSAsyncModuleFulfilledFunction : public JSFunction {
525 public:
526     CAST_CHECK(JSAsyncModuleFulfilledFunction, IsJSAsyncModuleFulfilledFunction);
527 
528     static constexpr size_t SIZE = JSFunction::SIZE;
529 
530     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, SIZE, SIZE)
531 
532     DECL_DUMP()
533 };
534 
535 class JSAsyncModuleRejectedFunction : public JSFunction {
536 public:
537     CAST_CHECK(JSAsyncModuleRejectedFunction, IsJSAsyncModuleRejectedFunction);
538 
539     static constexpr size_t SIZE = JSFunction::SIZE;
540 
541     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, SIZE, SIZE)
542 
543     DECL_DUMP()
544 };
545 
546 class JSPromiseAllResolveElementFunction : public JSFunction {
547 public:
548     CAST_CHECK(JSPromiseAllResolveElementFunction, IsJSPromiseAllResolveElementFunction);
549 
550     static constexpr size_t INDEX_OFFSET = JSFunction::SIZE;
551     ACCESSORS(Index, INDEX_OFFSET, VALUES_OFFSET);
552     ACCESSORS(Values, VALUES_OFFSET, CAPABILITIES_OFFSET);
553     ACCESSORS(Capabilities, CAPABILITIES_OFFSET, REMAINING_ELEMENTS_OFFSET);
554     ACCESSORS(RemainingElements, REMAINING_ELEMENTS_OFFSET, ALREADY_CALLED_OFFSET);
555     ACCESSORS(AlreadyCalled, ALREADY_CALLED_OFFSET, SIZE);
556 
557     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, INDEX_OFFSET, SIZE)
558 
559     DECL_DUMP()
560 };
561 
562 // PromiseAnyRejectElementFunction
563 class JSPromiseAnyRejectElementFunction : public JSFunction {
564 public:
565     CAST_CHECK(JSPromiseAnyRejectElementFunction, IsJSPromiseAnyRejectElementFunction);
566 
567     static constexpr size_t ERRORS_OFFSET = JSFunction::SIZE;
568 
569     ACCESSORS(Errors, ERRORS_OFFSET, CAPABILITY_OFFSET);
570     ACCESSORS(Capability, CAPABILITY_OFFSET, REMAINING_ELEMENTS_OFFSET);
571     ACCESSORS(RemainingElements, REMAINING_ELEMENTS_OFFSET, ALREADY_CALLED_OFFSET);
572     ACCESSORS(AlreadyCalled, ALREADY_CALLED_OFFSET, INDEX_OFFSET);
573     ACCESSORS_PRIMITIVE_FIELD(Index, uint32_t, INDEX_OFFSET, LAST_OFFSET);
574     DEFINE_ALIGN_SIZE(LAST_OFFSET);
575 
576     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, ERRORS_OFFSET, INDEX_OFFSET)
577 
578     DECL_DUMP()
579 };
580 
581 // PromiseAllSettledElementFunction
582 class JSPromiseAllSettledElementFunction : public JSFunction {
583 public:
584     CAST_CHECK(JSPromiseAllSettledElementFunction, IsJSPromiseAllSettledElementFunction);
585 
586     static constexpr size_t ALREADY_CALLED_OFFSET = JSFunction::SIZE;
587     ACCESSORS(AlreadyCalled, ALREADY_CALLED_OFFSET, VALUES_OFFSET);
588     ACCESSORS(Values, VALUES_OFFSET, CAPABILITY_OFFSET);
589     ACCESSORS(Capability, CAPABILITY_OFFSET, REMAINING_ELEMENTS_OFFSET);
590     ACCESSORS(RemainingElements, REMAINING_ELEMENTS_OFFSET, INDEX_OFFSET);
591     ACCESSORS_PRIMITIVE_FIELD(Index, uint32_t, INDEX_OFFSET, LAST_OFFSET);
592     DEFINE_ALIGN_SIZE(LAST_OFFSET);
593 
594     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, ALREADY_CALLED_OFFSET, INDEX_OFFSET)
595 
596     DECL_DUMP()
597 };
598 
599 // PromiseFinallyFunction
600 class JSPromiseFinallyFunction : public JSFunction {
601 public:
602     CAST_CHECK(JSPromiseFinallyFunction, IsJSPromiseFinallyFunction);
603 
604     static constexpr size_t CONSTRUCTOR_OFFSET = JSFunction::SIZE;
605     ACCESSORS(Constructor, CONSTRUCTOR_OFFSET, ONFINALLY_OFFSET);
606     ACCESSORS(OnFinally, ONFINALLY_OFFSET, SIZE);
607 
608     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, CONSTRUCTOR_OFFSET, SIZE)
609 
610     DECL_DUMP()
611 };
612 
613 // ValueThunkOrThrowReason
614 class JSPromiseValueThunkOrThrowerFunction : public JSFunction {
615 public:
616     CAST_CHECK(JSPromiseValueThunkOrThrowerFunction, IsJSPromiseValueThunkOrThrowerFunction);
617 
618     static constexpr size_t RESULT_OFFSET = JSFunction::SIZE;
619     ACCESSORS(Result, RESULT_OFFSET, SIZE);
620 
621     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, RESULT_OFFSET, SIZE)
622 
623     DECL_DUMP()
624 };
625 
626 class JSIntlBoundFunction : public JSFunction {
627 public:
628     CAST_CHECK(JSIntlBoundFunction, IsJSIntlBoundFunction);
629 
630     static JSTaggedValue IntlNameGetter(JSThread *thread, const JSHandle<JSObject> &self);
631 
632     static constexpr size_t NUMBER_FORMAT_OFFSET = JSFunction::SIZE;
633 
634     ACCESSORS(NumberFormat, NUMBER_FORMAT_OFFSET, DATETIME_FORMAT_OFFSET);
635     ACCESSORS(DateTimeFormat, DATETIME_FORMAT_OFFSET, COLLATOR_OFFSET);
636     ACCESSORS(Collator, COLLATOR_OFFSET, SIZE);
637 
638     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, NUMBER_FORMAT_OFFSET, SIZE)
639     DECL_DUMP()
640 };
641 
642 class JSAsyncGeneratorFunction : public JSFunction {
643 public:
644     CAST_CHECK(JSAsyncGeneratorFunction, IsAsyncGeneratorFunction);
645     static constexpr size_t  SIZE = JSFunction::SIZE;
646     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, SIZE, SIZE)
647     DECL_DUMP()
648 };
649 
650 class JSAsyncFromSyncIterUnwarpFunction : public JSFunction {
651 public:
652     CAST_CHECK(JSAsyncFromSyncIterUnwarpFunction, IsJSAsyncFromSyncIterUnwarpFunction);
653     static constexpr size_t DONE_OFFSET = JSFunction::SIZE;
654     ACCESSORS(Done, DONE_OFFSET, SIZE);
655 
656     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, DONE_OFFSET, SIZE);
657     DECL_DUMP()
658 };
659 
660 class JSSharedFunction : public JSFunction {
661 public:
662     CAST_CHECK(JSSharedFunction, IsJSSharedFunction);
663     static constexpr size_t SIZE = JSFunction::SIZE;
664     static constexpr uint32_t MAX_INLINE = PropertyAttributes::MAX_FAST_PROPS_CAPACITY -
665         SIZE / JSTaggedValue::TaggedTypeSize() + 1;
666     DECL_VISIT_OBJECT_FOR_JS_OBJECT(JSFunction, SIZE, SIZE)
667 };
668 
669 class FunctionTemplate : public TaggedObject {
670 public:
GetFunctionKind(const JSThread * thread)671     FunctionKind GetFunctionKind(const JSThread *thread) const
672     {
673         JSTaggedValue method = GetMethod(thread);
674         return Method::ConstCast(method.GetTaggedObject())->GetFunctionKind();
675     }
676 
IsGetterOrSetter(const JSThread * thread)677     inline bool IsGetterOrSetter(const JSThread *thread) const
678     {
679         FunctionKind kind = GetFunctionKind(thread);
680         return kind == FunctionKind::GETTER_FUNCTION || kind == FunctionKind::SETTER_FUNCTION;
681     }
682 
IsGetter(const JSThread * thread)683     inline bool IsGetter(const JSThread *thread) const
684     {
685         FunctionKind kind = GetFunctionKind(thread);
686         return kind == FunctionKind::GETTER_FUNCTION;
687     }
688 
689     CAST_CHECK(FunctionTemplate, IsFunctionTemplate);
690     static constexpr size_t METHOD_OFFSET = TaggedObject::SIZE;
691     ACCESSORS(Method, METHOD_OFFSET, MODULE_OFFSET);
692     ACCESSORS(Module, MODULE_OFFSET, RAW_PROFILE_TYPE_INFO_OFFSET);
693     ACCESSORS(RawProfileTypeInfo, RAW_PROFILE_TYPE_INFO_OFFSET, LENGTH_OFFSET);
694     ACCESSORS_PRIMITIVE_FIELD(Length, uint32_t, LENGTH_OFFSET, LAST_OFFSET)
695     DEFINE_ALIGN_SIZE(LAST_OFFSET);
696 
697     DECL_VISIT_OBJECT(METHOD_OFFSET, LENGTH_OFFSET);
698     DECL_DUMP()
699 };
700 
701 }  // namespace panda::ecmascript
702 #endif  // ECMASCRIPT_JSFUNCTION_H
703