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