• 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_JS_TAGGED_VALUE_H
17 #define ECMASCRIPT_JS_TAGGED_VALUE_H
18 
19 #include "ecmascript/base/bit_helper.h"
20 #include "ecmascript/base/config.h"
21 #include "ecmascript/mem/c_string.h"
22 #include "ecmascript/mem/mem_common.h"
23 
24 namespace panda::ecmascript {
25 class JSArray;
26 class JSObject;
27 class JSTaggedNumber;
28 template<typename T>
29 class JSHandle;
30 class TaggedArray;
31 class LinkedHashMap;
32 class LinkedHashSet;
33 class PropertyDescriptor;
34 class OperationResult;
35 class EcmaString;
36 class JSThread;
37 
38 static constexpr double SAFE_NUMBER = 9007199254740991LL;
39 
40 // Don't switch the order!
41 enum PreferredPrimitiveType : uint8_t { PREFER_NUMBER = 0, PREFER_STRING, NO_PREFERENCE };
42 
43 // Result of an abstract relational comparison of x and y, implemented according
44 // to ES6 section 7.2.11 Abstract Relational Comparison.
45 enum class ComparisonResult {
46     LESS,      // x < y
47     EQUAL,     // x = y
48     GREAT,     // x > y
49     UNDEFINED  // at least one of x or y was undefined or NaN
50 };
51 
52 using JSTaggedType = uint64_t;
53 
54 //  Every double with all of its exponent bits set and its highest mantissa bit set is a quiet NaN.
55 //  That leaves 51 bits unaccounted for. We’ll avoid one of those so that we don’t step on Intel’s
56 //  “QNaN Floating-Point Indefinite” value, leaving us 50 bits. Those remaining bits can be anything.
57 //  so we use a special quietNaN as TaggedInt tag(highest 16bits as 0xFFFF), and need to encode double
58 //  to the value will begin with a 16-bit pattern within the range 0x0001..0xFFFE.
59 
60 //  Nan-boxing pointer is used and the first four bytes are used as tag:
61 //    Object:             [0x0000] [48 bit direct pointer]
62 //    WeakRef:            [0x0000] [47 bits direct pointer] | 1
63 //                   /    [0x0001] [48 bit any value]
64 //    TaggedDouble:       ......
65 //                   \    [0xFFFE] [48 bit any value]
66 //    TaggedInt:          [0xFFFF] [0x0000] [32 bit signed integer]
67 //
68 //  There are some special markers of Object:
69 //    False:       [56 bits 0] | 0x06          // 0110
70 //    True:        [56 bits 0] | 0x07          // 0111
71 //    Undefined:   [56 bits 0] | 0x02          // 0010
72 //    Null:        [56 bits 0] | 0x03          // 0011
73 //    Hole:        [56 bits 0] | 0x05          // 0101
74 //    Optimized:   [56 bits 0] | 0x0C          // 1100
75 
76 class JSTaggedValue {
77 public:
78     static constexpr size_t BIT_PER_BYTE = 8;
79     static constexpr size_t TAG_BITS_SIZE = 16;  // 16 means bit numbers of 0xFFFF
80     static constexpr size_t TAG_BITS_SHIFT = base::BitNumbers<JSTaggedType>() - TAG_BITS_SIZE;
81     static_assert((TAG_BITS_SHIFT + TAG_BITS_SIZE) == sizeof(JSTaggedType) * BIT_PER_BYTE, "Insufficient bits!");
82     static constexpr JSTaggedType TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT;
83     // int tag
84     static constexpr JSTaggedType TAG_INT = TAG_MARK;
85     static constexpr JSTaggedType TAG_INT32_INC_MAX = INT32_MAX + 1ULL;
86     static constexpr JSTaggedType TAG_INT32_DEC_MIN = INT32_MIN - 1ULL;
87     // object tag
88     static constexpr JSTaggedType TAG_OBJECT = 0x0000ULL << TAG_BITS_SHIFT;
89     // weak object tag
90     static constexpr JSTaggedType TAG_WEAK = TAG_OBJECT | 0x01ULL;
91     // special tag
92     static constexpr JSTaggedType TAG_NULL = 0x01ULL;
93     static constexpr JSTaggedType TAG_SPECIAL = 0x02ULL;
94     static constexpr JSTaggedType TAG_BOOLEAN = 0x04ULL;
95     static constexpr JSTaggedType TAG_EXCEPTION = 0x08ULL;
96     static constexpr JSTaggedType TAG_OPTIMIZED_OUT = 0x12ULL;
97     // tag mask
98     static constexpr JSTaggedType TAG_SPECIAL_MASK = TAG_MARK | TAG_SPECIAL;
99     static constexpr JSTaggedType TAG_BOOLEAN_MASK = TAG_SPECIAL | TAG_BOOLEAN;
100     static constexpr JSTaggedType TAG_HEAPOBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN;
101     static constexpr JSTaggedType TAG_WEAK_MASK = TAG_HEAPOBJECT_MASK | TAG_WEAK;
102     // special value
103     static constexpr JSTaggedType VALUE_HOLE = 0x05ULL;
104     static constexpr JSTaggedType VALUE_NULL = TAG_OBJECT | TAG_SPECIAL | TAG_NULL;
105     static constexpr JSTaggedType VALUE_FALSE = TAG_BOOLEAN_MASK | static_cast<JSTaggedType>(false);
106     static constexpr JSTaggedType VALUE_TRUE = TAG_BOOLEAN_MASK | static_cast<JSTaggedType>(true);
107     static constexpr JSTaggedType VALUE_UNDEFINED = TAG_SPECIAL;
108     static constexpr JSTaggedType VALUE_EXCEPTION = TAG_SPECIAL | TAG_EXCEPTION;
109     static constexpr JSTaggedType VALUE_ZERO = TAG_INT | 0x00ULL;
110     static constexpr JSTaggedType VALUE_OPTIMIZED_OUT = TAG_SPECIAL | TAG_OPTIMIZED_OUT;
111 
112     static constexpr size_t INT_SIGN_BIT_OFFSET = 31;
113     static constexpr size_t DOUBLE_ENCODE_OFFSET_BIT = 48;
114     static constexpr JSTaggedType DOUBLE_ENCODE_OFFSET = 1ULL << DOUBLE_ENCODE_OFFSET_BIT;
115 
Cast(TaggedObject * object)116     static JSTaggedValue Cast(TaggedObject *object)
117     {
118         return JSTaggedValue(object);
119     }
120 
121     static const JSTaggedType NULL_POINTER = VALUE_HOLE;
122     static const JSTaggedType INVALID_VALUE_LIMIT = 0x40000ULL;
123 
CastDoubleToTagged(double value)124     static inline JSTaggedType CastDoubleToTagged(double value)
125     {
126         return base::bit_cast<JSTaggedType>(value);
127     }
128 
CastTaggedToDouble(JSTaggedType value)129     static inline double CastTaggedToDouble(JSTaggedType value)
130     {
131         return base::bit_cast<double>(value);
132     }
133 
TaggedTypeSize()134     static inline constexpr size_t TaggedTypeSize()
135     {
136         return sizeof(JSTaggedType);
137     }
138 
139     static constexpr size_t SizeArch32 = sizeof(JSTaggedType);
140 
141     static constexpr size_t SizeArch64 = sizeof(JSTaggedType);
142 
143     explicit JSTaggedValue(void *) = delete;
144 
JSTaggedValue()145     ARK_INLINE constexpr JSTaggedValue() : value_(JSTaggedValue::NULL_POINTER) {}
146 
JSTaggedValue(JSTaggedType v)147     ARK_INLINE constexpr explicit JSTaggedValue(JSTaggedType v) : value_(v) {}
148 
JSTaggedValue(int v)149     ARK_INLINE constexpr explicit JSTaggedValue(int v) : value_(static_cast<JSTaggedType>(v) | TAG_INT) {}
150 
JSTaggedValue(unsigned int v)151     ARK_INLINE explicit JSTaggedValue(unsigned int v)
152     {
153         if (static_cast<int32_t>(v) < 0) {
154             value_ = JSTaggedValue(static_cast<double>(v)).GetRawData();
155             return;
156         }
157         value_ = JSTaggedValue(static_cast<int32_t>(v)).GetRawData();
158     }
159 
JSTaggedValue(bool v)160     ARK_INLINE constexpr explicit JSTaggedValue(bool v)
161         : value_(static_cast<JSTaggedType>(v) | TAG_BOOLEAN_MASK) {}
162 
JSTaggedValue(double v)163     ARK_INLINE explicit JSTaggedValue(double v)
164     {
165         ASSERT_PRINT(!IsImpureNaN(v), "pureNaN will break the encoding of tagged double: "
166                                           << std::hex << CastDoubleToTagged(v));
167         value_ = CastDoubleToTagged(v) + DOUBLE_ENCODE_OFFSET;
168     }
169 
JSTaggedValue(const TaggedObject * v)170     ARK_INLINE explicit JSTaggedValue(const TaggedObject *v) : value_(static_cast<JSTaggedType>(ToUintPtr(v))) {}
171 
JSTaggedValue(int64_t v)172     ARK_INLINE explicit JSTaggedValue(int64_t v)
173     {
174         if (UNLIKELY(static_cast<int32_t>(v) != v)) {
175             value_ = JSTaggedValue(static_cast<double>(v)).GetRawData();
176             return;
177         }
178         value_ = JSTaggedValue(static_cast<int32_t>(v)).GetRawData();
179     }
180 
181     ~JSTaggedValue() = default;
182     DEFAULT_COPY_SEMANTIC(JSTaggedValue);
183     DEFAULT_MOVE_SEMANTIC(JSTaggedValue);
184 
CreateWeakRef()185     inline void CreateWeakRef()
186     {
187         ASSERT_PRINT(IsHeapObject() && ((value_ & TAG_WEAK) == 0U),
188                      "The least significant two bits of JSTaggedValue are not zero.");
189         value_ = value_ | TAG_WEAK;
190     }
191 
RemoveWeakTag()192     inline void RemoveWeakTag()
193     {
194         ASSERT_PRINT(IsHeapObject() && ((value_ & TAG_WEAK) == TAG_WEAK), "The tagged value is not a weak ref.");
195         value_ = value_ & (~TAG_WEAK);
196     }
197 
CreateAndGetWeakRef()198     inline JSTaggedValue CreateAndGetWeakRef() const
199     {
200         ASSERT_PRINT(IsHeapObject() && ((value_ & TAG_WEAK) == 0U),
201                      "The least significant two bits of JSTaggedValue are not zero.");
202         return JSTaggedValue(value_ | TAG_WEAK);
203     }
204 
GetWeakRawValue()205     inline JSTaggedValue GetWeakRawValue() const
206     {
207         if (IsHeapObject()) {
208             return JSTaggedValue(value_ & (~TAG_WEAK));
209         }
210         return JSTaggedValue(value_);
211     }
212 
IsWeak()213     ARK_INLINE bool IsWeak() const
214     {
215         return ((value_ & TAG_WEAK_MASK) == TAG_WEAK);
216     }
217 
IsDouble()218     ARK_INLINE bool IsDouble() const
219     {
220         return !IsInt() && !IsObject();
221     }
222 
IsInt()223     ARK_INLINE bool IsInt() const
224     {
225         return (value_ & TAG_MARK) == TAG_INT;
226     }
227 
IsSpecial()228     ARK_INLINE bool IsSpecial() const
229     {
230         return ((value_ & TAG_SPECIAL_MASK) == TAG_SPECIAL) || IsHole();
231     }
232 
IsObject()233     ARK_INLINE bool IsObject() const
234     {
235         return ((value_ & TAG_MARK) == TAG_OBJECT);
236     }
237 
GetWeakReferentUnChecked()238     ARK_INLINE TaggedObject *GetWeakReferentUnChecked() const
239     {
240         return reinterpret_cast<TaggedObject *>(value_ & (~TAG_WEAK));
241     }
242 
IsHeapObject()243     ARK_INLINE bool IsHeapObject() const
244     {
245         return ((value_ & TAG_HEAPOBJECT_MASK) == 0U);
246     }
247 
IsInvalidValue()248     ARK_INLINE bool IsInvalidValue() const
249     {
250         return value_ <= INVALID_VALUE_LIMIT;
251     }
252 
GetDouble()253     ARK_INLINE double GetDouble() const
254     {
255         ASSERT_PRINT(IsDouble(), "can not convert JSTaggedValue to Double : " << std::hex << value_);
256         return CastTaggedToDouble(value_ - DOUBLE_ENCODE_OFFSET);
257     }
258 
GetInt()259     ARK_INLINE int GetInt() const
260     {
261         ASSERT_PRINT(IsInt(), "can not convert JSTaggedValue to Int :" << std::hex << value_);
262         return static_cast<int>(value_ & (~TAG_MARK));
263     }
264 
GetRawData()265     ARK_INLINE JSTaggedType GetRawData() const
266     {
267         return value_;
268     }
269 
270     //  This function returns the heap object pointer which may have the weak tag.
GetRawHeapObject()271     ARK_INLINE TaggedObject *GetRawHeapObject() const
272     {
273         ASSERT_PRINT(IsHeapObject(), "can not convert JSTaggedValue to HeapObject :" << std::hex << value_);
274         return reinterpret_cast<TaggedObject *>(value_);
275     }
276 
GetWeakReferent()277     ARK_INLINE TaggedObject *GetWeakReferent() const
278     {
279         ASSERT_PRINT(IsWeak(), "can not convert JSTaggedValue to WeakRef HeapObject :" << std::hex << value_);
280         return reinterpret_cast<TaggedObject *>(value_ & (~TAG_WEAK));
281     }
282 
Cast(void * ptr)283     static ARK_INLINE JSTaggedType Cast(void *ptr)
284     {
285         ASSERT_PRINT(sizeof(void *) == TaggedTypeSize(), "32bit platform is not support yet");
286         return static_cast<JSTaggedType>(ToUintPtr(ptr));
287     }
288 
IsFalse()289     ARK_INLINE bool IsFalse() const
290     {
291         return value_ == VALUE_FALSE;
292     }
293 
IsTrue()294     ARK_INLINE bool IsTrue() const
295     {
296         return value_ == VALUE_TRUE;
297     }
298 
IsUndefined()299     ARK_INLINE bool IsUndefined() const
300     {
301         return value_ == VALUE_UNDEFINED;
302     }
303 
IsNull()304     ARK_INLINE bool IsNull() const
305     {
306         return value_ == VALUE_NULL;
307     }
308 
IsUndefinedOrNull()309     ARK_INLINE bool IsUndefinedOrNull() const
310     {
311         return ((value_ & TAG_HEAPOBJECT_MASK) == TAG_SPECIAL);
312     }
313 
IsHole()314     ARK_INLINE bool IsHole() const
315     {
316         return value_ == VALUE_HOLE || value_ == 0U;
317     }
318 
IsException()319     ARK_INLINE bool IsException() const
320     {
321         return value_ == VALUE_EXCEPTION;
322     }
323 
IsImpureNaN(double value)324     static ARK_INLINE bool IsImpureNaN(double value)
325     {
326         // Tests if the double value would break tagged double encoding.
327         return base::bit_cast<JSTaggedType>(value) >= (TAG_INT - DOUBLE_ENCODE_OFFSET);
328     }
329 
330     ARK_INLINE bool operator==(const JSTaggedValue &other) const
331     {
332         return value_ == other.value_;
333     }
334 
335     ARK_INLINE bool operator!=(const JSTaggedValue &other) const
336     {
337         return value_ != other.value_;
338     }
339 
IsWeakForHeapObject()340     ARK_INLINE bool IsWeakForHeapObject() const
341     {
342         return (value_ & TAG_WEAK) == 1U;
343     }
344 
False()345     static ARK_INLINE constexpr JSTaggedValue False()
346     {
347         return JSTaggedValue(VALUE_FALSE);
348     }
349 
True()350     static ARK_INLINE constexpr JSTaggedValue True()
351     {
352         return JSTaggedValue(VALUE_TRUE);
353     }
354 
Undefined()355     static ARK_INLINE constexpr JSTaggedValue Undefined()
356     {
357         return JSTaggedValue(VALUE_UNDEFINED);
358     }
359 
Null()360     static ARK_INLINE constexpr JSTaggedValue Null()
361     {
362         return JSTaggedValue(VALUE_NULL);
363     }
364 
Hole()365     static ARK_INLINE constexpr JSTaggedValue Hole()
366     {
367         return JSTaggedValue(VALUE_HOLE);
368     }
369 
Exception()370     static ARK_INLINE constexpr JSTaggedValue Exception()
371     {
372         return JSTaggedValue(VALUE_EXCEPTION);
373     }
374 
GetNumber()375     ARK_INLINE double GetNumber() const
376     {
377         return IsInt() ? GetInt() : GetDouble();
378     }
379 
GetTaggedObject()380     ARK_INLINE TaggedObject *GetTaggedObject() const
381     {
382         ASSERT_PRINT(IsHeapObject() && ((value_ & TAG_WEAK) == 0U),
383                      "can not convert JSTaggedValue to HeapObject :" << std::hex << value_);
384         return reinterpret_cast<TaggedObject *>(value_);
385     }
386 
GetHeapObject()387     ARK_INLINE TaggedObject *GetHeapObject() const
388     {
389         if (IsWeakForHeapObject()) {
390             return GetTaggedWeakRef();
391         }
392         return GetTaggedObject();
393     }
394 
GetRawTaggedObject()395     ARK_INLINE TaggedObject *GetRawTaggedObject() const
396     {
397         return reinterpret_cast<TaggedObject *>(GetRawHeapObject());
398     }
399 
GetTaggedWeakRef()400     ARK_INLINE TaggedObject *GetTaggedWeakRef() const
401     {
402         return reinterpret_cast<TaggedObject *>(GetWeakReferent());
403     }
404 
405     static JSTaggedValue OrdinaryToPrimitive(JSThread *thread, const JSHandle<JSTaggedValue> &tagged,
406                                              PreferredPrimitiveType type = PREFER_NUMBER);
407 
408     // ecma6 7.1 Type Conversion
409     static JSTaggedValue ToPrimitive(JSThread *thread, const JSHandle<JSTaggedValue> &tagged,
410                                      PreferredPrimitiveType type = NO_PREFERENCE);
411     bool ToBoolean() const;
412     static JSTaggedNumber ToNumber(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
413     static JSTaggedValue ToBigInt(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
414     static JSTaggedValue ToBigInt64(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
415     static JSTaggedValue ToBigUint64(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
416     static JSTaggedNumber ToInteger(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
417     static JSHandle<JSTaggedValue> ToNumeric(JSThread *thread, JSHandle<JSTaggedValue> tagged);
418     static int32_t ToInt32(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
419     static uint32_t ToUint32(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
420     static int16_t ToInt16(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
421     static uint16_t ToUint16(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
422     static int8_t ToInt8(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
423     static uint8_t ToUint8(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
424     static uint8_t ToUint8Clamp(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
425     static JSHandle<EcmaString> ToString(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
426     static JSHandle<EcmaString> ToString(JSThread *thread, JSTaggedValue val);
427     static JSHandle<JSObject> ToObject(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
428     static JSHandle<JSTaggedValue> ToPropertyKey(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
429     static JSTaggedNumber ToLength(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
430     static JSTaggedValue CanonicalNumericIndexString(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
431     static JSTaggedNumber ToIndex(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
432     static JSTaggedNumber StringToDouble(JSTaggedValue tagged);
433 
434     static bool ToArrayLength(JSThread *thread, const JSHandle<JSTaggedValue> &tagged, uint32_t *output);
435     static bool ToElementIndex(JSTaggedValue key, uint32_t *output);
436     static bool StringToElementIndex(JSTaggedValue key, uint32_t *output);
437     uint32_t GetArrayLength() const;
438 
439     // ecma6 7.2 Testing and Comparison Operations
440     bool IsCallable() const;
441     bool IsConstructor() const;
442     bool IsExtensible(JSThread *thread) const;
443     bool IsInteger() const;
444     bool WithinInt32() const;
445     bool IsZero() const;
446     static bool IsPropertyKey(const JSHandle<JSTaggedValue> &key);
447     static JSHandle<JSTaggedValue> RequireObjectCoercible(JSThread *thread, const JSHandle<JSTaggedValue> &tagged,
448                                                           const char *message = "RequireObjectCoercible throw Error");
449     static bool SameValue(const JSTaggedValue &x, const JSTaggedValue &y);
450     static bool SameValue(const JSHandle<JSTaggedValue> &xHandle, const JSHandle<JSTaggedValue> &yHandle);
451     static bool SameValueZero(const JSTaggedValue &x, const JSTaggedValue &y);
452     static bool Less(JSThread *thread, const JSHandle<JSTaggedValue> &x, const JSHandle<JSTaggedValue> &y);
453     static bool Equal(JSThread *thread, const JSHandle<JSTaggedValue> &x, const JSHandle<JSTaggedValue> &y);
454     static bool StrictEqual(const JSThread *thread, const JSHandle<JSTaggedValue> &x, const JSHandle<JSTaggedValue> &y);
455     static bool StrictEqual(const JSTaggedValue &x, const JSTaggedValue &y);
456     static bool SameValueNumberic(const JSTaggedValue &x, const JSTaggedValue &y);
457 
458     // ES6 7.4 Operations on Iterator Objects
459     static JSObject *CreateIterResultObject(JSThread *thread, const JSHandle<JSTaggedValue> &value, bool done);
460 
461     // ECMAScript 2023 allow the use of most Symbols as keys in weak collections
462     static bool CanBeHeldWeakly(JSThread *thread, const JSHandle<JSTaggedValue> &tagged);
463 
464     // ecma6 7.3
465     static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
466                                        const JSHandle<JSTaggedValue> &key);
467 
468     static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t key);
469     static OperationResult GetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
470                                        const JSHandle<JSTaggedValue> &key, const JSHandle<JSTaggedValue> &receiver);
471     static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t key,
472                             const JSHandle<JSTaggedValue> &value, bool mayThrow = false);
473 
474     static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
475                             const JSHandle<JSTaggedValue> &value, bool mayThrow = false);
476 
477     static bool SetProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
478                             const JSHandle<JSTaggedValue> &value, const JSHandle<JSTaggedValue> &receiver,
479                             bool mayThrow = false);
480     static bool DeleteProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
481                                const JSHandle<JSTaggedValue> &key);
482     static bool DeletePropertyOrThrow(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
483                                       const JSHandle<JSTaggedValue> &key);
484     static bool DefinePropertyOrThrow(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
485                                       const JSHandle<JSTaggedValue> &key, const PropertyDescriptor &desc);
486     static bool DefineOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
487                                   const JSHandle<JSTaggedValue> &key, const PropertyDescriptor &desc);
488     static bool GetOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key,
489                                PropertyDescriptor &desc);
490     static bool SetPrototype(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
491                              const JSHandle<JSTaggedValue> &proto);
492     static JSTaggedValue GetPrototype(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
493     static bool PreventExtensions(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
494     static JSHandle<TaggedArray> GetOwnPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
495     static JSHandle<TaggedArray> GetAllPropertyKeys(JSThread *thread,
496         const JSHandle<JSTaggedValue> &obj, uint32_t filter);
497     static JSHandle<TaggedArray> GetOwnEnumPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
498     static bool HasProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, const JSHandle<JSTaggedValue> &key);
499     static bool HasProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj, uint32_t key);
500     static bool HasOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
501                                const JSHandle<JSTaggedValue> &key);
502     static bool GlobalHasOwnProperty(JSThread *thread, const JSHandle<JSTaggedValue> &key);
503 
504     // Type
505     bool IsJSMap() const;
506     bool IsJSSet() const;
507     bool IsJSWeakMap() const;
508     bool IsJSWeakSet() const;
509     bool IsJSWeakRef() const;
510     bool IsJSFinalizationRegistry() const;
511     bool IsCellRecord() const;
512     bool IsJSRegExp() const;
513     bool IsNumber() const;
514     bool IsBigInt() const;
515     bool IsString() const;
516     bool IsLineString() const;
517     bool IsConstantString() const;
518     bool IsTreeString() const;
519     bool IsStringOrSymbol() const;
520     bool IsTaggedArray() const;
521     bool IsDictionary() const;
522     bool IsByteArray() const;
523     bool IsConstantPool() const;
524     bool IsAOTLiteralInfo() const;
525     bool IsVTable() const;
526     bool IsLinkedNode() const;
527     bool IsRBTreeNode() const;
528     bool IsNativePointer() const;
529     bool IsJSNativePointer() const;
530     bool CheckIsJSNativePointer() const;
531     bool IsBoolean() const;
532     bool IsSymbol() const;
533     bool IsJSObject() const;
534     bool IsJSGlobalObject() const;
535     bool IsJSError() const;
536     bool IsArray(JSThread *thread) const;
537     bool IsCOWArray() const;
538     bool IsJSArray() const;
539     bool IsJSCOWArray() const;
540     bool IsStableJSArray(JSThread *thread) const;
541     bool IsStableJSArguments(JSThread *thread) const;
542     bool HasStableElements(JSThread *thread) const;
543     bool IsTypedArray() const;
544     bool IsJSTypedArray() const;
545     bool IsJSInt8Array() const;
546     bool IsJSUint8Array() const;
547     bool IsJSUint8ClampedArray() const;
548     bool IsJSInt16Array() const;
549     bool IsJSUint16Array() const;
550     bool IsJSInt32Array() const;
551     bool IsJSUint32Array() const;
552     bool IsJSFloat32Array() const;
553     bool IsJSFloat64Array() const;
554     bool IsJSBigInt64Array() const;
555     bool IsJSBigUint64Array() const;
556     bool IsArguments() const;
557     bool IsDate() const;
558     bool IsBoundFunction() const;
559     bool IsJSIntlBoundFunction() const;
560     bool IsProxyRevocFunction() const;
561     bool IsJSAsyncFunction() const;
562     bool IsJSAsyncAwaitStatusFunction() const;
563     bool IsClassConstructor() const;
564     bool IsClassPrototype() const;
565     bool IsJSFunction() const;
566     bool IsJSFunctionBase() const;
567     bool CheckIsJSFunctionBase() const;
568     bool IsECMAObject() const;
569     bool IsJSPrimitiveRef() const;
570     bool IsJSPrimitive() const;
571     bool IsAccessorData() const;
572     bool IsInternalAccessor() const;
573     bool IsAccessor() const;
574     bool IsJSGlobalEnv() const;
575     bool IsJSProxy() const;
576     bool CheckIsJSProxy() const;
577     bool IsJSHClass() const;
578     bool IsForinIterator() const;
579     bool IsStringIterator() const;
580     bool IsArrayBuffer() const;
581     bool IsSharedArrayBuffer() const;
582 
583     bool IsJSSetIterator() const;
584     bool IsJSRegExpIterator() const;
585     bool IsJSMapIterator() const;
586     bool IsJSArrayIterator() const;
587     bool IsIterator() const;
588     bool IsAsyncIterator() const;
589     bool IsGeneratorFunction() const;
590     bool IsAsyncGeneratorFunction() const;
591     bool IsGeneratorObject() const;
592     bool IsGeneratorContext() const;
593     bool IsAsyncGeneratorRequest() const;
594     bool IsAsyncIteratorRecord() const;
595     bool IsAsyncFromSyncIterator() const;
596     bool IsAsyncGeneratorObject() const;
597     bool IsAsyncFuncObject() const;
598     bool IsJSPromise() const;
599     bool IsRecord() const;
600     bool IsPromiseReaction() const;
601     bool IsProgram() const;
602     bool IsJSPromiseReactionFunction() const;
603     bool IsJSPromiseExecutorFunction() const;
604     bool IsJSAsyncFromSyncIterUnwarpFunction() const;
605     bool IsJSPromiseAllResolveElementFunction() const;
606     bool IsJSAsyncGeneratorResNextRetProRstFtn() const;
607     bool IsPromiseCapability() const;
608     bool IsPromiseIteratorRecord() const;
609     bool IsPromiseRecord() const;
610     bool IsJSPromiseAnyRejectElementFunction() const;
611     bool IsJSPromiseAllSettledElementFunction() const;
612     bool IsJSPromiseFinallyFunction() const;
613     bool IsJSPromiseValueThunkOrThrowerFunction() const;
614     bool IsResolvingFunctionsRecord() const;
615     bool IsCompletionRecord() const;
616     bool IsDataView() const;
617     bool IsTemplateMap() const;
618     bool IsMicroJobQueue() const;
619     bool IsPendingJob() const;
620     bool IsJSLocale() const;
621     bool IsJSDateTimeFormat() const;
622     bool IsJSRelativeTimeFormat() const;
623     bool IsJSIntl() const;
624     bool IsJSNumberFormat() const;
625     bool IsJSCollator() const;
626     bool IsJSPluralRules() const;
627     bool IsJSDisplayNames() const;
628     bool IsJSListFormat() const;
629     bool IsMethod() const;
630     bool IsClassLiteral() const;
631 
632     // non ECMA standard jsapis
633     bool IsJSAPIArrayList() const;
634     bool IsJSAPIArrayListIterator() const;
635     bool IsJSAPIHashMap() const;
636     bool IsJSAPIHashMapIterator() const;
637     bool IsJSAPIHashSet() const;
638     bool IsJSAPIHashSetIterator() const;
639     bool IsJSAPILightWeightMap() const;
640     bool IsJSAPILightWeightMapIterator() const;
641     bool IsJSAPILightWeightSet() const;
642     bool IsJSAPILightWeightSetIterator() const;
643     bool IsJSAPITreeMap() const;
644     bool IsJSAPITreeSet() const;
645     bool IsJSAPITreeMapIterator() const;
646     bool IsJSAPITreeSetIterator() const;
647     bool IsJSAPIVector() const;
648     bool IsJSAPIVectorIterator() const;
649     bool IsJSAPIQueue() const;
650     bool IsJSAPIQueueIterator() const;
651     bool IsJSAPIPlainArray() const;
652     bool IsJSAPIPlainArrayIterator() const;
653     bool IsJSAPIDeque() const;
654     bool IsJSAPIDequeIterator() const;
655     bool IsJSAPIStack() const;
656     bool IsJSAPIStackIterator() const;
657     bool IsJSAPIList() const;
658     bool IsJSAPILinkedList() const;
659     bool IsJSAPIListIterator() const;
660     bool IsJSAPILinkedListIterator() const;
661     bool IsSpecialContainer() const;
662     bool HasOrdinaryGet() const;
663     bool IsPrototypeHandler() const;
664     bool IsTransitionHandler() const;
665     bool IsTransWithProtoHandler() const;
666     bool IsStoreTSHandler() const;
667     bool IsPropertyBox() const;
668     bool IsProtoChangeMarker() const;
669     bool IsProtoChangeDetails() const;
670     bool IsMachineCodeObject() const;
671     bool IsClassInfoExtractor() const;
672     bool IsTSType() const;
673     bool IsTSObjectType() const;
674     bool IsTSClassType() const;
675     bool IsTSUnionType() const;
676     bool IsTSInterfaceType() const;
677     bool IsTSClassInstanceType() const;
678     bool IsTSFunctionType() const;
679     bool IsTSArrayType() const;
680     bool IsTSIteratorInstanceType() const;
681     bool IsTSNamespaceType() const;
682 
683     bool IsCjsExports() const;
684     bool IsCjsModule() const;
685     bool IsCjsRequire() const;
686     bool IsModuleRecord() const;
687     bool IsSourceTextModule() const;
688     bool IsImportEntry() const;
689     bool IsLocalExportEntry() const;
690     bool IsIndirectExportEntry() const;
691     bool IsStarExportEntry() const;
692     bool IsResolvedBinding() const;
693     bool IsResolvedIndexBinding() const;
694     bool IsModuleNamespace() const;
695     static bool IsSameTypeOrHClass(JSTaggedValue x, JSTaggedValue y);
696 
697     static ComparisonResult Compare(JSThread *thread, const JSHandle<JSTaggedValue> &x,
698                                     const JSHandle<JSTaggedValue> &y);
699     static ComparisonResult StrictNumberCompare(double x, double y);
700     static bool StrictNumberEquals(double x, double y);
701     static bool StrictIntEquals(int x, int y);
702     static bool StringCompare(EcmaString *xStr, EcmaString *yStr);
703 
704     static JSHandle<JSTaggedValue> ToPrototypeOrObj(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
705     inline uint32_t GetKeyHashCode() const;
706     static JSTaggedValue GetSuperBase(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
707     static JSTaggedValue TryCastDoubleToInt32(double d);
708 
709     void DumpTaggedValue(std::ostream &os) const DUMP_API_ATTR;
710     void Dump(std::ostream &os) const DUMP_API_ATTR;
711     void D() const DUMP_API_ATTR;
712     void DumpForSnapshot(std::vector<std::pair<CString, JSTaggedValue>> &vec,
713                          bool isVmMode = true) const;
714     static void DV(JSTaggedType val) DUMP_API_ATTR;
715 
716 private:
717     JSTaggedType value_;
718 
719     inline double ExtractNumber() const;
720 
721     void DumpSpecialValue(std::ostream &os) const;
722     void DumpHeapObjectType(std::ostream &os) const;
723 
724     // non ECMA standard jsapis
725     static bool HasContainerProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
726                                      const JSHandle<JSTaggedValue> &key);
727     static JSHandle<TaggedArray> GetOwnContainerPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
728     static JSHandle<TaggedArray> GetOwnContainerEnumPropertyKeys(JSThread *thread, const JSHandle<JSTaggedValue> &obj);
729     static bool GetContainerProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
730                                      const JSHandle<JSTaggedValue> &key, PropertyDescriptor &desc);
731     static OperationResult GetJSAPIProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
732                                             const JSHandle<JSTaggedValue> &key);
733     static bool SetJSAPIProperty(JSThread *thread, const JSHandle<JSTaggedValue> &obj,
734                                  const JSHandle<JSTaggedValue> &key,
735                                  const JSHandle<JSTaggedValue> &value);
736 };
737 STATIC_ASSERT_EQ_ARCH(sizeof(JSTaggedValue), JSTaggedValue::SizeArch32, JSTaggedValue::SizeArch64);
738 }  // namespace panda::ecmascript
739 #endif  // ECMASCRIPT_JS_TAGGED_VALUE_H
740