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