1 /* 2 * Copyright (c) 2021 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_string.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_native_pointer.h" 26 #include "ecmascript/js_tagged_value.h" 27 #include "ecmascript/mem/slots.h" 28 #include "ecmascript/mem/visitor.h" 29 #include "ecmascript/method.h" 30 #include "ecmascript/object_operator.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 // Integrity level for objects 44 enum IntegrityLevel { SEALED, FROZEN }; 45 46 enum PositionKind { UNKNOWN = 0, INDEXED_PROPERTY = 1, INLINE_NAMED_PROPERTY = 2, OUT_NAMED_PROPERTY = 3 }; 47 enum PropertyKind { KEY = 0, VALUE, KEY_VALUE }; 48 49 // ecma6.0 6.2.4 The Property Descriptor Specification Type 50 class PropertyDescriptor final { 51 public: 52 PropertyDescriptor() = delete; 53 54 ~PropertyDescriptor() = default; 55 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyDescriptor); 56 DEFAULT_COPY_SEMANTIC(PropertyDescriptor); 57 PropertyDescriptor(const JSThread * thread)58 explicit PropertyDescriptor(const JSThread *thread) : thread_(thread) {} 59 PropertyDescriptor(const JSThread * thread,JSHandle<JSTaggedValue> v)60 PropertyDescriptor(const JSThread *thread, JSHandle<JSTaggedValue> v) : thread_(thread), value_(v) {} 61 PropertyDescriptor(const JSThread * thread,JSHandle<JSTaggedValue> v,bool w,bool e,bool c)62 PropertyDescriptor(const JSThread *thread, JSHandle<JSTaggedValue> v, bool w, bool e, bool c) 63 : thread_(thread), 64 writable_(w), 65 enumerable_(e), 66 configurable_(c), 67 hasWritable_(true), 68 hasEnumerable_(true), 69 hasConfigurable_(true), 70 value_(v) 71 { 72 } 73 PropertyDescriptor(const JSThread * thread,bool w,bool e,bool c)74 PropertyDescriptor(const JSThread *thread, bool w, bool e, bool c) 75 : PropertyDescriptor(thread, JSHandle<JSTaggedValue>(), w, e, c) 76 { 77 } 78 GetValue()79 inline JSHandle<JSTaggedValue> GetValue() const 80 { 81 if (value_.IsEmpty()) { 82 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined()); 83 } 84 return value_; 85 } 86 SetValue(JSHandle<JSTaggedValue> value)87 inline void SetValue(JSHandle<JSTaggedValue> value) 88 { 89 value_ = value; 90 } 91 IsWritable()92 inline bool IsWritable() const 93 { 94 return writable_; 95 } 96 SetWritable(bool flag)97 inline void SetWritable(bool flag) 98 { 99 writable_ = flag; 100 hasWritable_ = true; 101 } 102 IsEnumerable()103 inline bool IsEnumerable() const 104 { 105 return enumerable_; 106 } 107 SetEnumerable(bool flag)108 inline void SetEnumerable(bool flag) 109 { 110 enumerable_ = flag; 111 hasEnumerable_ = true; 112 } 113 IsConfigurable()114 inline bool IsConfigurable() const 115 { 116 return configurable_; 117 } 118 SetConfigurable(bool flag)119 inline void SetConfigurable(bool flag) 120 { 121 configurable_ = flag; 122 hasConfigurable_ = true; 123 } 124 HasValue()125 inline bool HasValue() const 126 { 127 return !value_.IsEmpty(); 128 } 129 HasWritable()130 inline bool HasWritable() const 131 { 132 return hasWritable_; 133 } 134 HasConfigurable()135 inline bool HasConfigurable() const 136 { 137 return hasConfigurable_; 138 } 139 HasEnumerable()140 inline bool HasEnumerable() const 141 { 142 return hasEnumerable_; 143 } 144 HasGetter()145 inline bool HasGetter() const 146 { 147 return !getter_.IsEmpty(); 148 } 149 HasSetter()150 inline bool HasSetter() const 151 { 152 return !setter_.IsEmpty(); 153 } 154 GetGetter()155 inline JSHandle<JSTaggedValue> GetGetter() const 156 { 157 if (getter_->IsNull()) { 158 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined()); 159 } 160 return getter_; 161 } 162 GetSetter()163 inline JSHandle<JSTaggedValue> GetSetter() const 164 { 165 if (setter_->IsNull()) { 166 return JSHandle<JSTaggedValue>(thread_, JSTaggedValue::Undefined()); 167 } 168 return setter_; 169 } 170 SetGetter(JSHandle<JSTaggedValue> value)171 inline void SetGetter(JSHandle<JSTaggedValue> value) 172 { 173 getter_ = value; 174 } 175 SetSetter(JSHandle<JSTaggedValue> value)176 inline void SetSetter(JSHandle<JSTaggedValue> value) 177 { 178 setter_ = value; 179 } 180 181 // 6.2.4.1 IsAccessorDescriptor()182 inline bool IsAccessorDescriptor() const 183 { 184 // 2. If both Desc.[[Get]] and Desc.[[Set]] are absent, return false. 185 return !(getter_.IsEmpty() && setter_.IsEmpty()); 186 } 187 IsDataDescriptor()188 inline bool IsDataDescriptor() const 189 { 190 // 2. If both Desc.[[Value]] and Desc.[[Writable]] are absent, return false. 191 return !(value_.IsEmpty() && !hasWritable_); 192 } 193 IsGenericDescriptor()194 inline bool IsGenericDescriptor() const 195 { 196 // 2. If IsAccessorDescriptor(Desc) and IsDataDescriptor(Desc) are both false, return true 197 return !IsAccessorDescriptor() && !IsDataDescriptor(); 198 } 199 IsEmpty()200 inline bool IsEmpty() const 201 { 202 return !hasWritable_ && !hasEnumerable_ && !hasConfigurable_ && !HasValue() && !HasGetter() && !HasSetter(); 203 } 204 205 static void CompletePropertyDescriptor(const JSThread *thread, PropertyDescriptor &desc); 206 207 private: 208 const JSThread *thread_{nullptr}; 209 210 bool writable_ {false}; 211 bool enumerable_ {false}; 212 bool configurable_ {false}; 213 bool hasWritable_ {false}; 214 bool hasEnumerable_ {false}; 215 bool hasConfigurable_ {false}; 216 217 JSHandle<JSTaggedValue> value_ {}; 218 JSHandle<JSTaggedValue> getter_ {}; 219 JSHandle<JSTaggedValue> setter_ {}; 220 }; 221 222 enum class ElementTypes { ALLTYPES, STRING_AND_SYMBOL }; 223 224 class PropertyMetaData { 225 public: 226 using IsFoundField = BitField<bool, 0, 1>; 227 using IsInlinedPropsField = IsFoundField::NextFlag; 228 using RepresentationField = IsInlinedPropsField::NextField<Representation, 3>; 229 using OffsetField = RepresentationField::NextField<uint32_t, PropertyAttributes::OFFSET_BITFIELD_NUM>; 230 PropertyMetaData(uint32_t metaData)231 explicit PropertyMetaData(uint32_t metaData) : metaData_(metaData) {} 232 233 ~PropertyMetaData() = default; 234 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(PropertyMetaData); 235 DEFAULT_COPY_SEMANTIC(PropertyMetaData); 236 PropertyMetaData(bool isFound)237 explicit PropertyMetaData(bool isFound) 238 { 239 SetFound(isFound); 240 } 241 IsFound()242 inline bool IsFound() const 243 { 244 return IsFoundField::Get(metaData_); 245 } 246 SetFound(bool flag)247 inline void SetFound(bool flag) 248 { 249 IsFoundField::Set(flag, &metaData_); 250 } 251 GetIsInlinedProps()252 inline bool GetIsInlinedProps() const 253 { 254 return IsInlinedPropsField::Get(metaData_); 255 } 256 SetIsInlinedProps(bool flag)257 inline void SetIsInlinedProps(bool flag) 258 { 259 IsInlinedPropsField::Set(flag, &metaData_); 260 } 261 GetRepresentation()262 inline Representation GetRepresentation() const 263 { 264 return RepresentationField::Get(metaData_); 265 } 266 SetRepresentation(Representation representation)267 inline void SetRepresentation(Representation representation) 268 { 269 RepresentationField::Set<uint32_t>(representation, &metaData_); 270 } 271 SetOffset(uint32_t offset)272 inline void SetOffset(uint32_t offset) 273 { 274 OffsetField::Set<uint32_t>(offset, &metaData_); 275 } 276 GetOffset()277 inline uint32_t GetOffset() const 278 { 279 return OffsetField::Get(metaData_); 280 } 281 282 private: 283 uint32_t metaData_{0}; 284 }; 285 286 class OperationResult { 287 public: OperationResult(const JSThread * thread,JSTaggedValue value,PropertyMetaData metaData)288 OperationResult(const JSThread *thread, JSTaggedValue value, PropertyMetaData metaData) 289 : metaData_(metaData) 290 { 291 thread_ = thread; 292 value_ = JSHandle<JSTaggedValue>(thread_, value); 293 } 294 295 ~OperationResult() = default; 296 DEFAULT_NOEXCEPT_MOVE_SEMANTIC(OperationResult); 297 DEFAULT_COPY_SEMANTIC(OperationResult); 298 GetValue()299 JSHandle<JSTaggedValue> GetValue() const 300 { 301 if (value_->IsPropertyBox()) { 302 return JSHandle<JSTaggedValue>(thread_, 303 PropertyBox::Cast(value_.GetTaggedValue().GetTaggedObject())->GetValue()); 304 } 305 return value_; 306 } 307 GetRawValue()308 JSHandle<JSTaggedValue> GetRawValue() const 309 { 310 return value_; 311 } 312 GetPropertyMetaData()313 const PropertyMetaData &GetPropertyMetaData() const 314 { 315 return metaData_; 316 } 317 318 private: 319 const JSThread *thread_ {nullptr}; 320 JSHandle<JSTaggedValue> value_ {}; 321 PropertyMetaData metaData_ {0U}; 322 }; 323 324 class ECMAObject : public TaggedObject { 325 public: 326 static constexpr int HASH_INDEX = 0; 327 static constexpr int FUNCTION_EXTRA_INDEX = 1; 328 static constexpr int RESOLVED_MAX_SIZE = 2; 329 330 CAST_CHECK(ECMAObject, IsECMAObject); 331 332 void SetCallable(bool flag); 333 bool IsCallable() const; 334 Method *GetCallTarget() const; 335 336 static constexpr size_t HASH_OFFSET = TaggedObjectSize(); 337 static constexpr size_t SIZE = HASH_OFFSET + sizeof(JSTaggedType); 338 339 void SetHash(int32_t hash); 340 int32_t GetHash() const; 341 bool HasHash() const; 342 InitializeHash()343 void InitializeHash() 344 { 345 Barriers::SetPrimitive<JSTaggedType>(this, ECMAObject::HASH_OFFSET, JSTaggedValue(0).GetRawData()); 346 } 347 348 void* GetNativePointerField(int32_t index) const; 349 void SetNativePointerField(int32_t index, void *nativePointer, 350 const DeleteEntryPoint &callBack, void *data, size_t nativeBindingsize = 0); 351 int32_t GetNativePointerFieldCount() const; 352 void SetNativePointerFieldCount(int32_t count); 353 354 DECL_VISIT_OBJECT(HASH_OFFSET, SIZE); 355 VisitObjects(const EcmaObjectRangeVisitor & visitor)356 void VisitObjects(const EcmaObjectRangeVisitor &visitor) 357 { 358 // no field in this object 359 VisitRangeSlot(visitor); 360 } 361 }; 362 363 class JSObject : public ECMAObject { 364 public: 365 static constexpr int MIN_ELEMENTS_LENGTH = 3; 366 static constexpr int MIN_PROPERTIES_LENGTH = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS; 367 static constexpr int PROPERTIES_GROW_SIZE = 4; 368 static constexpr int FAST_ELEMENTS_FACTOR = 3; 369 static constexpr int MIN_GAP = 256; 370 static constexpr int MAX_GAP = 1_KB; 371 static constexpr uint32_t MAX_ELEMENT_INDEX = std::numeric_limits<uint32_t>::max(); 372 373 CAST_CHECK(JSObject, IsECMAObject); 374 375 // ecma6.0 6.2.4.4 376 static JSHandle<JSTaggedValue> FromPropertyDescriptor(JSThread *thread, const PropertyDescriptor &desc); 377 378 // ecma6.0 6.2.4.5 ToPropertyDescriptor ( Obj ) 379 static void ToPropertyDescriptor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, PropertyDescriptor &desc); 380 static bool ToPropertyDescriptorFast(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 381 PropertyDescriptor &desc); 382 383 // ecma6 7.3 Operations on Objects 384 static JSHandle<JSTaggedValue> GetMethod(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 385 const JSHandle<JSTaggedValue> &key); 386 387 static bool CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 388 const JSHandle<JSTaggedValue> &value); 389 390 static bool CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 391 const JSHandle<JSTaggedValue> &value); 392 393 static bool CreateMethodProperty(JSThread *thread, const JSHandle<JSObject> &obj, 394 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value); 395 396 static bool CreateDataPropertyOrThrow(JSThread *thread, const JSHandle<JSObject> &obj, 397 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value); 398 399 static bool CreateDataPropertyOrThrow(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 400 const JSHandle<JSTaggedValue> &value); 401 402 static JSHandle<TaggedArray> EnumerableOwnNames(JSThread *thread, const JSHandle<JSObject> &obj); 403 404 // 7.3.23 EnumerableOwnPropertyNames ( O, kind ) 405 static JSHandle<TaggedArray> EnumerableOwnPropertyNames(JSThread *thread, const JSHandle<JSObject> &obj, 406 PropertyKind kind); 407 static void EnumerableOwnPropertyNamesHelper(JSThread *thread, const JSHandle<JSObject> &obj, 408 const JSHandle<TaggedArray> &arr, JSHandle<TaggedArray> &properties, 409 uint32_t &index, bool &fastMode, PropertyKind kind); 410 411 static JSHandle<GlobalEnv> GetFunctionRealm(JSThread *thread, const JSHandle<JSTaggedValue> &object); 412 413 static bool SetIntegrityLevel(JSThread *thread, const JSHandle<JSObject> &obj, IntegrityLevel level); 414 415 static bool TestIntegrityLevel(JSThread *thread, const JSHandle<JSObject> &obj, IntegrityLevel level); 416 417 static JSHandle<JSTaggedValue> SpeciesConstructor(JSThread *thread, const JSHandle<JSObject> &obj, 418 const JSHandle<JSTaggedValue> &defaultConstructort); 419 // 7.3.17 420 template<ElementTypes types = ElementTypes::ALLTYPES> 421 static JSHandle<JSTaggedValue> CreateListFromArrayLike(JSThread *thread, const JSHandle<JSTaggedValue> &obj); 422 423 // ecma6 9.1 424 // [[GetPrototypeOf]] 425 static JSTaggedValue GetPrototype(const JSHandle<JSObject> &obj); 426 427 // [[SetPrototypeOf]] 428 static bool SetPrototype(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &proto); 429 430 static JSTaggedValue GetCtorFromPrototype(JSThread *thread, JSTaggedValue prototype); 431 432 // [[IsExtensible]] 433 bool IsExtensible() const; 434 435 // [[PreventExtensions]] 436 static bool PreventExtensions(JSThread *thread, const JSHandle<JSObject> &obj); 437 438 // [[GetOwnProperty]] -> Undefined | Property Descriptor 439 static bool GetOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 440 PropertyDescriptor &desc); 441 442 static bool GlobalGetOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc); 443 444 static bool OrdinaryGetOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, 445 const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc); 446 447 // [[DefineOwnProperty]] 448 static bool DefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 449 const PropertyDescriptor &desc); 450 451 static bool DefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 452 const PropertyDescriptor &desc); 453 454 static bool OrdinaryDefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, 455 const JSHandle<JSTaggedValue> &key, const PropertyDescriptor &desc); 456 457 static bool OrdinaryDefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 458 const PropertyDescriptor &desc); 459 460 static bool IsCompatiblePropertyDescriptor(bool extensible, const PropertyDescriptor &desc, 461 const PropertyDescriptor ¤t); 462 463 static bool ValidateAndApplyPropertyDescriptor(ObjectOperator *op, bool extensible, const PropertyDescriptor &desc, 464 const PropertyDescriptor ¤t); 465 466 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSObject> &obj, 467 const JSHandle<JSTaggedValue> &key); 468 469 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 470 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &receiver); 471 472 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 473 const JSHandle<JSTaggedValue> &key); 474 475 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t index); 476 477 static OperationResult GetPropertyFromGlobal(JSThread *thread, const JSHandle<JSTaggedValue> &key); 478 479 static bool SetProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 480 const JSHandle<JSTaggedValue> &value, bool mayThrow = false); 481 482 static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 483 const JSHandle<JSTaggedValue> &value, bool mayThrow = false); 484 485 static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 486 const JSHandle<JSTaggedValue> &value, const JSHandle<JSTaggedValue> &receiver, 487 bool mayThrow = false); 488 489 static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t index, 490 const JSHandle<JSTaggedValue> &value, bool mayThrow = false); 491 492 static bool GlobalSetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &key, 493 const JSHandle<JSTaggedValue> &value, bool mayThrow); 494 495 // [[HasProperty]] 496 static bool HasProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key); 497 498 static bool HasProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index); 499 500 // 9.1.10 [[Delete]] 501 static bool DeleteProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key); 502 503 // [[OwnPropertyKeys]] 504 static JSHandle<TaggedArray> GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj); 505 506 static JSHandle<TaggedArray> GetAllPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t filter); 507 508 static JSHandle<TaggedArray> GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj); 509 510 // 9.1.13 ObjectCreate 511 static JSHandle<JSObject> ObjectCreate(JSThread *thread, const JSHandle<JSObject> &proto); 512 513 // 12.9.4 Runtime Semantics: InstanceofOperator(O, C) 514 static bool InstanceOf(JSThread *thread, const JSHandle<JSTaggedValue> &object, 515 const JSHandle<JSTaggedValue> &target); 516 517 // 13.7.5.15 EnumerateObjectProperties ( O ); same as [[Enumerate]] 518 static JSHandle<JSForInIterator> EnumerateObjectProperties(JSThread *thread, const JSHandle<JSTaggedValue> &obj); 519 520 static bool IsRegExp(JSThread *thread, const JSHandle<JSTaggedValue> &argument); 521 522 static JSTaggedValue CallGetter(JSThread *thread, const AccessorData *accessor, 523 const JSHandle<JSTaggedValue> &receiver); 524 static bool CallSetter(JSThread *thread, const AccessorData &accessor, const JSHandle<JSTaggedValue> &receiver, 525 const JSHandle<JSTaggedValue> &value, bool mayThrow = false); 526 527 void FillElementsWithHoles(const JSThread *thread, uint32_t start, uint32_t end); 528 529 JSHClass *GetJSHClass() const; 530 bool IsJSGlobalObject() const; 531 bool IsConstructor() const; 532 bool IsECMAObject() const; 533 bool IsJSError() const; 534 bool IsArguments() const; 535 bool IsDate() const; 536 bool IsJSArray() const; 537 bool IsJSMap() const; 538 bool IsJSSet() const; 539 bool IsJSRegExp() const; 540 bool IsJSFunction() const; 541 bool IsBoundFunction() const; 542 bool IsJSIntlBoundFunction() const; 543 bool IsProxyRevocFunction() const; 544 bool IsAccessorData() const; 545 bool IsJSGlobalEnv() const; 546 bool IsJSProxy() const; 547 bool IsGeneratorObject() const; 548 bool IsAsyncGeneratorObject() const; 549 bool IsForinIterator() const; 550 bool IsJSSetIterator() const; 551 bool IsJSRegExpIterator() const; 552 bool IsJSMapIterator() const; 553 bool IsJSArrayIterator() const; 554 bool IsJSAPIArrayListIterator() const; 555 bool IsJSAPIStackIterator() const; 556 bool IsJSAPIVectorIterator() const; 557 bool IsJSAPILinkedListIterator() const; 558 bool IsJSAPIListIterator() const; 559 bool IsJSPrimitiveRef() const; 560 bool IsElementDict() const; 561 bool IsPropertiesDict() const; 562 bool IsTypedArray() const; 563 564 static void DefinePropertyByLiteral(JSThread *thread, const JSHandle<JSObject> &obj, 565 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value, 566 bool useForClass = false); 567 static void DefineSetter(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 568 const JSHandle<JSTaggedValue> &value); 569 static void DefineGetter(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 570 const JSHandle<JSTaggedValue> &value); 571 static JSHandle<JSObject> CreateObjectFromProperties(const JSThread *thread, 572 const JSHandle<TaggedArray> &properties, 573 JSTaggedValue ihc = JSTaggedValue::Undefined()); 574 static void GetAllKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset, 575 const JSHandle<TaggedArray> &keyArray); 576 static void GetAllKeys(const JSHandle<JSObject> &obj, std::vector<JSTaggedValue> &keyVector); 577 578 static void GetAllKeysByFilter(const JSThread *thread, const JSHandle<JSObject> &obj, 579 uint32_t &keyArrayEffectivelength, 580 const JSHandle<TaggedArray> &keyArray, 581 uint32_t filter); 582 static void GetAllElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 583 const JSHandle<TaggedArray> &keyArray); 584 static void GetAllElementKeysByFilter(JSThread *thread, 585 const JSHandle<JSObject> &obj, 586 const JSHandle<TaggedArray> &keyArray, 587 uint32_t &keyArrayEffectiveLength, 588 uint32_t filter); 589 590 static void GetALLElementKeysIntoVector(const JSThread *thread, const JSHandle<JSObject> &obj, 591 std::vector<JSTaggedValue> &keyVector); 592 uint32_t GetNumberOfKeys(); 593 uint32_t GetNumberOfElements(); 594 595 static JSHandle<TaggedArray> GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 596 uint32_t numOfElements, uint32_t *keys); 597 static void GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 598 const JSHandle<TaggedArray> &keyArray); 599 static JSHandle<TaggedArray> GetAllEnumKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset, 600 uint32_t numOfKeys, uint32_t *keys); 601 static void GetAllEnumKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset, 602 const JSHandle<TaggedArray> &keyArray); 603 604 static void AddAccessor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 605 const JSHandle<AccessorData> &value, PropertyAttributes attr); 606 607 static constexpr size_t PROPERTIES_OFFSET = ECMAObject::SIZE; 608 609 ACCESSORS(Properties, PROPERTIES_OFFSET, ELEMENTS_OFFSET); 610 ACCESSORS(Elements, ELEMENTS_OFFSET, SIZE); 611 612 DECL_VISIT_OBJECT_FOR_JS_OBJECT(ECMAObject, PROPERTIES_OFFSET, SIZE) 613 614 DECL_DUMP() 615 616 static JSHandle<NameDictionary> TransitionToDictionary(const JSThread *thread, const JSHandle<JSObject> &receiver); 617 618 inline std::pair<bool, JSTaggedValue> ConvertValueWithRep(uint32_t index, JSTaggedValue value); 619 inline void SetPropertyInlinedPropsWithRep(const JSThread *thread, uint32_t index, JSTaggedValue value); 620 template <bool needBarrier = true> 621 inline void SetPropertyInlinedProps(const JSThread *thread, uint32_t index, JSTaggedValue value); 622 template <bool needBarrier = true> 623 inline void SetPropertyInlinedProps(const JSThread *thread, const JSHClass *hclass, uint32_t index, 624 JSTaggedValue value); 625 inline JSTaggedValue GetPropertyInlinedPropsWithRep(uint32_t index, PropertyAttributes attr) const; 626 inline JSTaggedValue GetPropertyInlinedPropsWithRep(const JSHClass *hclass, uint32_t index, 627 PropertyAttributes attr) const; 628 inline JSTaggedValue GetPropertyInlinedProps(uint32_t index) const; 629 inline JSTaggedValue GetPropertyInlinedProps(const JSHClass *hclass, uint32_t index) const; 630 inline JSTaggedValue GetProperty(const JSHClass *hclass, PropertyAttributes attr) const; 631 template <bool needBarrier = true> 632 inline void SetProperty(const JSThread *thread, const JSHClass *hclass, PropertyAttributes attr, 633 JSTaggedValue value); 634 635 static bool IsArrayLengthWritable(JSThread *thread, const JSHandle<JSObject> &receiver); 636 bool UpdatePropertyInDictionary(const JSThread *thread, JSTaggedValue key, JSTaggedValue value); 637 static bool ShouldTransToDict(uint32_t capacity, uint32_t index); 638 static JSHandle<TaggedArray> GrowElementsCapacity(const JSThread *thread, const JSHandle<JSObject> &obj, 639 uint32_t capacity); 640 641 static JSHandle<JSTaggedValue> IterableToList(JSThread *thread, const JSHandle<JSTaggedValue> &items, 642 JSTaggedValue method = JSTaggedValue::Undefined()); 643 644 protected: 645 static void ElementsToDictionary(const JSThread *thread, JSHandle<JSObject> obj); 646 647 private: 648 friend class ObjectOperator; 649 friend class LoadICRuntime; 650 friend class StoreICRuntime; 651 friend class ObjectFastOperator; 652 friend class ICRuntimeStub; 653 friend class RuntimeStubs; 654 655 static bool AddElementInternal( 656 JSThread *thread, const JSHandle<JSObject> &receiver, uint32_t index, const JSHandle<JSTaggedValue> &value, 657 PropertyAttributes attr = PropertyAttributes(PropertyAttributes::GetDefaultAttributes())); 658 659 static JSTaggedValue GetProperty(JSThread *thread, ObjectOperator *op); 660 static bool SetProperty(ObjectOperator *op, const JSHandle<JSTaggedValue> &value, bool mayThrow); 661 static void DeletePropertyInternal(JSThread *thread, const JSHandle<JSObject> &obj, 662 const JSHandle<JSTaggedValue> &key, uint32_t index); 663 int FindProperty(const JSHandle<JSTaggedValue> &key); 664 665 static uint32_t ComputeElementCapacity(uint32_t oldCapacity); 666 static uint32_t ComputePropertyCapacity(uint32_t oldCapacity); 667 668 static JSTaggedValue ShouldGetValueFromBox(ObjectOperator *op); 669 static std::pair<JSHandle<TaggedArray>, JSHandle<TaggedArray>> GetOwnEnumerableNamesInFastMode( 670 JSThread *thread, const JSHandle<JSObject> &obj, uint32_t *copyLengthOfKeys, uint32_t *copyLengthOfElements); 671 static bool CheckHClassHit(const JSHandle<JSObject> &obj, const JSHandle<JSHClass> &cls); 672 static uint32_t SetValuesOrEntries(JSThread *thread, const JSHandle<TaggedArray> &prop, uint32_t index, 673 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value, 674 PropertyKind kind); 675 }; 676 } // namespace ecmascript 677 } // namespace panda 678 679 #endif 680