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 32namespace 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 110enum 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 116enum 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 122enum 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 128enum 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 136enum 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 144enum 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 150enum class BranchKind : uint8_t { 151 NORMAL_BRANCH = 0, 152 TRUE_BRANCH, 153 FALSE_BRANCH, 154 STRONG_TRUE_BRANCH, 155 STRONG_FALSE_BRANCH, 156}; 157 158enum 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 167enum class MemoryType : uint8_t { 168 ELEMENT_TYPE = 0, 169}; 170 171class TypedCallMetaData : public OneParameterMetaData { 172public: 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 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 199 bool IsNoGC() const 200 { 201 return noGC_; 202 } 203private: 204 bool noGC_; 205}; 206 207class NewConstructMetaData : public OneParameterMetaData { 208public: 209 static constexpr int NEED_PUSH_ARGV_BIT_SIZE = 1; 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 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 223 bool NeedPushArgv() const 224 { 225 return NeedPushArgvBit::Get(bitField_); 226 } 227 228 uint64_t GetValue() const 229 { 230 return bitField_; 231 } 232 233private: 234 using NeedPushArgvBit = panda::BitField<bool, 0, NEED_PUSH_ARGV_BIT_SIZE>; 235 236 uint64_t bitField_; 237}; 238 239class TypedUnaryAccessor { 240public: 241 // type bits shift 242 static constexpr int OPRAND_TYPE_BITS = 32; 243 explicit TypedUnaryAccessor(uint64_t value) : bitField_(value) {} 244 245 ParamType GetParamType() const 246 { 247 return ParamType(TypedValueBits::Get(bitField_)); 248 } 249 250 TypedUnOp GetTypedUnOp() const 251 { 252 return TypedUnOpBits::Get(bitField_); 253 } 254 255 static uint64_t ToValue(ParamType paramType, TypedUnOp unaryOp) 256 { 257 return TypedValueBits::Encode(paramType.Value()) | TypedUnOpBits::Encode(unaryOp); 258 } 259 260private: 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 267class TypedBinaryAccessor { 268public: 269 // type bits shift 270 static constexpr int OPRAND_TYPE_BITS = 32; 271 explicit TypedBinaryAccessor(uint64_t value) : bitField_(value) {} 272 273 ParamType GetParamType() const 274 { 275 return ParamType(TypedValueBits::Get(bitField_)); 276 } 277 278 TypedBinOp GetTypedBinOp() const 279 { 280 return TypedBinOpBits::Get(bitField_); 281 } 282 283 static uint64_t ToValue(ParamType operandType, TypedBinOp binOp) 284 { 285 return TypedValueBits::Encode(operandType.Value()) | TypedBinOpBits::Encode(binOp); 286 } 287 288private: 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 295class TypedCallTargetCheckAccessor { 296public: 297 // type bits shift 298 static constexpr int CALLTARGETCHECK_OP_BITS = 32; 299 explicit TypedCallTargetCheckAccessor(uint64_t value) : bitField_(value) {} 300 301 TypedCallTargetCheckOp GetCallTargetCheckOp() const 302 { 303 return CallTargetCheckOpBits::Get(bitField_); 304 } 305 306 static uint64_t ToValue(TypedCallTargetCheckOp op) 307 { 308 return CallTargetCheckOpBits::Encode(op); 309 } 310 311private: 312 using CallTargetCheckOpBits = panda::BitField<TypedCallTargetCheckOp, 0, CALLTARGETCHECK_OP_BITS>; 313 314 uint64_t bitField_; 315}; 316 317class BranchAccessor { 318public: 319 // type bits shift 320 static constexpr int OPRAND_TYPE_BITS = 32; 321 explicit BranchAccessor(uint64_t value) : bitField_(value) {} 322 323 int32_t GetTrueWeight() const 324 { 325 return TrueWeightBits::Get(bitField_); 326 } 327 328 int32_t GetFalseWeight() const 329 { 330 return FalseWeightBits::Get(bitField_); 331 } 332 333 static uint64_t ToValue(uint32_t trueWeight, uint32_t falseWeight) 334 { 335 return TrueWeightBits::Encode(trueWeight) 336 | FalseWeightBits::Encode(falseWeight); 337 } 338private: 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 345class MemoryAttribute { 346public: 347 MemoryAttribute() = default; 348 ~MemoryAttribute() = default; 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 368 static MemoryAttribute Default() 369 { 370 return Create(NOT_ATOMIC); 371 } 372 373 static MemoryAttribute NeedBarrier() 374 { 375 return Create(NOT_ATOMIC, NEED_BARRIER); 376 } 377 378 static MemoryAttribute UnknownBarrier() 379 { 380 return Create(NOT_ATOMIC, UNKNOWN_BARRIER); 381 } 382 383 static MemoryAttribute DefaultWithShareBarrier() 384 { 385 return Create(NOT_ATOMIC, UNKNOWN_BARRIER, SHARED); 386 } 387 388 static MemoryAttribute NeedNotShareBarrier() 389 { 390 return Create(NOT_ATOMIC, NEED_BARRIER, NON_SHARE); 391 } 392 393 static MemoryAttribute NeedBarrierAndAtomic() 394 { 395 return Create(MEMORY_ORDER_RELEASE, NEED_BARRIER); 396 } 397 398 static MemoryAttribute NoBarrier() 399 { 400 return Create(NOT_ATOMIC, NO_BARRIER); 401 } 402 403 void SetBarrier(Barrier barrier) 404 { 405 BarrierField::Set<uint32_t>(barrier, &value_); 406 } 407 408 Barrier GetBarrier() const 409 { 410 return BarrierField::Get(value_); 411 } 412 413 void SetShare(ShareFlag share) 414 { 415 ShareField::Set<uint32_t>(share, &value_); 416 } 417 418 ShareFlag GetShare() const 419 { 420 return ShareField::Get(value_); 421 } 422 423 void SetOrder(Order order) 424 { 425 OrderField::Set<uint32_t>(order, &value_); 426 } 427 428 Order GetOrder() const 429 { 430 return OrderField::Get(value_); 431 } 432 433 uint32_t Value() const 434 { 435 return value_; 436 } 437 438private: 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 455class LoadStoreAccessor { 456public: 457 static constexpr int MEMORY_ORDER_BITS = 32; 458 explicit LoadStoreAccessor(uint64_t value) : bitField_(value) {} 459 460 MemoryAttribute GetMemoryAttribute() const 461 { 462 return MemoryAttribute(MemoryAttributeBits::Get(bitField_)); 463 } 464 465 static uint64_t ToValue(MemoryAttribute mAttr) 466 { 467 return MemoryAttributeBits::Encode(mAttr.Value()); 468 } 469private: 470 using MemoryAttributeBits = panda::BitField<uint32_t, 0, MEMORY_ORDER_BITS>; 471 472 uint64_t bitField_; 473}; 474 475class LoadStoreConstOffsetAccessor { 476public: 477 static constexpr int OPRAND_OFFSET_BITS = 32; 478 static constexpr int MEMORY_ATTRIBUTE_BITS = 32; 479 explicit LoadStoreConstOffsetAccessor(uint64_t value) : bitField_(value) {} 480 481 MemoryAttribute GetMemoryAttribute() const 482 { 483 return MemoryAttribute(MemoryAttributeBits::Get(bitField_)); 484 } 485 486 size_t GetOffset() const 487 { 488 return static_cast<size_t>(OprandOffsetBits::Get(bitField_)); 489 } 490 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 } 496private: 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 503class TypedJumpAccessor { 504public: 505 // type bits shift 506 static constexpr int OPRAND_TYPE_BITS = 32; 507 static constexpr int JUMP_OP_BITS = 8; 508 explicit TypedJumpAccessor(uint64_t value) : bitField_(value) {} 509 510 ParamType GetParamType() const 511 { 512 return ParamType(TypedValueBits::Get(bitField_)); 513 } 514 515 TypedJumpOp GetTypedJumpOp() const 516 { 517 return TypedJumpOpBits::Get(bitField_); 518 } 519 520 uint32_t GetTrueWeight() const 521 { 522 return TrueWeightBits::Get(bitField_); 523 } 524 525 uint32_t GetFalseWeight() const 526 { 527 return FalseWeightBits::Get(bitField_); 528 } 529 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 537private: 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