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