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