1 /* 2 * Copyright (c) 2021 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_CIRCUIT_BUILDER_H 17 #define ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H 18 19 #include "ecmascript/base/number_helper.h" 20 #include "ecmascript/compiler/assembler/assembler.h" 21 #include "ecmascript/compiler/builtins/builtins_call_signature.h" 22 #include "ecmascript/compiler/circuit.h" 23 #include "ecmascript/compiler/call_signature.h" 24 #include "ecmascript/compiler/gate.h" 25 #include "ecmascript/compiler/gate_accessor.h" 26 #include "ecmascript/compiler/variable_type.h" 27 #include "ecmascript/global_env_constants.h" 28 #include "ecmascript/jspandafile/constpool_value.h" 29 #include "ecmascript/js_hclass.h" 30 #include "ecmascript/js_runtime_options.h" 31 #include "ecmascript/js_tagged_value.h" 32 #include "ecmascript/tagged_array.h" 33 34 namespace panda::ecmascript::kungfu { 35 using namespace panda::ecmascript; 36 #define DEFVAlUE(varname, cirBuilder, type, val) \ 37 Variable varname(cirBuilder, type, cirBuilder->NextVariableId(), val) 38 39 class Environment; 40 class Label; 41 class Variable; 42 class StubBuilder; 43 class TSHCRLowering; 44 class NTypeHCRLowering; 45 class SlowPathLowering; 46 47 #define BINARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(V) \ 48 V(Int16Add, Add, MachineType::I16) \ 49 V(Int32Add, Add, MachineType::I32) \ 50 V(Int64Add, Add, MachineType::I64) \ 51 V(DoubleAdd, Add, MachineType::F64) \ 52 V(PtrAdd, Add, MachineType::ARCH) \ 53 V(Int16Sub, Sub, MachineType::I16) \ 54 V(Int32Sub, Sub, MachineType::I32) \ 55 V(Int64Sub, Sub, MachineType::I64) \ 56 V(DoubleSub, Sub, MachineType::F64) \ 57 V(PtrSub, Sub, MachineType::ARCH) \ 58 V(Int32Mul, Mul, MachineType::I32) \ 59 V(Int64Mul, Mul, MachineType::I64) \ 60 V(DoubleMul, Mul, MachineType::F64) \ 61 V(PtrMul, Mul, MachineType::ARCH) \ 62 V(Int32Div, Sdiv, MachineType::I32) \ 63 V(Int64Div, Sdiv, MachineType::I64) \ 64 V(DoubleDiv, Fdiv, MachineType::F64) \ 65 V(Int32Mod, Smod, MachineType::I32) \ 66 V(DoubleMod, Smod, MachineType::F64) \ 67 V(BoolAnd, And, MachineType::I1) \ 68 V(Int8And, And, MachineType::I8) \ 69 V(Int32And, And, MachineType::I32) \ 70 V(Int64And, And, MachineType::I64) \ 71 V(BoolOr, Or, MachineType::I1) \ 72 V(Int32Or, Or, MachineType::I32) \ 73 V(Int64Or, Or, MachineType::I64) \ 74 V(Int32Xor, Xor, MachineType::I32) \ 75 V(Int64Xor, Xor, MachineType::I64) \ 76 V(Int16LSL, Lsl, MachineType::I16) \ 77 V(Int32LSL, Lsl, MachineType::I32) \ 78 V(Int64LSL, Lsl, MachineType::I64) \ 79 V(Int8LSR, Lsr, MachineType::I8) \ 80 V(Int32LSR, Lsr, MachineType::I32) \ 81 V(Int64LSR, Lsr, MachineType::I64) \ 82 V(Int32ASR, Asr, MachineType::I32) 83 84 #define UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(V) \ 85 V(BoolNot, Rev, MachineType::I1) \ 86 V(Int32Not, Rev, MachineType::I32) \ 87 V(Int64Not, Rev, MachineType::I64) \ 88 V(CastDoubleToInt64, Bitcast, MachineType::I64) \ 89 V(CastInt64ToFloat64, Bitcast, MachineType::F64) \ 90 V(CastInt32ToFloat32, Bitcast, MachineType::F32) \ 91 V(SExtInt32ToInt64, Sext, MachineType::I64) \ 92 V(SExtInt1ToInt64, Sext, MachineType::I64) \ 93 V(SExtInt1ToInt32, Sext, MachineType::I32) \ 94 V(ZExtInt8ToInt16, Zext, MachineType::I16) \ 95 V(ZExtInt32ToInt64, Zext, MachineType::I64) \ 96 V(ZExtInt1ToInt64, Zext, MachineType::I64) \ 97 V(ZExtInt1ToInt32, Zext, MachineType::I32) \ 98 V(ZExtInt8ToInt32, Zext, MachineType::I32) \ 99 V(ZExtInt8ToInt64, Zext, MachineType::I64) \ 100 V(ZExtInt8ToPtr, Zext, MachineType::ARCH) \ 101 V(ZExtInt16ToPtr, Zext, MachineType::ARCH) \ 102 V(ZExtInt32ToPtr, Zext, MachineType::ARCH) \ 103 V(SExtInt32ToPtr, Sext, MachineType::ARCH) \ 104 V(ZExtInt16ToInt32, Zext, MachineType::I32) \ 105 V(ZExtInt16ToInt64, Zext, MachineType::I64) \ 106 V(TruncInt16ToInt8, Trunc, MachineType::I8) \ 107 V(TruncInt64ToInt32, Trunc, MachineType::I32) \ 108 V(TruncPtrToInt32, Trunc, MachineType::I32) \ 109 V(TruncInt64ToInt1, Trunc, MachineType::I1) \ 110 V(TruncInt64ToInt16, Trunc, MachineType::I16) \ 111 V(TruncInt32ToInt1, Trunc, MachineType::I1) \ 112 V(TruncInt32ToInt8, Trunc, MachineType::I8) \ 113 V(TruncInt32ToInt16, Trunc, MachineType::I16) \ 114 V(TruncFloatToInt64, TruncFloatToInt64, MachineType::I64) \ 115 V(TruncFloatToInt32, TruncFloatToInt32, MachineType::I32) \ 116 V(ExtFloat32ToDouble, Fext, MachineType::F64) \ 117 V(TruncDoubleToFloat32, Ftrunc, MachineType::F32) \ 118 V(ChangeInt32ToFloat64, SignedIntToFloat, MachineType::F64) \ 119 V(ChangeInt32ToFloat32, SignedIntToFloat, MachineType::F32) \ 120 V(ChangeUInt32ToFloat64, UnsignedIntToFloat, MachineType::F64) \ 121 V(ChangeFloat64ToInt32, FloatToSignedInt, MachineType::I32) \ 122 V(SExtInt16ToInt64, Sext, MachineType::I64) \ 123 V(SExtInt16ToInt32, Sext, MachineType::I32) \ 124 V(SExtInt8ToInt32, Sext, MachineType::I32) \ 125 V(SExtInt8ToInt64, Sext, MachineType::I64) 126 127 #define UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH_PRIVATE(V) \ 128 V(ChangeTaggedPointerToInt64, TaggedToInt64, MachineType::I64) 129 130 #define BINARY_CMP_METHOD_LIST_WITHOUT_BITWIDTH(V) \ 131 V(DoubleLessThan, Fcmp, static_cast<BitField>(FCmpCondition::OLT)) \ 132 V(DoubleLessThanOrEqual, Fcmp, static_cast<BitField>(FCmpCondition::OLE)) \ 133 V(DoubleGreaterThan, Fcmp, static_cast<BitField>(FCmpCondition::OGT)) \ 134 V(DoubleGreaterThanOrEqual, Fcmp, static_cast<BitField>(FCmpCondition::OGE)) \ 135 V(DoubleEqual, Fcmp, static_cast<BitField>(FCmpCondition::OEQ)) \ 136 V(DoubleNotEqual, Fcmp, static_cast<BitField>(FCmpCondition::ONE)) \ 137 V(Int32LessThan, Icmp, static_cast<BitField>(ICmpCondition::SLT)) \ 138 V(Int32LessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SLE)) \ 139 V(Int32GreaterThan, Icmp, static_cast<BitField>(ICmpCondition::SGT)) \ 140 V(Int32GreaterThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SGE)) \ 141 V(Int32UnsignedLessThan, Icmp, static_cast<BitField>(ICmpCondition::ULT)) \ 142 V(Int32UnsignedLessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::ULE)) \ 143 V(Int32UnsignedGreaterThan, Icmp, static_cast<BitField>(ICmpCondition::UGT)) \ 144 V(Int32UnsignedGreaterThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::UGE)) \ 145 V(Int64LessThan, Icmp, static_cast<BitField>(ICmpCondition::SLT)) \ 146 V(Int64LessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SLE)) \ 147 V(Int64GreaterThan, Icmp, static_cast<BitField>(ICmpCondition::SGT)) \ 148 V(Int64GreaterThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::SGE)) \ 149 V(Int64UnsignedLessThanOrEqual, Icmp, static_cast<BitField>(ICmpCondition::ULE)) 150 151 class CompilationConfig { 152 public: 153 explicit CompilationConfig(const std::string &triple, const JSRuntimeOptions *options = nullptr) tripleStr_(triple)154 : tripleStr_(triple), triple_(GetTripleFromString(triple)) 155 { 156 if (options != nullptr) { 157 isTraceBc_ = options->IsTraceBC(); 158 profiling_ = options->GetOptCodeProfiler(); 159 stressDeopt_ = options->GetStressDeopt(); 160 verifyVTable_ = options->GetVerifyVTable(); 161 } 162 } 163 ~CompilationConfig() = default; 164 Is32Bit()165 inline bool Is32Bit() const 166 { 167 return triple_ == Triple::TRIPLE_ARM32; 168 } 169 IsAArch64()170 inline bool IsAArch64() const 171 { 172 return triple_ == Triple::TRIPLE_AARCH64; 173 } 174 IsAmd64()175 inline bool IsAmd64() const 176 { 177 return triple_ == Triple::TRIPLE_AMD64; 178 } 179 Is64Bit()180 inline bool Is64Bit() const 181 { 182 return IsAArch64() || IsAmd64(); 183 } 184 GetTriple()185 Triple GetTriple() const 186 { 187 return triple_; 188 } 189 GetTripleStr()190 std::string GetTripleStr() const 191 { 192 return tripleStr_; 193 } 194 IsTraceBC()195 bool IsTraceBC() const 196 { 197 return isTraceBc_; 198 } 199 IsProfiling()200 bool IsProfiling() const 201 { 202 return profiling_; 203 } 204 IsStressDeopt()205 bool IsStressDeopt() const 206 { 207 return stressDeopt_; 208 } 209 IsVerifyVTbale()210 bool IsVerifyVTbale() const 211 { 212 return verifyVTable_; 213 } 214 215 private: GetTripleFromString(const std::string & triple)216 inline Triple GetTripleFromString(const std::string &triple) 217 { 218 if (triple.compare(TARGET_X64) == 0) { 219 return Triple::TRIPLE_AMD64; 220 } 221 222 if (triple.compare(TARGET_AARCH64) == 0) { 223 return Triple::TRIPLE_AARCH64; 224 } 225 226 if (triple.compare(TARGET_ARM32) == 0) { 227 return Triple::TRIPLE_ARM32; 228 } 229 LOG_ECMA(FATAL) << "this branch is unreachable"; 230 UNREACHABLE(); 231 } 232 std::string tripleStr_; 233 Triple triple_; 234 bool isTraceBc_ {false}; 235 bool profiling_ {false}; 236 bool stressDeopt_ {false}; 237 bool verifyVTable_ {false}; 238 }; 239 240 class CircuitBuilder { 241 public: CircuitBuilder(Circuit * circuit)242 explicit CircuitBuilder(Circuit *circuit) : circuit_(circuit), acc_(circuit) {} CircuitBuilder(Circuit * circuit,CompilationConfig * cmpCfg)243 CircuitBuilder(Circuit *circuit, CompilationConfig *cmpCfg) 244 : circuit_(circuit), acc_(circuit), cmpCfg_(cmpCfg) 245 { 246 } 247 ~CircuitBuilder() = default; 248 NO_MOVE_SEMANTIC(CircuitBuilder); 249 NO_COPY_SEMANTIC(CircuitBuilder); 250 static constexpr uint32_t GATE_TWO_VALUESIN = 2; 251 // low level interface 252 GateRef HeapObjectCheck(GateRef gate, GateRef frameState); 253 GateRef StableArrayCheck(GateRef gate, ElementsKind kind, ArrayMetaDataAccessor::Mode mode); 254 GateRef COWArrayCheck(GateRef gate); 255 GateRef HClassStableArrayCheck(GateRef gate, GateRef frameState, ArrayMetaDataAccessor accessor); 256 GateRef ArrayGuardianCheck(GateRef frameState); 257 GateRef TypedArrayCheck(GateType type, GateRef gate); 258 GateRef LoadTypedArrayLength(GateType type, GateRef gate); 259 GateRef RangeGuard(GateRef gate, uint32_t left, uint32_t right); 260 GateRef IndexCheck(GateType type, GateRef gate, GateRef index); 261 GateRef ObjectTypeCheck(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex); 262 GateRef ObjectTypeCompare(GateType type, bool isHeapObject, GateRef gate, GateRef hclassIndex); 263 GateRef TryPrimitiveTypeCheck(GateType type, GateRef gate); 264 GateRef CallTargetCheck(GateRef gate, GateRef function, GateRef id, GateRef param, const char* comment = nullptr); 265 GateRef JSCallTargetFromDefineFuncCheck(GateType type, GateRef func, GateRef gate); 266 template<TypedCallTargetCheckOp Op> 267 GateRef JSCallTargetTypeCheck(GateType type, GateRef func, GateRef methodIndex, GateRef gate); 268 template<TypedCallTargetCheckOp Op> 269 GateRef JSCallThisTargetTypeCheck(GateType type, GateRef func, GateRef gate); 270 template<TypedCallTargetCheckOp Op> 271 inline GateRef JSNoGCCallThisTargetTypeCheck(GateType type, GateRef func, GateRef methodId, GateRef gate); 272 GateRef DeoptCheck(GateRef condition, GateRef frameState, DeoptType type); 273 GateRef TypedCallOperator(GateRef hirGate, MachineType type, const std::initializer_list<GateRef>& args); 274 inline GateRef TypedCallBuiltin(GateRef hirGate, GateRef x, BuiltinsStubCSigns::ID id); 275 inline GateRef TypedCallThis3Builtin(GateRef hirGate, GateRef thisObj, GateRef a0, GateRef a1, GateRef a2, 276 BuiltinsStubCSigns::ID id); 277 GateRef TypeConvert(MachineType type, GateType typeFrom, GateType typeTo, const std::vector<GateRef>& inList); 278 GateRef AddWithOverflow(GateRef left, GateRef right); 279 GateRef SubWithOverflow(GateRef left, GateRef right); 280 GateRef MulWithOverflow(GateRef left, GateRef right); 281 GateRef ExtractValue(MachineType mt, GateRef pointer, GateRef index); 282 GateRef Sqrt(GateRef param); 283 GateRef Int32CheckRightIsZero(GateRef right); 284 GateRef Float64CheckRightIsZero(GateRef right); 285 GateRef ValueCheckNegOverflow(GateRef value); 286 GateRef OverflowCheck(GateRef value); 287 GateRef LexVarIsHoleCheck(GateRef value); 288 GateRef Int32UnsignedUpperBoundCheck(GateRef value, GateRef upperBound); 289 GateRef Int32DivWithCheck(GateRef left, GateRef right); 290 MachineType GetMachineTypeOfValueType(ValueType type); 291 GateType GetGateTypeOfValueType(ValueType type); 292 GateRef IsJsCOWArray(GateRef obj); 293 GateRef IsCOWArray(GateRef objectType); 294 GateRef GetElementsArray(GateRef object); 295 GateRef Convert(GateRef gate, ValueType src, ValueType dst); 296 GateRef ConvertBoolToTaggedBoolean(GateRef gate); 297 GateRef ConvertTaggedBooleanToBool(GateRef gate); 298 GateRef ConvertInt32ToBool(GateRef gate); 299 GateRef ConvertFloat64ToBool(GateRef gate); 300 GateRef ConvertInt32ToTaggedInt(GateRef gate); 301 GateRef ConvertFloat64ToTaggedDouble(GateRef gate); 302 GateRef ConvertFloat64ToInt32(GateRef gate); 303 GateRef ConvertInt32ToFloat64(GateRef gate); 304 GateRef ConvertBoolToInt32(GateRef gate, ConvertSupport support); 305 GateRef ConvertBoolToFloat64(GateRef gate, ConvertSupport support); 306 GateRef ConvertUInt32ToBool(GateRef gate); 307 GateRef ConvertUInt32ToTaggedNumber(GateRef gate); 308 GateRef ConvertUInt32ToFloat64(GateRef gate); 309 GateRef CheckAndConvert( 310 GateRef gate, ValueType src, ValueType dst, ConvertSupport support = ConvertSupport::ENABLE); 311 GateRef ConvertHoleAsUndefined(GateRef receiver); 312 GateRef CheckUInt32AndConvertToInt32(GateRef gate); 313 GateRef CheckTaggedIntAndConvertToInt32(GateRef gate); 314 GateRef CheckTaggedDoubleAndConvertToInt32(GateRef gate); 315 GateRef CheckTaggedNumberAndConvertToInt32(GateRef gate); 316 GateRef CheckTaggedIntAndConvertToFloat64(GateRef gate); 317 GateRef CheckTaggedDoubleAndConvertToFloat64(GateRef gate); 318 GateRef CheckTaggedNumberAndConvertToFloat64(GateRef gate); 319 GateRef CheckTaggedNumberAndConvertToBool(GateRef gate); 320 GateRef CheckTaggedBooleanAndConvertToBool(GateRef gate); 321 GateRef TypedConditionJump(MachineType type, TypedJumpOp jumpOp, GateType typeVal, 322 const std::vector<GateRef>& inList); 323 GateRef TypedNewAllocateThis(GateRef ctor, GateRef hclassIndex, GateRef frameState); 324 GateRef TypedSuperAllocateThis(GateRef superCtor, GateRef newTarget, GateRef frameState); 325 GateRef GetSuperConstructor(GateRef ctor); 326 GateRef Arguments(size_t index); 327 GateRef Merge(const std::vector<GateRef> &inList); 328 GateRef Selector(OpCode opcode, MachineType machineType, GateRef control, const std::vector<GateRef> &values, 329 int valueCounts, VariableType type = VariableType::VOID()); 330 GateRef Selector(OpCode opcode, GateRef control, const std::vector<GateRef> &values, 331 int valueCounts, VariableType type = VariableType::VOID()); 332 GateRef Int8(int8_t val); 333 GateRef Int16(int16_t val); 334 GateRef Int32(int32_t value); 335 GateRef Int64(int64_t value); 336 GateRef IntPtr(int64_t val); 337 GateRef StringPtr(const std::string &str); 338 GateRef Boolean(bool value); 339 GateRef Double(double value); 340 GateRef UndefineConstant(); 341 GateRef HoleConstant(); 342 GateRef NullPtrConstant(); 343 GateRef NullConstant(); 344 GateRef ExceptionConstant(); 345 GateRef RelocatableData(uint64_t val); 346 GateRef Alloca(size_t size); 347 GateRef Branch(GateRef state, GateRef condition); 348 GateRef SwitchBranch(GateRef state, GateRef index, int caseCounts); 349 GateRef Return(GateRef state, GateRef depend, GateRef value); 350 GateRef ReturnVoid(GateRef state, GateRef depend); 351 GateRef Goto(GateRef state); 352 GateRef LoopBegin(GateRef state); 353 GateRef LoopEnd(GateRef state); 354 GateRef IfTrue(GateRef ifBranch); 355 GateRef IfFalse(GateRef ifBranch); 356 GateRef SwitchCase(GateRef switchBranch, int64_t value); 357 GateRef DefaultCase(GateRef switchBranch); 358 GateRef DependRelay(GateRef state, GateRef depend); 359 GateRef ReadSp(); 360 GateRef BinaryArithmetic(const GateMetaData* meta, MachineType machineType, 361 GateRef left, GateRef right, GateType gateType = GateType::Empty()); 362 GateRef BinaryCmp(const GateMetaData* meta, GateRef left, GateRef right); 363 static MachineType GetMachineTypeFromVariableType(VariableType type); 364 GateRef GetCallBuiltinId(GateRef method); GetCircuit()365 Circuit *GetCircuit() const 366 { 367 return circuit_; 368 } 369 // constant 370 inline GateRef True(); 371 inline GateRef False(); 372 inline GateRef Undefined(); 373 inline GateRef Hole(); 374 375 // call operation 376 GateRef CallBCHandler(GateRef glue, GateRef target, const std::vector<GateRef> &args, 377 const char* comment = nullptr); 378 GateRef CallBCDebugger(GateRef glue, GateRef target, const std::vector<GateRef> &args, 379 const char* comment = nullptr); 380 GateRef CallBuiltin(GateRef glue, GateRef target, const std::vector<GateRef> &args, 381 const char* comment = nullptr); 382 GateRef CallBuiltinWithArgv(GateRef glue, GateRef target, const std::vector<GateRef> &args, 383 const char* comment = nullptr); 384 GateRef CallRuntimeVarargs(GateRef glue, int index, GateRef argc, GateRef argv, const char* comment = nullptr); 385 GateRef CallRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args, GateRef hirGate, 386 const char* comment = nullptr); 387 GateRef CallNGCRuntime(GateRef glue, GateRef gate, int index, const std::vector<GateRef> &args, bool useLabel); 388 389 GateRef CallNGCRuntime(GateRef glue, int index, GateRef depend, const std::vector<GateRef> &args, 390 GateRef hirGate, const char* comment = nullptr); 391 GateRef FastCallOptimized(GateRef glue, GateRef code, GateRef depend, const std::vector<GateRef> &args, 392 GateRef hirGate); 393 GateRef CallOptimized(GateRef glue, GateRef code, GateRef depend, const std::vector<GateRef> &args, 394 GateRef hirGate); 395 396 GateRef CallStub(GateRef glue, GateRef hirGate, int index, const std::vector<GateRef> &args, 397 const char* comment = nullptr); 398 GateRef CallBuiltinRuntime(GateRef glue, GateRef depend, const std::vector<GateRef> &args, 399 bool isNew = false, const char* comment = nullptr); 400 GateRef Call(const CallSignature* cs, GateRef glue, GateRef target, GateRef depend, 401 const std::vector<GateRef> &args, GateRef hirGate, const char* comment = nullptr); 402 GateRef NoLabelCallRuntime(GateRef glue, GateRef depend, size_t index, std::vector<GateRef> &args, GateRef hirGate); 403 404 void StartCallTimer(GateRef glue, GateRef gate, const std::vector<GateRef> &args, bool useLabel); 405 void EndCallTimer(GateRef glue, GateRef gate, const std::vector<GateRef> &args, bool useLabel); 406 407 // memory 408 inline GateRef Load(VariableType type, GateRef base, GateRef offset); 409 inline GateRef Load(VariableType type, GateRef base, GateRef offset, GateRef depend); 410 void Store(VariableType type, GateRef glue, GateRef base, GateRef offset, GateRef value); 411 void StoreWithNoBarrier(VariableType type, GateRef base, GateRef offset, GateRef value); 412 413 #define ARITHMETIC_BINARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID) \ 414 inline GateRef NAME(GateRef x, GateRef y, GateType type = GateType::Empty()) \ 415 { \ 416 return BinaryArithmetic(circuit_->OPCODEID(), MACHINETYPEID, x, y, type); \ 417 } 418 419 BINARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(ARITHMETIC_BINARY_OP_WITH_BITWIDTH) 420 #undef ARITHMETIC_BINARY_OP_WITH_BITWIDTH 421 422 #define ARITHMETIC_UNARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID) \ 423 inline GateRef NAME(GateRef x) \ 424 { \ 425 return circuit_->NewGate(circuit_->OPCODEID(), MACHINETYPEID, { x }, GateType::NJSValue()); \ 426 } 427 428 UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH(ARITHMETIC_UNARY_OP_WITH_BITWIDTH) 429 #undef ARITHMETIC_UNARY_OP_WITH_BITWIDTH 430 431 #define CMP_BINARY_OP_WITHOUT_BITWIDTH(NAME, OPCODEID, CONDITION) \ 432 inline GateRef NAME(GateRef x, GateRef y) \ 433 { \ 434 return BinaryCmp(circuit_->OPCODEID(static_cast<uint64_t>(CONDITION)), x, y); \ 435 } 436 437 BINARY_CMP_METHOD_LIST_WITHOUT_BITWIDTH(CMP_BINARY_OP_WITHOUT_BITWIDTH) 438 #undef CMP_BINARY_OP_WITHOUT_BITWIDTH 439 440 inline GateRef Equal(GateRef x, GateRef y); 441 inline GateRef NotEqual(GateRef x, GateRef y); 442 443 // js world 444 // cast operation 445 inline GateRef GetInt64OfTInt(GateRef x); 446 inline GateRef GetInt32OfTInt(GateRef x); 447 inline GateRef TaggedCastToIntPtr(GateRef x); 448 inline GateRef GetDoubleOfTDouble(GateRef x); 449 inline GateRef GetBooleanOfTBoolean(GateRef x); 450 inline GateRef GetDoubleOfTNumber(GateRef x); 451 inline GateRef DoubleToInt(GateRef x, Label *exit); 452 inline GateRef Int32ToTaggedPtr(GateRef x); 453 inline GateRef Int64ToTaggedPtr(GateRef x); 454 inline GateRef Int32ToTaggedInt(GateRef x); 455 // bit operation 456 inline GateRef IsSpecial(GateRef x, JSTaggedType type); 457 inline GateRef TaggedIsInt(GateRef x); 458 inline GateRef TaggedIsDouble(GateRef x); 459 inline GateRef TaggedIsObject(GateRef x); 460 inline GateRef TaggedIsNumber(GateRef x); 461 inline GateRef TaggedIsNumeric(GateRef x); 462 inline GateRef TaggedIsNotHole(GateRef x); 463 inline GateRef TaggedIsHole(GateRef x); 464 inline GateRef TaggedIsNullPtr(GateRef x); 465 inline GateRef TaggedIsUndefined(GateRef x); 466 inline GateRef TaggedIsException(GateRef x); 467 inline GateRef TaggedIsSpecial(GateRef x); 468 inline GateRef TaggedIsHeapObject(GateRef x); 469 inline GateRef TaggedIsAsyncGeneratorObject(GateRef x); 470 inline GateRef TaggedIsJSGlobalObject(GateRef x); 471 inline GateRef TaggedIsGeneratorObject(GateRef x); 472 inline GateRef TaggedIsJSArray(GateRef x); 473 inline GateRef TaggedIsPropertyBox(GateRef x); 474 inline GateRef TaggedIsWeak(GateRef x); 475 inline GateRef TaggedIsPrototypeHandler(GateRef x); 476 inline GateRef TaggedIsTransitionHandler(GateRef x); 477 inline GateRef TaggedIsStoreTSHandler(GateRef x); 478 inline GateRef TaggedIsTransWithProtoHandler(GateRef x); 479 inline GateRef TaggedIsUndefinedOrNull(GateRef x); 480 inline GateRef TaggedIsTrue(GateRef x); 481 inline GateRef TaggedIsFalse(GateRef x); 482 inline GateRef TaggedIsNull(GateRef x); 483 inline GateRef TaggedIsBoolean(GateRef x); 484 inline GateRef IsAOTLiteralInfo(GateRef x); 485 inline GateRef TaggedGetInt(GateRef x); 486 inline GateRef ToTaggedInt(GateRef x); 487 inline GateRef ToTaggedIntPtr(GateRef x); 488 inline GateRef DoubleToTaggedDoublePtr(GateRef x); 489 inline GateRef BooleanToTaggedBooleanPtr(GateRef x); 490 inline GateRef BooleanToInt32(GateRef x); 491 inline GateRef BooleanToFloat64(GateRef x); 492 inline GateRef Float32ToTaggedDoublePtr(GateRef x); 493 inline GateRef TaggedDoublePtrToFloat32(GateRef x); 494 inline GateRef TaggedIntPtrToFloat32(GateRef x); 495 inline GateRef DoubleToTaggedDouble(GateRef x); 496 inline GateRef DoubleToTagged(GateRef x); 497 inline GateRef DoubleIsNAN(GateRef x); 498 inline GateRef TaggedTrue(); 499 inline GateRef TaggedFalse(); 500 // Pointer/Arithmetic/Logic Operations 501 inline GateRef IntPtrDiv(GateRef x, GateRef y); 502 inline GateRef IntPtrOr(GateRef x, GateRef y); 503 inline GateRef IntPtrLSL(GateRef x, GateRef y); 504 inline GateRef IntPtrLSR(GateRef x, GateRef y); 505 inline GateRef Int64NotEqual(GateRef x, GateRef y); 506 inline GateRef Int32NotEqual(GateRef x, GateRef y); 507 inline GateRef Int64Equal(GateRef x, GateRef y); 508 inline GateRef Int8Equal(GateRef x, GateRef y); 509 inline GateRef Int32Equal(GateRef x, GateRef y); 510 inline GateRef IntPtrGreaterThan(GateRef x, GateRef y); 511 template<OpCode Op, MachineType Type> 512 inline GateRef BinaryOp(GateRef x, GateRef y); 513 template<OpCode Op, MachineType Type> 514 inline GateRef BinaryOpWithOverflow(GateRef x, GateRef y); 515 inline GateRef GetLengthFromTaggedArray(GateRef array); 516 inline GateRef GetValueFromTaggedArray(GateRef array, GateRef index); 517 inline void SetValueToTaggedArray(VariableType valType, GateRef glue, GateRef array, GateRef index, GateRef val); 518 GateRef TaggedIsString(GateRef obj); 519 GateRef TaggedIsStringOrSymbol(GateRef obj); 520 inline GateRef GetGlobalConstantString(ConstantIndex index); 521 inline GateRef LoadObjectFromWeakRef(GateRef x); 522 GateRef ComputeTaggedArraySize(GateRef length); 523 524 GateRef IsJSHClass(GateRef obj); 525 GateRef HasPendingException(GateRef glue); 526 // middle ir: operations with any type 527 template<TypedBinOp Op> 528 inline GateRef TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType, GateType gateType, 529 PGOSampleType sampleType); 530 template<TypedUnOp Op> 531 inline GateRef TypedUnaryOp(GateRef x, GateType xType, GateType gateType); 532 template<TypedJumpOp Op> 533 inline GateRef TypedConditionJump(GateRef x, GateType xType); 534 inline GateRef PrimitiveToNumber(GateRef x, VariableType type); 535 536 // middle ir: object operations 537 GateRef ToLength(GateRef receiver); 538 template<TypedLoadOp Op> 539 GateRef LoadElement(GateRef receiver, GateRef index); 540 template<TypedStoreOp Op> 541 GateRef StoreElement(GateRef receiver, GateRef index, GateRef value); 542 GateRef StoreMemory(MemoryType Op, VariableType type, GateRef receiver, GateRef index, GateRef value); 543 GateRef LoadProperty(GateRef receiver, GateRef propertyLookupResult, bool isFunction); 544 GateRef StoreProperty(GateRef receiver, GateRef propertyLookupResult, GateRef value); 545 GateRef LoadArrayLength(GateRef array); 546 GateRef Construct(GateRef hirGate, std::vector<GateRef> args); 547 GateRef TypedCall(GateRef hirGate, std::vector<GateRef> args, bool isNoGC); 548 GateRef TypedFastCall(GateRef hirGate, std::vector<GateRef> args, bool isNoGC); 549 GateRef CallGetter(GateRef hirGate, GateRef receiver, GateRef propertyLookupResult, const char* comment = nullptr); 550 GateRef CallSetter(GateRef hirGate, GateRef receiver, GateRef propertyLookupResult, 551 GateRef value, const char* comment = nullptr); 552 GateRef GetConstPool(GateRef jsFunc); 553 GateRef GetGlobalEnv(); 554 GateRef GetGlobalEnvObjHClass(GateRef env, size_t index); 555 GateRef GetGlobalConstantValue(ConstantIndex index); 556 GateRef LoadConstOffset(VariableType type, GateRef receiver, size_t offset); 557 GateRef StoreConstOffset(VariableType type, GateRef receiver, size_t offset, GateRef value); 558 GateRef LoadObjectFromConstPool(GateRef jsFunc, GateRef index); 559 // Object Operations 560 inline GateRef LoadHClass(GateRef object); 561 inline GateRef IsJSFunction(GateRef obj); 562 inline GateRef IsJSFunctionWithBit(GateRef obj); 563 inline GateRef IsOptimizedAndNotFastCall(GateRef obj); 564 inline GateRef IsOptimized(GateRef obj); 565 inline GateRef IsOptimizedWithBitField(GateRef bitfield); 566 inline GateRef CanFastCall(GateRef obj); 567 inline GateRef CanFastCallWithBitField(GateRef bitfield); 568 inline GateRef IsDictionaryMode(GateRef object); 569 inline void StoreHClass(GateRef glue, GateRef object, GateRef hClass); 570 inline GateRef IsJsType(GateRef object, JSType type); 571 inline GateRef GetObjectType(GateRef hClass); 572 inline GateRef IsDictionaryModeByHClass(GateRef hClass); 573 inline GateRef GetElementsKindByHClass(GateRef hClass); 574 inline GateRef IsIsStableElementsByHClass(GateRef hClass); 575 inline GateRef IsStableElements(GateRef hClass); 576 inline GateRef IsStableArguments(GateRef hClass); 577 inline GateRef IsStableArray(GateRef hClass); 578 inline GateRef DoubleIsINF(GateRef x); 579 inline GateRef IsDictionaryElement(GateRef hClass); 580 inline GateRef IsClassConstructor(GateRef object); 581 inline GateRef IsClassConstructorWithBitField(GateRef bitfield); 582 inline GateRef IsConstructor(GateRef object); 583 inline GateRef IsClassPrototype(GateRef object); 584 inline GateRef IsExtensible(GateRef object); 585 inline GateRef GetExpectedNumOfArgs(GateRef method); 586 inline GateRef TaggedObjectIsEcmaObject(GateRef obj); 587 inline GateRef IsJSObject(GateRef obj); 588 inline GateRef TaggedObjectIsString(GateRef obj); 589 inline GateRef TaggedObjectBothAreString(GateRef x, GateRef y); 590 inline GateRef IsCallable(GateRef obj); 591 inline GateRef IsCallableFromBitField(GateRef bitfield); 592 inline GateRef LogicAnd(GateRef x, GateRef y); 593 inline GateRef LogicOr(GateRef x, GateRef y); 594 inline GateRef BothAreString(GateRef x, GateRef y); 595 inline GateRef GetObjectSizeFromHClass(GateRef hClass); 596 GateRef GetGlobalObject(GateRef glue); 597 GateRef GetMethodFromFunction(GateRef function); 598 GateRef GetModuleFromFunction(GateRef function); 599 GateRef GetHomeObjectFromFunction(GateRef function); 600 GateRef FunctionIsResolved(GateRef function); 601 GateRef GetLengthFromString(GateRef value); 602 GateRef GetHashcodeFromString(GateRef glue, GateRef value); 603 GateRef TryGetHashcodeFromString(GateRef string); 604 GateRef IsUtf16String(GateRef string); 605 GateRef TaggedIsBigInt(GateRef obj); 606 void SetLexicalEnvToFunction(GateRef glue, GateRef function, GateRef value); 607 GateRef GetFunctionLexicalEnv(GateRef function); 608 void SetModuleToFunction(GateRef glue, GateRef function, GateRef value); 609 void SetPropertyInlinedProps(GateRef glue, GateRef obj, GateRef hClass, 610 GateRef value, GateRef attrOffset, VariableType type); 611 void SetHomeObjectToFunction(GateRef glue, GateRef function, GateRef value); 612 GateRef GetConstPoolFromFunction(GateRef jsFunc); 613 GateRef GetCodeAddr(GateRef method); 614 GateRef GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef jsFunc, GateRef index, ConstPoolType type); 615 GateRef GetObjectFromConstPool(GateRef glue, GateRef hirGate, GateRef constPool, GateRef module, GateRef index, 616 ConstPoolType type); 617 void ClearConstantCache(GateRef gate); 618 619 // middle ir: create new obj 620 GateRef StartAllocate(); 621 GateRef FinishAllocate(); 622 GateRef HeapAlloc(GateRef size, GateType type, RegionSpaceFlag flag); 623 GateRef CreateArray(size_t arraySize); 624 GateRef CreateArrayWithBuffer(size_t arraySize, GateRef constPoolIndex, GateRef elementIndex); 625 SetEnvironment(Environment * env)626 void SetEnvironment(Environment *env) 627 { 628 env_ = env; 629 } GetCurrentEnvironment()630 Environment *GetCurrentEnvironment() const 631 { 632 return env_; 633 } SetCompilationConfig(CompilationConfig * cmpCfg)634 void SetCompilationConfig(CompilationConfig *cmpCfg) 635 { 636 cmpCfg_ = cmpCfg; 637 } GetCompilationConfig()638 CompilationConfig *GetCompilationConfig() const 639 { 640 return cmpCfg_; 641 } 642 // label related 643 void NewEnvironment(GateRef hir); 644 void DeleteCurrentEnvironment(); 645 inline int NextVariableId(); 646 inline void HandleException(GateRef result, Label *success, Label *exception, Label *exit); 647 inline void HandleException(GateRef result, Label *success, Label *fail, Label *exit, GateRef exceptionVal); 648 inline void SubCfgEntry(Label *entry); 649 inline void SubCfgExit(); 650 inline GateRef Return(GateRef value); 651 inline GateRef Return(); 652 inline void Bind(Label *label); 653 inline void Bind(Label *label, bool justSlowPath); 654 void Jump(Label *label); 655 void Branch(GateRef condition, Label *trueLabel, Label *falseLabel); 656 void Switch(GateRef index, Label *defaultLabel, int64_t *keysValue, Label *keysLabel, int numberOfKeys); 657 void LoopBegin(Label *loopHead); 658 void LoopEnd(Label *loopHead); 659 inline Label *GetCurrentLabel() const; 660 inline GateRef GetState() const; 661 inline GateRef GetDepend() const; 662 inline StateDepend GetStateDepend() const; 663 664 GateRef GetGlobalEnvValue(VariableType type, GateRef env, size_t index); 665 GateRef IsBase(GateRef ctor); 666 inline GateRef GetMethodId(GateRef func); 667 inline GateRef LoadFromTaggedArray(GateRef array, size_t index); 668 inline GateRef StoreToTaggedArray(GateRef array, size_t index, GateRef value); 669 670 private: 671 inline void SetDepend(GateRef depend); 672 inline void SetState(GateRef state); 673 674 #define ARITHMETIC_UNARY_OP_WITH_BITWIDTH(NAME, OPCODEID, MACHINETYPEID) \ 675 inline GateRef NAME(GateRef x) \ 676 { \ 677 return circuit_->NewGate(circuit_->OPCODEID(), MACHINETYPEID, { x }, GateType::NJSValue()); \ 678 } 679 UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH_PRIVATE(ARITHMETIC_UNARY_OP_WITH_BITWIDTH)680 UNARY_ARITHMETIC_METHOD_LIST_WITH_BITWIDTH_PRIVATE(ARITHMETIC_UNARY_OP_WITH_BITWIDTH) 681 #undef ARITHMETIC_UNARY_OP_WITH_BITWIDTH 682 683 Circuit *circuit_ {nullptr}; 684 GateAccessor acc_; 685 Environment *env_ {nullptr}; 686 CompilationConfig *cmpCfg_ {nullptr}; 687 friend StubBuilder; 688 friend TSHCRLowering; 689 friend NTypeHCRLowering; 690 friend SlowPathLowering; 691 }; 692 693 class Label { 694 public: 695 Label() = default; 696 explicit Label(Environment *env); 697 explicit Label(CircuitBuilder *cirBuilder); 698 ~Label() = default; 699 Label(Label const &label) = default; 700 Label &operator=(Label const &label) = default; 701 Label(Label &&label) = default; 702 Label &operator=(Label &&label) = default; 703 inline void Seal(); WriteVariable(Variable * var,GateRef value)704 inline void WriteVariable(Variable *var, GateRef value) 705 { 706 impl_->WriteVariable(var, value); 707 } ReadVariable(Variable * var)708 inline GateRef ReadVariable(Variable *var) 709 { 710 return impl_->ReadVariable(var); 711 } 712 inline void Bind(); 713 inline void MergeAllControl(); 714 inline void MergeAllDepend(); 715 inline void AppendPredecessor(const Label *predecessor); 716 inline std::vector<Label> GetPredecessors() const; 717 inline void SetControl(GateRef control); 718 inline void SetPreControl(GateRef control); 719 inline void MergeControl(GateRef control); 720 inline GateRef GetControl() const; 721 inline GateRef GetDepend() const; 722 inline void SetDepend(GateRef depend); 723 724 private: 725 class LabelImpl { 726 public: LabelImpl(Environment * env,GateRef control)727 LabelImpl(Environment *env, GateRef control) 728 : env_(env), control_(control), predeControl_(-1), isSealed_(false) 729 { 730 } 731 ~LabelImpl() = default; 732 NO_MOVE_SEMANTIC(LabelImpl); 733 NO_COPY_SEMANTIC(LabelImpl); 734 void Seal(); 735 void WriteVariable(Variable *var, GateRef value); 736 GateRef ReadVariable(Variable *var); 737 void Bind(); 738 void MergeAllControl(); 739 void MergeAllDepend(); 740 void AppendPredecessor(LabelImpl *predecessor); GetPredecessors()741 std::vector<LabelImpl *> GetPredecessors() const 742 { 743 return predecessors_; 744 } SetControl(GateRef control)745 void SetControl(GateRef control) 746 { 747 control_ = control; 748 } SetPreControl(GateRef control)749 void SetPreControl(GateRef control) 750 { 751 predeControl_ = control; 752 } MergeControl(GateRef control)753 void MergeControl(GateRef control) 754 { 755 if (predeControl_ == Circuit::NullGate()) { 756 predeControl_ = control; 757 control_ = predeControl_; 758 } else { 759 otherPredeControls_.push_back(control); 760 } 761 } GetControl()762 GateRef GetControl() const 763 { 764 return control_; 765 } SetDepend(GateRef depend)766 void SetDepend(GateRef depend) 767 { 768 depend_ = depend; 769 } GetDepend()770 GateRef GetDepend() const 771 { 772 return depend_; 773 } 774 775 private: 776 bool IsNeedSeal() const; IsSealed()777 bool IsSealed() const 778 { 779 return isSealed_; 780 } 781 bool IsLoopHead() const; 782 bool IsControlCase() const; 783 GateRef ReadVariableRecursive(Variable *var); 784 Environment *env_; 785 GateRef control_; 786 GateRef predeControl_ {Circuit::NullGate()}; 787 GateRef depend_ {Circuit::NullGate()}; 788 GateRef loopDepend_ {Circuit::NullGate()}; 789 std::vector<GateRef> otherPredeControls_; 790 bool isSealed_ {false}; 791 std::map<Variable *, GateRef> valueMap_; 792 std::vector<GateRef> phi; 793 std::vector<LabelImpl *> predecessors_; 794 std::map<Variable *, GateRef> incompletePhis_; 795 }; 796 Label(LabelImpl * impl)797 explicit Label(LabelImpl *impl) : impl_(impl) {} 798 friend class Environment; GetRawLabel()799 LabelImpl *GetRawLabel() const 800 { 801 return impl_; 802 } 803 LabelImpl *impl_ {nullptr}; 804 }; 805 806 class Environment { 807 public: 808 using LabelImpl = Label::LabelImpl; 809 Environment(GateRef hir, Circuit *circuit, CircuitBuilder *builder); 810 Environment(GateRef stateEntry, GateRef dependEntry, const std::initializer_list<GateRef>& args, 811 Circuit *circuit, CircuitBuilder *builder); 812 Environment(size_t arguments, CircuitBuilder *builder); 813 ~Environment(); GetCurrentLabel()814 Label *GetCurrentLabel() const 815 { 816 return currentLabel_; 817 } SetCurrentLabel(Label * label)818 void SetCurrentLabel(Label *label) 819 { 820 currentLabel_ = label; 821 } GetBuilder()822 CircuitBuilder *GetBuilder() const 823 { 824 return circuitBuilder_; 825 } GetCircuit()826 Circuit *GetCircuit() const 827 { 828 return circuit_; 829 } NextVariableId()830 int NextVariableId() 831 { 832 return nextVariableId_++; 833 } SetCompilationConfig(const CompilationConfig * cfg)834 void SetCompilationConfig(const CompilationConfig *cfg) 835 { 836 ccfg_ = cfg; 837 } GetCompilationConfig()838 const CompilationConfig *GetCompilationConfig() const 839 { 840 return ccfg_; 841 } Is32Bit()842 inline bool Is32Bit() const 843 { 844 return ccfg_->Is32Bit(); 845 } IsAArch64()846 inline bool IsAArch64() const 847 { 848 return ccfg_->IsAArch64(); 849 } IsAmd64()850 inline bool IsAmd64() const 851 { 852 return ccfg_->IsAmd64(); 853 } IsArch64Bit()854 inline bool IsArch64Bit() const 855 { 856 return ccfg_->IsAmd64() || ccfg_->IsAArch64(); 857 } IsAsmInterp()858 inline bool IsAsmInterp() const 859 { 860 return circuit_->GetFrameType() == FrameType::ASM_INTERPRETER_FRAME; 861 } IsArch32Bit()862 inline bool IsArch32Bit() const 863 { 864 return ccfg_->Is32Bit(); 865 } GetArgument(size_t index)866 inline GateRef GetArgument(size_t index) const 867 { 868 return arguments_.at(index); 869 } 870 871 inline Label GetLabelFromSelector(GateRef sel); 872 inline void AddSelectorToLabel(GateRef sel, Label label); 873 inline LabelImpl *NewLabel(Environment *env, GateRef control = -1); 874 inline void SubCfgEntry(Label *entry); 875 inline void SubCfgExit(); 876 inline GateRef GetInput(size_t index) const; 877 878 private: 879 Label *currentLabel_ {nullptr}; 880 Circuit *circuit_ {nullptr}; 881 CircuitBuilder *circuitBuilder_ {nullptr}; 882 std::unordered_map<GateRef, LabelImpl *> phiToLabels_; 883 std::vector<GateRef> inputList_; 884 Label entry_; 885 std::vector<LabelImpl *> rawLabels_; 886 std::stack<Label *> stack_; 887 int nextVariableId_ {0}; 888 std::vector<GateRef> arguments_; 889 const CompilationConfig *ccfg_ {nullptr}; 890 }; 891 892 class Variable { 893 public: Variable(Environment * env,VariableType type,uint32_t id,GateRef value)894 Variable(Environment *env, VariableType type, uint32_t id, GateRef value) : id_(id), type_(type), env_(env) 895 { 896 Bind(value); 897 env_->GetCurrentLabel()->WriteVariable(this, value); 898 } Variable(CircuitBuilder * cirbuilder,VariableType type,uint32_t id,GateRef value)899 Variable(CircuitBuilder *cirbuilder, VariableType type, uint32_t id, GateRef value) 900 : id_(id), type_(type), env_(cirbuilder->GetCurrentEnvironment()) 901 { 902 Bind(value); 903 env_->GetCurrentLabel()->WriteVariable(this, value); 904 } 905 ~Variable() = default; 906 NO_MOVE_SEMANTIC(Variable); 907 NO_COPY_SEMANTIC(Variable); Bind(GateRef value)908 void Bind(GateRef value) 909 { 910 currentValue_ = value; 911 } Value()912 GateRef Value() const 913 { 914 return currentValue_; 915 } Type()916 VariableType Type() const 917 { 918 return type_; 919 } IsBound()920 bool IsBound() const 921 { 922 return currentValue_ != 0; 923 } 924 Variable &operator=(const GateRef value) 925 { 926 env_->GetCurrentLabel()->WriteVariable(this, value); 927 Bind(value); 928 return *this; 929 } 930 GateRef operator*() 931 { 932 return env_->GetCurrentLabel()->ReadVariable(this); 933 } ReadVariable()934 GateRef ReadVariable() 935 { 936 return env_->GetCurrentLabel()->ReadVariable(this); 937 } WriteVariable(GateRef value)938 void WriteVariable(GateRef value) 939 { 940 env_->GetCurrentLabel()->WriteVariable(this, value); 941 Bind(value); 942 } 943 GateRef AddPhiOperand(GateRef val); 944 GateRef AddOperandToSelector(GateRef val, size_t idx, GateRef in); 945 GateRef TryRemoveTrivialPhi(GateRef phi); GetId()946 uint32_t GetId() const 947 { 948 return id_; 949 } 950 951 private: GetCircuit()952 Circuit* GetCircuit() const 953 { 954 return env_->GetCircuit(); 955 } 956 957 uint32_t id_; 958 VariableType type_; 959 GateRef currentValue_ {0}; 960 Environment *env_; 961 }; 962 } // namespace panda::ecmascript::kungfu 963 964 #endif // ECMASCRIPT_COMPILER_CIRCUIT_BUILDER_H 965