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