• 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_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(INT8ARRAY_LOAD_ELEMENT)           \
75     V(UINT8ARRAY_LOAD_ELEMENT)          \
76     V(UINT8CLAMPEDARRAY_LOAD_ELEMENT)   \
77     V(INT16ARRAY_LOAD_ELEMENT)          \
78     V(UINT16ARRAY_LOAD_ELEMENT)         \
79     V(INT32ARRAY_LOAD_ELEMENT)          \
80     V(UINT32ARRAY_LOAD_ELEMENT)         \
81     V(FLOAT32ARRAY_LOAD_ELEMENT)        \
82     V(FLOAT64ARRAY_LOAD_ELEMENT)        \
83     V(STRING_LOAD_ELEMENT)
84 
85 #define TYPED_STORE_OP_LIST(V)          \
86     V(ARRAY_STORE_ELEMENT)              \
87     V(INT8ARRAY_STORE_ELEMENT)          \
88     V(UINT8ARRAY_STORE_ELEMENT)         \
89     V(UINT8CLAMPEDARRAY_STORE_ELEMENT)  \
90     V(INT16ARRAY_STORE_ELEMENT)         \
91     V(UINT16ARRAY_STORE_ELEMENT)        \
92     V(INT32ARRAY_STORE_ELEMENT)         \
93     V(UINT32ARRAY_STORE_ELEMENT)        \
94     V(FLOAT32ARRAY_STORE_ELEMENT)       \
95     V(FLOAT64ARRAY_STORE_ELEMENT)
96 
97 #define TYPED_CALL_TARGET_CHECK_OP_LIST(V)  \
98     V(JSCALL_IMMEDIATE_AFTER_FUNC_DEF)      \
99     V(JSCALL)                               \
100     V(JSCALL_FAST)                          \
101     V(JSCALLTHIS)                           \
102     V(JSCALLTHIS_FAST)                      \
103     V(JSCALLTHIS_NOGC)                      \
104     V(JSCALLTHIS_FAST_NOGC)
105 
106 enum class TypedBinOp : uint8_t {
107 #define DECLARE_TYPED_BIN_OP(OP) OP,
108     TYPED_BIN_OP_LIST(DECLARE_TYPED_BIN_OP)
109 #undef DECLARE_TYPED_BIN_OP
110 };
111 
112 enum class TypedUnOp : uint8_t {
113 #define DECLARE_TYPED_UN_OP(OP) OP,
114     TYPED_UN_OP_LIST(DECLARE_TYPED_UN_OP)
115 #undef DECLARE_TYPED_UN_OP
116 };
117 
118 enum class TypedJumpOp : uint8_t {
119 #define DECLARE_TYPED_JUMP_OP(OP) OP,
120     TYPED_JUMP_OP_LIST(DECLARE_TYPED_JUMP_OP)
121 #undef DECLARE_TYPED_JUMP_OP
122 };
123 
124 enum class TypedLoadOp : uint8_t {
125 #define DECLARE_TYPED_LOAD_OP(OP) OP,
126     TYPED_LOAD_OP_LIST(DECLARE_TYPED_LOAD_OP)
127 #undef DECLARE_TYPED_LOAD_OP
128     TYPED_ARRAY_FIRST = INT8ARRAY_LOAD_ELEMENT,
129     TYPED_ARRAY_LAST = FLOAT64ARRAY_LOAD_ELEMENT,
130 };
131 
132 enum class TypedStoreOp : uint8_t {
133 #define DECLARE_TYPED_STORE_OP(OP) OP,
134     TYPED_STORE_OP_LIST(DECLARE_TYPED_STORE_OP)
135 #undef DECLARE_TYPED_STORE_OP
136     TYPED_ARRAY_FIRST = INT8ARRAY_STORE_ELEMENT,
137     TYPED_ARRAY_LAST = FLOAT64ARRAY_STORE_ELEMENT,
138 };
139 
140 enum class TypedCallTargetCheckOp : uint8_t {
141 #define DECLARE_TYPED_CALL_TARGET_CHECK_OP(OP) OP,
142     TYPED_CALL_TARGET_CHECK_OP_LIST(DECLARE_TYPED_CALL_TARGET_CHECK_OP)
143 #undef DECLARE_TYPED_CALL_TARGET_CHECK_OP
144 };
145 
146 enum class BranchKind : uint8_t {
147     NORMAL_BRANCH = 0,
148     TRUE_BRANCH,
149     FALSE_BRANCH,
150     STRONG_TRUE_BRANCH,
151     STRONG_FALSE_BRANCH,
152 };
153 
154 enum class TypedOpKind : uint8_t {
155     TYPED_BIN_OP,
156     TYPED_CALL_TARGET_CHECK_OP,
157     TYPED_UN_OP,
158     TYPED_JUMP_OP,
159     TYPED_STORE_OP,
160     TYPED_LOAD_OP,
161 };
162 
163 enum class MemoryType : uint8_t {
164     ELEMENT_TYPE = 0,
165 };
166 
167 class TypedCallMetaData : public OneParameterMetaData {
168 public:
TypedCallMetaData(OpCode opcode,GateFlags flags,uint32_t statesIn,uint16_t dependsIn,uint32_t valuesIn,uint64_t value,bool noGC)169     TypedCallMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn,
170         uint16_t dependsIn, uint32_t valuesIn, uint64_t value, bool noGC)
171         : OneParameterMetaData(opcode, flags, statesIn, dependsIn, valuesIn, value),
172         noGC_(noGC)
173     {
174         SetKind(GateMetaData::Kind::TYPED_CALL);
175     }
176 
equal(const GateMetaData & other)177     bool equal(const GateMetaData &other) const override
178     {
179         if (!OneParameterMetaData::equal(other)) {
180             return false;
181         }
182         auto cast_other = static_cast<const TypedCallMetaData *>(&other);
183         if (noGC_ == cast_other->noGC_) {
184             return true;
185         }
186         return false;
187     }
188 
Cast(const GateMetaData * meta)189     static const TypedCallMetaData* Cast(const GateMetaData* meta)
190     {
191         meta->AssertKind(GateMetaData::Kind::TYPED_CALL);
192         return static_cast<const TypedCallMetaData*>(meta);
193     }
194 
IsNoGC()195     bool IsNoGC() const
196     {
197         return noGC_;
198     }
199 private:
200     bool noGC_;
201 };
202 
203 class TypedCallTargetCheckMetaData : public OneParameterMetaData {
204 public:
TypedCallTargetCheckMetaData(uint32_t valuesIn,uint64_t value,TypedCallTargetCheckOp checkOp)205     TypedCallTargetCheckMetaData(uint32_t valuesIn, uint64_t value, TypedCallTargetCheckOp checkOp)
206         : OneParameterMetaData(OpCode::TYPED_CALLTARGETCHECK_OP, GateFlags::CHECKABLE, 1, 1, valuesIn, value),
207         checkOp_(checkOp)
208     {
209         SetKind(GateMetaData::Kind::TYPED_CALLTARGETCHECK_OP);
210     }
211 
equal(const GateMetaData & other)212     bool equal(const GateMetaData &other) const override
213     {
214         if (!OneParameterMetaData::equal(other)) {
215             return false;
216         }
217         auto cast_other =
218             static_cast<const TypedCallTargetCheckMetaData *>(&other);
219         if (checkOp_ == cast_other->checkOp_) {
220             return true;
221         }
222         return false;
223     }
224 
Cast(const GateMetaData * meta)225     static const TypedCallTargetCheckMetaData* Cast(const GateMetaData* meta)
226     {
227         meta->AssertKind(GateMetaData::Kind::TYPED_CALLTARGETCHECK_OP);
228         return static_cast<const TypedCallTargetCheckMetaData*>(meta);
229     }
230 
GetTypedCallTargetCheckOp()231     TypedCallTargetCheckOp GetTypedCallTargetCheckOp() const
232     {
233         return checkOp_;
234     }
235 private:
236     TypedCallTargetCheckOp checkOp_;
237 };
238 
239 class TypedBinaryMetaData : public OneParameterMetaData {
240 public:
TypedBinaryMetaData(uint64_t value,TypedBinOp binOp,PGOTypeRef type)241     TypedBinaryMetaData(uint64_t value, TypedBinOp binOp, PGOTypeRef type)
242         : OneParameterMetaData(OpCode::TYPED_BINARY_OP, GateFlags::NO_WRITE, 1, 1, 2, value), // 2: valuesIn
243         binOp_(binOp), type_(type)
244     {
245         SetKind(GateMetaData::Kind::TYPED_BINARY_OP);
246     }
247 
equal(const GateMetaData & other)248     bool equal(const GateMetaData &other) const override
249     {
250         if (!OneParameterMetaData::equal(other)) {
251             return false;
252         }
253         auto cast_other = static_cast<const TypedBinaryMetaData *>(&other);
254         if (binOp_ == cast_other->binOp_ && type_ == cast_other->type_) {
255             return true;
256         }
257         return false;
258     }
259 
Cast(const GateMetaData * meta)260     static const TypedBinaryMetaData* Cast(const GateMetaData* meta)
261     {
262         meta->AssertKind(GateMetaData::Kind::TYPED_BINARY_OP);
263         return static_cast<const TypedBinaryMetaData*>(meta);
264     }
265 
GetTypedBinaryOp()266     TypedBinOp GetTypedBinaryOp() const
267     {
268         return binOp_;
269     }
270 
GetType()271     PGOTypeRef GetType() const
272     {
273         return type_;
274     }
275 
Str()276     std::string Str() const
277     {
278         return GateMetaData::Str(binOp_);
279     }
280 
281     static TypedBinOp GetRevCompareOp(TypedBinOp op);
282     static TypedBinOp GetSwapCompareOp(TypedBinOp op);
283 private:
284     TypedBinOp binOp_;
285     PGOTypeRef type_;
286 };
287 
288 class TypedUnaryAccessor {
289 public:
290     // type bits shift
291     static constexpr int OPRAND_TYPE_BITS = 32;
TypedUnaryAccessor(uint64_t value)292     explicit TypedUnaryAccessor(uint64_t value) : bitField_(value) {}
293 
GetTypeValue()294     GateType GetTypeValue() const
295     {
296         return GateType(TypedValueBits::Get(bitField_));
297     }
298 
GetTypedUnOp()299     TypedUnOp GetTypedUnOp() const
300     {
301         return TypedUnOpBits::Get(bitField_);
302     }
303 
ToValue(GateType typeValue,TypedUnOp unaryOp)304     static uint64_t ToValue(GateType typeValue, TypedUnOp unaryOp)
305     {
306         return TypedValueBits::Encode(typeValue.Value())
307             | TypedUnOpBits::Encode(unaryOp);
308     }
309 
310 private:
311     using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
312     using TypedUnOpBits = TypedValueBits::NextField<TypedUnOp, OPRAND_TYPE_BITS>;
313 
314     uint64_t bitField_;
315 };
316 
317 class TypedBinaryAccessor {
318 public:
319     // type bits shift
320     static constexpr int OPRAND_TYPE_BITS = 32;
TypedBinaryAccessor(uint64_t value)321     explicit TypedBinaryAccessor(uint64_t value) : bitField_(value) {}
TypedBinaryAccessor(GateType gate,TypedBinOp binOp)322     explicit TypedBinaryAccessor(GateType gate, TypedBinOp binOp)
323     {
324         bitField_ = TypedValueBits::Encode(gate.Value()) | TypedBinOpBits::Encode(binOp);
325     }
326 
GetTypeValue()327     GateType GetTypeValue() const
328     {
329         return GateType(TypedValueBits::Get(bitField_));
330     }
331 
GetTypedBinOp()332     TypedBinOp GetTypedBinOp() const
333     {
334         return TypedBinOpBits::Get(bitField_);
335     }
336 
ToValue()337     uint64_t ToValue() const
338     {
339         return bitField_;
340     }
341 
342 private:
343     using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
344     using TypedBinOpBits = TypedValueBits::NextField<TypedBinOp, OPRAND_TYPE_BITS>;
345 
346     uint64_t bitField_;
347 };
348 
349 class BranchAccessor {
350 public:
351     // type bits shift
352     static constexpr int OPRAND_TYPE_BITS = 32;
BranchAccessor(uint64_t value)353     explicit BranchAccessor(uint64_t value) : bitField_(value) {}
354 
GetTrueWeight()355     int32_t GetTrueWeight() const
356     {
357         return TrueWeightBits::Get(bitField_);
358     }
359 
GetFalseWeight()360     int32_t GetFalseWeight() const
361     {
362         return FalseWeightBits::Get(bitField_);
363     }
364 
ToValue(uint32_t trueWeight,uint32_t falseWeight)365     static uint64_t ToValue(uint32_t trueWeight, uint32_t falseWeight)
366     {
367         return TrueWeightBits::Encode(trueWeight)
368             | FalseWeightBits::Encode(falseWeight);
369     }
370 private:
371     using TrueWeightBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
372     using FalseWeightBits = TrueWeightBits::NextField<uint32_t, OPRAND_TYPE_BITS>;
373 
374     uint64_t bitField_;
375 };
376 
377 class MemoryOrder {
378 public:
379     MemoryOrder() = default;
380     ~MemoryOrder() = default;
MemoryOrder(uint32_t v)381     explicit MemoryOrder(uint32_t v) : value_(v) {}
382 
383     enum Order {
384         NOT_ATOMIC = 0,
385         MEMORY_ORDER_RELEASE
386     };
387 
388     enum Barrier {
389         NEED_BARRIER = 0,
390         NO_BARRIER
391     };
392 
Default()393     static MemoryOrder Default()
394     {
395         return Create(NOT_ATOMIC);
396     }
397 
398     static MemoryOrder Create(Order order, Barrier barrier = NO_BARRIER)
399     {
400         uint32_t value = OrderField::Encode(order) | BarrierField::Encode(barrier);
401         return MemoryOrder(value);
402     }
403 
SetBarrier(Barrier barrier)404     void SetBarrier(Barrier barrier)
405     {
406         BarrierField::Set<uint32_t>(barrier, &value_);
407     }
408 
GetBarrier()409     Barrier GetBarrier() const
410     {
411         return BarrierField::Get(value_);
412     }
413 
SetOrder(Order order)414     void SetOrder(Order order)
415     {
416         OrderField::Set<uint32_t>(order, &value_);
417     }
418 
GetOrder()419     Order GetOrder() const
420     {
421         return OrderField::Get(value_);
422     }
423 
Value()424     uint32_t Value() const
425     {
426         return value_;
427     }
428 
429 private:
430     static constexpr uint32_t ORDER_BITS = 8;
431     static constexpr uint32_t BARRIER_BITS = 8;
432     using OrderField = panda::BitField<Order, 0, ORDER_BITS>;
433     using BarrierField = OrderField::NextField<Barrier, BARRIER_BITS>;
434 
435     uint32_t value_;
436 };
437 
438 class LoadStoreAccessor {
439 public:
440     static constexpr int MEMORY_ORDER_BITS = 32;
LoadStoreAccessor(uint64_t value)441     explicit LoadStoreAccessor(uint64_t value) : bitField_(value) {}
442 
GetMemoryOrder()443     MemoryOrder GetMemoryOrder() const
444     {
445         return MemoryOrder(MemoryOrderBits::Get(bitField_));
446     }
447 
ToValue(MemoryOrder order)448     static uint64_t ToValue(MemoryOrder order)
449     {
450         return MemoryOrderBits::Encode(order.Value());
451     }
452 private:
453     using MemoryOrderBits = panda::BitField<uint32_t, 0, MEMORY_ORDER_BITS>;
454 
455     uint64_t bitField_;
456 };
457 
458 class LoadStoreConstOffsetAccessor {
459 public:
460     static constexpr int OPRAND_OFFSET_BITS = 32;
461     static constexpr int MEMORY_ORDER_BITS = 32;
LoadStoreConstOffsetAccessor(uint64_t value)462     explicit LoadStoreConstOffsetAccessor(uint64_t value) : bitField_(value) {}
463 
GetMemoryOrder()464     MemoryOrder GetMemoryOrder() const
465     {
466         return MemoryOrder(MemoryOrderBits::Get(bitField_));
467     }
468 
GetOffset()469     size_t GetOffset() const
470     {
471         return static_cast<size_t>(OprandOffsetBits::Get(bitField_));
472     }
473 
ToValue(size_t offset,MemoryOrder order)474     static uint64_t ToValue(size_t offset, MemoryOrder order)
475     {
476         return OprandOffsetBits::Encode(static_cast<uint32_t>(offset)) |
477                MemoryOrderBits::Encode(order.Value());
478     }
479 private:
480     using OprandOffsetBits = panda::BitField<uint32_t, 0, OPRAND_OFFSET_BITS>;
481     using MemoryOrderBits = OprandOffsetBits::NextField<uint32_t, MEMORY_ORDER_BITS>;
482 
483     uint64_t bitField_;
484 };
485 
486 class TypedJumpAccessor {
487 public:
488     // type bits shift
489     static constexpr int OPRAND_TYPE_BITS = 32;
490     static constexpr int JUMP_OP_BITS = 8;
TypedJumpAccessor(uint64_t value)491     explicit TypedJumpAccessor(uint64_t value) : bitField_(value) {}
492 
GetTypeValue()493     GateType GetTypeValue() const
494     {
495         return GateType(TypedValueBits::Get(bitField_));
496     }
497 
GetTypedJumpOp()498     TypedJumpOp GetTypedJumpOp() const
499     {
500         return TypedJumpOpBits::Get(bitField_);
501     }
502 
GetTrueWeight()503     uint32_t GetTrueWeight() const
504     {
505         return TrueWeightBits::Get(bitField_);
506     }
507 
GetFalseWeight()508     uint32_t GetFalseWeight() const
509     {
510         return FalseWeightBits::Get(bitField_);
511     }
512 
ToValue(GateType typeValue,TypedJumpOp jumpOp,uint32_t weight)513     static uint64_t ToValue(GateType typeValue, TypedJumpOp jumpOp, uint32_t weight)
514     {
515         return TypedValueBits::Encode(typeValue.Value())
516             | TypedJumpOpBits::Encode(jumpOp)
517             | WeightBits::Encode(weight);
518     }
519 
520 private:
521     using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>;
522     using TypedJumpOpBits = TypedValueBits::NextField<TypedJumpOp, JUMP_OP_BITS>;
523     using WeightBits = TypedJumpOpBits::NextField<uint32_t, PGOSampleType::WEIGHT_BITS + PGOSampleType::WEIGHT_BITS>;
524     using FalseWeightBits = TypedJumpOpBits::NextField<uint32_t, PGOSampleType::WEIGHT_BITS>;
525     using TrueWeightBits = FalseWeightBits::NextField<uint32_t, PGOSampleType::WEIGHT_BITS>;
526 
527     uint64_t bitField_;
528 };
529 
530 }
531 
532 #endif  // ECMASCRIPT_COMPILER_MCR_GATE_META_DATA_H
533