• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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_INTERNALS_H
17 #define ECMASCRIPT_JS_TAGGED_VALUE_INTERNALS_H
18 
19 #include "ecmascript/base/bit_helper.h"
20 
21 namespace panda::ecmascript {
22 
23 using JSTaggedType = uint64_t;
24 
25 //  Every double with all of its exponent bits set and its highest mantissa bit set is a quiet NaN.
26 //  That leaves 51 bits unaccounted for. We’ll avoid one of those so that we don’t step on Intel’s
27 //  “QNaN Floating-Point Indefinite” value, leaving us 50 bits. Those remaining bits can be anything.
28 //  so we use a special quietNaN as TaggedInt tag(highest 16bits as 0xFFFF), and need to encode double
29 //  to the value will begin with a 16-bit pattern within the range 0x0001..0xFFFE.
30 
31 //  Nan-boxing pointer is used and the first four bytes are used as tag:
32 //    Object:             [0x0000] [48 bit direct pointer]
33 //    WeakRef:            [0x0000] [47 bits direct pointer] | 1
34 //                   /    [0x0001] [48 bit any value]
35 //    TaggedDouble:       ......
36 //                   \    [0xFFFE] [48 bit any value]
37 //    TaggedInt:          [0xFFFF] [0x0000] [32 bit signed integer]
38 //
39 //  There are some special markers of Object:
40 //    False:       [56 bits 0] | 0x06          // 0110
41 //    True:        [56 bits 0] | 0x07          // 0111
42 //    Undefined:   [56 bits 0] | 0x02          // 0010
43 //    Null:        [56 bits 0] | 0x03          // 0011
44 //    Hole:        [56 bits 0] | 0x05          // 0101
45 //    Optimized:   [56 bits 0] | 0x0C          // 1100
46 
47 class JSTaggedValueInternals {
48 public:
49     static constexpr size_t BIT_PER_BYTE = 8;
50     static constexpr size_t TAG_BITS_SIZE = 16;  // 16 means bit numbers of 0xFFFF
51     static constexpr size_t TAG_BITS_SHIFT = base::BitNumbers<JSTaggedType>() - TAG_BITS_SIZE;
52     static_assert((TAG_BITS_SHIFT + TAG_BITS_SIZE) == sizeof(JSTaggedType) * BIT_PER_BYTE, "Insufficient bits!");
53     static constexpr JSTaggedType TAG_MARK = 0xFFFFULL << TAG_BITS_SHIFT;
54     // int tag
55     static constexpr JSTaggedType TAG_INT = TAG_MARK;
56     static constexpr JSTaggedType TAG_INT32_INC_MAX = INT32_MAX + 1ULL;
57     static constexpr JSTaggedType TAG_INT32_DEC_MIN = INT32_MIN - 1ULL;
58     // object tag
59     static constexpr JSTaggedType TAG_OBJECT = 0x0000ULL << TAG_BITS_SHIFT;
60     // weak object tag
61     static constexpr JSTaggedType TAG_WEAK = TAG_OBJECT | 0x01ULL;
62     // special tag
63     static constexpr JSTaggedType TAG_NULL = 0x01ULL;
64     static constexpr JSTaggedType TAG_SPECIAL = 0x02ULL;
65     static constexpr JSTaggedType TAG_BOOLEAN = 0x04ULL;
66     static constexpr JSTaggedType TAG_EXCEPTION = 0x08ULL;
67     static constexpr JSTaggedType TAG_OPTIMIZED_OUT = 0x12ULL;
68     // tag mask
69     static constexpr JSTaggedType TAG_SPECIAL_MASK = TAG_MARK | TAG_SPECIAL;
70     static constexpr JSTaggedType TAG_BOOLEAN_MASK = TAG_SPECIAL | TAG_BOOLEAN;
71     static constexpr JSTaggedType TAG_HEAPOBJECT_MASK = TAG_MARK | TAG_SPECIAL | TAG_BOOLEAN;
72     static constexpr JSTaggedType TAG_WEAK_MASK = TAG_HEAPOBJECT_MASK | TAG_WEAK;
73     // special value
74     static constexpr JSTaggedType VALUE_HOLE = 0x05ULL;
75     static constexpr JSTaggedType VALUE_NULL = TAG_OBJECT | TAG_SPECIAL | TAG_NULL;
76     static constexpr JSTaggedType VALUE_FALSE = TAG_BOOLEAN_MASK | static_cast<JSTaggedType>(false);
77     static constexpr JSTaggedType VALUE_TRUE = TAG_BOOLEAN_MASK | static_cast<JSTaggedType>(true);
78     static constexpr JSTaggedType VALUE_UNDEFINED = TAG_SPECIAL;
79     static constexpr JSTaggedType VALUE_EXCEPTION = TAG_SPECIAL | TAG_EXCEPTION;
80     static constexpr JSTaggedType VALUE_ZERO = TAG_INT | 0x00ULL;
81     static constexpr JSTaggedType VALUE_OPTIMIZED_OUT = TAG_SPECIAL | TAG_OPTIMIZED_OUT;
82 
83     static constexpr size_t INT_SIGN_BIT_OFFSET = 31;
84     static constexpr size_t DOUBLE_ENCODE_OFFSET_BIT = 48;
85     static constexpr JSTaggedType DOUBLE_ENCODE_OFFSET = 1ULL << DOUBLE_ENCODE_OFFSET_BIT;
86     // Tagged +0.0 = IEEE754 representation of +0.0 + offset
87     static constexpr JSTaggedType VALUE_POSITIVE_ZERO = 0x0000'0000'0000'0000uLL + DOUBLE_ENCODE_OFFSET;
88     // Tagged -0.0 = IEEE754 representation of -0.0 + offset
89     static constexpr JSTaggedType VALUE_NEGATIVE_ZERO = 0x8000'0000'0000'0000uLL + DOUBLE_ENCODE_OFFSET;
90 };
91 } // namespace panda::ecmascript
92 #endif // ECMASCRIPT_JS_TAGGED_VALUE_INTERNALS_H
93