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_FRAME_STATE_H 17 #define ECMASCRIPT_COMPILER_FRAME_STATE_H 18 19 #include "ecmascript/compiler/argument_accessor.h" 20 #include "ecmascript/compiler/base/bit_set.h" 21 #include "ecmascript/compiler/circuit.h" 22 #include "ecmascript/compiler/gate.h" 23 #include "ecmascript/compiler/gate_accessor.h" 24 #include "ecmascript/jspandafile/method_literal.h" 25 26 namespace panda::ecmascript::kungfu { 27 class BytecodeCircuitBuilder; 28 struct BytecodeRegion; 29 30 class FrameStateInfo { 31 public: FrameStateInfo(size_t numVregs)32 explicit FrameStateInfo(size_t numVregs) : values_(numVregs), liveout_(numVregs) {} 33 SetValuesAt(size_t index,GateRef gate)34 void SetValuesAt(size_t index, GateRef gate) 35 { 36 ASSERT(index < values_.size()); 37 values_[index] = gate; 38 } 39 SetBit(size_t index)40 void SetBit(size_t index) 41 { 42 liveout_.SetBit(index); 43 } 44 ClearBit(size_t index)45 void ClearBit(size_t index) 46 { 47 liveout_.ClearBit(index); 48 } 49 ValuesAt(size_t index)50 GateRef ValuesAt(size_t index) const 51 { 52 ASSERT(index < values_.size()); 53 return values_[index]; 54 } 55 CopyFrom(FrameStateInfo * other)56 void CopyFrom(FrameStateInfo *other) 57 { 58 values_.assign(other->values_.begin(), other->values_.end()); 59 liveout_.CopyFrom(other->liveout_); 60 } 61 MergeLiveout(FrameStateInfo * other)62 bool MergeLiveout(FrameStateInfo *other) 63 { 64 return liveout_.UnionWithChanged(other->liveout_); 65 } 66 private: 67 // [numVRegs_] [extra args] [numArgs_] [accumulator] 68 std::vector<GateRef> values_ {}; 69 BitSet liveout_; 70 }; 71 72 class FrameStateBuilder { 73 public: 74 FrameStateBuilder(BytecodeCircuitBuilder *builder, 75 Circuit *circuit, const MethodLiteral *literal); 76 ~FrameStateBuilder(); 77 78 void BuildFrameState(); 79 private: ValuesAt(size_t index)80 GateRef ValuesAt(size_t index) const 81 { 82 return liveOutResult_->ValuesAt(index); 83 } 84 ValuesAtAccumulator()85 GateRef ValuesAtAccumulator() const 86 { 87 return ValuesAt(accumulatorIndex_); 88 } UpdateVirtualRegister(size_t index,GateRef gate)89 void UpdateVirtualRegister(size_t index, GateRef gate) 90 { 91 liveOutResult_->SetValuesAt(index, gate); 92 if (gate == Circuit::NullGate()) { 93 liveOutResult_->ClearBit(index); 94 } else { 95 liveOutResult_->SetBit(index); 96 } 97 } UpdateAccumulator(GateRef gate)98 void UpdateAccumulator(GateRef gate) 99 { 100 UpdateVirtualRegister(accumulatorIndex_, gate); 101 } 102 void BindStateSplit(GateRef gate, size_t pcOffset, FrameStateInfo *stateInfo); 103 void BindStateSplit(size_t size); 104 void UpdateVirtualRegister(size_t id, size_t index, GateRef gate); 105 GateRef FrameState(size_t pcOffset, FrameStateInfo *stateInfo); 106 107 FrameStateInfo *CreateEmptyStateInfo(); 108 void BuildPostOrderList(size_t size); 109 bool ComputeLiveOut(size_t bbId); 110 void ComputeLiveState(); 111 void ComputeLiveOutBC(uint32_t index, const BytecodeInfo &bytecodeInfo); 112 bool MergeIntoPredBC(uint32_t predPc); 113 bool MergeIntoPredBB(BytecodeRegion *bb, BytecodeRegion *predBb); GetOrOCreateBCEndStateInfo(uint32_t bcIndex)114 FrameStateInfo *GetOrOCreateBCEndStateInfo(uint32_t bcIndex) 115 { 116 auto currentInfo = bcEndStateInfos_[bcIndex]; 117 if (currentInfo == nullptr) { 118 currentInfo = CreateEmptyStateInfo(); 119 bcEndStateInfos_[bcIndex] = currentInfo; 120 } 121 return currentInfo; 122 } GetBBBeginStateInfo(size_t bbId)123 FrameStateInfo *GetBBBeginStateInfo(size_t bbId) const 124 { 125 return bbBeginStateInfos_.at(bbId); 126 } 127 void UpdateVirtualRegistersOfSuspend(GateRef gate); 128 void UpdateVirtualRegistersOfResume(GateRef gate); 129 void SaveBBBeginStateInfo(size_t bbId); 130 FrameStateInfo *GetCurrentFrameInfo(BytecodeRegion &bb, uint32_t bcId); 131 GateRef GetPhiComponent(BytecodeRegion *bb, BytecodeRegion *predBb, GateRef phi); 132 133 BytecodeCircuitBuilder *builder_{nullptr}; 134 FrameStateInfo *liveOutResult_{nullptr}; 135 size_t numVregs_ {0}; 136 size_t accumulatorIndex_ {0}; 137 Circuit *circuit_ {nullptr}; 138 GateAccessor gateAcc_; 139 ArgumentAccessor argAcc_; 140 std::vector<FrameStateInfo *> bcEndStateInfos_; 141 std::vector<FrameStateInfo *> bbBeginStateInfos_; 142 std::vector<size_t> postOrderList_; 143 }; 144 } // panda::ecmascript::kungfu 145 #endif // ECMASCRIPT_COMPILER_FRAME_STATE_H