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