1 /* 2 * Copyright (c) 2022 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_GATE_META_DATA_H 17 #define ECMASCRIPT_COMPILER_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/pgo_profiler/pgo_profiler_type.h" 27 #include "ecmascript/elements.h" 28 #include "libpandabase/macros.h" 29 30 namespace panda::ecmascript::kungfu { 31 using GateRef = int32_t; 32 enum MachineType : uint8_t { // Bit width 33 NOVALUE = 0, 34 ANYVALUE, 35 ARCH, 36 FLEX, 37 I1, 38 I8, 39 I16, 40 I32, 41 I64, 42 F32, 43 F64, 44 }; 45 46 enum class TypedBinOp : uint8_t { 47 TYPED_ADD = 0, 48 TYPED_SUB, 49 TYPED_MUL, 50 TYPED_DIV, 51 TYPED_MOD, 52 TYPED_LESS, 53 TYPED_LESSEQ, 54 TYPED_GREATER, 55 TYPED_GREATEREQ, 56 TYPED_EQ, 57 TYPED_NOTEQ, 58 TYPED_STRICTEQ, 59 TYPED_SHL, 60 TYPED_SHR, 61 TYPED_ASHR, 62 TYPED_AND, 63 TYPED_OR, 64 TYPED_XOR, 65 TYPED_EXP, 66 }; 67 68 enum class TypedCallTargetCheckOp : uint8_t { 69 JSCALL_IMMEDIATE_AFTER_FUNC_DEF = 0, 70 JSCALL, 71 JSCALL_FAST, 72 JSCALLTHIS, 73 JSCALLTHIS_FAST, 74 JSCALLTHIS_NOGC, 75 JSCALLTHIS_FAST_NOGC, 76 }; 77 78 enum class TypedUnOp : uint8_t { 79 TYPED_NEG = 0, 80 TYPED_NOT, 81 TYPED_INC, 82 TYPED_DEC, 83 TYPED_ISFALSE, 84 TYPED_ISTRUE, 85 }; 86 87 enum class TypedJumpOp : uint8_t { 88 TYPED_JEQZ = 0, 89 TYPED_JNEZ, 90 }; 91 92 #define GATE_META_DATA_DEOPT_REASON(V) \ 93 V(NotInt, NOTINT) \ 94 V(NotDouble, NOTDOUBLE) \ 95 V(NotNumber, NOTNUMBER) \ 96 V(NotBool, NOTBOOL) \ 97 V(NotHeapObject, NOTHEAPOBJECT) \ 98 V(NotStableArray, NOTSARRAY) \ 99 V(NotArray, NOTARRAY) \ 100 V(NotOnHeap, NOTONHEAP) \ 101 V(InconsistentHClass, INCONSISTENTHCLASS) \ 102 V(NotNewObj, NOTNEWOBJ) \ 103 V(NotArrayIndex, NOTARRAYIDX) \ 104 V(NotIncOverflow, NOTINCOV) \ 105 V(NotDecOverflow, NOTDECOV) \ 106 V(NotNegativeOverflow, NOTNEGOV) \ 107 V(NotCallTarget, NOTCALLTGT) \ 108 V(NotJSCallTarget, NOTJSCALLTGT) \ 109 V(CowArray, COWARRAY) \ 110 V(DivideZero, DIVZERO) \ 111 V(InlineFail, INLINEFAIL) \ 112 V(NotJSFastCallTarget, NOTJSFASTCALLTGT) \ 113 V(LexVarIsHole, LEXVARISHOLE) \ 114 V(ModZero, MODZERO) \ 115 V(Int32Overflow, INT32OVERFLOW) 116 117 enum class DeoptType : uint8_t { 118 NOTCHECK = 0, 119 #define DECLARE_DEOPT_TYPE(NAME, TYPE) TYPE, 120 GATE_META_DATA_DEOPT_REASON(DECLARE_DEOPT_TYPE) 121 #undef DECLARE_DEOPT_TYPE 122 }; 123 124 enum class ICmpCondition : uint8_t { 125 EQ = 1, 126 UGT, 127 UGE, 128 ULT, 129 ULE, 130 NE, 131 SGT, 132 SGE, 133 SLT, 134 SLE, 135 }; 136 137 enum class FCmpCondition : uint8_t { 138 ALW_FALSE = 0, 139 OEQ, 140 OGT, 141 OGE, 142 OLT, 143 OLE, 144 ONE, 145 ORD, 146 UNO, 147 UEQ, 148 UGT, 149 UGE, 150 ULT, 151 ULE, 152 UNE, 153 ALW_TRUE, 154 }; 155 156 enum class TypedStoreOp : uint8_t { 157 ARRAY_STORE_ELEMENT = 0, 158 INT8ARRAY_STORE_ELEMENT, 159 UINT8ARRAY_STORE_ELEMENT, 160 UINT8CLAMPEDARRAY_STORE_ELEMENT, 161 INT16ARRAY_STORE_ELEMENT, 162 UINT16ARRAY_STORE_ELEMENT, 163 INT32ARRAY_STORE_ELEMENT, 164 UINT32ARRAY_STORE_ELEMENT, 165 FLOAT32ARRAY_STORE_ELEMENT, 166 FLOAT64ARRAY_STORE_ELEMENT, 167 168 TYPED_ARRAY_FIRST = INT8ARRAY_STORE_ELEMENT, 169 }; 170 171 enum class MemoryType : uint8_t { 172 ELEMENT_TYPE = 0, 173 }; 174 175 enum class TypedLoadOp : uint8_t { 176 ARRAY_LOAD_INT_ELEMENT = 0, 177 ARRAY_LOAD_DOUBLE_ELEMENT, 178 ARRAY_LOAD_OBJECT_ELEMENT, 179 ARRAY_LOAD_TAGGED_ELEMENT, 180 ARRAY_LOAD_HOLE_TAGGED_ELEMENT, 181 INT8ARRAY_LOAD_ELEMENT, 182 UINT8ARRAY_LOAD_ELEMENT, 183 UINT8CLAMPEDARRAY_LOAD_ELEMENT, 184 INT16ARRAY_LOAD_ELEMENT, 185 UINT16ARRAY_LOAD_ELEMENT, 186 INT32ARRAY_LOAD_ELEMENT, 187 UINT32ARRAY_LOAD_ELEMENT, 188 FLOAT32ARRAY_LOAD_ELEMENT, 189 FLOAT64ARRAY_LOAD_ELEMENT, 190 191 TYPED_ARRAY_FIRST = INT8ARRAY_LOAD_ELEMENT, 192 }; 193 194 std::string MachineTypeToStr(MachineType machineType); 195 196 #define BINARY_GATE_META_DATA_CACHE_LIST(V) \ 197 V(Add, ADD, GateFlags::NONE_FLAG, 0, 0, 2) \ 198 V(Sub, SUB, GateFlags::NONE_FLAG, 0, 0, 2) \ 199 V(Mul, MUL, GateFlags::NONE_FLAG, 0, 0, 2) \ 200 V(Exp, EXP, GateFlags::NONE_FLAG, 0, 0, 2) \ 201 V(Sdiv, SDIV, GateFlags::NONE_FLAG, 0, 0, 2) \ 202 V(Smod, SMOD, GateFlags::NONE_FLAG, 0, 0, 2) \ 203 V(Udiv, UDIV, GateFlags::NONE_FLAG, 0, 0, 2) \ 204 V(Umod, UMOD, GateFlags::NONE_FLAG, 0, 0, 2) \ 205 V(Fdiv, FDIV, GateFlags::NONE_FLAG, 0, 0, 2) \ 206 V(Fmod, FMOD, GateFlags::NONE_FLAG, 0, 0, 2) \ 207 V(And, AND, GateFlags::NONE_FLAG, 0, 0, 2) \ 208 V(Xor, XOR, GateFlags::NONE_FLAG, 0, 0, 2) \ 209 V(Or, OR, GateFlags::NONE_FLAG, 0, 0, 2) \ 210 V(Lsl, LSL, GateFlags::NONE_FLAG, 0, 0, 2) \ 211 V(Lsr, LSR, GateFlags::NONE_FLAG, 0, 0, 2) \ 212 V(Asr, ASR, GateFlags::NONE_FLAG, 0, 0, 2) \ 213 V(AddWithOverflow, ADD_WITH_OVERFLOW, GateFlags::NONE_FLAG, 0, 0, 2) \ 214 V(SubWithOverflow, SUB_WITH_OVERFLOW, GateFlags::NONE_FLAG, 0, 0, 2) \ 215 V(MulWithOverflow, MUL_WITH_OVERFLOW, GateFlags::NONE_FLAG, 0, 0, 2) \ 216 V(ExtractValue, EXTRACT_VALUE, GateFlags::NONE_FLAG, 0, 0, 2) \ 217 V(Sqrt, SQRT, GateFlags::NO_WRITE, 0, 0, 1) \ 218 V(Int32CheckRightIsZero, INT32_CHECK_RIGHT_IS_ZERO, GateFlags::CHECKABLE, 1, 1, 1) \ 219 V(Float64CheckRightIsZero, FLOAT64_CHECK_RIGHT_IS_ZERO, GateFlags::CHECKABLE, 1, 1, 1) \ 220 V(ValueCheckNegOverflow, VALUE_CHECK_NEG_OVERFLOW, GateFlags::CHECKABLE, 1, 1, 1) \ 221 V(OverflowCheck, OVERFLOW_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ 222 V(Int32UnsignedUpperBoundCheck, INT32_UNSIGNED_UPPER_BOUND_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \ 223 V(Int32DivWithCheck, INT32_DIV_WITH_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \ 224 V(LexVarIsHoleCheck, LEX_VAR_IS_HOLE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) 225 226 #define UNARY_GATE_META_DATA_CACHE_LIST(V) \ 227 V(Zext, ZEXT, GateFlags::NONE_FLAG, 0, 0, 1) \ 228 V(Sext, SEXT, GateFlags::NONE_FLAG, 0, 0, 1) \ 229 V(Trunc, TRUNC, GateFlags::NONE_FLAG, 0, 0, 1) \ 230 V(Fext, FEXT, GateFlags::NONE_FLAG, 0, 0, 1) \ 231 V(Ftrunc, FTRUNC, GateFlags::NONE_FLAG, 0, 0, 1) \ 232 V(Rev, REV, GateFlags::NONE_FLAG, 0, 0, 1) \ 233 V(TruncFloatToInt64, TRUNC_FLOAT_TO_INT64, GateFlags::NONE_FLAG, 0, 0, 1) \ 234 V(TruncFloatToInt32, TRUNC_FLOAT_TO_INT32, GateFlags::NONE_FLAG, 0, 0, 1) \ 235 V(TaggedToInt64, TAGGED_TO_INT64, GateFlags::NONE_FLAG, 0, 0, 1) \ 236 V(Int64ToTagged, INT64_TO_TAGGED, GateFlags::NONE_FLAG, 0, 0, 1) \ 237 V(SignedIntToFloat, SIGNED_INT_TO_FLOAT, GateFlags::NONE_FLAG, 0, 0, 1) \ 238 V(UnsignedIntToFloat, UNSIGNED_INT_TO_FLOAT, GateFlags::NONE_FLAG, 0, 0, 1) \ 239 V(FloatToSignedInt, FLOAT_TO_SIGNED_INT, GateFlags::NONE_FLAG, 0, 0, 1) \ 240 V(UnsignedFloatToInt, UNSIGNED_FLOAT_TO_INT, GateFlags::NONE_FLAG, 0, 0, 1) \ 241 V(Bitcast, BITCAST, GateFlags::NONE_FLAG, 0, 0, 1) 242 243 #define IMMUTABLE_META_DATA_CACHE_LIST(V) \ 244 V(CircuitRoot, CIRCUIT_ROOT, GateFlags::NONE_FLAG, 0, 0, 0) \ 245 V(StateEntry, STATE_ENTRY, GateFlags::ROOT, 0, 0, 0) \ 246 V(DependEntry, DEPEND_ENTRY, GateFlags::ROOT, 0, 0, 0) \ 247 V(ReturnList, RETURN_LIST, GateFlags::ROOT, 0, 0, 0) \ 248 V(ArgList, ARG_LIST, GateFlags::ROOT, 0, 0, 0) \ 249 V(Return, RETURN, GateFlags::HAS_ROOT, 1, 1, 1) \ 250 V(ReturnVoid, RETURN_VOID, GateFlags::HAS_ROOT, 1, 1, 0) \ 251 V(Throw, THROW, GateFlags::CONTROL, 1, 1, 1) \ 252 V(OrdinaryBlock, ORDINARY_BLOCK, GateFlags::CONTROL, 1, 0, 0) \ 253 V(IfBranch, IF_BRANCH, GateFlags::CONTROL, 1, 0, 1) \ 254 V(IfTrue, IF_TRUE, GateFlags::CONTROL, 1, 0, 0) \ 255 V(IfFalse, IF_FALSE, GateFlags::CONTROL, 1, 0, 0) \ 256 V(LoopBegin, LOOP_BEGIN, GateFlags::CONTROL, 2, 0, 0) \ 257 V(LoopBack, LOOP_BACK, GateFlags::CONTROL, 1, 0, 0) \ 258 V(LoopExit, LOOP_EXIT, GateFlags::CONTROL, 1, 0, 0) \ 259 V(LoopExitDepend, LOOP_EXIT_DEPEND, GateFlags::FIXED, 1, 1, 0) \ 260 V(LoopExitValue, LOOP_EXIT_VALUE, GateFlags::FIXED, 1, 0, 1) \ 261 V(DependRelay, DEPEND_RELAY, GateFlags::FIXED, 1, 1, 0) \ 262 V(IfSuccess, IF_SUCCESS, GateFlags::CONTROL, 1, 0, 0) \ 263 V(IfException, IF_EXCEPTION, GateFlags::CONTROL, 1, 1, 0) \ 264 V(GetException, GET_EXCEPTION, GateFlags::NONE_FLAG, 1, 1, 0) \ 265 V(GetConstPool, GET_CONSTPOOL, GateFlags::NO_WRITE, 0, 1, 1) \ 266 V(GetGlobalEnv, GET_GLOBAL_ENV, GateFlags::NO_WRITE, 0, 1, 0) \ 267 V(StateSplit, STATE_SPLIT, GateFlags::CHECKABLE, 1, 1, 0) \ 268 V(Load, LOAD, GateFlags::NO_WRITE, 0, 1, 1) \ 269 V(Store, STORE, GateFlags::NONE_FLAG, 0, 1, 2) \ 270 V(TypedCallCheck, TYPED_CALL_CHECK, GateFlags::CHECKABLE, 1, 1, 3) \ 271 V(HeapObjectCheck, HEAP_OBJECT_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ 272 V(COWArrayCheck, COW_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ 273 V(ArrayGuardianCheck, ARRAY_GUARDIAN_CHECK, GateFlags::CHECKABLE, 1, 1, 0) \ 274 V(DeoptCheck, DEOPT_CHECK, GateFlags::NO_WRITE, 1, 1, 3) \ 275 V(StoreProperty, STORE_PROPERTY, GateFlags::NONE_FLAG, 1, 1, 3) \ 276 V(StorePropertyNoBarrier, STORE_PROPERTY_NO_BARRIER, GateFlags::NONE_FLAG, 1, 1, 3) \ 277 V(ToLength, TO_LENGTH, GateFlags::NONE_FLAG, 1, 1, 1) \ 278 V(DefaultCase, DEFAULT_CASE, GateFlags::CONTROL, 1, 0, 0) \ 279 V(LoadArrayLength, LOAD_ARRAY_LENGTH, GateFlags::NO_WRITE, 1, 1, 1) \ 280 V(TypedNewAllocateThis, TYPED_NEW_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \ 281 V(TypedSuperAllocateThis, TYPED_SUPER_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \ 282 V(GetSuperConstructor, GET_SUPER_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1) \ 283 V(CheckSafePointAndStackOver, CHECK_SAFEPOINT_AND_STACKOVER, GateFlags::NO_WRITE, 1, 1, 0) \ 284 V(Dead, DEAD, GateFlags::NONE_FLAG, 0, 0, 0) \ 285 V(FrameArgs, FRAME_ARGS, GateFlags::NONE_FLAG, 0, 0, 4) \ 286 V(GetEnv, GET_ENV, GateFlags::NONE_FLAG, 0, 0, 1) \ 287 V(ConvertHoleAsUndefined, CONVERT_HOLE_AS_UNDEFINED, GateFlags::NO_WRITE, 1, 1, 1) \ 288 V(StartAllocate, START_ALLOCATE, GateFlags::NONE_FLAG, 0, 1, 0) \ 289 V(FinishAllocate, FINISH_ALLOCATE, GateFlags::NONE_FLAG, 0, 1, 0) \ 290 V(LoadGetter, LOAD_GETTER, GateFlags::NONE_FLAG, 0, 1, 2) \ 291 V(LoadSetter, LOAD_SETTER, GateFlags::NONE_FLAG, 0, 1, 2) \ 292 V(ReadSp, READSP, GateFlags::NONE_FLAG, 0, 0, 0) \ 293 BINARY_GATE_META_DATA_CACHE_LIST(V) \ 294 UNARY_GATE_META_DATA_CACHE_LIST(V) 295 296 #define GATE_META_DATA_LIST_WITH_VALUE_IN(V) \ 297 V(ValueSelector, VALUE_SELECTOR, GateFlags::FIXED, 1, 0, value) \ 298 V(FrameValues, FRAME_VALUES, GateFlags::NONE_FLAG, 0, 0, value) \ 299 V(RuntimeCall, RUNTIME_CALL, GateFlags::NONE_FLAG, 0, 1, value) \ 300 V(RuntimeCallWithArgv, RUNTIME_CALL_WITH_ARGV, GateFlags::NONE_FLAG, 0, 1, value) \ 301 V(NoGcRuntimeCall, NOGC_RUNTIME_CALL, GateFlags::NO_WRITE, 0, 1, value) \ 302 V(Call, CALL, GateFlags::NONE_FLAG, 0, 1, value) \ 303 V(BytecodeCall, BYTECODE_CALL, GateFlags::NONE_FLAG, 0, 1, value) \ 304 V(DebuggerBytecodeCall, DEBUGGER_BYTECODE_CALL, GateFlags::NONE_FLAG, 0, 1, value) \ 305 V(BuiltinsCallWithArgv, BUILTINS_CALL_WITH_ARGV, GateFlags::NONE_FLAG, 0, 1, value) \ 306 V(BuiltinsCall, BUILTINS_CALL, GateFlags::NONE_FLAG, 0, 1, value) \ 307 V(SaveRegister, SAVE_REGISTER, GateFlags::NONE_FLAG, 0, 1, value) 308 309 #define GATE_META_DATA_LIST_WITH_PC_OFFSET(V) \ 310 V(TypedCallBuiltin, TYPED_CALL_BUILTIN, GateFlags::NO_WRITE, 1, 1, value) \ 311 V(Construct, CONSTRUCT, GateFlags::NONE_FLAG, 1, 1, value) 312 313 #define GATE_META_DATA_LIST_FOR_CALL(V) \ 314 V(TypedCall, TYPEDCALL, GateFlags::NONE_FLAG, 1, 1, value) \ 315 V(TypedFastCall, TYPEDFASTCALL, GateFlags::NONE_FLAG, 1, 1, value) 316 317 #define GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(V) \ 318 V(CallGetter, CALL_GETTER, GateFlags::NONE_FLAG, 1, 1, 2) \ 319 V(CallSetter, CALL_SETTER, GateFlags::NONE_FLAG, 1, 1, 3) 320 321 #define GATE_META_DATA_LIST_WITH_SIZE(V) \ 322 V(Merge, MERGE, GateFlags::CONTROL, value, 0, 0) \ 323 V(DependSelector, DEPEND_SELECTOR, GateFlags::FIXED, 1, value, 0) \ 324 GATE_META_DATA_LIST_WITH_VALUE_IN(V) 325 326 #define GATE_META_DATA_LIST_WITH_GATE_TYPE(V) \ 327 V(PrimitiveTypeCheck, PRIMITIVE_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ 328 V(TypedArrayCheck, TYPED_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ 329 V(LoadTypedArrayLength, LOAD_TYPED_ARRAY_LENGTH, GateFlags::NO_WRITE, 1, 1, 1) \ 330 V(IndexCheck, INDEX_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \ 331 V(TypedUnaryOp, TYPED_UNARY_OP, GateFlags::NO_WRITE, 1, 1, 1) \ 332 V(TypedConditionJump, TYPED_CONDITION_JUMP, GateFlags::NO_WRITE, 1, 1, 1) \ 333 V(TypedConvert, TYPE_CONVERT, GateFlags::NO_WRITE, 1, 1, 1) \ 334 V(CheckAndConvert, CHECK_AND_CONVERT, GateFlags::CHECKABLE, 1, 1, 1) \ 335 V(Convert, CONVERT, GateFlags::NONE_FLAG, 0, 0, 1) \ 336 V(JSInlineTargetTypeCheck, JSINLINETARGET_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \ 337 V(InlineAccessorCheck, INLINE_ACCESSOR_CHECK, GateFlags::CHECKABLE, 1, 1, 2) 338 339 #define GATE_META_DATA_LIST_WITH_VALUE(V) \ 340 V(Icmp, ICMP, GateFlags::NONE_FLAG, 0, 0, 2) \ 341 V(Fcmp, FCMP, GateFlags::NONE_FLAG, 0, 0, 2) \ 342 V(Alloca, ALLOCA, GateFlags::NONE_FLAG, 0, 0, 0) \ 343 V(SwitchBranch, SWITCH_BRANCH, GateFlags::CONTROL, 1, 0, 1) \ 344 V(SwitchCase, SWITCH_CASE, GateFlags::CONTROL, 1, 0, 0) \ 345 V(HeapAlloc, HEAP_ALLOC, GateFlags::NONE_FLAG, 1, 1, 1) \ 346 V(LoadConstOffset, LOAD_CONST_OFFSET, GateFlags::NO_WRITE, 0, 1, 1) \ 347 V(StoreConstOffset, STORE_CONST_OFFSET, GateFlags::NONE_FLAG, 1, 1, 2) \ 348 V(LoadElement, LOAD_ELEMENT, GateFlags::NO_WRITE, 1, 1, 2) \ 349 V(StoreElement, STORE_ELEMENT, GateFlags::NONE_FLAG, 1, 1, 3) \ 350 V(StoreMemory, STORE_MEMORY, GateFlags::NONE_FLAG, 1, 1, 3) \ 351 V(RestoreRegister, RESTORE_REGISTER, GateFlags::NONE_FLAG, 0, 0, 1) \ 352 V(Constant, CONSTANT, GateFlags::NONE_FLAG, 0, 0, 0) \ 353 V(RelocatableData, RELOCATABLE_DATA, GateFlags::NONE_FLAG, 0, 0, 0) \ 354 V(GetGlobalEnvObjHClass, GET_GLOBAL_ENV_OBJ_HCLASS, GateFlags::NO_WRITE, 0, 1, 1) \ 355 V(GetGlobalConstantValue, GET_GLOBAL_CONSTANT_VALUE, GateFlags::NO_WRITE, 0, 1, 0) \ 356 V(FrameState, FRAME_STATE, GateFlags::HAS_FRAME_STATE, 0, 0, 2) \ 357 V(CreateArray, CREATE_ARRAY, GateFlags::NONE_FLAG, 1, 1, 0) \ 358 V(CreateArrayWithBuffer, CREATE_ARRAY_WITH_BUFFER, GateFlags::CHECKABLE, 1, 1, 2) \ 359 V(RangeGuard, RANGE_GUARD, GateFlags::NO_WRITE, 1, 1, 1) \ 360 V(StableArrayCheck, STABLE_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ 361 V(HClassStableArrayCheck, HCLASS_STABLE_ARRAY_CHECK, GateFlags::CHECKABLE, 1, 1, 1) \ 362 V(ObjectTypeCheck, OBJECT_TYPE_CHECK, GateFlags::CHECKABLE, 1, 1, 2) \ 363 V(ObjectTypeCompare, OBJECT_TYPE_COMPARE, GateFlags::CHECKABLE, 1, 1, 2) 364 365 #define GATE_META_DATA_LIST_WITH_ONE_PARAMETER(V) \ 366 V(Arg, ARG, GateFlags::HAS_ROOT, 0, 0, 0) \ 367 GATE_META_DATA_LIST_WITH_VALUE(V) \ 368 GATE_META_DATA_LIST_WITH_GATE_TYPE(V) 369 370 #define GATE_META_DATA_LIST_WITH_BOOL(V) \ 371 V(LoadProperty, LOAD_PROPERTY, GateFlags::NO_WRITE, 1, 1, 2) \ 372 373 #define GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(V) \ 374 V(CallOptimized, CALL_OPTIMIZED, GateFlags::NONE_FLAG, 0, 1, value) \ 375 V(FastCallOptimized, FAST_CALL_OPTIMIZED, GateFlags::NONE_FLAG, 0, 1, value) \ 376 377 #define GATE_OPCODE_LIST(V) \ 378 V(JS_BYTECODE) \ 379 V(TYPED_BINARY_OP) \ 380 V(TYPED_CALLTARGETCHECK_OP) \ 381 V(CONSTSTRING) 382 383 enum class OpCode : uint8_t { 384 NOP = 0, 385 #define DECLARE_GATE_OPCODE(NAME, OP, R, S, D, V) OP, 386 IMMUTABLE_META_DATA_CACHE_LIST(DECLARE_GATE_OPCODE) 387 GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_OPCODE) 388 GATE_META_DATA_LIST_WITH_ONE_PARAMETER(DECLARE_GATE_OPCODE) 389 GATE_META_DATA_LIST_WITH_PC_OFFSET(DECLARE_GATE_OPCODE) 390 GATE_META_DATA_LIST_FOR_CALL(DECLARE_GATE_OPCODE) 391 GATE_META_DATA_LIST_WITH_PC_OFFSET_FIXED_VALUE(DECLARE_GATE_OPCODE) 392 GATE_META_DATA_LIST_WITH_BOOL(DECLARE_GATE_OPCODE) 393 GATE_META_DATA_LIST_WITH_BOOL_VALUE_IN(DECLARE_GATE_OPCODE) 394 #undef DECLARE_GATE_OPCODE 395 #define DECLARE_GATE_OPCODE(NAME) NAME, 396 GATE_OPCODE_LIST(DECLARE_GATE_OPCODE) 397 #undef DECLARE_GATE_OPCODE 398 }; 399 400 enum GateFlags : uint8_t { 401 NONE_FLAG = 0, 402 NO_WRITE = 1 << 0, 403 HAS_ROOT = 1 << 1, 404 HAS_FRAME_STATE = 1 << 2, 405 CONTROL = NO_WRITE, 406 CONTROL_ROOT = NO_WRITE | HAS_ROOT, 407 CHECKABLE = NO_WRITE | HAS_FRAME_STATE, 408 ROOT = NO_WRITE | HAS_ROOT, 409 FIXED = NO_WRITE, 410 }; 411 412 class GateMetaData : public ChunkObject { 413 public: 414 enum class Kind : uint8_t { 415 IMMUTABLE = 0, 416 MUTABLE_WITH_SIZE, 417 IMMUTABLE_ONE_PARAMETER, 418 MUTABLE_ONE_PARAMETER, 419 IMMUTABLE_BOOL, 420 MUTABLE_STRING, 421 JSBYTECODE, 422 TYPED_BINARY_OP, 423 TYPED_CALLTARGETCHECK_OP, 424 TYPED_CALL, 425 }; 426 GateMetaData() = default; GateMetaData(OpCode opcode,GateFlags flags,uint32_t statesIn,uint16_t dependsIn,uint32_t valuesIn)427 GateMetaData(OpCode opcode, GateFlags flags, 428 uint32_t statesIn, uint16_t dependsIn, uint32_t valuesIn) 429 : opcode_(opcode), flags_(flags), 430 statesIn_(statesIn), dependsIn_(dependsIn), valuesIn_(valuesIn) {} 431 GetRevCompareOp(TypedBinOp op)432 static TypedBinOp GetRevCompareOp(TypedBinOp op) 433 { 434 switch (op) { 435 case TypedBinOp::TYPED_LESS: 436 return TypedBinOp::TYPED_GREATEREQ; 437 case TypedBinOp::TYPED_LESSEQ: 438 return TypedBinOp::TYPED_GREATER; 439 case TypedBinOp::TYPED_GREATER: 440 return TypedBinOp::TYPED_LESSEQ; 441 case TypedBinOp::TYPED_GREATEREQ: 442 return TypedBinOp::TYPED_LESS; 443 case TypedBinOp::TYPED_EQ: 444 return TypedBinOp::TYPED_NOTEQ; 445 case TypedBinOp::TYPED_NOTEQ: 446 return TypedBinOp::TYPED_EQ; 447 default: 448 UNREACHABLE(); 449 return op; 450 } 451 } 452 GetSwapCompareOp(TypedBinOp op)453 static TypedBinOp GetSwapCompareOp(TypedBinOp op) 454 { 455 switch (op) { 456 case TypedBinOp::TYPED_LESS: 457 return TypedBinOp::TYPED_GREATER; 458 case TypedBinOp::TYPED_LESSEQ: 459 return TypedBinOp::TYPED_GREATEREQ; 460 case TypedBinOp::TYPED_GREATER: 461 return TypedBinOp::TYPED_LESS; 462 case TypedBinOp::TYPED_GREATEREQ: 463 return TypedBinOp::TYPED_LESSEQ; 464 case TypedBinOp::TYPED_EQ: 465 return TypedBinOp::TYPED_EQ; 466 case TypedBinOp::TYPED_NOTEQ: 467 return TypedBinOp::TYPED_NOTEQ; 468 default: 469 UNREACHABLE(); 470 return op; 471 } 472 } 473 GetStateCount()474 size_t GetStateCount() const 475 { 476 return statesIn_; 477 } 478 GetDependCount()479 size_t GetDependCount() const 480 { 481 return dependsIn_; 482 } 483 GetInValueCount()484 size_t GetInValueCount() const 485 { 486 return valuesIn_; 487 } 488 GetRootCount()489 size_t GetRootCount() const 490 { 491 return HasRoot() ? 1 : 0; 492 } 493 GetInFrameStateCount()494 size_t GetInFrameStateCount() const 495 { 496 return HasFrameState() ? 1 : 0; 497 } 498 GetNumIns()499 size_t GetNumIns() const 500 { 501 return GetStateCount() + GetDependCount() + GetInValueCount() 502 + GetInFrameStateCount() + GetRootCount(); 503 } 504 GetInValueStarts()505 size_t GetInValueStarts() const 506 { 507 return GetStateCount() + GetDependCount(); 508 } 509 GetInFrameStateStarts()510 size_t GetInFrameStateStarts() const 511 { 512 return GetInValueStarts() + GetInValueCount(); 513 } 514 GetOpCode()515 OpCode GetOpCode() const 516 { 517 return opcode_; 518 } 519 GetKind()520 Kind GetKind() const 521 { 522 return kind_; 523 } 524 AssertKind(Kind kind)525 void AssertKind([[maybe_unused]] Kind kind) const 526 { 527 ASSERT(GetKind() == kind); 528 } 529 IsOneParameterKind()530 bool IsOneParameterKind() const 531 { 532 return GetKind() == Kind::IMMUTABLE_ONE_PARAMETER || GetKind() == Kind::MUTABLE_ONE_PARAMETER || 533 GetKind() == Kind::TYPED_BINARY_OP || GetKind() == Kind::TYPED_CALLTARGETCHECK_OP; 534 } 535 IsStringType()536 bool IsStringType() const 537 { 538 return GetKind() == Kind::MUTABLE_STRING; 539 } 540 541 bool IsRoot() const; 542 bool IsProlog() const; 543 bool IsFixed() const; 544 bool IsSchedulable() const; 545 bool IsState() const; // note: IsState(STATE_ENTRY) == false 546 bool IsGeneralState() const; 547 bool IsTerminalState() const; 548 bool IsVirtualState() const; 549 bool IsCFGMerge() const; 550 bool IsControlCase() const; 551 bool IsLoopHead() const; 552 bool IsNop() const; 553 bool IsConstant() const; 554 bool IsDependSelector() const; 555 bool IsTypedOperator() const; 556 bool IsCheckWithOneIn() const; 557 bool IsCheckWithTwoIns() const; HasFrameState()558 bool HasFrameState() const 559 { 560 return HasFlag(GateFlags::HAS_FRAME_STATE); 561 } 562 IsNotWrite()563 bool IsNotWrite() const 564 { 565 return HasFlag(GateFlags::NO_WRITE); 566 } 567 568 ~GateMetaData() = default; 569 570 std::string TypedBinOpToStr(TypedBinOp typedBinOp) const; 571 static std::string Str(OpCode opcode); Str()572 std::string Str() const 573 { 574 return Str(opcode_); 575 } 576 protected: SetKind(Kind kind)577 void SetKind(Kind kind) 578 { 579 kind_ = kind; 580 } 581 SetFlags(GateFlags flags)582 void SetFlags(GateFlags flags) 583 { 584 flags_ = flags; 585 } 586 DecreaseIn(size_t idx)587 void DecreaseIn(size_t idx) 588 { 589 ASSERT(GetKind() == Kind::MUTABLE_WITH_SIZE); 590 if (idx < statesIn_) { 591 statesIn_--; 592 } else if (idx < statesIn_ + dependsIn_) { 593 dependsIn_--; 594 } else { 595 valuesIn_--; 596 } 597 } 598 HasRoot()599 bool HasRoot() const 600 { 601 return HasFlag(GateFlags::HAS_ROOT); 602 } 603 HasFlag(GateFlags flag)604 bool HasFlag(GateFlags flag) const 605 { 606 return (GetFlags() & flag) == flag; 607 } 608 GetFlags()609 GateFlags GetFlags() const 610 { 611 return flags_; 612 } 613 614 private: 615 friend class Gate; 616 friend class Circuit; 617 friend class GateMetaBuilder; 618 619 OpCode opcode_ { OpCode::NOP }; 620 Kind kind_ { Kind::IMMUTABLE }; 621 GateFlags flags_ { GateFlags::NONE_FLAG }; 622 uint32_t statesIn_ { 0 }; 623 uint32_t dependsIn_ { 0 }; 624 uint32_t valuesIn_ { 0 }; 625 }; 626 627 inline std::ostream& operator<<(std::ostream& os, OpCode opcode) 628 { 629 return os << GateMetaData::Str(opcode); 630 } 631 632 class BoolMetaData : public GateMetaData { 633 public: BoolMetaData(OpCode opcode,GateFlags flags,uint32_t statesIn,uint16_t dependsIn,uint32_t valuesIn,bool value)634 BoolMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn, 635 uint16_t dependsIn, uint32_t valuesIn, bool value) 636 : GateMetaData(opcode, flags, statesIn, dependsIn, valuesIn), value_(value) 637 { 638 SetKind(GateMetaData::Kind::IMMUTABLE_BOOL); 639 } 640 Cast(const GateMetaData * meta)641 static const BoolMetaData* Cast(const GateMetaData* meta) 642 { 643 meta->AssertKind(GateMetaData::Kind::IMMUTABLE_BOOL); 644 return static_cast<const BoolMetaData*>(meta); 645 } 646 GetBool()647 bool GetBool() const 648 { 649 return value_; 650 } 651 652 private: 653 bool value_ { false }; 654 }; 655 656 class JSBytecodeMetaData : public GateMetaData { 657 public: JSBytecodeMetaData(size_t valuesIn,EcmaOpcode opcode,uint32_t pcOffset,GateFlags flags)658 explicit JSBytecodeMetaData(size_t valuesIn, EcmaOpcode opcode, uint32_t pcOffset, GateFlags flags) 659 : GateMetaData(OpCode::JS_BYTECODE, flags, 1, 1, valuesIn), 660 opcode_(opcode), pcOffset_(pcOffset) 661 { 662 SetKind(GateMetaData::Kind::JSBYTECODE); 663 } 664 Cast(const GateMetaData * meta)665 static const JSBytecodeMetaData* Cast(const GateMetaData* meta) 666 { 667 meta->AssertKind(GateMetaData::Kind::JSBYTECODE); 668 return static_cast<const JSBytecodeMetaData*>(meta); 669 } 670 GetPcOffset()671 uint32_t GetPcOffset() const 672 { 673 return pcOffset_; 674 } 675 SetType(PGOSampleType type)676 void SetType(PGOSampleType type) 677 { 678 type_ = type; 679 } 680 GetType()681 PGOSampleType GetType() const 682 { 683 return type_; 684 } 685 GetByteCodeOpcode()686 EcmaOpcode GetByteCodeOpcode() const 687 { 688 return opcode_; 689 } 690 SetElementsKind(ElementsKind kind)691 void SetElementsKind(ElementsKind kind) 692 { 693 elementsKind_ = kind; 694 } 695 GetElementsKind()696 ElementsKind GetElementsKind() const 697 { 698 // Need return elementsKind_, close feature temporarily, wait for CreateArray 699 return ElementsKind::GENERIC; 700 } 701 702 private: 703 EcmaOpcode opcode_; 704 uint32_t pcOffset_; 705 PGOSampleType type_; 706 ElementsKind elementsKind_ {ElementsKind::GENERIC}; 707 }; 708 709 class OneParameterMetaData : public GateMetaData { 710 public: OneParameterMetaData(OpCode opcode,GateFlags flags,uint32_t statesIn,uint16_t dependsIn,uint32_t valuesIn,uint64_t value)711 OneParameterMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn, 712 uint16_t dependsIn, uint32_t valuesIn, uint64_t value) 713 : GateMetaData(opcode, flags, statesIn, dependsIn, valuesIn), value_(value) 714 { 715 SetKind(GateMetaData::Kind::IMMUTABLE_ONE_PARAMETER); 716 } 717 Cast(const GateMetaData * meta)718 static const OneParameterMetaData* Cast(const GateMetaData* meta) 719 { 720 ASSERT(meta->IsOneParameterKind()); 721 return static_cast<const OneParameterMetaData*>(meta); 722 } 723 GetValue()724 uint64_t GetValue() const 725 { 726 return value_; 727 } 728 SetValue(uint64_t value)729 void SetValue(uint64_t value) 730 { 731 value_ = value; 732 } 733 734 private: 735 uint64_t value_ { 0 }; 736 }; 737 738 class TypedCallMetaData : public OneParameterMetaData { 739 public: TypedCallMetaData(OpCode opcode,GateFlags flags,uint32_t statesIn,uint16_t dependsIn,uint32_t valuesIn,uint64_t value,bool noGC)740 TypedCallMetaData(OpCode opcode, GateFlags flags, uint32_t statesIn, 741 uint16_t dependsIn, uint32_t valuesIn, uint64_t value, bool noGC) 742 : OneParameterMetaData(opcode, flags, statesIn, dependsIn, valuesIn, value), 743 noGC_(noGC) 744 { 745 SetKind(GateMetaData::Kind::TYPED_CALL); 746 } 747 Cast(const GateMetaData * meta)748 static const TypedCallMetaData* Cast(const GateMetaData* meta) 749 { 750 meta->AssertKind(GateMetaData::Kind::TYPED_CALL); 751 return static_cast<const TypedCallMetaData*>(meta); 752 } 753 IsNoGC()754 bool IsNoGC() const 755 { 756 return noGC_; 757 } 758 private: 759 bool noGC_; 760 }; 761 762 class TypedCallTargetCheckMetaData : public OneParameterMetaData { 763 public: TypedCallTargetCheckMetaData(uint32_t valuesIn,uint64_t value,TypedCallTargetCheckOp checkOp)764 TypedCallTargetCheckMetaData(uint32_t valuesIn, uint64_t value, TypedCallTargetCheckOp checkOp) 765 : OneParameterMetaData(OpCode::TYPED_CALLTARGETCHECK_OP, GateFlags::CHECKABLE, 1, 1, valuesIn, value), 766 checkOp_(checkOp) 767 { 768 SetKind(GateMetaData::Kind::TYPED_CALLTARGETCHECK_OP); 769 } 770 Cast(const GateMetaData * meta)771 static const TypedCallTargetCheckMetaData* Cast(const GateMetaData* meta) 772 { 773 meta->AssertKind(GateMetaData::Kind::TYPED_CALLTARGETCHECK_OP); 774 return static_cast<const TypedCallTargetCheckMetaData*>(meta); 775 } 776 GetTypedCallTargetCheckOp()777 TypedCallTargetCheckOp GetTypedCallTargetCheckOp() const 778 { 779 return checkOp_; 780 } 781 private: 782 TypedCallTargetCheckOp checkOp_; 783 }; 784 785 class TypedBinaryMetaData : public OneParameterMetaData { 786 public: TypedBinaryMetaData(uint64_t value,TypedBinOp binOp,PGOSampleType type)787 TypedBinaryMetaData(uint64_t value, TypedBinOp binOp, PGOSampleType type) 788 : OneParameterMetaData(OpCode::TYPED_BINARY_OP, GateFlags::NO_WRITE, 1, 1, 2, value), // 2: valuesIn 789 binOp_(binOp), type_(type) 790 { 791 SetKind(GateMetaData::Kind::TYPED_BINARY_OP); 792 } 793 Cast(const GateMetaData * meta)794 static const TypedBinaryMetaData* Cast(const GateMetaData* meta) 795 { 796 meta->AssertKind(GateMetaData::Kind::TYPED_BINARY_OP); 797 return static_cast<const TypedBinaryMetaData*>(meta); 798 } 799 GetTypedBinaryOp()800 TypedBinOp GetTypedBinaryOp() const 801 { 802 return binOp_; 803 } 804 GetType()805 PGOSampleType GetType() const 806 { 807 return type_; 808 } 809 private: 810 TypedBinOp binOp_; 811 PGOSampleType type_; 812 }; 813 814 class StringMetaData : public GateMetaData { 815 public: StringMetaData(Chunk * chunk,const std::string & str)816 StringMetaData(Chunk* chunk, const std::string &str) 817 : GateMetaData(OpCode::CONSTSTRING, GateFlags::NONE_FLAG, 0, 0, 0), 818 stringData_(str.size() + 1, chunk) 819 { 820 auto srcLength = str.size(); 821 auto destlength = stringData_.size(); 822 auto dest = stringData_.data(); 823 auto src = str.c_str(); 824 if (destlength <= static_cast<size_t>(srcLength) || strcpy_s(dest, destlength, src) != EOK) { 825 LOG_COMPILER(FATAL) << "StringMetaData strcpy_s failed"; 826 } 827 SetKind(GateMetaData::Kind::MUTABLE_STRING); 828 } 829 GetString()830 const ChunkVector<char> &GetString() const 831 { 832 return stringData_; 833 } 834 835 private: 836 ChunkVector<char> stringData_; 837 }; 838 839 class GateTypeAccessor { 840 public: GateTypeAccessor(uint64_t value)841 explicit GateTypeAccessor(uint64_t value) 842 : type_(static_cast<uint32_t>(value)) {} 843 GetGateType()844 GateType GetGateType() const 845 { 846 return type_; 847 } 848 ToValue(GateType type)849 static uint64_t ToValue(GateType type) 850 { 851 return static_cast<uint64_t>(type.Value()); 852 } 853 private: 854 GateType type_; 855 }; 856 857 class ValuePairTypeAccessor { 858 public: 859 // type bits shift 860 static constexpr int OPRAND_TYPE_BITS = 8; ValuePairTypeAccessor(uint64_t value)861 explicit ValuePairTypeAccessor(uint64_t value) : bitField_(value) {} 862 GetSrcType()863 ValueType GetSrcType() const 864 { 865 return static_cast<ValueType>(LeftBits::Get(bitField_)); 866 } 867 GetDstType()868 ValueType GetDstType() const 869 { 870 return static_cast<ValueType>(RightBits::Get(bitField_)); 871 } 872 IsConvertSupport()873 bool IsConvertSupport() const 874 { 875 return ConvertSupportBits::Get(bitField_) == ConvertSupport::ENABLE; 876 } 877 878 static uint64_t ToValue(ValueType srcType, ValueType dstType, ConvertSupport support = ConvertSupport::ENABLE) 879 { 880 uint8_t srcVlaue = static_cast<uint8_t>(srcType); 881 uint8_t dstVlaue = static_cast<uint8_t>(dstType); 882 return LeftBits::Encode(srcVlaue) | RightBits::Encode(dstVlaue) | ConvertSupportBits::Encode(support); 883 } 884 885 private: 886 using LeftBits = panda::BitField<uint8_t, 0, OPRAND_TYPE_BITS>; 887 using RightBits = LeftBits::NextField<uint8_t, OPRAND_TYPE_BITS>; 888 using ConvertSupportBits = RightBits::NextField<ConvertSupport, OPRAND_TYPE_BITS>; 889 890 uint64_t bitField_; 891 }; 892 893 class GatePairTypeAccessor { 894 public: 895 // type bits shift 896 static constexpr int OPRAND_TYPE_BITS = 32; GatePairTypeAccessor(uint64_t value)897 explicit GatePairTypeAccessor(uint64_t value) : bitField_(value) {} 898 GetLeftType()899 GateType GetLeftType() const 900 { 901 return GateType(LeftBits::Get(bitField_)); 902 } 903 GetRightType()904 GateType GetRightType() const 905 { 906 return GateType(RightBits::Get(bitField_)); 907 } 908 ToValue(GateType leftType,GateType rightType)909 static uint64_t ToValue(GateType leftType, GateType rightType) 910 { 911 return LeftBits::Encode(leftType.Value()) | RightBits::Encode(rightType.Value()); 912 } 913 914 private: 915 using LeftBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>; 916 using RightBits = LeftBits::NextField<uint32_t, OPRAND_TYPE_BITS>; 917 918 uint64_t bitField_; 919 }; 920 921 class TypedUnaryAccessor { 922 public: 923 // type bits shift 924 static constexpr int OPRAND_TYPE_BITS = 32; TypedUnaryAccessor(uint64_t value)925 explicit TypedUnaryAccessor(uint64_t value) : bitField_(value) {} 926 GetTypeValue()927 GateType GetTypeValue() const 928 { 929 return GateType(TypedValueBits::Get(bitField_)); 930 } 931 GetTypedUnOp()932 TypedUnOp GetTypedUnOp() const 933 { 934 return TypedUnOpBits::Get(bitField_); 935 } 936 ToValue(GateType typeValue,TypedUnOp unaryOp)937 static uint64_t ToValue(GateType typeValue, TypedUnOp unaryOp) 938 { 939 return TypedValueBits::Encode(typeValue.Value()) 940 | TypedUnOpBits::Encode(unaryOp); 941 } 942 943 private: 944 using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>; 945 using TypedUnOpBits = TypedValueBits::NextField<TypedUnOp, OPRAND_TYPE_BITS>; 946 947 uint64_t bitField_; 948 }; 949 950 class TypedJumpAccessor { 951 public: 952 // type bits shift 953 static constexpr int OPRAND_TYPE_BITS = 32; TypedJumpAccessor(uint64_t value)954 explicit TypedJumpAccessor(uint64_t value) : bitField_(value) {} 955 GetTypeValue()956 GateType GetTypeValue() const 957 { 958 return GateType(TypedValueBits::Get(bitField_)); 959 } 960 GetTypedJumpOp()961 TypedJumpOp GetTypedJumpOp() const 962 { 963 return TypedJumpOpBits::Get(bitField_); 964 } 965 ToValue(GateType typeValue,TypedJumpOp jumpOp)966 static uint64_t ToValue(GateType typeValue, TypedJumpOp jumpOp) 967 { 968 return TypedValueBits::Encode(typeValue.Value()) 969 | TypedJumpOpBits::Encode(jumpOp); 970 } 971 972 private: 973 using TypedValueBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>; 974 using TypedJumpOpBits = TypedValueBits::NextField<TypedJumpOp, OPRAND_TYPE_BITS>; 975 976 uint64_t bitField_; 977 }; 978 979 class FrameStateOutput { 980 public: 981 static constexpr uint32_t INVALID_INDEX = static_cast<uint32_t>(-1); FrameStateOutput(uint32_t value)982 explicit FrameStateOutput(uint32_t value) : index_(value) {} 983 Invalid()984 static FrameStateOutput Invalid() 985 { 986 return FrameStateOutput(INVALID_INDEX); 987 } 988 IsInvalid()989 bool IsInvalid() const 990 { 991 return index_ == INVALID_INDEX; 992 } 993 GetValue()994 uint32_t GetValue() const 995 { 996 return index_; 997 } 998 private: 999 uint32_t index_; 1000 }; 1001 1002 class UInt32PairAccessor { 1003 public: 1004 // type bits shift 1005 static constexpr int OPRAND_TYPE_BITS = 32; UInt32PairAccessor(uint64_t value)1006 explicit UInt32PairAccessor(uint64_t value) : bitField_(value) {} UInt32PairAccessor(uint32_t first,uint32_t second)1007 explicit UInt32PairAccessor(uint32_t first, uint32_t second) 1008 { 1009 bitField_ = FirstBits::Encode(first) | SecondBits::Encode(second); 1010 } 1011 GetFirstValue()1012 uint32_t GetFirstValue() const 1013 { 1014 return FirstBits::Get(bitField_); 1015 } 1016 GetSecondValue()1017 uint32_t GetSecondValue() const 1018 { 1019 return SecondBits::Get(bitField_); 1020 } 1021 ToValue()1022 uint64_t ToValue() const 1023 { 1024 return bitField_; 1025 } 1026 1027 private: 1028 using FirstBits = panda::BitField<uint32_t, 0, OPRAND_TYPE_BITS>; 1029 using SecondBits = FirstBits::NextField<uint32_t, OPRAND_TYPE_BITS>; 1030 1031 uint64_t bitField_; 1032 }; 1033 1034 class ArrayMetaDataAccessor { 1035 public: 1036 enum Mode : uint8_t { 1037 CREATE = 0, 1038 LOAD_ELEMENT, 1039 STORE_ELEMENT, 1040 LOAD_LENGTH 1041 }; 1042 1043 static constexpr int BITS_SIZE = 8; 1044 static constexpr int ARRAY_LENGTH_BITS_SIZE = 32; ArrayMetaDataAccessor(uint64_t value)1045 explicit ArrayMetaDataAccessor(uint64_t value) : bitField_(value) {} 1046 explicit ArrayMetaDataAccessor(ElementsKind kind, Mode mode, uint32_t length = 0) 1047 { 1048 bitField_ = ElementsKindBits::Encode(kind) | ModeBits::Encode(mode) | ArrayLengthBits::Encode(length); 1049 } 1050 GetElementsKind()1051 ElementsKind GetElementsKind() const 1052 { 1053 return ElementsKindBits::Get(bitField_); 1054 } 1055 SetArrayLength(uint32_t length)1056 void SetArrayLength(uint32_t length) 1057 { 1058 bitField_ = ArrayLengthBits::Update(bitField_, length); 1059 } 1060 GetArrayLength()1061 uint32_t GetArrayLength() const 1062 { 1063 return ArrayLengthBits::Get(bitField_); 1064 } 1065 IsLoadElement()1066 bool IsLoadElement() const 1067 { 1068 return GetMode() == Mode::LOAD_ELEMENT; 1069 } 1070 ToValue()1071 uint64_t ToValue() const 1072 { 1073 return bitField_; 1074 } 1075 1076 private: GetMode()1077 Mode GetMode() const 1078 { 1079 return ModeBits::Get(bitField_); 1080 } 1081 1082 using ElementsKindBits = panda::BitField<ElementsKind, 0, BITS_SIZE>; 1083 using ModeBits = ElementsKindBits::NextField<Mode, BITS_SIZE>; 1084 using ArrayLengthBits = ModeBits::NextField<uint32_t, ARRAY_LENGTH_BITS_SIZE>; 1085 1086 uint64_t bitField_; 1087 }; 1088 1089 class ObjectTypeAccessor { 1090 public: 1091 static constexpr int TYPE_BITS_SIZE = 32; 1092 static constexpr int IS_HEAP_OBJECT_BIT_SIZE = 1; 1093 ObjectTypeAccessor(uint64_t value)1094 explicit ObjectTypeAccessor(uint64_t value) : bitField_(value) {} 1095 explicit ObjectTypeAccessor(GateType type, bool isHeapObject = false) 1096 { 1097 bitField_ = TypeBits::Encode(type.Value()) | IsHeapObjectBit::Encode(isHeapObject); 1098 } 1099 GetType()1100 GateType GetType() const 1101 { 1102 return GateType(TypeBits::Get(bitField_)); 1103 } 1104 IsHeapObject()1105 bool IsHeapObject() const 1106 { 1107 return IsHeapObjectBit::Get(bitField_); 1108 } 1109 ToValue()1110 uint64_t ToValue() const 1111 { 1112 return bitField_; 1113 } 1114 1115 private: 1116 using TypeBits = panda::BitField<uint32_t, 0, TYPE_BITS_SIZE>; 1117 using IsHeapObjectBit = TypeBits::NextField<bool, IS_HEAP_OBJECT_BIT_SIZE>; 1118 1119 uint64_t bitField_; 1120 }; 1121 } // namespace panda::ecmascript::kungfu 1122 1123 #endif // ECMASCRIPT_COMPILER_GATE_META_DATA_H 1124