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(Chunk * chunk,size_t numVregs)32 explicit FrameStateInfo(Chunk* chunk, size_t numVregs) 33 : values_(numVregs, chunk), liveout_(chunk, numVregs) {} 34 SetValuesAt(size_t index,GateRef gate)35 void SetValuesAt(size_t index, GateRef gate) 36 { 37 ASSERT(index < values_.size()); 38 values_[index] = gate; 39 } 40 SetBit(size_t index)41 void SetBit(size_t index) 42 { 43 liveout_.SetBit(index); 44 } 45 ClearBit(size_t index)46 void ClearBit(size_t index) 47 { 48 liveout_.ClearBit(index); 49 } 50 ValuesAt(size_t index)51 GateRef ValuesAt(size_t index) const 52 { 53 ASSERT(index < values_.size()); 54 return values_[index]; 55 } 56 CopyFrom(FrameStateInfo * other)57 void CopyFrom(FrameStateInfo *other) 58 { 59 values_.assign(other->values_.begin(), other->values_.end()); 60 liveout_.CopyFrom(other->liveout_); 61 } 62 MergeLiveout(FrameStateInfo * other)63 bool MergeLiveout(FrameStateInfo *other) 64 { 65 return liveout_.UnionWithChanged(other->liveout_); 66 } 67 private: 68 // [numVRegs_] [extra args] [numArgs_] [accumulator] 69 ChunkVector<GateRef> values_; 70 BitSet liveout_; 71 }; 72 73 class FrameStateBuilder { 74 public: 75 FrameStateBuilder(BytecodeCircuitBuilder *builder, 76 Circuit *circuit, const MethodLiteral *literal); 77 ~FrameStateBuilder(); 78 79 void BuildFrameState(); 80 private: 81 static constexpr size_t FIXED_ARGS = 2; // ac & env ValuesAt(size_t index)82 GateRef ValuesAt(size_t index) const 83 { 84 return liveOutResult_->ValuesAt(index); 85 } 86 ValuesAtAccumulator()87 GateRef ValuesAtAccumulator() const 88 { 89 return ValuesAt(accumulatorIndex_); 90 } UpdateVirtualRegister(size_t index,GateRef gate)91 void UpdateVirtualRegister(size_t index, GateRef gate) 92 { 93 liveOutResult_->SetValuesAt(index, gate); 94 if (gate == Circuit::NullGate()) { 95 liveOutResult_->ClearBit(index); 96 } else { 97 liveOutResult_->SetBit(index); 98 } 99 } UpdateAccumulator(GateRef gate)100 void UpdateAccumulator(GateRef gate) 101 { 102 UpdateVirtualRegister(accumulatorIndex_, gate); 103 } 104 void BindStateSplit(GateRef state, GateRef depend, GateRef frameState); 105 void BindStateSplit(GateRef gate, GateRef frameState); 106 void BindBBStateSplit(); 107 void UpdateVirtualRegister(size_t id, size_t index, GateRef gate); 108 GateRef BuildFrameStateGate(size_t pcOffset, GateRef frameValues, FrameStateOutput output); 109 GateRef BuildFrameValues(FrameStateInfo *stateInfo); 110 111 FrameStateInfo *CreateEmptyStateInfo(); 112 void BuildPostOrderList(size_t size); 113 bool ComputeLiveOut(size_t bbId); 114 void ComputeLiveState(); 115 void ComputeLiveOutBC(uint32_t index, const BytecodeInfo &bytecodeInfo, size_t bbId); 116 bool IsAsyncResolveOrSusp(const BytecodeInfo &bytecodeInfo); 117 bool MergeIntoPredBC(uint32_t predPc, size_t diff); 118 bool MergeIntoPredBB(BytecodeRegion *bb, BytecodeRegion *predBb); 119 size_t LoopExitCount(BytecodeRegion *bb, BytecodeRegion *bbNext); 120 GateRef TryGetLoopExitValue(GateRef value, size_t diff); GetOrOCreateBCEndStateInfo(uint32_t bcIndex)121 FrameStateInfo *GetOrOCreateBCEndStateInfo(uint32_t bcIndex) 122 { 123 auto currentInfo = bcEndStateInfos_[bcIndex]; 124 if (currentInfo == nullptr) { 125 currentInfo = CreateEmptyStateInfo(); 126 bcEndStateInfos_[bcIndex] = currentInfo; 127 } 128 return currentInfo; 129 } GetEntryBBBeginStateInfo()130 FrameStateInfo *GetEntryBBBeginStateInfo() 131 { 132 auto entry = CreateEmptyStateInfo(); 133 auto first = bbBeginStateInfos_.at(1); // 1: first block 134 for (size_t i = 0; i < numVregs_; ++i) { 135 auto value = first->ValuesAt(i); 136 if (value == Circuit::NullGate()) { 137 continue; 138 } 139 if (gateAcc_.IsValueSelector(value)) { 140 value = gateAcc_.GetValueIn(value); 141 } 142 entry->SetValuesAt(i, value); 143 } 144 return entry; 145 } GetBBBeginStateInfo(size_t bbId)146 FrameStateInfo *GetBBBeginStateInfo(size_t bbId) 147 { 148 if (bbId == 0) { // 0: entry block 149 return GetEntryBBBeginStateInfo(); 150 } 151 return bbBeginStateInfos_.at(bbId); 152 } 153 void UpdateVirtualRegistersOfSuspend(GateRef gate); 154 void UpdateVirtualRegistersOfResume(GateRef gate); 155 void SaveBBBeginStateInfo(size_t bbId); 156 FrameStateInfo *GetFrameInfoBefore(BytecodeRegion &bb, uint32_t bcId); 157 FrameStateInfo *GetFrameInfoAfter(uint32_t bcId); 158 GateRef GetPreBBInput(BytecodeRegion *bb, BytecodeRegion *predBb, GateRef gate); 159 GateRef GetPhiComponent(BytecodeRegion *bb, BytecodeRegion *predBb, GateRef phi); 160 void BuildFrameState(BytecodeRegion& bb, const BytecodeInfo &bytecodeInfo, size_t index); 161 void BuildStateSplitAfter(size_t index, BytecodeRegion& bb); 162 void BuildStateSplitBefore(BytecodeRegion& bb, size_t index); 163 bool ShouldInsertFrameStateBefore(BytecodeRegion& bb, size_t index); 164 void BuildCallFrameState(size_t index, BytecodeRegion& bb); 165 size_t GetNearestNextIndex(size_t index, BytecodeRegion& bb) const; 166 167 BytecodeCircuitBuilder *builder_{nullptr}; 168 FrameStateInfo *liveOutResult_{nullptr}; 169 size_t numVregs_ {0}; 170 size_t accumulatorIndex_ {0}; 171 Circuit *circuit_ {nullptr}; 172 GateAccessor gateAcc_; 173 ChunkVector<FrameStateInfo *> bcEndStateInfos_; 174 ChunkVector<FrameStateInfo *> bbBeginStateInfos_; 175 ChunkVector<size_t> postOrderList_; 176 }; 177 } // panda::ecmascript::kungfu 178 #endif // ECMASCRIPT_COMPILER_FRAME_STATE_H 179