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