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