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