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_COMPILER_MCR_GATE_META_DATA_H
17 #define ECMASCRIPT_COMPILER_MCR_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/elements.h"
27 #include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
28 #include "libpandabase/macros.h"
29 
30 #include "ecmascript/compiler/share_gate_meta_data.h"
31 
32 namespace panda::ecmascript::kungfu {
33 
34 #define TYPED_BIN_OP_LIST(V)    \
35     V(TYPED_ADD)                \
36     V(TYPED_SUB)                \
37     V(TYPED_MUL)                \
38     V(TYPED_DIV)                \
39     V(TYPED_MOD)                \
40     V(TYPED_LESS)               \
41     V(TYPED_LESSEQ)             \
42     V(TYPED_GREATER)            \
43     V(TYPED_GREATEREQ)          \
44     V(TYPED_EQ)                 \
45     V(TYPED_NOTEQ)              \
46     V(TYPED_STRICTEQ)           \
47     V(TYPED_STRICTNOTEQ)        \
48     V(TYPED_SHL)                \
49     V(TYPED_SHR)                \
50     V(TYPED_ASHR)               \
51     V(TYPED_AND)                \
52     V(TYPED_OR)                 \
53     V(TYPED_XOR)                \
54     V(TYPED_EXP)
55 
56 #define TYPED_UN_OP_LIST(V) \
57     V(TYPED_NEG)            \
58     V(TYPED_NOT)            \
59     V(TYPED_INC)            \
60     V(TYPED_DEC)            \
61     V(TYPED_ISFALSE)        \
62     V(TYPED_ISTRUE)
63 
64 #define TYPED_JUMP_OP_LIST(V)   \
65     V(TYPED_JEQZ)               \
66     V(TYPED_JNEZ)
67 
68 #define TYPED_LOAD_OP_LIST(V)           \
69     V(ARRAY_LOAD_INT_ELEMENT)           \
70     V(ARRAY_LOAD_DOUBLE_ELEMENT)        \
71     V(ARRAY_LOAD_OBJECT_ELEMENT)        \
72     V(ARRAY_LOAD_TAGGED_ELEMENT)        \
73     V(ARRAY_LOAD_HOLE_TAGGED_ELEMENT)   \
74     V(ARRAY_LOAD_HOLE_INT_ELEMENT)      \
75     V(ARRAY_LOAD_HOLE_DOUBLE_ELEMENT)   \
76     V(INT8ARRAY_LOAD_ELEMENT)           \
77     V(UINT8ARRAY_LOAD_ELEMENT)          \
78     V(UINT8CLAMPEDARRAY_LOAD_ELEMENT)   \
79     V(INT16ARRAY_LOAD_ELEMENT)          \
80     V(UINT16ARRAY_LOAD_ELEMENT)         \
81     V(INT32ARRAY_LOAD_ELEMENT)          \
82     V(UINT32ARRAY_LOAD_ELEMENT)         \
83     V(FLOAT32ARRAY_LOAD_ELEMENT)        \
84     V(FLOAT64ARRAY_LOAD_ELEMENT)        \
85     V(STRING_LOAD_ELEMENT)
86 
87 #define TYPED_STORE_OP_LIST(V)          \
88     V(ARRAY_STORE_ELEMENT)              \
89     V(ARRAY_STORE_INT_ELEMENT)          \
90     V(ARRAY_STORE_DOUBLE_ELEMENT)       \
91     V(INT8ARRAY_STORE_ELEMENT)          \
92     V(UINT8ARRAY_STORE_ELEMENT)         \
93     V(UINT8CLAMPEDARRAY_STORE_ELEMENT)  \
94     V(INT16ARRAY_STORE_ELEMENT)         \
95     V(UINT16ARRAY_STORE_ELEMENT)        \
96     V(INT32ARRAY_STORE_ELEMENT)         \
97     V(UINT32ARRAY_STORE_ELEMENT)        \
98     V(FLOAT32ARRAY_STORE_ELEMENT)       \
99     V(FLOAT64ARRAY_STORE_ELEMENT)
100 
101 #define TYPED_CALL_TARGET_CHECK_OP_LIST(V)  \
102     V(JSCALL)                               \
103     V(JSCALL_FAST)                          \
104     V(JSCALLTHIS)                           \
105     V(JSCALLTHIS_FAST)                      \
106     V(JSCALLTHIS_NOGC)                      \
107     V(JSCALLTHIS_FAST_NOGC)                 \
108     V(JS_NEWOBJRANGE)
109 
110 enum class TypedBinOp : uint8_t {
111 #define DECLARE_TYPED_BIN_OP(OP) OP,
112     TYPED_BIN_OP_LIST(DECLARE_TYPED_BIN_OP)
113 #undef DECLARE_TYPED_BIN_OP
114 };
115 
116 enum class TypedUnOp : uint8_t {
117 #define DECLARE_TYPED_UN_OP(OP) OP,
118     TYPED_UN_OP_LIST(DECLARE_TYPED_UN_OP)
119 #undef DECLARE_TYPED_UN_OP
120 };
121 
122 enum class TypedJumpOp : uint8_t {
123 #define DECLARE_TYPED_JUMP_OP(OP) OP,
124     TYPED_JUMP_OP_LIST(DECLARE_TYPED_JUMP_OP)
125 #undef DECLARE_TYPED_JUMP_OP
126 };
127 
128 enum class TypedLoadOp : uint8_t {
129 #define DECLARE_TYPED_LOAD_OP(OP) OP,
130     TYPED_LOAD_OP_LIST(DECLARE_TYPED_LOAD_OP)
131 #undef DECLARE_TYPED_LOAD_OP
132     TYPED_ARRAY_FIRST = INT8ARRAY_LOAD_ELEMENT,
133     TYPED_ARRAY_LAST = FLOAT64ARRAY_LOAD_ELEMENT,
134 };
135 
136 enum class TypedStoreOp : uint8_t {
137 #define DECLARE_TYPED_STORE_OP(OP) OP,
138     TYPED_STORE_OP_LIST(DECLARE_TYPED_STORE_OP)
139 #undef DECLARE_TYPED_STORE_OP
140     TYPED_ARRAY_FIRST = INT8ARRAY_STORE_ELEMENT,
141     TYPED_ARRAY_LAST = FLOAT64ARRAY_STORE_ELEMENT,
142 };
143 
144 enum class TypedCallTargetCheckOp : uint8_t {
145 #define DECLARE_TYPED_CALL_TARGET_CHECK_OP(OP) OP,
146     TYPED_CALL_TARGET_CHECK_OP_LIST(DECLARE_TYPED_CALL_TARGET_CHECK_OP)
147 #undef DECLARE_TYPED_CALL_TARGET_CHECK_OP
148 };
149 
150 enum class BranchKind : uint8_t {
151     NORMAL_BRANCH = 0,
152     TRUE_BRANCH,
153     FALSE_BRANCH,
154     STRONG_TRUE_BRANCH,
155     STRONG_FALSE_BRANCH,
156 };
157 
158 enum class TypedOpKind : uint8_t {
159     TYPED_BIN_OP,
160     TYPED_CALL_TARGET_CHECK_OP,
161     TYPED_UN_OP,
162     TYPED_JUMP_OP,
163     TYPED_STORE_OP,
164     TYPED_LOAD_OP,
165 };
166 
167 enum class MemoryType : uint8_t {
168     ELEMENT_TYPE = 0,
169 };
170 
171 class TypedCallMetaData : public OneParameterMetaData {
172 public:
TypedCallMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn, uint16_t dependsIn, uint32_t valuesIn, uint64_t value, bool noGC)173     TypedCallMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn,
174         uint16_t dependsIn, uint32_t valuesIn, uint64_t value, bool noGC)
175         : OneParameterMetaData(opcode, flags, statesIn, dependsIn, valuesIn, value),
176         noGC_(noGC)
177     {
178         SetKind(GateMetaData::Kind::TYPED_CALL);
179     }
180 
181     bool equal(const GateMetaData &other) const override
182     {
183         if (!OneParameterMetaData::equal(other)) {
184             return false;
185         }
186         auto cast_other = static_cast<const TypedCallMetaData *>(&other);
187         if (noGC_ == cast_other->noGC_) {
188             return true;
189         }
190         return false;
191     }
192 
Cast(const GateMetaData* meta)193     static const TypedCallMetaData* Cast(const GateMetaData* meta)
194     {
195         meta->AssertKind(GateMetaData::Kind::TYPED_CALL);
196         return static_cast<const TypedCallMetaData*>(meta);
197     }
198 
IsNoGC() const199     bool IsNoGC() const
200     {
201         return noGC_;
202     }
203 private:
204     bool noGC_;
205 };
206 
207 class NewConstructMetaData : public OneParameterMetaData {
208 public:
209     static constexpr int NEED_PUSH_ARGV_BIT_SIZE = 1;
NewConstructMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn, uint16_t dependsIn, uint32_t valuesIn, uint64_t value, bool needPushArgv)210     NewConstructMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn,
211         uint16_t dependsIn, uint32_t valuesIn, uint64_t value, bool needPushArgv)
212         : OneParameterMetaData(opcode, flags, statesIn, dependsIn, valuesIn, value)
213     {
214         bitField_ = NeedPushArgvBit::Encode(needPushArgv);
215     }
216 
Cast(const GateMetaData* meta)217     static const NewConstructMetaData* Cast(const GateMetaData* meta)
218     {
219         meta->AssertKind(GateMetaData::Kind::CALL_NEW);
220         return static_cast<const NewConstructMetaData*>(meta);
221     }
222 
NeedPushArgv() const223     bool NeedPushArgv() const
224     {
225         return NeedPushArgvBit::Get(bitField_);
226     }
227 
GetValue() const228     uint64_t GetValue() const
229     {
230         return bitField_;
231     }
232 
233 private:
234     using NeedPushArgvBit = panda::BitField<bool, 0, NEED_PUSH_ARGV_BIT_SIZE>;
235 
236     uint64_t bitField_;
237 };
238 
239 class TypedUnaryAccessor {
240 public:
241     // type bits shift
242     static constexpr int OPRAND_TYPE_BITS = 32;
TypedUnaryAccessor(uint64_t value)243     explicit TypedUnaryAccessor(uint64_t value) : bitField_(value) {}
244 
GetParamType() const245     ParamType GetParamType() const
246     {
247         return ParamType(TypedValueBits::Get(bitField_));
248     }
249 
GetTypedUnOp() const250     TypedUnOp GetTypedUnOp() const
251     {
252         return TypedUnOpBits::Get(bitField_);
253     }
254 
ToValue(ParamType paramType, TypedUnOp unaryOp)255     static uint64_t ToValue(ParamType paramType, TypedUnOp unaryOp)
256     {
257         return TypedValueBits::Encode(paramType.Value()) | TypedUnOpBits::Encode(unaryOp);
258     }
259 
260 private:
261     using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
262     using TypedUnOpBits = TypedValueBits::NextField<TypedUnOp, OPRAND_TYPE_BITS>;
263 
264     uint64_t bitField_;
265 };
266 
267 class TypedBinaryAccessor {
268 public:
269     // type bits shift
270     static constexpr int OPRAND_TYPE_BITS = 32;
TypedBinaryAccessor(uint64_t value)271     explicit TypedBinaryAccessor(uint64_t value) : bitField_(value) {}
272 
GetParamType() const273     ParamType GetParamType() const
274     {
275         return ParamType(TypedValueBits::Get(bitField_));
276     }
277 
GetTypedBinOp() const278     TypedBinOp GetTypedBinOp() const
279     {
280         return TypedBinOpBits::Get(bitField_);
281     }
282 
ToValue(ParamType operandType, TypedBinOp binOp)283     static uint64_t ToValue(ParamType operandType, TypedBinOp binOp)
284     {
285         return TypedValueBits::Encode(operandType.Value()) | TypedBinOpBits::Encode(binOp);
286     }
287 
288 private:
289     using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
290     using TypedBinOpBits = TypedValueBits::NextField<TypedBinOp, OPRAND_TYPE_BITS>;
291 
292     uint64_t bitField_;
293 };
294 
295 class TypedCallTargetCheckAccessor {
296 public:
297     // type bits shift
298     static constexpr int CALLTARGETCHECK_OP_BITS = 32;
TypedCallTargetCheckAccessor(uint64_t value)299     explicit TypedCallTargetCheckAccessor(uint64_t value) : bitField_(value) {}
300 
GetCallTargetCheckOp() const301     TypedCallTargetCheckOp GetCallTargetCheckOp() const
302     {
303         return CallTargetCheckOpBits::Get(bitField_);
304     }
305 
ToValue(TypedCallTargetCheckOp op)306     static uint64_t ToValue(TypedCallTargetCheckOp op)
307     {
308         return CallTargetCheckOpBits::Encode(op);
309     }
310 
311 private:
312     using CallTargetCheckOpBits = panda::BitField<TypedCallTargetCheckOp, 0, CALLTARGETCHECK_OP_BITS>;
313 
314     uint64_t bitField_;
315 };
316 
317 class BranchAccessor {
318 public:
319     // type bits shift
320     static constexpr int OPRAND_TYPE_BITS = 32;
BranchAccessor(uint64_t value)321     explicit BranchAccessor(uint64_t value) : bitField_(value) {}
322 
GetTrueWeight() const323     int32_t GetTrueWeight() const
324     {
325         return TrueWeightBits::Get(bitField_);
326     }
327 
GetFalseWeight() const328     int32_t GetFalseWeight() const
329     {
330         return FalseWeightBits::Get(bitField_);
331     }
332 
ToValue(uint32_t trueWeight, uint32_t falseWeight)333     static uint64_t ToValue(uint32_t trueWeight, uint32_t falseWeight)
334     {
335         return TrueWeightBits::Encode(trueWeight)
336             | FalseWeightBits::Encode(falseWeight);
337     }
338 private:
339     using TrueWeightBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
340     using FalseWeightBits = TrueWeightBits::NextField<uint32_t, OPRAND_TYPE_BITS>;
341 
342     uint64_t bitField_;
343 };
344 
345 class MemoryAttribute {
346 public:
347     MemoryAttribute() = default;
348     ~MemoryAttribute() = default;
MemoryAttribute(uint32_t v)349     explicit MemoryAttribute(uint32_t v) : value_(v) {}
350 
351     enum Order {
352         NOT_ATOMIC = 0,
353         MEMORY_ORDER_RELEASE
354     };
355 
356     enum Barrier {
357         NEED_BARRIER = 0,
358         NO_BARRIER,
359         UNKNOWN_BARRIER
360     };
361 
362     enum ShareFlag {
363         UNKNOWN = 0,
364         NON_SHARE,
365         SHARED
366     };
367 
Default()368     static MemoryAttribute Default()
369     {
370         return Create(NOT_ATOMIC);
371     }
372 
NeedBarrier()373     static MemoryAttribute NeedBarrier()
374     {
375         return Create(NOT_ATOMIC, NEED_BARRIER);
376     }
377 
UnknownBarrier()378     static MemoryAttribute UnknownBarrier()
379     {
380         return Create(NOT_ATOMIC, UNKNOWN_BARRIER);
381     }
382 
DefaultWithShareBarrier()383     static MemoryAttribute DefaultWithShareBarrier()
384     {
385         return Create(NOT_ATOMIC, UNKNOWN_BARRIER, SHARED);
386     }
387 
NeedNotShareBarrier()388     static MemoryAttribute NeedNotShareBarrier()
389     {
390         return Create(NOT_ATOMIC, NEED_BARRIER, NON_SHARE);
391     }
392 
NeedBarrierAndAtomic()393     static MemoryAttribute NeedBarrierAndAtomic()
394     {
395         return Create(MEMORY_ORDER_RELEASE, NEED_BARRIER);
396     }
397 
NoBarrier()398     static MemoryAttribute NoBarrier()
399     {
400         return Create(NOT_ATOMIC, NO_BARRIER);
401     }
402 
SetBarrier(Barrier barrier)403     void SetBarrier(Barrier barrier)
404     {
405         BarrierField::Set<uint32_t>(barrier, &value_);
406     }
407 
GetBarrier() const408     Barrier GetBarrier() const
409     {
410         return BarrierField::Get(value_);
411     }
412 
SetShare(ShareFlag share)413     void SetShare(ShareFlag share)
414     {
415         ShareField::Set<uint32_t>(share, &value_);
416     }
417 
GetShare() const418     ShareFlag GetShare() const
419     {
420         return ShareField::Get(value_);
421     }
422 
SetOrder(Order order)423     void SetOrder(Order order)
424     {
425         OrderField::Set<uint32_t>(order, &value_);
426     }
427 
GetOrder() const428     Order GetOrder() const
429     {
430         return OrderField::Get(value_);
431     }
432 
Value() const433     uint32_t Value() const
434     {
435         return value_;
436     }
437 
438 private:
Create(Order order, Barrier barrier = UNKNOWN_BARRIER, ShareFlag share = UNKNOWN)439     static MemoryAttribute Create(Order order, Barrier barrier = UNKNOWN_BARRIER, ShareFlag share = UNKNOWN)
440     {
441         uint32_t value = OrderField::Encode(order) | BarrierField::Encode(barrier) | ShareField::Encode(share);
442         return MemoryAttribute(value);
443     }
444 
445     static constexpr uint32_t ORDER_BITS = 8;
446     static constexpr uint32_t BARRIER_BITS = 8;
447     static constexpr uint32_t SHARE_BITS = 8;
448     using OrderField = panda::BitField<Order, 0, ORDER_BITS>;
449     using BarrierField = OrderField::NextField<Barrier, BARRIER_BITS>;
450     using ShareField = BarrierField::NextField<ShareFlag, SHARE_BITS>;
451 
452     uint32_t value_;
453 };
454 
455 class LoadStoreAccessor {
456 public:
457     static constexpr int MEMORY_ORDER_BITS = 32;
LoadStoreAccessor(uint64_t value)458     explicit LoadStoreAccessor(uint64_t value) : bitField_(value) {}
459 
GetMemoryAttribute() const460     MemoryAttribute GetMemoryAttribute() const
461     {
462         return MemoryAttribute(MemoryAttributeBits::Get(bitField_));
463     }
464 
ToValue(MemoryAttribute mAttr)465     static uint64_t ToValue(MemoryAttribute mAttr)
466     {
467         return MemoryAttributeBits::Encode(mAttr.Value());
468     }
469 private:
470     using MemoryAttributeBits = panda::BitField<uint32_t, 0, MEMORY_ORDER_BITS>;
471 
472     uint64_t bitField_;
473 };
474 
475 class LoadStoreConstOffsetAccessor {
476 public:
477     static constexpr int OPRAND_OFFSET_BITS = 32;
478     static constexpr int MEMORY_ATTRIBUTE_BITS = 32;
LoadStoreConstOffsetAccessor(uint64_t value)479     explicit LoadStoreConstOffsetAccessor(uint64_t value) : bitField_(value) {}
480 
GetMemoryAttribute() const481     MemoryAttribute GetMemoryAttribute() const
482     {
483         return MemoryAttribute(MemoryAttributeBits::Get(bitField_));
484     }
485 
GetOffset() const486     size_t GetOffset() const
487     {
488         return static_cast<size_t>(OprandOffsetBits::Get(bitField_));
489     }
490 
ToValue(size_t offset, MemoryAttribute mAttr)491     static uint64_t ToValue(size_t offset, MemoryAttribute mAttr)
492     {
493         return OprandOffsetBits::Encode(static_cast<uint32_t>(offset)) |
494                MemoryAttributeBits::Encode(mAttr.Value());
495     }
496 private:
497     using OprandOffsetBits = panda::BitField<uint32_t, 0, OPRAND_OFFSET_BITS>;
498     using MemoryAttributeBits = OprandOffsetBits::NextField<uint32_t, MEMORY_ATTRIBUTE_BITS>;
499 
500     uint64_t bitField_;
501 };
502 
503 class TypedJumpAccessor {
504 public:
505     // type bits shift
506     static constexpr int OPRAND_TYPE_BITS = 32;
507     static constexpr int JUMP_OP_BITS = 8;
TypedJumpAccessor(uint64_t value)508     explicit TypedJumpAccessor(uint64_t value) : bitField_(value) {}
509 
GetParamType() const510     ParamType GetParamType() const
511     {
512         return ParamType(TypedValueBits::Get(bitField_));
513     }
514 
GetTypedJumpOp() const515     TypedJumpOp GetTypedJumpOp() const
516     {
517         return TypedJumpOpBits::Get(bitField_);
518     }
519 
GetTrueWeight() const520     uint32_t GetTrueWeight() const
521     {
522         return TrueWeightBits::Get(bitField_);
523     }
524 
GetFalseWeight() const525     uint32_t GetFalseWeight() const
526     {
527         return FalseWeightBits::Get(bitField_);
528     }
529 
ToValue(ParamType paramType, TypedJumpOp jumpOp, uint32_t weight)530     static uint64_t ToValue(ParamType paramType, TypedJumpOp jumpOp, uint32_t weight)
531     {
532         return TypedValueBits::Encode(paramType.Value())
533             | TypedJumpOpBits::Encode(jumpOp)
534             | WeightBits::Encode(weight);
535     }
536 
537 private:
538     using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
539     using TypedJumpOpBits = TypedValueBits::NextField<TypedJumpOp, JUMP_OP_BITS>;
540     using WeightBits = TypedJumpOpBits::NextField<uint32_t, PGOSampleType::WEIGHT_BITS + PGOSampleType::WEIGHT_BITS>;
541     using FalseWeightBits = TypedJumpOpBits::NextField<uint32_t, PGOSampleType::WEIGHT_BITS>;
542     using TrueWeightBits = FalseWeightBits::NextField<uint32_t, PGOSampleType::WEIGHT_BITS>;
543 
544     uint64_t bitField_;
545 };
546 
547 }
548 
549 #endif  // ECMASCRIPT_COMPILER_MCR_GATE_META_DATA_H
550