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