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