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_JSOBJECT_H 17 #define ECMASCRIPT_JSOBJECT_H 18 19 #include "ecmascript/ecma_macros.h" 20 #include "ecmascript/ecma_vm.h" 21 #include "ecmascript/enum_cache.h" 22 #include "ecmascript/filter_helper.h" 23 #include "ecmascript/ic/property_box.h" 24 #include "ecmascript/js_handle.h" 25 #include "ecmascript/js_hclass.h" 26 #include "ecmascript/js_tagged_value.h" 27 #include "ecmascript/mem/layout_visitor.h" 28 #include "ecmascript/mem/slots.h" 29 #include "ecmascript/mem/visitor.h" 30 #include "ecmascript/method.h" 31 #include "ecmascript/property_attributes.h" 32 #include "ecmascript/tagged_array.h" 33 34 namespace panda { 35 namespace ecmascript { 36 class ObjectOperator; 37 class JSFunction; 38 class AccessorData; 39 class JSArray; 40 class JSForInIterator; 41 class LexicalEnv; 42 class GlobalEnv; 43 class TaggedQueue; 44 class NumberDictionary; 45 class DependentInfos; 46 47 namespace builtins { 48 class BuiltinsArkTools; 49 } 50 51 using SCheckMode = JSShared::SCheckMode; 52 53 // Integrity level for objects 54 enum IntegrityLevel { SEALED, FROZEN }; 55 56 enum PositionKind { UNKNOWN = 0, INDEXED_PROPERTY = 1, INLINE_NAMED_PROPERTY = 2, OUT_NAMED_PROPERTY = 3 }; 57 enum PropertyKind { KEY = 0, VALUE, KEY_VALUE }; 58 59 enum class TrackTypeUpdateMode { ENABLE, DISABLE }; 60 61 // ecma6.0 6.2.4 The Property Descriptor Specification Type 62 class PropertyDescriptor final { 63 public: 64 PropertyDescriptor() = delete; 65 66 ~PropertyDescriptor() = default; 67 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyDescriptor); 68 DEFAULT_COPY_SEMANTIC(PropertyDescriptor); 69 PropertyDescriptor(const JSThread * thread)70 explicit PropertyDescriptor(const JSThread *thread) : thread_(thread) {} 71 PropertyDescriptor(const JSThread * thread,JSHandle<JSTaggedValue> v)72 PropertyDescriptor(const JSThread *thread, JSHandle<JSTaggedValue> v) : thread_(thread), value_(v) {} 73 PropertyDescriptor(const JSThread * thread,JSHandle<JSTaggedValue> v,bool w,bool e,bool c)74 PropertyDescriptor(const JSThread *thread, JSHandle<JSTaggedValue> v, bool w, bool e, bool c) 75 : thread_(thread), 76 writable_(w), 77 enumerable_(e), 78 configurable_(c), 79 hasWritable_(true), 80 hasEnumerable_(true), 81 hasConfigurable_(true), 82 value_(v) 83 { 84 } 85 PropertyDescriptor(const JSThread * thread,bool w,bool e,bool c)86 PropertyDescriptor(const JSThread *thread, bool w, bool e, bool c) 87 : PropertyDescriptor(thread, JSHandle<JSTaggedValue>(), w, e, c) 88 { 89 } 90 GetValue()91 inline JSHandle<JSTaggedValue> GetValue() const 92 { 93 if (value_.IsEmpty()) { 94 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined()); 95 } 96 return value_; 97 } 98 GetKey()99 inline JSHandle<JSTaggedValue> GetKey() const 100 { 101 if (key_.IsEmpty()) { 102 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined()); 103 } 104 return key_; 105 } 106 SetValue(JSHandle<JSTaggedValue> value)107 inline void SetValue(JSHandle<JSTaggedValue> value) 108 { 109 value_ = value; 110 } 111 SetKey(JSHandle<JSTaggedValue> key)112 inline void SetKey(JSHandle<JSTaggedValue> key) 113 { 114 key_ = key; 115 } 116 SetSharedFieldType(SharedFieldType fieldType)117 inline void SetSharedFieldType(SharedFieldType fieldType) 118 { 119 fieldType_ = fieldType; 120 } 121 GetSharedFieldType()122 inline SharedFieldType GetSharedFieldType() const 123 { 124 return fieldType_; 125 } 126 IsWritable()127 inline bool IsWritable() const 128 { 129 return writable_; 130 } 131 SetWritable(bool flag)132 inline void SetWritable(bool flag) 133 { 134 writable_ = flag; 135 hasWritable_ = true; 136 } 137 IsEnumerable()138 inline bool IsEnumerable() const 139 { 140 return enumerable_; 141 } 142 SetEnumerable(bool flag)143 inline void SetEnumerable(bool flag) 144 { 145 enumerable_ = flag; 146 hasEnumerable_ = true; 147 } 148 IsConfigurable()149 inline bool IsConfigurable() const 150 { 151 return configurable_; 152 } 153 SetConfigurable(bool flag)154 inline void SetConfigurable(bool flag) 155 { 156 configurable_ = flag; 157 hasConfigurable_ = true; 158 } 159 HasValue()160 inline bool HasValue() const 161 { 162 return !value_.IsEmpty(); 163 } 164 HasWritable()165 inline bool HasWritable() const 166 { 167 return hasWritable_; 168 } 169 HasConfigurable()170 inline bool HasConfigurable() const 171 { 172 return hasConfigurable_; 173 } 174 HasEnumerable()175 inline bool HasEnumerable() const 176 { 177 return hasEnumerable_; 178 } 179 HasGetter()180 inline bool HasGetter() const 181 { 182 return !getter_.IsEmpty(); 183 } 184 HasSetter()185 inline bool HasSetter() const 186 { 187 return !setter_.IsEmpty(); 188 } 189 GetGetter()190 inline JSHandle<JSTaggedValue> GetGetter() const 191 { 192 if (getter_->IsNull()) { 193 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined()); 194 } 195 return getter_; 196 } 197 GetSetter()198 inline JSHandle<JSTaggedValue> GetSetter() const 199 { 200 if (setter_->IsNull()) { 201 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined()); 202 } 203 return setter_; 204 } 205 SetGetter(JSHandle<JSTaggedValue> value)206 inline void SetGetter(JSHandle<JSTaggedValue> value) 207 { 208 getter_ = value; 209 } 210 SetSetter(JSHandle<JSTaggedValue> value)211 inline void SetSetter(JSHandle<JSTaggedValue> value) 212 { 213 setter_ = value; 214 } 215 216 // 6.2.4.1 IsAccessorDescriptor()217 inline bool IsAccessorDescriptor() const 218 { 219 // 2. If both Desc.[[Get]] and Desc.[[Set]] are absent, return false. 220 return !(getter_.IsEmpty() && setter_.IsEmpty()); 221 } 222 IsDataDescriptor()223 inline bool IsDataDescriptor() const 224 { 225 // 2. If both Desc.[[Value]] and Desc.[[Writable]] are absent, return false. 226 return !(value_.IsEmpty() && !hasWritable_); 227 } 228 IsGenericDescriptor()229 inline bool IsGenericDescriptor() const 230 { 231 // 2. If IsAccessorDescriptor(Desc) and IsDataDescriptor(Desc) are both false, return true 232 return !IsAccessorDescriptor() && !IsDataDescriptor(); 233 } 234 IsEmpty()235 inline bool IsEmpty() const 236 { 237 return !hasWritable_ && !hasEnumerable_ && !hasConfigurable_ && !HasValue() && !HasGetter() && !HasSetter(); 238 } 239 240 static void CompletePropertyDescriptor(const JSThread *thread, PropertyDescriptor &desc); 241 242 private: 243 const JSThread *thread_{nullptr}; 244 245 bool writable_ {false}; 246 bool enumerable_ {false}; 247 bool configurable_ {false}; 248 bool hasWritable_ {false}; 249 bool hasEnumerable_ {false}; 250 bool hasConfigurable_ {false}; 251 SharedFieldType fieldType_ {SharedFieldType::NONE}; 252 253 JSHandle<JSTaggedValue> value_ {}; 254 JSHandle<JSTaggedValue> getter_ {}; 255 JSHandle<JSTaggedValue> setter_ {}; 256 JSHandle<JSTaggedValue> key_ {}; 257 }; 258 259 enum class ElementTypes { ALLTYPES, STRING_AND_SYMBOL }; 260 261 class PropertyMetaData { 262 public: 263 using IsFoundField = BitField<bool, 0, 1>; 264 using IsInlinedPropsField = IsFoundField::NextFlag; 265 // 3: The bit field that represents the "Representation" of the property 266 using RepresentationField = IsInlinedPropsField::NextField<Representation, 3>; 267 using OffsetField = RepresentationField::NextField<uint32_t, PropertyAttributes::MAX_FAST_PROPS_CAPACITY_LOG2>; 268 PropertyMetaData(uint32_t metaData)269 explicit PropertyMetaData(uint32_t metaData) : metaData_(metaData) {} 270 271 ~PropertyMetaData() = default; 272 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyMetaData); 273 DEFAULT_COPY_SEMANTIC(PropertyMetaData); 274 PropertyMetaData(bool isFound)275 explicit PropertyMetaData(bool isFound) 276 { 277 SetFound(isFound); 278 } 279 IsFound()280 inline bool IsFound() const 281 { 282 return IsFoundField::Get(metaData_); 283 } 284 SetFound(bool flag)285 inline void SetFound(bool flag) 286 { 287 IsFoundField::Set(flag, &metaData_); 288 } 289 GetIsInlinedProps()290 inline bool GetIsInlinedProps() const 291 { 292 return IsInlinedPropsField::Get(metaData_); 293 } 294 SetIsInlinedProps(bool flag)295 inline void SetIsInlinedProps(bool flag) 296 { 297 IsInlinedPropsField::Set(flag, &metaData_); 298 } 299 GetRepresentation()300 inline Representation GetRepresentation() const 301 { 302 return RepresentationField::Get(metaData_); 303 } 304 SetRepresentation(Representation representation)305 inline void SetRepresentation(Representation representation) 306 { 307 RepresentationField::Set<uint32_t>(representation, &metaData_); 308 } 309 SetOffset(uint32_t offset)310 inline void SetOffset(uint32_t offset) 311 { 312 OffsetField::Set<uint32_t>(offset, &metaData_); 313 } 314 GetOffset()315 inline uint32_t GetOffset() const 316 { 317 return OffsetField::Get(metaData_); 318 } 319 320 private: 321 uint32_t metaData_{0}; 322 }; 323 324 class OperationResult { 325 public: OperationResult(const JSThread * thread,JSTaggedValue value,PropertyMetaData metaData)326 OperationResult(const JSThread *thread, JSTaggedValue value, PropertyMetaData metaData) 327 : metaData_(metaData) 328 { 329 thread_ = thread; 330 value_ = JSHandle<JSTaggedValue>(thread_, value); 331 } 332 333 ~OperationResult() = default; 334 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(OperationResult); 335 DEFAULT_COPY_SEMANTIC(OperationResult); 336 GetValue()337 JSHandle<JSTaggedValue> GetValue() const 338 { 339 if (value_->IsPropertyBox()) { 340 return JSHandle<JSTaggedValue>(thread_, 341 PropertyBox::Cast(value_.GetTaggedValue().GetTaggedObject())->GetValue(thread_)); 342 } 343 return value_; 344 } 345 GetRawValue()346 JSHandle<JSTaggedValue> GetRawValue() const 347 { 348 return value_; 349 } 350 GetPropertyMetaData()351 const PropertyMetaData &GetPropertyMetaData() const 352 { 353 return metaData_; 354 } 355 356 private: 357 const JSThread *thread_ {nullptr}; 358 JSHandle<JSTaggedValue> value_ {}; 359 PropertyMetaData metaData_ {0U}; 360 }; 361 362 363 // HashField possible layout: 364 // [ hashValue ] | [extraInfo] | [ hashValue, extraInfo, nativePointer, ... ] 365 // nativePointer number depends on the extraLength of taggedArray 366 class ECMAObject : public TaggedObject { 367 public: 368 static constexpr int HASH_INDEX = 0; 369 static constexpr int FUNCTION_EXTRA_INDEX = 1; 370 static constexpr int RESOLVED_MAX_SIZE = 2; 371 372 CAST_CHECK(ECMAObject, IsECMAObject); 373 374 void SetCallable(bool flag); 375 bool IsCallable() const; 376 Method *GetCallTarget(const JSThread *thread) const; 377 void *GetNativePointer(const JSThread *thread) const; 378 379 static constexpr size_t HASH_OFFSET = TaggedObjectSize(); 380 static constexpr size_t SIZE = HASH_OFFSET + sizeof(JSTaggedType); 381 382 static void SetHash(const JSThread *thread, int32_t hash, const JSHandle<ECMAObject> &obj); 383 int32_t GetHash(const JSThread *thread) const; 384 bool HasHash(const JSThread *thread) const; 385 InitializeHash()386 void InitializeHash() 387 { 388 Barriers::SetPrimitive<JSTaggedType>(this, ECMAObject::HASH_OFFSET, JSTaggedValue(0).GetRawData()); 389 } 390 391 JSTaggedValue GetNativePointerByIndex(const JSThread *thread, int32_t index) const; 392 void* GetNativePointerField(const JSThread *thread, int32_t index) const; 393 static void SetNativePointerField(const JSThread *thread, const JSHandle<JSObject> &obj, int32_t index, 394 void *nativePointer, const NativePointerCallback &callBack, void *data, 395 size_t nativeBindingsize = 0, Concurrent isConcurrent = Concurrent::NO); 396 int32_t GetNativePointerFieldCount(const JSThread *thread) const; 397 static void SetNativePointerFieldCount(const JSThread *thread, const JSHandle<JSObject> &obj, int32_t count); 398 399 DECL_VISIT_OBJECT(HASH_OFFSET, SIZE); 400 401 template <VisitType visitType, class DerivedVisitor> VisitObjects(BaseObjectVisitor<DerivedVisitor> & visitor)402 void VisitObjects(BaseObjectVisitor<DerivedVisitor> &visitor) 403 { 404 // no field in this object 405 VisitRangeSlot<visitType>(visitor); 406 } 407 }; 408 409 class JSObject : public ECMAObject { 410 public: 411 static constexpr int MIN_ELEMENTS_LENGTH = 3; 412 static constexpr int MIN_PROPERTIES_LENGTH = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS; 413 static constexpr int FAST_ELEMENTS_FACTOR = 3; 414 static constexpr int MIN_GAP = 256; 415 static constexpr int MAX_GAP = 1_KB; 416 static constexpr uint32_t MAX_ELEMENT_INDEX = std::numeric_limits<uint32_t>::max(); 417 static constexpr int MIN_ELEMENTS_HINT_LENGTH = 1_KB; 418 static constexpr int MAX_ELEMENTS_HINT_LENGTH = 2_MB; 419 static constexpr int ELEMENTS_HINT_FACTOR = 8; 420 static constexpr int SHOULD_TRANS_TO_FAST_ELEMENTS_FACTOR = 2; 421 static constexpr size_t PAIR_SIZE = 2; 422 static constexpr size_t VALUE_OFFSET = 1; 423 424 CAST_CHECK(JSObject, IsECMAObject); 425 426 // ecma6.0 6.2.4.4 427 static JSHandle<JSTaggedValue> FromPropertyDescriptor(JSThread *thread, const PropertyDescriptor &desc); 428 429 // ecma6.0 6.2.4.5 ToPropertyDescriptor ( Obj ) 430 static void ToPropertyDescriptor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, PropertyDescriptor &desc); 431 static bool ToPropertyDescriptorFast(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 432 PropertyDescriptor &desc); 433 434 static JSHandle<JSTaggedValue> CallFunction(JSThread *thread, const JSHandle<JSTaggedValue> &func); 435 436 // ecma6 7.3 Operations on Objects 437 static JSHandle<JSTaggedValue> GetMethod(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 438 const JSHandle<JSTaggedValue> &key); 439 440 static JSHandle<JSTaggedValue> FastGetMethod(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 441 const JSHandle<JSTaggedValue> &key); 442 443 static bool CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 444 const JSHandle<JSTaggedValue> &value, SCheckMode sCheckMode = SCheckMode::CHECK); 445 446 static bool CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 447 const JSHandle<JSTaggedValue> &value, SCheckMode sCheckMode = SCheckMode::CHECK); 448 449 static bool CreateMethodProperty(JSThread *thread, const JSHandle<JSObject> &obj, 450 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value); 451 452 static bool CreateDataPropertyOrThrow(JSThread *thread, const JSHandle<JSObject> &obj, 453 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value, 454 SCheckMode sCheckMode = SCheckMode::CHECK); 455 456 static bool CreateDataPropertyOrThrow(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 457 const JSHandle<JSTaggedValue> &value, 458 SCheckMode sCheckMode = SCheckMode::CHECK); 459 460 static JSHandle<TaggedArray> PUBLIC_API EnumerableOwnNames(JSThread *thread, const JSHandle<JSObject> &obj); 461 462 // 7.3.23 EnumerableOwnPropertyNames ( O, kind ) 463 static JSHandle<TaggedArray> EnumerableOwnPropertyNames(JSThread *thread, const JSHandle<JSObject> &obj, 464 PropertyKind kind); 465 static void EnumerableOwnPropertyNamesHelper(JSThread *thread, const JSHandle<JSObject> &obj, 466 const JSHandle<TaggedArray> &arr, JSHandle<TaggedArray> &properties, 467 uint32_t &index, bool &fastMode, PropertyKind kind); 468 469 static JSHandle<GlobalEnv> GetFunctionRealm(JSThread *thread, const JSHandle<JSTaggedValue> &object); 470 471 static bool SetIntegrityLevel(JSThread *thread, const JSHandle<JSObject> &obj, IntegrityLevel level); 472 473 static bool FreezeSharedObject(JSThread *thread, const JSHandle<JSObject> &obj); 474 475 static bool TestIntegrityLevel(JSThread *thread, const JSHandle<JSObject> &obj, IntegrityLevel level); 476 477 static JSHandle<JSTaggedValue> SpeciesConstructor(JSThread *thread, const JSHandle<JSObject> &obj, 478 const JSHandle<JSTaggedValue> &defaultConstructor); 479 static JSHandle<JSTaggedValue> SlowSpeciesConstructor(JSThread *thread, 480 const JSHandle<JSTaggedValue> &objConstructor, 481 const JSHandle<JSTaggedValue> &defaultConstructor); 482 // 7.3.17 483 template<ElementTypes types = ElementTypes::ALLTYPES> 484 static JSHandle<JSTaggedValue> CreateListFromArrayLike(JSThread *thread, const JSHandle<JSTaggedValue> &obj); 485 486 // ecma6 9.1 487 // [[GetPrototypeOf]] 488 static JSTaggedValue GetPrototype(const JSThread *thread, const JSHandle<JSObject> &obj); 489 490 static JSTaggedValue GetPrototype(const JSThread *thread, JSTaggedValue obj); 491 492 // [[SetPrototypeOf]] 493 static bool SetPrototype(JSThread *thread, const JSHandle<JSObject> &obj, 494 const JSHandle<JSTaggedValue> &proto, 495 bool isChangeProto = false); 496 497 // [[IsExtensible]] 498 bool IsExtensible() const; 499 500 // [[PreventExtensions]] 501 static bool PreventExtensions(JSThread *thread, const JSHandle<JSObject> &obj); 502 503 // [[GetOwnProperty]] -> Undefined | Property Descriptor 504 static bool GetOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 505 PropertyDescriptor &desc); 506 507 static bool GlobalGetOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc); 508 509 static bool OrdinaryGetOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, 510 const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc); 511 512 // [[DefineOwnProperty]] 513 static bool DefineOwnProperty(JSThread *thread, ObjectOperator *op, 514 const PropertyDescriptor &desc, SCheckMode sCheckMode = SCheckMode::CHECK); 515 516 static bool DefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 517 const PropertyDescriptor &desc, SCheckMode sCheckMode = SCheckMode::CHECK); 518 519 static bool DefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 520 const PropertyDescriptor &desc, SCheckMode sCheckMode = SCheckMode::CHECK); 521 522 static bool OrdinaryDefineOwnProperty(JSThread *thread, ObjectOperator *op, 523 const PropertyDescriptor &desc, SCheckMode sCheckMode = SCheckMode::CHECK); 524 525 static bool OrdinaryDefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, 526 const JSHandle<JSTaggedValue> &key, const PropertyDescriptor &desc, 527 SCheckMode sCheckMode = SCheckMode::CHECK); 528 529 static bool OrdinaryDefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 530 const PropertyDescriptor &desc, 531 SCheckMode sCheckMode = SCheckMode::CHECK); 532 533 static bool IsCompatiblePropertyDescriptor(bool extensible, const PropertyDescriptor &desc, 534 const PropertyDescriptor ¤t); 535 536 static bool ValidateAndApplyPropertyDescriptor(ObjectOperator *op, bool extensible, const PropertyDescriptor &desc, 537 const PropertyDescriptor ¤t, 538 SCheckMode sCheckMode = SCheckMode::CHECK); 539 540 static OperationResult PUBLIC_API GetProperty(JSThread *thread, const JSHandle<JSObject> &obj, 541 const JSHandle<JSTaggedValue> &key); 542 543 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 544 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &receiver); 545 546 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 547 const JSHandle<JSTaggedValue> &key, SCheckMode sCheckMode = SCheckMode::CHECK); 548 549 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t index); 550 551 static OperationResult GetPropertyFromGlobal(JSThread *thread, const JSHandle<JSTaggedValue> &key); 552 553 static bool SetProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 554 JSHandle<JSTaggedValue> value, bool mayThrow = false); 555 556 static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 557 JSHandle<JSTaggedValue> value, bool mayThrow = false, 558 SCheckMode checkMode = SCheckMode::CHECK); 559 560 static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 561 JSHandle<JSTaggedValue> value, const JSHandle<JSTaggedValue> &receiver, 562 bool mayThrow = false); 563 564 static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t index, 565 JSHandle<JSTaggedValue> value, bool mayThrow = false); 566 567 static bool GlobalSetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &key, 568 JSHandle<JSTaggedValue> value, bool mayThrow); 569 570 // [[HasProperty]] 571 static bool HasProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key); 572 573 static bool HasProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index); 574 575 // 9.1.10 [[Delete]] 576 static bool DeleteProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 577 SCheckMode sCheckMode = SCheckMode::CHECK); 578 579 // [[OwnPropertyKeys]] 580 static JSHandle<TaggedArray> GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj); 581 582 static JSHandle<TaggedArray> GetAllPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t filter); 583 584 static void CollectEnumKeys(JSThread *thread, const JSHandle<JSObject> &obj, 585 JSHandle<TaggedArray> keyArray, uint32_t *keys, 586 JSHandle<TaggedQueue> shadowQueue, int32_t lastLength = -1); 587 588 static void AppendOwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj, 589 JSHandle<TaggedArray> keyArray, uint32_t *keys, 590 JSHandle<TaggedQueue> shadowQueue); 591 592 static JSHandle<TaggedArray> GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj); 593 594 // 9.1.13 ObjectCreate 595 static JSHandle<JSObject> ObjectCreate(JSThread *thread, const JSHandle<JSObject> &proto); 596 597 // 12.9.4 Runtime Semantics: InstanceofOperator(O, C) 598 static bool InstanceOf(JSThread *thread, const JSHandle<JSTaggedValue> &object, 599 const JSHandle<JSTaggedValue> &target); 600 601 static JSTaggedValue TryGetEnumCache(JSThread *thread, JSTaggedValue obj); 602 603 // 13.7.5.15 EnumerateObjectProperties ( O ); same as [[Enumerate]] 604 static JSHandle<JSForInIterator> EnumerateObjectProperties(JSThread *thread, const JSHandle<JSTaggedValue> &obj); 605 static JSHandle<JSForInIterator> LoadEnumerateProperties(JSThread *thread, const JSHandle<JSTaggedValue> &object); 606 607 static bool IsRegExp(JSThread *thread, const JSHandle<JSTaggedValue> &argument); 608 609 static JSTaggedValue CallGetter(JSThread *thread, const AccessorData *accessor, 610 const JSHandle<JSTaggedValue> &receiver); 611 static bool PUBLIC_API CallSetter(JSThread *thread, const AccessorData &accessor, 612 const JSHandle<JSTaggedValue> &receiver, 613 const JSHandle<JSTaggedValue> &value, bool mayThrow = false); 614 615 static void FillElementsWithHoles(const JSThread *thread, const JSHandle<JSObject> &obj, 616 uint32_t start, uint32_t end); 617 GetJSHClass()618 JSHClass *GetJSHClass() const 619 { 620 return GetClass(); 621 } 622 uint32_t GetNonInlinedFastPropsCapacity() const; 623 bool IsJSGlobalObject() const; 624 bool IsConstructor() const; 625 bool IsECMAObject() const; 626 bool IsJSError() const; 627 bool IsArguments() const; 628 bool IsDate() const; 629 bool IsJSArray() const; 630 bool IsJSSArray() const; 631 bool IsJSShared() const; 632 bool IsJSMap() const; 633 bool IsJSSet() const; 634 bool IsJSRegExp() const; 635 bool IsJSFunction() const; 636 bool IsBoundFunction() const; 637 bool IsJSIntlBoundFunction() const; 638 bool IsProxyRevocFunction() const; 639 bool IsAccessorData() const; 640 bool IsJSGlobalEnv() const; 641 bool IsJSProxy() const; 642 bool IsGeneratorObject() const; 643 bool IsAsyncGeneratorObject() const; 644 bool IsForinIterator() const; 645 bool IsJSSetIterator() const; 646 bool IsJSRegExpIterator() const; 647 bool IsJSMapIterator() const; 648 bool IsJSArrayIterator() const; 649 bool IsJSAPIArrayListIterator() const; 650 bool IsJSAPIStackIterator() const; 651 bool IsJSAPIVectorIterator() const; 652 bool IsJSAPIBitVectorIterator() const; 653 bool IsJSAPILinkedListIterator() const; 654 bool IsJSAPIListIterator() const; 655 bool IsJSPrimitiveRef() const; 656 bool IsElementDict(const JSThread *thread) const; 657 bool IsPropertiesDict(const JSThread *thread) const; 658 bool IsTypedArray() const; 659 bool IsSharedTypedArray() const; 660 bool PUBLIC_API ElementsAndPropertiesIsEmpty(JSThread *thread) const; 661 662 static PUBLIC_API void DefinePropertyByLiteral(JSThread *thread, const JSHandle<JSObject> &obj, 663 const JSHandle<JSTaggedValue> &key, 664 const JSHandle<JSTaggedValue> &value, 665 bool useForClass = false); 666 static void DefineSetter(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 667 const JSHandle<JSTaggedValue> &value); 668 static void DefineGetter(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 669 const JSHandle<JSTaggedValue> &value); 670 static PUBLIC_API JSHandle<JSObject> CreateObjectFromProperties(const JSThread *thread, 671 const JSHandle<TaggedArray> &properties, 672 JSTaggedValue ihc = JSTaggedValue::Undefined()); 673 static JSHandle<JSObject> CreateObjectFromPropertiesByIHClass(const JSThread *thread, 674 const JSHandle<TaggedArray> &properties, 675 uint32_t propsLen, 676 const JSHandle<JSHClass> &ihc, 677 TrackTypeUpdateMode trackMode); 678 static bool CheckPropertiesForRep(const JSThread *thread, 679 const JSHandle<TaggedArray> &properties, uint32_t propsLen, const JSHandle<JSHClass> &ihc); 680 static void GetAllKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset, 681 const JSHandle<TaggedArray> &keyArray); 682 static void GetAllKeysForSerialization(const JSThread *thread, const JSHandle<JSObject> &obj, 683 std::vector<JSTaggedValue> &keyVector); 684 685 static void GetAllKeysByFilter(const JSThread *thread, const JSHandle<JSObject> &obj, 686 uint32_t &keyArrayEffectivelength, 687 const JSHandle<TaggedArray> &keyArray, 688 uint32_t filter); 689 static void GetAllElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 690 const JSHandle<TaggedArray> &keyArray); 691 static void GetAllElementKeysByFilter(JSThread *thread, 692 const JSHandle<JSObject> &obj, 693 const JSHandle<TaggedArray> &keyArray, 694 uint32_t &keyArrayEffectiveLength, 695 uint32_t filter); 696 697 static void GetALLElementKeysIntoVector(const JSThread *thread, const JSHandle<JSObject> &obj, 698 std::vector<JSTaggedValue> &keyVector); 699 std::pair<uint32_t, uint32_t> GetNumberOfEnumKeys(const JSThread *thread) const; 700 uint32_t GetNumberOfKeys(const JSThread *thread); 701 uint32_t GetNumberOfElements(JSThread *thread); 702 703 static JSHandle<TaggedArray> GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 704 uint32_t numOfElements, uint32_t *keys); 705 static void CollectEnumElements(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 706 JSHandle<TaggedArray> elementArray, uint32_t *keys, 707 int32_t lastLength = -1); 708 static void GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 709 const JSHandle<TaggedArray> &keyArray); 710 static JSHandle<TaggedArray> GetAllEnumKeys(JSThread *thread, const JSHandle<JSObject> &obj, 711 uint32_t numOfKeys, uint32_t *keys); 712 static uint32_t GetAllEnumKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 713 const JSHandle<TaggedArray> &keyArray); 714 715 static void AddAccessor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 716 const JSHandle<AccessorData> &value, PropertyAttributes attr); 717 718 static constexpr size_t PROPERTIES_OFFSET = ECMAObject::SIZE; 719 720 ACCESSORS(Properties, PROPERTIES_OFFSET, ELEMENTS_OFFSET); 721 ACCESSORS(Elements, ELEMENTS_OFFSET, SIZE); 722 723 DECL_VISIT_OBJECT_FOR_JS_OBJECT(ECMAObject, PROPERTIES_OFFSET, SIZE) 724 725 void Dump(const JSThread *thread, std::ostream &os, bool isPrivacy = false) const DUMP_API_ATTR; Dump(const JSThread * thread)726 void Dump(const JSThread *thread) const DUMP_API_ATTR 727 { 728 Dump(thread, std::cout); 729 } 730 void DumpForSnapshot(const JSThread *thread, std::vector<Reference> &vec) const; 731 static const CString ExtractConstructorAndRecordName(JSThread *thread, TaggedObject *obj, bool noAllocate = false, 732 bool *isCallGetter = nullptr); 733 734 static const CString ExtractFilePath(JSThread *thread, CString name, CString moduleName, 735 CString defaultName, CString fileName, int32_t line); 736 737 static JSHandle<NameDictionary> PUBLIC_API TransitionToDictionary(const JSThread *thread, 738 const JSHandle<JSObject> &receiver); 739 740 static inline std::pair<bool, JSTaggedValue> ConvertValueWithRep(PropertyAttributes attr, JSTaggedValue value); 741 742 inline void SetPropertyInlinedPropsWithRep(const JSThread *thread, uint32_t index, JSTaggedValue value); 743 template <size_t objectSize, uint32_t index, bool needBarrier = true> 744 inline void SetPropertyInlinedPropsWithSize(const JSThread* thread, JSTaggedValue value); 745 template <bool needBarrier = true> 746 inline void SetPropertyInlinedProps(const JSThread *thread, uint32_t index, JSTaggedValue value); 747 template <bool needBarrier = true> 748 inline void SetPropertyInlinedProps(const JSThread *thread, const JSHClass *hclass, uint32_t index, 749 JSTaggedValue value); 750 inline JSTaggedValue GetPropertyInlinedPropsWithRep(const JSThread *thread, uint32_t index, 751 PropertyAttributes attr) const; 752 inline JSTaggedValue GetPropertyInlinedPropsWithRep(const JSThread* thread, const JSHClass *hclass, uint32_t index, 753 PropertyAttributes attr) const; 754 template <size_t objectSize, uint32_t index> 755 inline JSTaggedValue GetPropertyInlinedPropsWithSize(const JSThread* thread) const; 756 inline JSTaggedValue GetPropertyInlinedProps(const JSThread* thread, uint32_t index) const; 757 inline JSTaggedValue GetPropertyInlinedProps(const JSThread* thread, const JSHClass *hclass, uint32_t index) const; 758 inline JSTaggedValue GetProperty(const JSThread* thread, const JSHClass *hclass, PropertyAttributes attr) const; 759 PropertyBox* GetGlobalPropertyBox(const JSThread *thread, const std::string& key); 760 template <bool needBarrier = true> 761 inline void SetProperty(const JSThread *thread, const JSHClass *hclass, PropertyAttributes attr, 762 JSTaggedValue value); 763 764 static bool IsArrayLengthWritable(JSThread *thread, const JSHandle<JSObject> &receiver); 765 bool UpdatePropertyInDictionary(const JSThread *thread, JSTaggedValue key, JSTaggedValue value); 766 static bool ShouldTransToDict(uint32_t capacity, uint32_t index); 767 static bool ShouldTransToFastElements(JSThread *thread, TaggedArray *elements, uint32_t capacity, uint32_t index); 768 static bool AttributesUnchanged(const JSThread *thread, const JSHandle<JSObject> &obj); 769 static JSHandle<TaggedArray> GrowElementsCapacity(const JSThread *thread, const JSHandle<JSObject> &obj, 770 uint32_t capacity, bool highGrowth = false, bool isNew = false); 771 772 static bool IsDepulicateKeys(JSThread *thread, JSHandle<TaggedArray> keys, int32_t lastLength, 773 JSHandle<TaggedQueue> shadowQueue, JSHandle<JSTaggedValue> key); 774 static JSHandle<EnumCache> GetOrCreateEnumCache(JSThread *thread, JSHandle<JSHClass> jsHClass); 775 static JSHandle<JSTaggedValue> GetOrCreateDependentInfos(JSThread *thread, JSHandle<JSHClass> jsHClass); 776 static JSHandle<JSTaggedValue> GetOrCreateDetectorDependentInfos(JSThread *thread, 777 uint32_t detectorID, 778 GlobalEnv *globalEnv); SetEnumCacheKind(const JSThread * thread,JSHandle<EnumCache> enumCache,const EnumCacheKind kind)779 static inline void SetEnumCacheKind([[maybe_unused]] const JSThread *thread, 780 JSHandle<EnumCache> enumCache, const EnumCacheKind kind) 781 { 782 enumCache->SetEnumCacheKind(static_cast<uint32_t>(kind)); 783 } 784 GetEnumCacheKind(JSTaggedValue enumCache)785 static inline EnumCacheKind GetEnumCacheKind(JSTaggedValue enumCache) 786 { 787 if (!enumCache.IsEnumCache()) { 788 return EnumCacheKind::NONE; 789 } 790 EnumCacheKind kind = static_cast<EnumCacheKind>(EnumCache::Cast(enumCache)->GetEnumCacheKind()); 791 ASSERT(kind == EnumCacheKind::NONE || 792 kind == EnumCacheKind::SIMPLE || 793 kind == EnumCacheKind::PROTOCHAIN); 794 return kind; 795 } 796 797 static void ClearHasDeleteProperty(JSHandle<JSTaggedValue> object); 798 799 static JSHandle<JSTaggedValue> IterableToList(JSThread *thread, const JSHandle<JSTaggedValue> &items, 800 JSTaggedValue method = JSTaggedValue::Undefined()); 801 802 static void TryOptimizeAsFastElements(const JSThread *thread, JSHandle<JSObject> obj); 803 static void OptimizeAsFastProperties(const JSThread *thread, JSHandle<JSObject> obj); 804 805 static void SetSProperties(JSThread *thread, JSHandle<JSObject> obj, const std::vector<PropertyDescriptor> &descs); 806 807 static void PUBLIC_API TryMigrateToGenericKindForJSObject(const JSThread *thread, const JSHandle<JSObject> &obj, 808 const ElementsKind oldKind); 809 static void ElementsToDictionary(const JSThread *thread, JSHandle<JSObject> obj); 810 811 // Find function in JsObject For Hook 812 static JSHandle<JSTaggedValue> FindFuncInObjectForHook(JSThread *thread, JSHandle<JSTaggedValue> object, 813 const std::string &className, const std::string &funcName); 814 815 private: 816 friend class ObjectOperator; 817 friend class LoadICRuntime; 818 friend class StoreICRuntime; 819 friend class ObjectFastOperator; 820 friend class ICRuntimeStub; 821 friend class RuntimeStubs; 822 friend class JSSharedArray; 823 friend class builtins::BuiltinsArkTools; 824 825 static bool HasMutantTaggedArrayElements(const JSThread *thread, const JSHandle<JSObject> &obj); 826 PropertyBox* GetGlobalPropertyBox(const JSThread *thread, JSTaggedValue key); 827 static bool CheckAndUpdateArrayLength(JSThread *thread, const JSHandle<JSObject> &receiver, 828 uint32_t index, ElementsKind &kind); 829 static bool PUBLIC_API AddElementInternal( 830 JSThread *thread, const JSHandle<JSObject> &receiver, uint32_t index, const JSHandle<JSTaggedValue> &value, 831 PropertyAttributes attr = PropertyAttributes(PropertyAttributes::GetDefaultAttributes())); 832 833 static JSTaggedValue GetProperty(JSThread *thread, ObjectOperator *op); 834 static bool SetProperty(ObjectOperator *op, JSHandle<JSTaggedValue> value, bool mayThrow); 835 static bool SetPropertyForData(ObjectOperator *op, const JSHandle<JSTaggedValue> &value, bool *isAccessor); 836 static bool SetPropertyForAccessor(ObjectOperator *op, const JSHandle<JSTaggedValue> &value); 837 static void DeletePropertyInternal(JSThread *thread, const JSHandle<JSObject> &obj, 838 const JSHandle<JSTaggedValue> &key, uint32_t index); 839 int FindProperty(const JSHandle<JSTaggedValue> &key); 840 841 static uint32_t ComputeElementCapacity(uint32_t oldCapacity, bool isNew = false); 842 static uint32_t ComputeElementCapacityHighGrowth(uint32_t oldCapacity); 843 static uint32_t ComputeElementCapacityWithHint(uint32_t oldCapacity, uint32_t hint); 844 static uint32_t ComputeNonInlinedFastPropsCapacity(JSThread *thread, uint32_t oldCapacity, 845 uint32_t maxNonInlinedFastPropsCapacity); 846 847 static JSTaggedValue ShouldGetValueFromBox(ObjectOperator *op); 848 static std::pair<JSHandle<TaggedArray>, JSHandle<TaggedArray>> GetOwnEnumerableNamesInFastMode( 849 JSThread *thread, const JSHandle<JSObject> &obj, uint32_t *copyLengthOfKeys, uint32_t *copyLengthOfElements); 850 static bool CheckHClassHit(const JSHandle<JSObject> &obj, const JSHandle<JSHClass> &cls); 851 static uint32_t SetValuesOrEntries(JSThread *thread, const JSHandle<TaggedArray> &prop, uint32_t index, 852 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value, 853 PropertyKind kind); 854 static bool IsSimpleEnumCacheValid(JSThread *thread, JSTaggedValue receiver); 855 static bool IsProtoChainCacheValid(JSThread *thread, JSTaggedValue receiver); 856 static void TrimInlinePropsSpace(const JSThread *thread, const JSHandle<JSObject> &object, 857 uint32_t numberInlinedProps); 858 static bool ValidateDataDescriptorWhenConfigurable(ObjectOperator *op, const PropertyDescriptor &desc, 859 const PropertyDescriptor ¤t, SCheckMode sCheckMode); 860 static bool SetPropertyForDataDescriptor(ObjectOperator *op, JSHandle<JSTaggedValue> value, 861 JSHandle<JSTaggedValue> &receiver, bool mayThrow, bool isInternalAccessor); 862 static bool SetPropertyForDataDescriptorProxy(JSThread *thread, ObjectOperator *op, 863 const JSHandle<JSTaggedValue> &value, 864 JSHandle<JSTaggedValue> &receiver); 865 }; 866 } // namespace ecmascript 867 } // namespace panda 868 869 #endif 870