• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_COMPILER_GATE_META_DATA_H
17 #define ECMASCRIPT_COMPILER_GATE_META_DATA_H
18 
19 #include <string>
20 
21 #include "ecmascript/compiler/bytecodes.h"
22 #include "ecmascript/compiler/type.h"
23 #include "ecmascript/mem/chunk.h"
24 #include "ecmascript/mem/chunk_containers.h"
25 
26 #include "ecmascript/pgo_profiler/pgo_profiler_type.h"
27 #include "ecmascript/elements.h"
28 #include "libpandabase/macros.h"
29 
30 namespace panda::ecmascript::kungfu {
31 using GateRef = int32_t;
32 enum MachineType : uint8_t { // Bit width
33     NOVALUE = 0,
34     ANYVALUE,
35     ARCH,
36     FLEX,
37     I1,
38     I8,
39     I16,
40     I32,
41     I64,
42     F32,
43     F64,
44 };
45 
46 enum class TypedBinOp : uint8_t {
47     TYPED_ADD = 0,
48     TYPED_SUB,
49     TYPED_MUL,
50     TYPED_DIV,
51     TYPED_MOD,
52     TYPED_LESS,
53     TYPED_LESSEQ,
54     TYPED_GREATER,
55     TYPED_GREATEREQ,
56     TYPED_EQ,
57     TYPED_NOTEQ,
58     TYPED_STRICTEQ,
59     TYPED_SHL,
60     TYPED_SHR,
61     TYPED_ASHR,
62     TYPED_AND,
63     TYPED_OR,
64     TYPED_XOR,
65     TYPED_EXP,
66 };
67 
68 enum class TypedCallTargetCheckOp : uint8_t {
69     JSCALL_IMMEDIATE_AFTER_FUNC_DEF = 0,
70     JSCALL,
71     JSCALL_FAST,
72     JSCALLTHIS,
73     JSCALLTHIS_FAST,
74     JSCALLTHIS_NOGC,
75     JSCALLTHIS_FAST_NOGC,
76 };
77 
78 enum class TypedUnOp : uint8_t {
79     TYPED_NEG = 0,
80     TYPED_NOT,
81     TYPED_INC,
82     TYPED_DEC,
83     TYPED_ISFALSE,
84     TYPED_ISTRUE,
85 };
86 
87 enum class TypedJumpOp : uint8_t {
88     TYPED_JEQZ = 0,
89     TYPED_JNEZ,
90 };
91 
92 #define GATE_META_DATA_DEOPT_REASON(V)        \
93     V(NotInt, NOTINT)                         \
94     V(NotDouble, NOTDOUBLE)                   \
95     V(NotNumber, NOTNUMBER)                   \
96     V(NotBool, NOTBOOL)                       \
97     V(NotHeapObject, NOTHEAPOBJECT)           \
98     V(NotStableArray, NOTSARRAY)              \
99     V(NotArray, NOTARRAY)                     \
100     V(NotOnHeap, NOTONHEAP)                   \
101     V(InconsistentHClass, INCONSISTENTHCLASS) \
102     V(NotNewObj, NOTNEWOBJ)                   \
103     V(NotArrayIndex, NOTARRAYIDX)             \
104     V(NotIncOverflow, NOTINCOV)               \
105     V(NotDecOverflow, NOTDECOV)               \
106     V(NotNegativeOverflow, NOTNEGOV)          \
107     V(NotCallTarget, NOTCALLTGT)              \
108     V(NotJSCallTarget, NOTJSCALLTGT)          \
109     V(CowArray, COWARRAY)                     \
110     V(DivideZero, DIVZERO)                    \
111     V(InlineFail, INLINEFAIL)                 \
112     V(NotJSFastCallTarget, NOTJSFASTCALLTGT)  \
113     V(LexVarIsHole, LEXVARISHOLE)             \
114     V(ModZero, MODZERO)                       \
115     V(Int32Overflow, INT32OVERFLOW)
116 
117 enum class DeoptType : uint8_t {
118     NOTCHECK = 0,
119 #define DECLARE_DEOPT_TYPE(NAME, TYPE) TYPE,
120     GATE_META_DATA_DEOPT_REASON(DECLARE_DEOPT_TYPE)
121 #undef DECLARE_DEOPT_TYPE
122 };
123 
124 enum class ICmpCondition : uint8_t {
125     EQ = 1,
126     UGT,
127     UGE,
128     ULT,
129     ULE,
130     NE,
131     SGT,
132     SGE,
133     SLT,
134     SLE,
135 };
136 
137 enum class FCmpCondition : uint8_t {
138     ALW_FALSE = 0,
139     OEQ,
140     OGT,
141     OGE,
142     OLT,
143     OLE,
144     ONE,
145     ORD,
146     UNO,
147     UEQ,
148     UGT,
149     UGE,
150     ULT,
151     ULE,
152     UNE,
153     ALW_TRUE,
154 };
155 
156 enum class TypedStoreOp : uint8_t {
157     ARRAY_STORE_ELEMENT = 0,
158     INT8ARRAY_STORE_ELEMENT,
159     UINT8ARRAY_STORE_ELEMENT,
160     UINT8CLAMPEDARRAY_STORE_ELEMENT,
161     INT16ARRAY_STORE_ELEMENT,
162     UINT16ARRAY_STORE_ELEMENT,
163     INT32ARRAY_STORE_ELEMENT,
164     UINT32ARRAY_STORE_ELEMENT,
165     FLOAT32ARRAY_STORE_ELEMENT,
166     FLOAT64ARRAY_STORE_ELEMENT,
167 
168     TYPED_ARRAY_FIRST = INT8ARRAY_STORE_ELEMENT,
169 };
170 
171 enum class MemoryType : uint8_t {
172     ELEMENT_TYPE = 0,
173 };
174 
175 enum class TypedLoadOp : uint8_t {
176     ARRAY_LOAD_INT_ELEMENT = 0,
177     ARRAY_LOAD_DOUBLE_ELEMENT,
178     ARRAY_LOAD_OBJECT_ELEMENT,
179     ARRAY_LOAD_TAGGED_ELEMENT,
180     ARRAY_LOAD_HOLE_TAGGED_ELEMENT,
181     INT8ARRAY_LOAD_ELEMENT,
182     UINT8ARRAY_LOAD_ELEMENT,
183     UINT8CLAMPEDARRAY_LOAD_ELEMENT,
184     INT16ARRAY_LOAD_ELEMENT,
185     UINT16ARRAY_LOAD_ELEMENT,
186     INT32ARRAY_LOAD_ELEMENT,
187     UINT32ARRAY_LOAD_ELEMENT,
188     FLOAT32ARRAY_LOAD_ELEMENT,
189     FLOAT64ARRAY_LOAD_ELEMENT,
190 
191     TYPED_ARRAY_FIRST = INT8ARRAY_LOAD_ELEMENT,
192 };
193 
194 std::string MachineTypeToStr(MachineType machineType);
195 
196 #define BINARY_GATE_META_DATA_CACHE_LIST(V)                                                          \
197     V(Add, ADD, GateFlags::NONE_FLAG, 0, 0, 2)                                                       \
198     V(Sub, SUB, GateFlags::NONE_FLAG, 0, 0, 2)                                                       \
199     V(Mul, MUL, GateFlags::NONE_FLAG, 0, 0, 2)                                                       \
200     V(Exp, EXP, GateFlags::NONE_FLAG, 0, 0, 2)                                                       \
201     V(Sdiv, SDIV, GateFlags::NONE_FLAG, 0, 0, 2)                                                     \
202     V(Smod, SMOD, GateFlags::NONE_FLAG, 0, 0, 2)                                                     \
203     V(Udiv, UDIV, GateFlags::NONE_FLAG, 0, 0, 2)                                                     \
204     V(Umod, UMOD, GateFlags::NONE_FLAG, 0, 0, 2)                                                     \
205     V(Fdiv, FDIV, GateFlags::NONE_FLAG, 0, 0, 2)                                                     \
206     V(Fmod, FMOD, GateFlags::NONE_FLAG, 0, 0, 2)                                                     \
207     V(And, AND, GateFlags::NONE_FLAG, 0, 0, 2)                                                       \
208     V(Xor, XOR, GateFlags::NONE_FLAG, 0, 0, 2)                                                       \
209     V(Or, OR, GateFlags::NONE_FLAG, 0, 0, 2)                                                         \
210     V(Lsl, LSL, GateFlags::NONE_FLAG, 0, 0, 2)                                                       \
211     V(Lsr, LSR, GateFlags::NONE_FLAG, 0, 0, 2)                                                       \
212     V(Asr, ASR, GateFlags::NONE_FLAG, 0, 0, 2)                                                       \
213     V(AddWithOverflow, ADD_WITH_OVERFLOW, GateFlags::NONE_FLAG, 0, 0, 2)                             \
214     V(SubWithOverflow, SUB_WITH_OVERFLOW, GateFlags::NONE_FLAG, 0, 0, 2)                             \
215     V(MulWithOverflow, MUL_WITH_OVERFLOW, GateFlags::NONE_FLAG, 0, 0, 2)                             \
216     V(ExtractValue, EXTRACT_VALUE, GateFlags::NONE_FLAG, 0, 0, 2)                                    \
217     V(Sqrt, SQRT, GateFlags::NO_WRITE, 0, 0, 1)                                                      \
218     V(Int32CheckRightIsZero, INT32_CHECK_RIGHT_IS_ZERO, GateFlags::CHECKABLE, 1, 1, 1)               \
219     V(Float64CheckRightIsZero, FLOAT64_CHECK_RIGHT_IS_ZERO, GateFlags::CHECKABLE, 1, 1, 1)           \
220     V(ValueCheckNegOverflow, VALUE_CHECK_NEG_OVERFLOW, GateFlags::CHECKABLE, 1, 1, 1)                \
221     V(OverflowCheck, OVERFLOW_CHECK, GateFlags::CHECKABLE, 1, 1, 1)                                  \
222     V(Int32UnsignedUpperBoundCheck, INT32_UNSIGNED_UPPER_BOUND_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \
223     V(Int32DivWithCheck, INT32_DIV_WITH_CHECK, GateFlags::CHECKABLE, 1, 1, 2)                        \
224     V(LexVarIsHoleCheck, LEX_VAR_IS_HOLE_CHECK, GateFlags::CHECKABLE, 1, 1, 1)
225 
226 #define UNARY_GATE_META_DATA_CACHE_LIST(V)                                       \
227     V(Zext, ZEXT, GateFlags::NONE_FLAG, 0, 0, 1)                                 \
228     V(Sext, SEXT, GateFlags::NONE_FLAG, 0, 0, 1)                                 \
229     V(Trunc, TRUNC, GateFlags::NONE_FLAG, 0, 0, 1)                               \
230     V(Fext, FEXT, GateFlags::NONE_FLAG, 0, 0, 1)                                 \
231     V(Ftrunc, FTRUNC, GateFlags::NONE_FLAG, 0, 0, 1)                             \
232     V(Rev, REV, GateFlags::NONE_FLAG, 0, 0, 1)                                   \
233     V(TruncFloatToInt64, TRUNC_FLOAT_TO_INT64, GateFlags::NONE_FLAG, 0, 0, 1)    \
234     V(TruncFloatToInt32, TRUNC_FLOAT_TO_INT32, GateFlags::NONE_FLAG, 0, 0, 1)    \
235     V(TaggedToInt64, TAGGED_TO_INT64, GateFlags::NONE_FLAG, 0, 0, 1)             \
236     V(Int64ToTagged, INT64_TO_TAGGED, GateFlags::NONE_FLAG, 0, 0, 1)             \
237     V(SignedIntToFloat, SIGNED_INT_TO_FLOAT, GateFlags::NONE_FLAG, 0, 0, 1)      \
238     V(UnsignedIntToFloat, UNSIGNED_INT_TO_FLOAT, GateFlags::NONE_FLAG, 0, 0, 1)  \
239     V(FloatToSignedInt, FLOAT_TO_SIGNED_INT, GateFlags::NONE_FLAG, 0, 0, 1)      \
240     V(UnsignedFloatToInt, UNSIGNED_FLOAT_TO_INT, GateFlags::NONE_FLAG, 0, 0, 1)  \
241     V(Bitcast, BITCAST, GateFlags::NONE_FLAG, 0, 0, 1)
242 
243 #define IMMUTABLE_META_DATA_CACHE_LIST(V)                                                       \
244     V(CircuitRoot, CIRCUIT_ROOT, GateFlags::NONE_FLAG, 0, 0, 0)                                 \
245     V(StateEntry, STATE_ENTRY, GateFlags::ROOT, 0, 0, 0)                                        \
246     V(DependEntry, DEPEND_ENTRY, GateFlags::ROOT, 0, 0, 0)                                      \
247     V(ReturnList, RETURN_LIST, GateFlags::ROOT, 0, 0, 0)                                        \
248     V(ArgList, ARG_LIST, GateFlags::ROOT, 0, 0, 0)                                              \
249     V(Return, RETURN, GateFlags::HAS_ROOT, 1, 1, 1)                                             \
250     V(ReturnVoid, RETURN_VOID, GateFlags::HAS_ROOT, 1, 1, 0)                                    \
251     V(Throw, THROW, GateFlags::CONTROL, 1, 1, 1)                                                \
252     V(OrdinaryBlock, ORDINARY_BLOCK, GateFlags::CONTROL, 1, 0, 0)                               \
253     V(IfBranch, IF_BRANCH, GateFlags::CONTROL, 1, 0, 1)                                         \
254     V(IfTrue, IF_TRUE, GateFlags::CONTROL, 1, 0, 0)                                             \
255     V(IfFalse, IF_FALSE, GateFlags::CONTROL, 1, 0, 0)                                           \
256     V(LoopBegin, LOOP_BEGIN, GateFlags::CONTROL, 2, 0, 0)                                       \
257     V(LoopBack, LOOP_BACK, GateFlags::CONTROL, 1, 0, 0)                                         \
258     V(LoopExit, LOOP_EXIT, GateFlags::CONTROL, 1, 0, 0)                                         \
259     V(LoopExitDepend, LOOP_EXIT_DEPEND, GateFlags::FIXED, 1, 1, 0)                              \
260     V(LoopExitValue, LOOP_EXIT_VALUE, GateFlags::FIXED, 1, 0, 1)                                \
261     V(DependRelay, DEPEND_RELAY, GateFlags::FIXED, 1, 1, 0)                                     \
262     V(IfSuccess, IF_SUCCESS, GateFlags::CONTROL, 1, 0, 0)                                       \
263     V(IfException, IF_EXCEPTION, GateFlags::CONTROL, 1, 1, 0)                                   \
264     V(GetException, GET_EXCEPTION, GateFlags::NONE_FLAG, 1, 1, 0)                               \
265     V(GetConstPool, GET_CONSTPOOL, GateFlags::NO_WRITE, 0, 1, 1)                                \
266     V(GetGlobalEnv, GET_GLOBAL_ENV, GateFlags::NO_WRITE, 0, 1, 0)                               \
267     V(StateSplit, STATE_SPLIT, GateFlags::CHECKABLE, 1, 1, 0)                                   \
268     V(Load, LOAD, GateFlags::NO_WRITE, 0, 1, 1)                                                 \
269     V(Store, STORE, GateFlags::NONE_FLAG, 0, 1, 2)                                              \
270     V(TypedCallCheck, TYPED_CALL_CHECK, GateFlags::CHECKABLE, 1, 1, 3)                          \
271     V(HeapObjectCheck, HEAP_OBJECT_CHECK, GateFlags::CHECKABLE, 1, 1, 1)                        \
272     V(COWArrayCheck, COW_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1)                            \
273     V(ArrayGuardianCheck, ARRAY_GUARDIAN_CHECK, GateFlags::CHECKABLE, 1, 1, 0)                  \
274     V(DeoptCheck, DEOPT_CHECK, GateFlags::NO_WRITE, 1, 1, 3)                                    \
275     V(StoreProperty, STORE_PROPERTY, GateFlags::NONE_FLAG, 1, 1, 3)                             \
276     V(StorePropertyNoBarrier, STORE_PROPERTY_NO_BARRIER, GateFlags::NONE_FLAG, 1, 1, 3)         \
277     V(ToLength, TO_LENGTH, GateFlags::NONE_FLAG, 1, 1, 1)                                       \
278     V(DefaultCase, DEFAULT_CASE, GateFlags::CONTROL, 1, 0, 0)                                   \
279     V(LoadArrayLength, LOAD_ARRAY_LENGTH, GateFlags::NO_WRITE, 1, 1, 1)                         \
280     V(TypedNewAllocateThis, TYPED_NEW_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2)             \
281     V(TypedSuperAllocateThis, TYPED_SUPER_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2)         \
282     V(GetSuperConstructor, GET_SUPER_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1)                 \
283     V(CheckSafePointAndStackOver, CHECK_SAFEPOINT_AND_STACKOVER, GateFlags::NO_WRITE, 1, 1, 0)  \
284     V(Dead, DEAD, GateFlags::NONE_FLAG, 0, 0, 0)                                                \
285     V(FrameArgs, FRAME_ARGS, GateFlags::NONE_FLAG, 0, 0, 4)                                     \
286     V(GetEnv, GET_ENV, GateFlags::NONE_FLAG, 0, 0, 1)                                           \
287     V(ConvertHoleAsUndefined, CONVERT_HOLE_AS_UNDEFINED, GateFlags::NO_WRITE, 1, 1, 1)          \
288     V(StartAllocate, START_ALLOCATE, GateFlags::NONE_FLAG, 0, 1, 0)                             \
289     V(FinishAllocate, FINISH_ALLOCATE, GateFlags::NONE_FLAG, 0, 1, 0)                           \
290     V(LoadGetter, LOAD_GETTER, GateFlags::NONE_FLAG, 0, 1, 2)                                   \
291     V(LoadSetter, LOAD_SETTER, GateFlags::NONE_FLAG, 0, 1, 2)                                   \
292     V(ReadSp, READSP, GateFlags::NONE_FLAG, 0, 0, 0)                                            \
293     BINARY_GATE_META_DATA_CACHE_LIST(V)                                                         \
294     UNARY_GATE_META_DATA_CACHE_LIST(V)
295 
296 #define GATE_META_DATA_LIST_WITH_VALUE_IN(V)                                             \
297     V(ValueSelector, VALUE_SELECTOR, GateFlags::FIXED, 1, 0, value)                      \
298     V(FrameValues, FRAME_VALUES, GateFlags::NONE_FLAG, 0, 0, value)                      \
299     V(RuntimeCall, RUNTIME_CALL, GateFlags::NONE_FLAG, 0, 1, value)                      \
300     V(RuntimeCallWithArgv, RUNTIME_CALL_WITH_ARGV, GateFlags::NONE_FLAG, 0, 1, value)    \
301     V(NoGcRuntimeCall, NOGC_RUNTIME_CALL, GateFlags::NO_WRITE, 0, 1, value)              \
302     V(Call, CALL, GateFlags::NONE_FLAG, 0, 1, value)                                     \
303     V(BytecodeCall, BYTECODE_CALL, GateFlags::NONE_FLAG, 0, 1, value)                    \
304     V(DebuggerBytecodeCall, DEBUGGER_BYTECODE_CALL, GateFlags::NONE_FLAG, 0, 1, value)   \
305     V(BuiltinsCallWithArgv, BUILTINS_CALL_WITH_ARGV, GateFlags::NONE_FLAG, 0, 1, value)  \
306     V(BuiltinsCall, BUILTINS_CALL, GateFlags::NONE_FLAG, 0, 1, value)                    \
307     V(SaveRegister, SAVE_REGISTER, GateFlags::NONE_FLAG, 0, 1, value)
308 
309 #define GATE_META_DATA_LIST_WITH_PC_OFFSET(V)                                  \
310     V(TypedCallBuiltin, TYPED_CALL_BUILTIN, GateFlags::NO_WRITE, 1, 1, value)  \
311     V(Construct, CONSTRUCT, GateFlags::NONE_FLAG, 1, 1, value)
312 
313 #define GATE_META_DATA_LIST_FOR_CALL(V)                                        \
314     V(TypedCall, TYPEDCALL, GateFlags::NONE_FLAG, 1, 1, value)                 \
315     V(TypedFastCall, TYPEDFASTCALL, GateFlags::NONE_FLAG, 1, 1, value)
316 
317 #define GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(V)                      \
318     V(CallGetter, CALL_GETTER, GateFlags::NONE_FLAG, 1, 1, 2)                  \
319     V(CallSetter, CALL_SETTER, GateFlags::NONE_FLAG, 1, 1, 3)
320 
321 #define GATE_META_DATA_LIST_WITH_SIZE(V)                                       \
322     V(Merge, MERGE, GateFlags::CONTROL, value, 0, 0)                           \
323     V(DependSelector, DEPEND_SELECTOR, GateFlags::FIXED, 1, value, 0)          \
324     GATE_META_DATA_LIST_WITH_VALUE_IN(V)
325 
326 #define GATE_META_DATA_LIST_WITH_GATE_TYPE(V)                                              \
327     V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1)             \
328     V(TypedArrayCheck, TYPED_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1)                   \
329     V(LoadTypedArrayLength, LOAD_TYPED_ARRAY_LENGTH, GateFlags::NO_WRITE, 1, 1, 1)         \
330     V(IndexCheck, INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2)                              \
331     V(TypedUnaryOp, TYPED_UNARY_OP, GateFlags::NO_WRITE, 1, 1, 1)                          \
332     V(TypedConditionJump, TYPED_CONDITION_JUMP, GateFlags::NO_WRITE, 1, 1, 1)              \
333     V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1)                            \
334     V(CheckAndConvert, CHECK_AND_CONVERT, GateFlags::CHECKABLE, 1, 1, 1)                   \
335     V(Convert, CONVERT, GateFlags::NONE_FLAG, 0, 0, 1)                                     \
336     V(JSInlineTargetTypeCheck, JSINLINETARGET_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2)   \
337     V(InlineAccessorCheck, INLINE_ACCESSOR_CHECK, GateFlags::CHECKABLE, 1, 1, 2)
338 
339 #define GATE_META_DATA_LIST_WITH_VALUE(V)                                               \
340     V(Icmp, ICMP, GateFlags::NONE_FLAG, 0, 0, 2)                                        \
341     V(Fcmp, FCMP, GateFlags::NONE_FLAG, 0, 0, 2)                                        \
342     V(Alloca, ALLOCA, GateFlags::NONE_FLAG, 0, 0, 0)                                    \
343     V(SwitchBranch, SWITCH_BRANCH, GateFlags::CONTROL, 1, 0, 1)                         \
344     V(SwitchCase, SWITCH_CASE, GateFlags::CONTROL, 1, 0, 0)                             \
345     V(HeapAlloc, HEAP_ALLOC, GateFlags::NONE_FLAG, 1, 1, 1)                             \
346     V(LoadConstOffset, LOAD_CONST_OFFSET, GateFlags::NO_WRITE, 0, 1, 1)                 \
347     V(StoreConstOffset, STORE_CONST_OFFSET, GateFlags::NONE_FLAG, 1, 1, 2)              \
348     V(LoadElement, LOAD_ELEMENT, GateFlags::NO_WRITE, 1, 1, 2)                          \
349     V(StoreElement, STORE_ELEMENT, GateFlags::NONE_FLAG, 1, 1, 3)                       \
350     V(StoreMemory, STORE_MEMORY, GateFlags::NONE_FLAG, 1, 1, 3)                         \
351     V(RestoreRegister, RESTORE_REGISTER, GateFlags::NONE_FLAG, 0, 0, 1)                 \
352     V(Constant, CONSTANT, GateFlags::NONE_FLAG, 0, 0, 0)                                \
353     V(RelocatableData, RELOCATABLE_DATA, GateFlags::NONE_FLAG, 0, 0, 0)                 \
354     V(GetGlobalEnvObjHClass, GET_GLOBAL_ENV_OBJ_HCLASS, GateFlags::NO_WRITE, 0, 1, 1)   \
355     V(GetGlobalConstantValue, GET_GLOBAL_CONSTANT_VALUE, GateFlags::NO_WRITE, 0, 1, 0)  \
356     V(FrameState, FRAME_STATE, GateFlags::HAS_FRAME_STATE, 0, 0, 2)                     \
357     V(CreateArray, CREATE_ARRAY, GateFlags::NONE_FLAG, 1, 1, 0)                         \
358     V(CreateArrayWithBuffer, CREATE_ARRAY_WITH_BUFFER, GateFlags::CHECKABLE, 1, 1, 2)   \
359     V(RangeGuard, RANGE_GUARD, GateFlags::NO_WRITE, 1, 1, 1)                            \
360     V(StableArrayCheck, STABLE_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1)              \
361     V(HClassStableArrayCheck, HCLASS_STABLE_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \
362     V(ObjectTypeCheck, OBJECT_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2)                \
363     V(ObjectTypeCompare, OBJECT_TYPE_COMPARE, GateFlags::CHECKABLE, 1, 1, 2)
364 
365 #define GATE_META_DATA_LIST_WITH_ONE_PARAMETER(V)         \
366     V(Arg, ARG, GateFlags::HAS_ROOT, 0, 0, 0)             \
367     GATE_META_DATA_LIST_WITH_VALUE(V)                     \
368     GATE_META_DATA_LIST_WITH_GATE_TYPE(V)
369 
370 #define GATE_META_DATA_LIST_WITH_BOOL(V)                                           \
371     V(LoadProperty, LOAD_PROPERTY, GateFlags::NO_WRITE, 1, 1, 2)                   \
372 
373 #define GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(V)                                  \
374     V(CallOptimized, CALL_OPTIMIZED, GateFlags::NONE_FLAG, 0, 1, value)            \
375     V(FastCallOptimized, FAST_CALL_OPTIMIZED, GateFlags::NONE_FLAG, 0, 1, value)   \
376 
377 #define GATE_OPCODE_LIST(V)     \
378     V(JS_BYTECODE)              \
379     V(TYPED_BINARY_OP)          \
380     V(TYPED_CALLTARGETCHECK_OP) \
381     V(CONSTSTRING)
382 
383 enum class OpCode : uint8_t {
384     NOP = 0,
385 #define DECLARE_GATE_OPCODE(NAME, OP, R, S, D, V) OP,
386     IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_OPCODE)
387     GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_OPCODE)
388     GATE_META_DATA_LIST_WITH_ONE_PARAMETER(DECLARE_GATE_OPCODE)
389     GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_OPCODE)
390     GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_OPCODE)
391     GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_GATE_OPCODE)
392     GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_OPCODE)
393     GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(DECLARE_GATE_OPCODE)
394 #undef DECLARE_GATE_OPCODE
395 #define DECLARE_GATE_OPCODE(NAME) NAME,
396     GATE_OPCODE_LIST(DECLARE_GATE_OPCODE)
397 #undef DECLARE_GATE_OPCODE
398 };
399 
400 enum GateFlags : uint8_t {
401     NONE_FLAG = 0,
402     NO_WRITE = 1 << 0,
403     HAS_ROOT = 1 << 1,
404     HAS_FRAME_STATE = 1 << 2,
405     CONTROL = NO_WRITE,
406     CONTROL_ROOT = NO_WRITE | HAS_ROOT,
407     CHECKABLE = NO_WRITE | HAS_FRAME_STATE,
408     ROOT = NO_WRITE | HAS_ROOT,
409     FIXED = NO_WRITE,
410 };
411 
412 class GateMetaData : public ChunkObject {
413 public:
414     enum class Kind : uint8_t {
415         IMMUTABLE = 0,
416         MUTABLE_WITH_SIZE,
417         IMMUTABLE_ONE_PARAMETER,
418         MUTABLE_ONE_PARAMETER,
419         IMMUTABLE_BOOL,
420         MUTABLE_STRING,
421         JSBYTECODE,
422         TYPED_BINARY_OP,
423         TYPED_CALLTARGETCHECK_OP,
424         TYPED_CALL,
425     };
426     GateMetaData() = default;
GateMetaData(OpCode opcode,GateFlags flags,uint32_t statesIn,uint16_t dependsIn,uint32_t valuesIn)427     GateMetaData(OpCode opcode, GateFlags flags,
428         uint32_t statesIn, uint16_t dependsIn, uint32_t valuesIn)
429         : opcode_(opcode), flags_(flags),
430         statesIn_(statesIn), dependsIn_(dependsIn), valuesIn_(valuesIn) {}
431 
GetRevCompareOp(TypedBinOp op)432     static TypedBinOp GetRevCompareOp(TypedBinOp op)
433     {
434         switch (op) {
435             case TypedBinOp::TYPED_LESS:
436                 return TypedBinOp::TYPED_GREATEREQ;
437             case TypedBinOp::TYPED_LESSEQ:
438                 return TypedBinOp::TYPED_GREATER;
439             case TypedBinOp::TYPED_GREATER:
440                 return TypedBinOp::TYPED_LESSEQ;
441             case TypedBinOp::TYPED_GREATEREQ:
442                 return TypedBinOp::TYPED_LESS;
443             case TypedBinOp::TYPED_EQ:
444                 return TypedBinOp::TYPED_NOTEQ;
445             case TypedBinOp::TYPED_NOTEQ:
446                 return TypedBinOp::TYPED_EQ;
447             default:
448                 UNREACHABLE();
449                 return op;
450         }
451     }
452 
GetSwapCompareOp(TypedBinOp op)453     static TypedBinOp GetSwapCompareOp(TypedBinOp op)
454     {
455         switch (op) {
456             case TypedBinOp::TYPED_LESS:
457                 return TypedBinOp::TYPED_GREATER;
458             case TypedBinOp::TYPED_LESSEQ:
459                 return TypedBinOp::TYPED_GREATEREQ;
460             case TypedBinOp::TYPED_GREATER:
461                 return TypedBinOp::TYPED_LESS;
462             case TypedBinOp::TYPED_GREATEREQ:
463                 return TypedBinOp::TYPED_LESSEQ;
464             case TypedBinOp::TYPED_EQ:
465                 return TypedBinOp::TYPED_EQ;
466             case TypedBinOp::TYPED_NOTEQ:
467                 return TypedBinOp::TYPED_NOTEQ;
468             default:
469                 UNREACHABLE();
470                 return op;
471         }
472     }
473 
GetStateCount()474     size_t GetStateCount() const
475     {
476         return statesIn_;
477     }
478 
GetDependCount()479     size_t GetDependCount() const
480     {
481         return dependsIn_;
482     }
483 
GetInValueCount()484     size_t GetInValueCount() const
485     {
486         return valuesIn_;
487     }
488 
GetRootCount()489     size_t GetRootCount() const
490     {
491         return HasRoot() ? 1 : 0;
492     }
493 
GetInFrameStateCount()494     size_t GetInFrameStateCount() const
495     {
496         return HasFrameState() ? 1 : 0;
497     }
498 
GetNumIns()499     size_t GetNumIns() const
500     {
501         return GetStateCount() + GetDependCount() + GetInValueCount()
502             + GetInFrameStateCount() + GetRootCount();
503     }
504 
GetInValueStarts()505     size_t GetInValueStarts() const
506     {
507         return GetStateCount() + GetDependCount();
508     }
509 
GetInFrameStateStarts()510     size_t GetInFrameStateStarts() const
511     {
512         return GetInValueStarts() + GetInValueCount();
513     }
514 
GetOpCode()515     OpCode GetOpCode() const
516     {
517         return opcode_;
518     }
519 
GetKind()520     Kind GetKind() const
521     {
522         return kind_;
523     }
524 
AssertKind(Kind kind)525     void AssertKind([[maybe_unused]] Kind kind) const
526     {
527         ASSERT(GetKind() == kind);
528     }
529 
IsOneParameterKind()530     bool IsOneParameterKind() const
531     {
532         return GetKind() == Kind::IMMUTABLE_ONE_PARAMETER || GetKind() == Kind::MUTABLE_ONE_PARAMETER ||
533             GetKind() == Kind::TYPED_BINARY_OP || GetKind() == Kind::TYPED_CALLTARGETCHECK_OP;
534     }
535 
IsStringType()536     bool IsStringType() const
537     {
538         return GetKind() == Kind::MUTABLE_STRING;
539     }
540 
541     bool IsRoot() const;
542     bool IsProlog() const;
543     bool IsFixed() const;
544     bool IsSchedulable() const;
545     bool IsState() const;  // note: IsState(STATE_ENTRY) == false
546     bool IsGeneralState() const;
547     bool IsTerminalState() const;
548     bool IsVirtualState() const;
549     bool IsCFGMerge() const;
550     bool IsControlCase() const;
551     bool IsLoopHead() const;
552     bool IsNop() const;
553     bool IsConstant() const;
554     bool IsDependSelector() const;
555     bool IsTypedOperator() const;
556     bool IsCheckWithOneIn() const;
557     bool IsCheckWithTwoIns() const;
HasFrameState()558     bool HasFrameState() const
559     {
560         return HasFlag(GateFlags::HAS_FRAME_STATE);
561     }
562 
IsNotWrite()563     bool IsNotWrite() const
564     {
565         return HasFlag(GateFlags::NO_WRITE);
566     }
567 
568     ~GateMetaData() = default;
569 
570     std::string TypedBinOpToStr(TypedBinOp typedBinOp) const;
571     static std::string Str(OpCode opcode);
Str()572     std::string Str() const
573     {
574         return Str(opcode_);
575     }
576 protected:
SetKind(Kind kind)577     void SetKind(Kind kind)
578     {
579         kind_ = kind;
580     }
581 
SetFlags(GateFlags flags)582     void SetFlags(GateFlags flags)
583     {
584         flags_ = flags;
585     }
586 
DecreaseIn(size_t idx)587     void DecreaseIn(size_t idx)
588     {
589         ASSERT(GetKind() == Kind::MUTABLE_WITH_SIZE);
590         if (idx < statesIn_) {
591             statesIn_--;
592         } else if (idx < statesIn_ + dependsIn_) {
593             dependsIn_--;
594         } else {
595             valuesIn_--;
596         }
597     }
598 
HasRoot()599     bool HasRoot() const
600     {
601         return HasFlag(GateFlags::HAS_ROOT);
602     }
603 
HasFlag(GateFlags flag)604     bool HasFlag(GateFlags flag) const
605     {
606         return (GetFlags() & flag) == flag;
607     }
608 
GetFlags()609     GateFlags GetFlags() const
610     {
611         return flags_;
612     }
613 
614 private:
615     friend class Gate;
616     friend class Circuit;
617     friend class GateMetaBuilder;
618 
619     OpCode opcode_ { OpCode::NOP };
620     Kind kind_ { Kind::IMMUTABLE };
621     GateFlags flags_ { GateFlags::NONE_FLAG };
622     uint32_t statesIn_ { 0 };
623     uint32_t dependsIn_ { 0 };
624     uint32_t valuesIn_ { 0 };
625 };
626 
627 inline std::ostream& operator<<(std::ostream& os, OpCode opcode)
628 {
629     return os << GateMetaData::Str(opcode);
630 }
631 
632 class BoolMetaData : public GateMetaData {
633 public:
BoolMetaData(OpCode opcode,GateFlags flags,uint32_t statesIn,uint16_t dependsIn,uint32_t valuesIn,bool value)634     BoolMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn,
635         uint16_t dependsIn, uint32_t valuesIn, bool value)
636         : GateMetaData(opcode, flags, statesIn, dependsIn, valuesIn), value_(value)
637     {
638         SetKind(GateMetaData::Kind::IMMUTABLE_BOOL);
639     }
640 
Cast(const GateMetaData * meta)641     static const BoolMetaData* Cast(const GateMetaData* meta)
642     {
643         meta->AssertKind(GateMetaData::Kind::IMMUTABLE_BOOL);
644         return static_cast<const BoolMetaData*>(meta);
645     }
646 
GetBool()647     bool GetBool() const
648     {
649         return value_;
650     }
651 
652 private:
653     bool value_ { false };
654 };
655 
656 class JSBytecodeMetaData : public GateMetaData {
657 public:
JSBytecodeMetaData(size_t valuesIn,EcmaOpcode opcode,uint32_t pcOffset,GateFlags flags)658     explicit JSBytecodeMetaData(size_t valuesIn, EcmaOpcode opcode, uint32_t pcOffset, GateFlags flags)
659         : GateMetaData(OpCode::JS_BYTECODE, flags, 1, 1, valuesIn),
660         opcode_(opcode), pcOffset_(pcOffset)
661     {
662         SetKind(GateMetaData::Kind::JSBYTECODE);
663     }
664 
Cast(const GateMetaData * meta)665     static const JSBytecodeMetaData* Cast(const GateMetaData* meta)
666     {
667         meta->AssertKind(GateMetaData::Kind::JSBYTECODE);
668         return static_cast<const JSBytecodeMetaData*>(meta);
669     }
670 
GetPcOffset()671     uint32_t GetPcOffset() const
672     {
673         return pcOffset_;
674     }
675 
SetType(PGOSampleType type)676     void SetType(PGOSampleType type)
677     {
678         type_ = type;
679     }
680 
GetType()681     PGOSampleType GetType() const
682     {
683         return type_;
684     }
685 
GetByteCodeOpcode()686     EcmaOpcode GetByteCodeOpcode() const
687     {
688         return opcode_;
689     }
690 
SetElementsKind(ElementsKind kind)691     void SetElementsKind(ElementsKind kind)
692     {
693         elementsKind_ = kind;
694     }
695 
GetElementsKind()696     ElementsKind GetElementsKind() const
697     {
698         // Need return elementsKind_, close feature temporarily, wait for CreateArray
699         return ElementsKind::GENERIC;
700     }
701 
702 private:
703     EcmaOpcode opcode_;
704     uint32_t pcOffset_;
705     PGOSampleType type_;
706     ElementsKind elementsKind_ {ElementsKind::GENERIC};
707 };
708 
709 class OneParameterMetaData : public GateMetaData {
710 public:
OneParameterMetaData(OpCode opcode,GateFlags flags,uint32_t statesIn,uint16_t dependsIn,uint32_t valuesIn,uint64_t value)711     OneParameterMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn,
712         uint16_t dependsIn, uint32_t valuesIn, uint64_t value)
713         : GateMetaData(opcode, flags, statesIn, dependsIn, valuesIn), value_(value)
714     {
715         SetKind(GateMetaData::Kind::IMMUTABLE_ONE_PARAMETER);
716     }
717 
Cast(const GateMetaData * meta)718     static const OneParameterMetaData* Cast(const GateMetaData* meta)
719     {
720         ASSERT(meta->IsOneParameterKind());
721         return static_cast<const OneParameterMetaData*>(meta);
722     }
723 
GetValue()724     uint64_t GetValue() const
725     {
726         return value_;
727     }
728 
SetValue(uint64_t value)729     void SetValue(uint64_t value)
730     {
731         value_ = value;
732     }
733 
734 private:
735     uint64_t value_ { 0 };
736 };
737 
738 class TypedCallMetaData : public OneParameterMetaData {
739 public:
TypedCallMetaData(OpCode opcode,GateFlags flags,uint32_t statesIn,uint16_t dependsIn,uint32_t valuesIn,uint64_t value,bool noGC)740     TypedCallMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn,
741         uint16_t dependsIn, uint32_t valuesIn, uint64_t value, bool noGC)
742         : OneParameterMetaData(opcode, flags, statesIn, dependsIn, valuesIn, value),
743         noGC_(noGC)
744     {
745         SetKind(GateMetaData::Kind::TYPED_CALL);
746     }
747 
Cast(const GateMetaData * meta)748     static const TypedCallMetaData* Cast(const GateMetaData* meta)
749     {
750         meta->AssertKind(GateMetaData::Kind::TYPED_CALL);
751         return static_cast<const TypedCallMetaData*>(meta);
752     }
753 
IsNoGC()754     bool IsNoGC() const
755     {
756         return noGC_;
757     }
758 private:
759     bool noGC_;
760 };
761 
762 class TypedCallTargetCheckMetaData : public OneParameterMetaData {
763 public:
TypedCallTargetCheckMetaData(uint32_t valuesIn,uint64_t value,TypedCallTargetCheckOp checkOp)764     TypedCallTargetCheckMetaData(uint32_t valuesIn, uint64_t value, TypedCallTargetCheckOp checkOp)
765         : OneParameterMetaData(OpCode::TYPED_CALLTARGETCHECK_OP, GateFlags::CHECKABLE, 1, 1, valuesIn, value),
766         checkOp_(checkOp)
767     {
768         SetKind(GateMetaData::Kind::TYPED_CALLTARGETCHECK_OP);
769     }
770 
Cast(const GateMetaData * meta)771     static const TypedCallTargetCheckMetaData* Cast(const GateMetaData* meta)
772     {
773         meta->AssertKind(GateMetaData::Kind::TYPED_CALLTARGETCHECK_OP);
774         return static_cast<const TypedCallTargetCheckMetaData*>(meta);
775     }
776 
GetTypedCallTargetCheckOp()777     TypedCallTargetCheckOp GetTypedCallTargetCheckOp() const
778     {
779         return checkOp_;
780     }
781 private:
782     TypedCallTargetCheckOp checkOp_;
783 };
784 
785 class TypedBinaryMetaData : public OneParameterMetaData {
786 public:
TypedBinaryMetaData(uint64_t value,TypedBinOp binOp,PGOSampleType type)787     TypedBinaryMetaData(uint64_t value, TypedBinOp binOp, PGOSampleType type)
788         : OneParameterMetaData(OpCode::TYPED_BINARY_OP, GateFlags::NO_WRITE, 1, 1, 2, value), // 2: valuesIn
789         binOp_(binOp), type_(type)
790     {
791         SetKind(GateMetaData::Kind::TYPED_BINARY_OP);
792     }
793 
Cast(const GateMetaData * meta)794     static const TypedBinaryMetaData* Cast(const GateMetaData* meta)
795     {
796         meta->AssertKind(GateMetaData::Kind::TYPED_BINARY_OP);
797         return static_cast<const TypedBinaryMetaData*>(meta);
798     }
799 
GetTypedBinaryOp()800     TypedBinOp GetTypedBinaryOp() const
801     {
802         return binOp_;
803     }
804 
GetType()805     PGOSampleType GetType() const
806     {
807         return type_;
808     }
809 private:
810     TypedBinOp binOp_;
811     PGOSampleType type_;
812 };
813 
814 class StringMetaData : public GateMetaData {
815 public:
StringMetaData(Chunk * chunk,const std::string & str)816     StringMetaData(Chunk* chunk, const std::string &str)
817         : GateMetaData(OpCode::CONSTSTRING, GateFlags::NONE_FLAG, 0, 0, 0),
818         stringData_(str.size() + 1, chunk)
819     {
820         auto srcLength = str.size();
821         auto destlength = stringData_.size();
822         auto dest = stringData_.data();
823         auto src = str.c_str();
824         if (destlength <= static_cast<size_t>(srcLength) || strcpy_s(dest, destlength, src) != EOK) {
825             LOG_COMPILER(FATAL) << "StringMetaData strcpy_s failed";
826         }
827         SetKind(GateMetaData::Kind::MUTABLE_STRING);
828     }
829 
GetString()830     const ChunkVector<char> &GetString() const
831     {
832         return stringData_;
833     }
834 
835 private:
836     ChunkVector<char> stringData_;
837 };
838 
839 class GateTypeAccessor {
840 public:
GateTypeAccessor(uint64_t value)841     explicit GateTypeAccessor(uint64_t value)
842         : type_(static_cast<uint32_t>(value)) {}
843 
GetGateType()844     GateType GetGateType() const
845     {
846         return type_;
847     }
848 
ToValue(GateType type)849     static uint64_t ToValue(GateType type)
850     {
851         return static_cast<uint64_t>(type.Value());
852     }
853 private:
854     GateType type_;
855 };
856 
857 class ValuePairTypeAccessor {
858 public:
859     // type bits shift
860     static constexpr int OPRAND_TYPE_BITS = 8;
ValuePairTypeAccessor(uint64_t value)861     explicit ValuePairTypeAccessor(uint64_t value) : bitField_(value) {}
862 
GetSrcType()863     ValueType GetSrcType() const
864     {
865         return static_cast<ValueType>(LeftBits::Get(bitField_));
866     }
867 
GetDstType()868     ValueType GetDstType() const
869     {
870         return static_cast<ValueType>(RightBits::Get(bitField_));
871     }
872 
IsConvertSupport()873     bool IsConvertSupport() const
874     {
875         return ConvertSupportBits::Get(bitField_) == ConvertSupport::ENABLE;
876     }
877 
878     static uint64_t ToValue(ValueType srcType, ValueType dstType, ConvertSupport support = ConvertSupport::ENABLE)
879     {
880         uint8_t srcVlaue = static_cast<uint8_t>(srcType);
881         uint8_t dstVlaue = static_cast<uint8_t>(dstType);
882         return LeftBits::Encode(srcVlaue) | RightBits::Encode(dstVlaue) | ConvertSupportBits::Encode(support);
883     }
884 
885 private:
886     using LeftBits = panda::BitField<uint8_t, 0, OPRAND_TYPE_BITS>;
887     using RightBits = LeftBits::NextField<uint8_t, OPRAND_TYPE_BITS>;
888     using ConvertSupportBits = RightBits::NextField<ConvertSupport, OPRAND_TYPE_BITS>;
889 
890     uint64_t bitField_;
891 };
892 
893 class GatePairTypeAccessor {
894 public:
895     // type bits shift
896     static constexpr int OPRAND_TYPE_BITS = 32;
GatePairTypeAccessor(uint64_t value)897     explicit GatePairTypeAccessor(uint64_t value) : bitField_(value) {}
898 
GetLeftType()899     GateType GetLeftType() const
900     {
901         return GateType(LeftBits::Get(bitField_));
902     }
903 
GetRightType()904     GateType GetRightType() const
905     {
906         return GateType(RightBits::Get(bitField_));
907     }
908 
ToValue(GateType leftType,GateType rightType)909     static uint64_t ToValue(GateType leftType, GateType rightType)
910     {
911         return LeftBits::Encode(leftType.Value()) | RightBits::Encode(rightType.Value());
912     }
913 
914 private:
915     using LeftBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
916     using RightBits = LeftBits::NextField<uint32_t, OPRAND_TYPE_BITS>;
917 
918     uint64_t bitField_;
919 };
920 
921 class TypedUnaryAccessor {
922 public:
923     // type bits shift
924     static constexpr int OPRAND_TYPE_BITS = 32;
TypedUnaryAccessor(uint64_t value)925     explicit TypedUnaryAccessor(uint64_t value) : bitField_(value) {}
926 
GetTypeValue()927     GateType GetTypeValue() const
928     {
929         return GateType(TypedValueBits::Get(bitField_));
930     }
931 
GetTypedUnOp()932     TypedUnOp GetTypedUnOp() const
933     {
934         return TypedUnOpBits::Get(bitField_);
935     }
936 
ToValue(GateType typeValue,TypedUnOp unaryOp)937     static uint64_t ToValue(GateType typeValue, TypedUnOp unaryOp)
938     {
939         return TypedValueBits::Encode(typeValue.Value())
940             | TypedUnOpBits::Encode(unaryOp);
941     }
942 
943 private:
944     using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
945     using TypedUnOpBits = TypedValueBits::NextField<TypedUnOp, OPRAND_TYPE_BITS>;
946 
947     uint64_t bitField_;
948 };
949 
950 class TypedJumpAccessor {
951 public:
952     // type bits shift
953     static constexpr int OPRAND_TYPE_BITS = 32;
TypedJumpAccessor(uint64_t value)954     explicit TypedJumpAccessor(uint64_t value) : bitField_(value) {}
955 
GetTypeValue()956     GateType GetTypeValue() const
957     {
958         return GateType(TypedValueBits::Get(bitField_));
959     }
960 
GetTypedJumpOp()961     TypedJumpOp GetTypedJumpOp() const
962     {
963         return TypedJumpOpBits::Get(bitField_);
964     }
965 
ToValue(GateType typeValue,TypedJumpOp jumpOp)966     static uint64_t ToValue(GateType typeValue, TypedJumpOp jumpOp)
967     {
968         return TypedValueBits::Encode(typeValue.Value())
969             | TypedJumpOpBits::Encode(jumpOp);
970     }
971 
972 private:
973     using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
974     using TypedJumpOpBits = TypedValueBits::NextField<TypedJumpOp, OPRAND_TYPE_BITS>;
975 
976     uint64_t bitField_;
977 };
978 
979 class FrameStateOutput {
980 public:
981     static constexpr uint32_t INVALID_INDEX = static_cast<uint32_t>(-1);
FrameStateOutput(uint32_t value)982     explicit FrameStateOutput(uint32_t value) : index_(value) {}
983 
Invalid()984     static FrameStateOutput Invalid()
985     {
986         return FrameStateOutput(INVALID_INDEX);
987     }
988 
IsInvalid()989     bool IsInvalid() const
990     {
991         return index_ == INVALID_INDEX;
992     }
993 
GetValue()994     uint32_t GetValue() const
995     {
996         return index_;
997     }
998 private:
999     uint32_t index_;
1000 };
1001 
1002 class UInt32PairAccessor {
1003 public:
1004     // type bits shift
1005     static constexpr int OPRAND_TYPE_BITS = 32;
UInt32PairAccessor(uint64_t value)1006     explicit UInt32PairAccessor(uint64_t value) : bitField_(value) {}
UInt32PairAccessor(uint32_t first,uint32_t second)1007     explicit UInt32PairAccessor(uint32_t first, uint32_t second)
1008     {
1009         bitField_ = FirstBits::Encode(first) | SecondBits::Encode(second);
1010     }
1011 
GetFirstValue()1012     uint32_t GetFirstValue() const
1013     {
1014         return FirstBits::Get(bitField_);
1015     }
1016 
GetSecondValue()1017     uint32_t GetSecondValue() const
1018     {
1019         return SecondBits::Get(bitField_);
1020     }
1021 
ToValue()1022     uint64_t ToValue() const
1023     {
1024         return bitField_;
1025     }
1026 
1027 private:
1028     using FirstBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
1029     using SecondBits = FirstBits::NextField<uint32_t, OPRAND_TYPE_BITS>;
1030 
1031     uint64_t bitField_;
1032 };
1033 
1034 class ArrayMetaDataAccessor {
1035 public:
1036     enum Mode : uint8_t {
1037         CREATE = 0,
1038         LOAD_ELEMENT,
1039         STORE_ELEMENT,
1040         LOAD_LENGTH
1041     };
1042 
1043     static constexpr int BITS_SIZE = 8;
1044     static constexpr int ARRAY_LENGTH_BITS_SIZE = 32;
ArrayMetaDataAccessor(uint64_t value)1045     explicit ArrayMetaDataAccessor(uint64_t value) : bitField_(value) {}
1046     explicit ArrayMetaDataAccessor(ElementsKind kind, Mode mode, uint32_t length = 0)
1047     {
1048         bitField_ = ElementsKindBits::Encode(kind) | ModeBits::Encode(mode) | ArrayLengthBits::Encode(length);
1049     }
1050 
GetElementsKind()1051     ElementsKind GetElementsKind() const
1052     {
1053         return ElementsKindBits::Get(bitField_);
1054     }
1055 
SetArrayLength(uint32_t length)1056     void SetArrayLength(uint32_t length)
1057     {
1058         bitField_ = ArrayLengthBits::Update(bitField_, length);
1059     }
1060 
GetArrayLength()1061     uint32_t GetArrayLength() const
1062     {
1063         return ArrayLengthBits::Get(bitField_);
1064     }
1065 
IsLoadElement()1066     bool IsLoadElement() const
1067     {
1068         return GetMode() == Mode::LOAD_ELEMENT;
1069     }
1070 
ToValue()1071     uint64_t ToValue() const
1072     {
1073         return bitField_;
1074     }
1075 
1076 private:
GetMode()1077     Mode GetMode() const
1078     {
1079         return ModeBits::Get(bitField_);
1080     }
1081 
1082     using ElementsKindBits = panda::BitField<ElementsKind, 0, BITS_SIZE>;
1083     using ModeBits = ElementsKindBits::NextField<Mode, BITS_SIZE>;
1084     using ArrayLengthBits = ModeBits::NextField<uint32_t, ARRAY_LENGTH_BITS_SIZE>;
1085 
1086     uint64_t bitField_;
1087 };
1088 
1089 class ObjectTypeAccessor {
1090 public:
1091     static constexpr int TYPE_BITS_SIZE = 32;
1092     static constexpr int IS_HEAP_OBJECT_BIT_SIZE = 1;
1093 
ObjectTypeAccessor(uint64_t value)1094     explicit ObjectTypeAccessor(uint64_t value) : bitField_(value) {}
1095     explicit ObjectTypeAccessor(GateType type, bool isHeapObject = false)
1096     {
1097         bitField_ = TypeBits::Encode(type.Value()) | IsHeapObjectBit::Encode(isHeapObject);
1098     }
1099 
GetType()1100     GateType GetType() const
1101     {
1102         return GateType(TypeBits::Get(bitField_));
1103     }
1104 
IsHeapObject()1105     bool IsHeapObject() const
1106     {
1107         return IsHeapObjectBit::Get(bitField_);
1108     }
1109 
ToValue()1110     uint64_t ToValue() const
1111     {
1112         return bitField_;
1113     }
1114 
1115 private:
1116     using TypeBits = panda::BitField<uint32_t, 0, TYPE_BITS_SIZE>;
1117     using IsHeapObjectBit = TypeBits::NextField<bool, IS_HEAP_OBJECT_BIT_SIZE>;
1118 
1119     uint64_t bitField_;
1120 };
1121 } // namespace panda::ecmascript::kungfu
1122 
1123 #endif  // ECMASCRIPT_COMPILER_GATE_META_DATA_H
1124