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_SNAPSHOT_MEM_ENCODE_BIT_H
17#define ECMASCRIPT_SNAPSHOT_MEM_ENCODE_BIT_H
18
19#include "ecmascript/mem/c_containers.h"
20#include "ecmascript/mem/slots.h"
21#include "ecmascript/snapshot/mem/constants.h"
22
23#include "libpandabase/utils/bit_field.h"
24
25/*
26 *                        EncodeBit: use uint64_t value to encode TaggedObject when serialize
27 *
28 *  |0000...000|  |0000...00| |0|    |0|       |0|    |00000000|  |0|     |0000...000|   |00...0|
29 *     16bit         8bit    1bit   1bit      1bit      8bit     1bit         18bit       10bit
30 *  is reference    unused   weak  builtins  special  obj type   string   obj offset    region index
31 */
32
33namespace panda::ecmascript {
34class EncodeBit final {
35public:
36    ~EncodeBit() = default;
37    EncodeBit() = delete;
38
39    DEFAULT_COPY_SEMANTIC(EncodeBit);
40    DEFAULT_MOVE_SEMANTIC(EncodeBit);
41
42    explicit EncodeBit(uint64_t value) : value_(value) {}
43
44    // encode bit
45    static constexpr int REGION_INDEX_BIT_NUMBER = 10;         // region index
46    static constexpr int OBJECT_OFFSET_IN_REGION_NUMBER = 18;  // object offset in current region
47    static constexpr int OBJECT_TO_STRING_FLAG_NUMBER = 1;     // 1 : reference to string
48    static constexpr int OBJECT_TYPE_BIT_NUMBER = 8;           // js_type
49    static constexpr int OBJECT_SPECIAL = 1;                   // special
50    static constexpr int GLOBAL_CONST_OR_BUILTINS = 1;         // is global const or builtins object
51    static constexpr int TS_WEAK_OBJECT = 1;                   // weak objects generated by AOT, e.g. TSHClass
52    static constexpr int UNUSED_BIT_NUMBER = 8;                // unused bit number
53    static constexpr int IS_REFERENCE_BIT_NUMBER = 16;         // [0x0000] is reference
54
55    using RegionIndexBits = BitField<size_t, 0, REGION_INDEX_BIT_NUMBER>;
56    using ObjectOffsetInRegionBits = RegionIndexBits::NextField<size_t, OBJECT_OFFSET_IN_REGION_NUMBER>;
57    using ObjectToStringBits = ObjectOffsetInRegionBits::NextField<bool, OBJECT_TO_STRING_FLAG_NUMBER>;
58    using ObjectTypeBits = ObjectToStringBits::NextField<size_t, OBJECT_TYPE_BIT_NUMBER>;
59    using ObjectSpecialBits = ObjectTypeBits::NextField<bool, OBJECT_SPECIAL>;
60    using GlobalConstOrBuiltinsBits = ObjectSpecialBits::NextField<bool, GLOBAL_CONST_OR_BUILTINS>;
61    using TSWeakObjectBits = GlobalConstOrBuiltinsBits::NextField<bool, TS_WEAK_OBJECT>;
62    using UnusedBits = TSWeakObjectBits::NextField<size_t, UNUSED_BIT_NUMBER>;
63    using IsReferenceBits = UnusedBits::NextField<size_t, IS_REFERENCE_BIT_NUMBER>;
64
65    void SetRegionIndex(size_t region_index)
66    {
67        RegionIndexBits::Set<uint64_t>(region_index, &value_);
68    }
69
70    void SetObjectOffsetInRegion(size_t object_offset)
71    {
72        ObjectOffsetInRegionBits::Set<uint64_t>(object_offset, &value_);
73    }
74
75    void SetReferenceToString(bool flag)
76    {
77        ObjectToStringBits::Set<uint64_t>(flag, &value_);
78    }
79
80    bool IsReferenceToString() const
81    {
82        return ObjectToStringBits::Decode(value_);
83    }
84
85    void SetObjectType(size_t object_type)
86    {
87        ObjectTypeBits::Set<uint64_t>(object_type, &value_);
88    }
89
90    uint64_t GetValue() const
91    {
92        return value_;
93    }
94
95    size_t GetRegionIndex() const
96    {
97        return RegionIndexBits::Decode(value_);
98    }
99
100    size_t GetObjectOffsetInRegion() const
101    {
102        return ObjectOffsetInRegionBits::Decode(value_);
103    }
104
105    size_t GetNativePointerOrObjectIndex() const
106    {
107        return (ObjectOffsetInRegionBits::Decode(value_) << REGION_INDEX_BIT_NUMBER) + RegionIndexBits::Decode(value_);
108    }
109
110    size_t GetObjectType() const
111    {
112        return ObjectTypeBits::Decode(value_);
113    }
114
115    bool IsReference() const
116    {
117        return IsReferenceBits::Decode(value_) == 0;
118    }
119
120    bool IsSpecial() const
121    {
122        return ObjectSpecialBits::Decode(value_);
123    }
124
125    void SetObjectSpecial()
126    {
127        ObjectSpecialBits::Set<uint64_t>(true, &value_);
128    }
129
130    bool IsGlobalConstOrBuiltins() const
131    {
132        return GlobalConstOrBuiltinsBits::Decode(value_);
133    }
134
135    void SetGlobalConstOrBuiltins()
136    {
137        GlobalConstOrBuiltinsBits::Set<uint64_t>(true, &value_);
138    }
139
140    bool IsTSWeakObject() const
141    {
142        return TSWeakObjectBits::Decode(value_);
143    }
144
145    void SetTSWeakObject()
146    {
147        TSWeakObjectBits::Set<uint64_t>(true, &value_);
148    }
149
150    // low 28 bits are used to record object location(region index and object offset), besides, it's
151    // used to record string index, global const and builtins object index, native pointer index
152    void SetNativePointerOrObjectIndex(size_t index)
153    {
154        ASSERT(index < Constants::MAX_OBJECT_INDEX);
155        ObjectOffsetInRegionBits::Set<uint64_t>(index >> REGION_INDEX_BIT_NUMBER, &value_);
156        RegionIndexBits::Set<uint64_t>(index & Constants::REGION_INDEX_MASK, &value_);
157    }
158
159    void ClearObjectSpecialFlag()
160    {
161        ObjectSpecialBits::Set<uint64_t>(false, &value_);
162    }
163
164private:
165    uint64_t value_;
166};
167static_assert(EncodeBit::REGION_INDEX_BIT_NUMBER + EncodeBit::OBJECT_OFFSET_IN_REGION_NUMBER +
168              EncodeBit::OBJECT_TO_STRING_FLAG_NUMBER + EncodeBit::OBJECT_TYPE_BIT_NUMBER + EncodeBit::OBJECT_SPECIAL +
169              EncodeBit::GLOBAL_CONST_OR_BUILTINS + EncodeBit::TS_WEAK_OBJECT + EncodeBit::UNUSED_BIT_NUMBER +
170              EncodeBit::IS_REFERENCE_BIT_NUMBER == Constants::UINT_64_BITS_COUNT);
171}  // namespace panda::ecmascript
172
173#endif  // ECMASCRIPT_SNAPSHOT_MEM_ENCODE_BIT_H
174