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::MAX_FAST_PROPS_CAPACITY_LOG2>; 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 void *GetNativePointer() const; 375 376 static constexpr size_t HASH_OFFSET = TaggedObjectSize(); 377 static constexpr size_t SIZE = HASH_OFFSET + sizeof(JSTaggedType); 378 379 static void SetHash(const JSThread *thread, int32_t hash, const JSHandle<ECMAObject> &obj); 380 int32_t GetHash() const; 381 bool HasHash() const; 382 InitializeHash()383 void InitializeHash() 384 { 385 Barriers::SetPrimitive<JSTaggedType>(this, ECMAObject::HASH_OFFSET, JSTaggedValue(0).GetRawData()); 386 } 387 388 void* GetNativePointerField(int32_t index) const; 389 static void SetNativePointerField(const JSThread *thread, const JSHandle<JSObject> &obj, int32_t index, 390 void *nativePointer, const NativePointerCallback &callBack, void *data, 391 size_t nativeBindingsize = 0, Concurrent isConcurrent = Concurrent::NO); 392 int32_t GetNativePointerFieldCount() const; 393 static void SetNativePointerFieldCount(const JSThread *thread, const JSHandle<JSObject> &obj, int32_t count); 394 395 DECL_VISIT_OBJECT(HASH_OFFSET, SIZE); 396 397 template <VisitType visitType, class DerivedVisitor> VisitObjects(EcmaObjectRangeVisitor<DerivedVisitor> & visitor)398 void VisitObjects(EcmaObjectRangeVisitor<DerivedVisitor> &visitor) 399 { 400 // no field in this object 401 VisitRangeSlot<visitType>(visitor); 402 } 403 }; 404 405 class JSObject : public ECMAObject { 406 public: 407 static constexpr int MIN_ELEMENTS_LENGTH = 3; 408 static constexpr int MIN_PROPERTIES_LENGTH = JSHClass::DEFAULT_CAPACITY_OF_IN_OBJECTS; 409 static constexpr int FAST_ELEMENTS_FACTOR = 3; 410 static constexpr int MIN_GAP = 256; 411 static constexpr int MAX_GAP = 1_KB; 412 static constexpr uint32_t MAX_ELEMENT_INDEX = std::numeric_limits<uint32_t>::max(); 413 static constexpr int MIN_ELEMENTS_HINT_LENGTH = 1_KB; 414 static constexpr int MAX_ELEMENTS_HINT_LENGTH = 2_MB; 415 static constexpr int ELEMENTS_HINT_FACTOR = 8; 416 static constexpr int SHOULD_TRANS_TO_FAST_ELEMENTS_FACTOR = 2; 417 418 CAST_CHECK(JSObject, IsECMAObject); 419 420 // ecma6.0 6.2.4.4 421 static JSHandle<JSTaggedValue> FromPropertyDescriptor(JSThread *thread, const PropertyDescriptor &desc); 422 423 // ecma6.0 6.2.4.5 ToPropertyDescriptor ( Obj ) 424 static void ToPropertyDescriptor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, PropertyDescriptor &desc); 425 static bool ToPropertyDescriptorFast(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 426 PropertyDescriptor &desc); 427 428 static JSHandle<JSTaggedValue> CallFunction(JSThread *thread, const JSHandle<JSTaggedValue> &func); 429 430 // ecma6 7.3 Operations on Objects 431 static JSHandle<JSTaggedValue> GetMethod(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 432 const JSHandle<JSTaggedValue> &key); 433 434 static JSHandle<JSTaggedValue> FastGetMethod(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 435 const JSHandle<JSTaggedValue> &key); 436 437 static bool CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 438 const JSHandle<JSTaggedValue> &value, SCheckMode sCheckMode = SCheckMode::CHECK); 439 440 static bool CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 441 const JSHandle<JSTaggedValue> &value, SCheckMode sCheckMode = SCheckMode::CHECK); 442 443 static bool CreateMethodProperty(JSThread *thread, const JSHandle<JSObject> &obj, 444 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value); 445 446 static bool CreateDataPropertyOrThrow(JSThread *thread, const JSHandle<JSObject> &obj, 447 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value, 448 SCheckMode sCheckMode = SCheckMode::CHECK); 449 450 static bool CreateDataPropertyOrThrow(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 451 const JSHandle<JSTaggedValue> &value, 452 SCheckMode sCheckMode = SCheckMode::CHECK); 453 454 static JSHandle<TaggedArray> PUBLIC_API EnumerableOwnNames(JSThread *thread, const JSHandle<JSObject> &obj); 455 456 // 7.3.23 EnumerableOwnPropertyNames ( O, kind ) 457 static JSHandle<TaggedArray> EnumerableOwnPropertyNames(JSThread *thread, const JSHandle<JSObject> &obj, 458 PropertyKind kind); 459 static void EnumerableOwnPropertyNamesHelper(JSThread *thread, const JSHandle<JSObject> &obj, 460 const JSHandle<TaggedArray> &arr, JSHandle<TaggedArray> &properties, 461 uint32_t &index, bool &fastMode, PropertyKind kind); 462 463 static JSHandle<GlobalEnv> GetFunctionRealm(JSThread *thread, const JSHandle<JSTaggedValue> &object); 464 465 static bool SetIntegrityLevel(JSThread *thread, const JSHandle<JSObject> &obj, IntegrityLevel level); 466 467 static bool FreezeSharedObject(JSThread *thread, const JSHandle<JSObject> &obj); 468 469 static bool TestIntegrityLevel(JSThread *thread, const JSHandle<JSObject> &obj, IntegrityLevel level); 470 471 static JSHandle<JSTaggedValue> SpeciesConstructor(JSThread *thread, const JSHandle<JSObject> &obj, 472 const JSHandle<JSTaggedValue> &defaultConstructor); 473 static JSHandle<JSTaggedValue> SlowSpeciesConstructor(JSThread *thread, 474 const JSHandle<JSTaggedValue> &objConstructor, 475 const JSHandle<JSTaggedValue> &defaultConstructor); 476 // 7.3.17 477 template<ElementTypes types = ElementTypes::ALLTYPES> 478 static JSHandle<JSTaggedValue> CreateListFromArrayLike(JSThread *thread, const JSHandle<JSTaggedValue> &obj); 479 480 // ecma6 9.1 481 // [[GetPrototypeOf]] 482 static JSTaggedValue GetPrototype(const JSHandle<JSObject> &obj); 483 484 static JSTaggedValue GetPrototype(JSTaggedValue obj); 485 486 // [[SetPrototypeOf]] 487 static bool SetPrototype(JSThread *thread, const JSHandle<JSObject> &obj, 488 const JSHandle<JSTaggedValue> &proto, 489 bool isChangeProto = false); 490 491 // [[IsExtensible]] 492 bool IsExtensible() const; 493 494 // [[PreventExtensions]] 495 static bool PreventExtensions(JSThread *thread, const JSHandle<JSObject> &obj); 496 497 // [[GetOwnProperty]] -> Undefined | Property Descriptor 498 static bool GetOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 499 PropertyDescriptor &desc); 500 501 static bool GlobalGetOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc); 502 503 static bool OrdinaryGetOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, 504 const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc); 505 506 // [[DefineOwnProperty]] 507 static bool DefineOwnProperty(JSThread *thread, ObjectOperator *op, 508 const PropertyDescriptor &desc, SCheckMode sCheckMode = SCheckMode::CHECK); 509 510 static bool DefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 511 const PropertyDescriptor &desc, SCheckMode sCheckMode = SCheckMode::CHECK); 512 513 static bool DefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 514 const PropertyDescriptor &desc, SCheckMode sCheckMode = SCheckMode::CHECK); 515 516 static bool OrdinaryDefineOwnProperty(JSThread *thread, ObjectOperator *op, 517 const PropertyDescriptor &desc, SCheckMode sCheckMode = SCheckMode::CHECK); 518 519 static bool OrdinaryDefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, 520 const JSHandle<JSTaggedValue> &key, const PropertyDescriptor &desc, 521 SCheckMode sCheckMode = SCheckMode::CHECK); 522 523 static bool OrdinaryDefineOwnProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index, 524 const PropertyDescriptor &desc, 525 SCheckMode sCheckMode = SCheckMode::CHECK); 526 527 static bool IsCompatiblePropertyDescriptor(bool extensible, const PropertyDescriptor &desc, 528 const PropertyDescriptor ¤t); 529 530 static bool ValidateAndApplyPropertyDescriptor(ObjectOperator *op, bool extensible, const PropertyDescriptor &desc, 531 const PropertyDescriptor ¤t, 532 SCheckMode sCheckMode = SCheckMode::CHECK); 533 534 static OperationResult PUBLIC_API GetProperty(JSThread *thread, const JSHandle<JSObject> &obj, 535 const JSHandle<JSTaggedValue> &key); 536 537 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 538 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &receiver); 539 540 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, 541 const JSHandle<JSTaggedValue> &key, SCheckMode sCheckMode = SCheckMode::CHECK); 542 543 static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t index); 544 545 static OperationResult GetPropertyFromGlobal(JSThread *thread, const JSHandle<JSTaggedValue> &key); 546 547 static bool SetProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 548 JSHandle<JSTaggedValue> value, bool mayThrow = false); 549 550 static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 551 JSHandle<JSTaggedValue> value, bool mayThrow = false, 552 SCheckMode checkMode = SCheckMode::CHECK); 553 554 static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 555 JSHandle<JSTaggedValue> value, const JSHandle<JSTaggedValue> &receiver, 556 bool mayThrow = false); 557 558 static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t index, 559 JSHandle<JSTaggedValue> value, bool mayThrow = false); 560 561 static bool GlobalSetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &key, 562 JSHandle<JSTaggedValue> value, bool mayThrow); 563 564 // [[HasProperty]] 565 static bool HasProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key); 566 567 static bool HasProperty(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t index); 568 569 // 9.1.10 [[Delete]] 570 static bool DeleteProperty(JSThread *thread, const JSHandle<JSObject> &obj, const JSHandle<JSTaggedValue> &key, 571 SCheckMode sCheckMode = SCheckMode::CHECK); 572 573 // [[OwnPropertyKeys]] 574 static JSHandle<TaggedArray> GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj); 575 576 static JSHandle<TaggedArray> GetAllPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj, uint32_t filter); 577 578 static void CollectEnumKeysAlongProtoChain(JSThread *thread, const JSHandle<JSObject> &obj, 579 JSHandle<TaggedArray> keyArray, uint32_t *keys, 580 JSHandle<TaggedQueue> shadowQueue, int32_t lastLength = -1); 581 582 static void AppendOwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj, 583 JSHandle<TaggedArray> keyArray, uint32_t *keys, 584 JSHandle<TaggedQueue> shadowQueue); 585 586 static JSHandle<TaggedArray> GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSObject> &obj); 587 588 // 9.1.13 ObjectCreate 589 static JSHandle<JSObject> ObjectCreate(JSThread *thread, const JSHandle<JSObject> &proto); 590 591 // 12.9.4 Runtime Semantics: InstanceofOperator(O, C) 592 static bool InstanceOf(JSThread *thread, const JSHandle<JSTaggedValue> &object, 593 const JSHandle<JSTaggedValue> &target); 594 595 static JSTaggedValue TryGetEnumCache(JSThread *thread, JSTaggedValue obj); 596 597 // 13.7.5.15 EnumerateObjectProperties ( O ); same as [[Enumerate]] 598 static JSHandle<JSForInIterator> EnumerateObjectProperties(JSThread *thread, const JSHandle<JSTaggedValue> &obj); 599 static JSHandle<JSForInIterator> LoadEnumerateProperties(JSThread *thread, const JSHandle<JSTaggedValue> &object); 600 601 static bool IsRegExp(JSThread *thread, const JSHandle<JSTaggedValue> &argument); 602 603 static JSTaggedValue CallGetter(JSThread *thread, const AccessorData *accessor, 604 const JSHandle<JSTaggedValue> &receiver); 605 static bool PUBLIC_API CallSetter(JSThread *thread, const AccessorData &accessor, 606 const JSHandle<JSTaggedValue> &receiver, 607 const JSHandle<JSTaggedValue> &value, bool mayThrow = false); 608 609 static void FillElementsWithHoles(const JSThread *thread, const JSHandle<JSObject> &obj, 610 uint32_t start, uint32_t end); 611 GetJSHClass()612 JSHClass *GetJSHClass() const 613 { 614 return GetClass(); 615 } 616 uint32_t GetNonInlinedFastPropsCapacity() const; 617 bool IsJSGlobalObject() const; 618 bool IsConstructor() const; 619 bool IsECMAObject() const; 620 bool IsJSError() const; 621 bool IsArguments() const; 622 bool IsDate() const; 623 bool IsJSArray() const; 624 bool IsJSSArray() const; 625 bool IsJSShared() const; 626 bool IsJSMap() const; 627 bool IsJSSet() const; 628 bool IsJSRegExp() const; 629 bool IsJSFunction() const; 630 bool IsBoundFunction() const; 631 bool IsJSIntlBoundFunction() const; 632 bool IsProxyRevocFunction() const; 633 bool IsAccessorData() const; 634 bool IsJSGlobalEnv() const; 635 bool IsJSProxy() const; 636 bool IsGeneratorObject() const; 637 bool IsAsyncGeneratorObject() const; 638 bool IsForinIterator() const; 639 bool IsJSSetIterator() const; 640 bool IsJSRegExpIterator() const; 641 bool IsJSMapIterator() const; 642 bool IsJSArrayIterator() const; 643 bool IsJSAPIArrayListIterator() const; 644 bool IsJSAPIStackIterator() const; 645 bool IsJSAPIVectorIterator() const; 646 bool IsJSAPIBitVectorIterator() const; 647 bool IsJSAPILinkedListIterator() const; 648 bool IsJSAPIListIterator() const; 649 bool IsJSPrimitiveRef() const; 650 bool IsElementDict() const; 651 bool IsPropertiesDict() const; 652 bool IsTypedArray() const; 653 bool IsSharedTypedArray() const; 654 bool PUBLIC_API ElementsAndPropertiesIsEmpty() const; 655 656 static PUBLIC_API void DefinePropertyByLiteral(JSThread *thread, const JSHandle<JSObject> &obj, 657 const JSHandle<JSTaggedValue> &key, 658 const JSHandle<JSTaggedValue> &value, 659 bool useForClass = false); 660 static void DefineSetter(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 661 const JSHandle<JSTaggedValue> &value); 662 static void DefineGetter(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 663 const JSHandle<JSTaggedValue> &value); 664 static PUBLIC_API JSHandle<JSObject> CreateObjectFromProperties(const JSThread *thread, 665 const JSHandle<TaggedArray> &properties, 666 JSTaggedValue ihc = JSTaggedValue::Undefined()); 667 static JSHandle<JSObject> CreateObjectFromProperties(const JSThread *thread, 668 const JSHandle<JSHClass> &hclass, 669 const JSHandle<TaggedArray> &properties, 670 uint32_t propsLen); 671 static JSHandle<JSObject> CreateObjectFromPropertiesByIHClass(const JSThread *thread, 672 const JSHandle<TaggedArray> &properties, 673 uint32_t propsLen, 674 const JSHandle<JSHClass> &ihc); 675 static bool CheckPropertiesForRep( 676 const JSHandle<TaggedArray> &properties, uint32_t propsLen, const JSHandle<JSHClass> &ihc); 677 static void GetAllKeys(const JSThread *thread, const JSHandle<JSObject> &obj, int offset, 678 const JSHandle<TaggedArray> &keyArray); 679 static void GetAllKeysForSerialization(const JSHandle<JSObject> &obj, std::vector<JSTaggedValue> &keyVector); 680 681 static void GetAllKeysByFilter(const JSThread *thread, const JSHandle<JSObject> &obj, 682 uint32_t &keyArrayEffectivelength, 683 const JSHandle<TaggedArray> &keyArray, 684 uint32_t filter); 685 static void GetAllElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 686 const JSHandle<TaggedArray> &keyArray); 687 static void GetAllElementKeysByFilter(JSThread *thread, 688 const JSHandle<JSObject> &obj, 689 const JSHandle<TaggedArray> &keyArray, 690 uint32_t &keyArrayEffectiveLength, 691 uint32_t filter); 692 693 static void GetALLElementKeysIntoVector(const JSThread *thread, const JSHandle<JSObject> &obj, 694 std::vector<JSTaggedValue> &keyVector); 695 std::pair<uint32_t, uint32_t> GetNumberOfEnumKeys() const; 696 uint32_t GetNumberOfKeys(); 697 uint32_t GetNumberOfElements(JSThread *thread); 698 699 static JSHandle<TaggedArray> GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 700 uint32_t numOfElements, uint32_t *keys); 701 static void CollectEnumElementsAlongProtoChain(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 702 JSHandle<TaggedArray> elementArray, uint32_t *keys, 703 int32_t lastLength = -1); 704 static void GetEnumElementKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 705 const JSHandle<TaggedArray> &keyArray); 706 static JSHandle<TaggedArray> GetAllEnumKeys(JSThread *thread, const JSHandle<JSObject> &obj, 707 uint32_t numOfKeys, uint32_t *keys); 708 static uint32_t GetAllEnumKeys(JSThread *thread, const JSHandle<JSObject> &obj, int offset, 709 const JSHandle<TaggedArray> &keyArray); 710 711 static void AddAccessor(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key, 712 const JSHandle<AccessorData> &value, PropertyAttributes attr); 713 714 static constexpr size_t PROPERTIES_OFFSET = ECMAObject::SIZE; 715 716 ACCESSORS(Properties, PROPERTIES_OFFSET, ELEMENTS_OFFSET); 717 ACCESSORS(Elements, ELEMENTS_OFFSET, SIZE); 718 719 DECL_VISIT_OBJECT_FOR_JS_OBJECT(ECMAObject, PROPERTIES_OFFSET, SIZE) 720 721 void Dump(std::ostream &os, bool isPrivacy = false) const DUMP_API_ATTR; Dump()722 void Dump() const DUMP_API_ATTR 723 { 724 Dump(std::cout); 725 } 726 void DumpForSnapshot(std::vector<Reference> &vec) const; 727 static const CString ExtractConstructorAndRecordName(JSThread *thread, TaggedObject *obj, bool noAllocate = false, 728 bool *isCallGetter = nullptr); 729 730 static JSHandle<NameDictionary> PUBLIC_API TransitionToDictionary(const JSThread *thread, 731 const JSHandle<JSObject> &receiver); 732 733 static inline std::pair<bool, JSTaggedValue> ConvertValueWithRep(PropertyAttributes attr, JSTaggedValue value); 734 735 inline void SetPropertyInlinedPropsWithRep(const JSThread *thread, uint32_t index, JSTaggedValue value); 736 template <size_t objectSize, uint32_t index, bool needBarrier = true> 737 inline void SetPropertyInlinedPropsWithSize(const JSThread* thread, JSTaggedValue value); 738 template <bool needBarrier = true> 739 inline void SetPropertyInlinedProps(const JSThread *thread, uint32_t index, JSTaggedValue value); 740 template <bool needBarrier = true> 741 inline void SetPropertyInlinedProps(const JSThread *thread, const JSHClass *hclass, uint32_t index, 742 JSTaggedValue value); 743 inline JSTaggedValue GetPropertyInlinedPropsWithRep(uint32_t index, PropertyAttributes attr) const; 744 inline JSTaggedValue GetPropertyInlinedPropsWithRep(const JSHClass *hclass, uint32_t index, 745 PropertyAttributes attr) const; 746 template <size_t objectSize, uint32_t index> 747 inline JSTaggedValue GetPropertyInlinedPropsWithSize() const; 748 inline JSTaggedValue GetPropertyInlinedProps(uint32_t index) const; 749 inline JSTaggedValue GetPropertyInlinedProps(const JSHClass *hclass, uint32_t index) const; 750 inline JSTaggedValue GetProperty(const JSHClass *hclass, PropertyAttributes attr) const; 751 PropertyBox* GetGlobalPropertyBox(JSThread *thread, const std::string& key); 752 template <bool needBarrier = true> 753 inline void SetProperty(const JSThread *thread, const JSHClass *hclass, PropertyAttributes attr, 754 JSTaggedValue value); 755 756 static bool IsArrayLengthWritable(JSThread *thread, const JSHandle<JSObject> &receiver); 757 bool UpdatePropertyInDictionary(const JSThread *thread, JSTaggedValue key, JSTaggedValue value); 758 static bool ShouldTransToDict(uint32_t capacity, uint32_t index); 759 static bool ShouldTransToFastElements(JSThread *thread, TaggedArray *elements, uint32_t capacity, uint32_t index); 760 static bool AttributesUnchanged(const JSThread *thread, const JSHandle<JSObject> &obj); 761 static JSHandle<TaggedArray> GrowElementsCapacity(const JSThread *thread, const JSHandle<JSObject> &obj, 762 uint32_t capacity, bool highGrowth = false, bool isNew = false); 763 764 static bool IsDepulicateKeys(JSThread *thread, JSHandle<TaggedArray> keys, int32_t lastLength, 765 JSHandle<TaggedQueue> shadowQueue, JSHandle<JSTaggedValue> key); 766 767 static void SetEnumCacheKind(JSThread *thread, TaggedArray *array, EnumCacheKind kind); 768 static EnumCacheKind GetEnumCacheKind(JSThread *thread, TaggedArray *array); 769 static EnumCacheKind GetEnumCacheKind(JSThread *thread, JSTaggedValue enumCache); 770 771 static void ClearHasDeleteProperty(JSHandle<JSTaggedValue> object); 772 773 static JSHandle<JSTaggedValue> IterableToList(JSThread *thread, const JSHandle<JSTaggedValue> &items, 774 JSTaggedValue method = JSTaggedValue::Undefined()); 775 776 static void TryOptimizeAsFastElements(const JSThread *thread, JSHandle<JSObject> obj); 777 static void OptimizeAsFastProperties(const JSThread *thread, JSHandle<JSObject> obj); 778 779 static void SetSProperties(JSThread *thread, JSHandle<JSObject> obj, const std::vector<PropertyDescriptor> &descs); 780 781 static void PUBLIC_API TryMigrateToGenericKindForJSObject(const JSThread *thread, const JSHandle<JSObject> &obj, 782 const ElementsKind oldKind); 783 static void ElementsToDictionary(const JSThread *thread, JSHandle<JSObject> obj); 784 785 private: 786 friend class ObjectOperator; 787 friend class LoadICRuntime; 788 friend class StoreICRuntime; 789 friend class ObjectFastOperator; 790 friend class ICRuntimeStub; 791 friend class RuntimeStubs; 792 friend class JSSharedArray; 793 friend class builtins::BuiltinsArkTools; 794 795 static bool HasMutantTaggedArrayElements(const JSHandle<JSObject> &obj); 796 PropertyBox* GetGlobalPropertyBox(JSTaggedValue key); 797 static bool CheckAndUpdateArrayLength(JSThread *thread, const JSHandle<JSObject> &receiver, 798 uint32_t index, ElementsKind &kind); 799 static bool PUBLIC_API AddElementInternal( 800 JSThread *thread, const JSHandle<JSObject> &receiver, uint32_t index, const JSHandle<JSTaggedValue> &value, 801 PropertyAttributes attr = PropertyAttributes(PropertyAttributes::GetDefaultAttributes())); 802 803 static JSTaggedValue GetProperty(JSThread *thread, ObjectOperator *op); 804 static bool SetProperty(ObjectOperator *op, JSHandle<JSTaggedValue> value, bool mayThrow); 805 static bool SetPropertyForData(ObjectOperator *op, const JSHandle<JSTaggedValue> &value, bool *isAccessor); 806 static bool SetPropertyForAccessor(ObjectOperator *op, const JSHandle<JSTaggedValue> &value); 807 static void DeletePropertyInternal(JSThread *thread, const JSHandle<JSObject> &obj, 808 const JSHandle<JSTaggedValue> &key, uint32_t index); 809 int FindProperty(const JSHandle<JSTaggedValue> &key); 810 811 static uint32_t ComputeElementCapacity(uint32_t oldCapacity, bool isNew = false); 812 static uint32_t ComputeElementCapacityHighGrowth(uint32_t oldCapacity); 813 static uint32_t ComputeElementCapacityWithHint(uint32_t oldCapacity, uint32_t hint); 814 static uint32_t ComputeNonInlinedFastPropsCapacity(JSThread *thread, uint32_t oldCapacity, 815 uint32_t maxNonInlinedFastPropsCapacity); 816 817 static JSTaggedValue ShouldGetValueFromBox(ObjectOperator *op); 818 static std::pair<JSHandle<TaggedArray>, JSHandle<TaggedArray>> GetOwnEnumerableNamesInFastMode( 819 JSThread *thread, const JSHandle<JSObject> &obj, uint32_t *copyLengthOfKeys, uint32_t *copyLengthOfElements); 820 static bool CheckHClassHit(const JSHandle<JSObject> &obj, const JSHandle<JSHClass> &cls); 821 static uint32_t SetValuesOrEntries(JSThread *thread, const JSHandle<TaggedArray> &prop, uint32_t index, 822 const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &value, 823 PropertyKind kind); 824 static bool IsSimpleEnumCacheValid(JSThread *thread, JSTaggedValue receiver); 825 static bool IsEnumCacheWithProtoChainInfoValid(JSThread *thread, JSTaggedValue receiver); 826 static void TrimInlinePropsSpace(const JSThread *thread, const JSHandle<JSObject> &object, 827 uint32_t numberInlinedProps); 828 static bool ValidateDataDescriptorWhenConfigurable(ObjectOperator *op, const PropertyDescriptor &desc, 829 const PropertyDescriptor ¤t, SCheckMode sCheckMode); 830 static bool SetPropertyForDataDescriptor(ObjectOperator *op, JSHandle<JSTaggedValue> value, 831 JSHandle<JSTaggedValue> &receiver, bool mayThrow, bool isInternalAccessor); 832 static bool SetPropertyForDataDescriptorProxy(JSThread *thread, ObjectOperator *op, 833 const JSHandle<JSTaggedValue> &value, 834 JSHandle<JSTaggedValue> &receiver); 835 }; 836 } // namespace ecmascript 837 } // namespace panda 838 839 #endif 840