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