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