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