• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &current);
512 
513     static bool ValidateAndApplyPropertyDescriptor(ObjectOperator *op, bool extensible, const PropertyDescriptor &desc,
514                                                    const PropertyDescriptor &current,
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 &current, 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