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