• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/compiler/pgo_type/pgo_type_recorder.h"
25 #include "ecmascript/jspandafile/method_literal.h"
26 
27 namespace panda::ecmascript::kungfu {
28 class BytecodeCircuitBuilder;
29 struct BytecodeRegion;
30 
31 class FrameLiveOut {
32 public:
FrameLiveOut(Chunk * chunk,size_t numVregs)33     explicit FrameLiveOut(Chunk* chunk, size_t numVregs)
34         : liveout_(chunk, numVregs), defRegisters_(chunk, numVregs) {}
35 
SetBit(size_t index)36     void SetBit(size_t index)
37     {
38         liveout_.SetBit(index);
39     }
40 
ClearBit(size_t index)41     void ClearBit(size_t index)
42     {
43         liveout_.ClearBit(index);
44     }
45 
TestBit(size_t index)46     bool TestBit(size_t index) const
47     {
48         return liveout_.TestBit(index);
49     }
50 
CopyFrom(FrameLiveOut * other)51     void CopyFrom(FrameLiveOut *other)
52     {
53         liveout_.CopyFrom(other->liveout_);
54     }
55 
MergeLiveout(FrameLiveOut * other)56     bool MergeLiveout(FrameLiveOut *other)
57     {
58         return liveout_.UnionWithChanged(other->liveout_);
59     }
60 
Reset()61     void Reset()
62     {
63         return liveout_.Reset();
64     }
65 
66 private:
67     // [numVRegs_] [extra args] [numArgs_] [accumulator]
68     BitSet liveout_;
69     BitSet defRegisters_;
70     friend class BlockLoopAnalysis;
71     friend class FrameStateBuilder;
72 };
73 
74 class FrameContext {
75 public:
FrameContext(Chunk * chunk,size_t numVregs)76     explicit FrameContext(Chunk* chunk, size_t numVregs)
77         : values_(numVregs, chunk) {}
78 
ValuesAt(size_t index)79     GateRef ValuesAt(size_t index) const
80     {
81         ASSERT(index < values_.size());
82         return values_[index];
83     }
84 
SetValuesAt(size_t index,GateRef gate)85     void SetValuesAt(size_t index, GateRef gate)
86     {
87         ASSERT(index < values_.size());
88         values_[index] = gate;
89     }
90 
CopyCurrentStatus(FrameContext * other)91     void CopyCurrentStatus(FrameContext *other)
92     {
93         currentState_ = other->currentState_;
94         currentDepend_ = other->currentDepend_;
95         needStateSplit_ = other->needStateSplit_;
96     }
97 private:
98     // [numVRegs_] [extra args] [numArgs_] [accumulator]
99     ChunkVector<GateRef> values_;
100     GateRef currentState_ {Circuit::NullGate()};
101     GateRef currentDepend_ {Circuit::NullGate()};
102     size_t currentIndex_ {0};
103     bool needStateSplit_ {false};
104     friend class FrameStateBuilder;
105     friend class BlockLoopAnalysis;
106 };
107 
108 class FrameStateBuilder {
109 public:
110     FrameStateBuilder(BytecodeCircuitBuilder *builder,
111         Circuit *circuit, const MethodLiteral *literal);
112     ~FrameStateBuilder();
113 
114     void DoBytecodeAnalysis();
115     void AdvanceToNextBc(const BytecodeInfo &bytecodeInfo, FrameLiveOut* liveout, uint32_t bcId);
116     void UpdateFrameValues(const BytecodeInfo &bytecodeInfo, uint32_t bcId,
117         GateRef gate);
118     void UpdateMoveValues(const BytecodeInfo &bytecodeInfo, uint32_t bcId);
119     void UpdateStateDepend(GateRef state, GateRef depend);
120     FrameLiveOut *GetOrOCreateBCEndLiveOut(uint32_t bcIndex);
121     FrameLiveOut *GetOrOCreateBBLiveOut(size_t bbIndex);
GetCurrentState()122     GateRef GetCurrentState() const
123     {
124         return liveContext_->currentState_;
125     }
126 
GetCurrentDepend()127     GateRef GetCurrentDepend() const
128     {
129         return liveContext_->currentDepend_;
130     }
131     void MergeIntoSuccessor(const BytecodeRegion &bb, const BytecodeRegion &bbNext);
132     void AdvanceToNextBB(const BytecodeRegion &bb);
133     void InitEntryBB(const BytecodeRegion &bb);
134 
GetRpoList()135     const ChunkDeque<size_t>& GetRpoList() const
136     {
137         return rpoList_;
138     }
139 
HasLoop()140     bool HasLoop() const
141     {
142         return numLoops_ > 0;
143     }
UpdateAccumulator(GateRef gate)144     void UpdateAccumulator(GateRef gate)
145     {
146         UpdateVirtualRegister(accumulatorIndex_, gate);
147     }
148 
149 private:
150     static constexpr size_t FIXED_ARGS = 2; // ac & env
151     struct LoopInfo {
152         size_t loopIndex {0};
153         size_t loopHeadId {0};
154         size_t numLoopBacks {0};
155         size_t sortIndx {0};
156         LoopInfo* parentInfo {nullptr};
157         BitSet* loopBodys {nullptr};
158         ChunkVector<BytecodeRegion*>* loopExits {nullptr};
159         BitSet* loopAssignment {nullptr};
160         FrameContext* mergedContext {nullptr};
161     };
162 
163     void BuildPostOrderList(size_t size);
164     bool ComputeLiveOut(size_t bbId);
165     void ComputeLiveState();
166     void ComputeLiveOutBC(const BytecodeInfo &bytecodeInfo);
167     bool MergeIntoPredBC(uint32_t predPc);
168     bool MergeFromSuccBB(size_t bbId);
169     void MergeFromCatchBB(size_t bbId);
170 
GetFrameLiveoutAfter(uint32_t bcId)171     FrameLiveOut *GetFrameLiveoutAfter(uint32_t bcId)
172     {
173         return bcEndStateLiveouts_[bcId];
174     }
175 
GetFrameLiveoutBefore(size_t bbId)176     FrameLiveOut *GetFrameLiveoutBefore(size_t bbId)
177     {
178         return bbBeginStateLiveouts_[bbId];
179     }
180 
ValuesAt(size_t index)181     GateRef ValuesAt(size_t index) const
182     {
183         return liveContext_->ValuesAt(index);
184     }
185 
ValuesAtAccumulator()186     GateRef ValuesAtAccumulator() const
187     {
188         return ValuesAt(accumulatorIndex_);
189     }
190 
UpdateVirtualRegister(size_t index,GateRef gate)191     void UpdateVirtualRegister(size_t index, GateRef gate)
192     {
193         liveContext_->SetValuesAt(index, gate);
194     }
195 
GetBcFrameStateCache()196     GateRef GetBcFrameStateCache()
197     {
198         ASSERT(frameStateCache_ != Circuit::NullGate());
199         auto cache = frameStateCache_;
200         frameStateCache_ = Circuit::NullGate();
201         return cache;
202     }
203 
GetMergedBbContext(uint32_t bbIndex)204     FrameContext *GetMergedBbContext(uint32_t bbIndex) const
205     {
206         ASSERT(bbIndex < bbFrameContext_.size());
207         return bbFrameContext_[bbIndex];
208     }
209 
210     FrameContext *GetOrOCreateMergedContext(uint32_t bbIndex);
211     void FillBcInputs(const BytecodeInfo &bytecodeInfo, uint32_t bcIndex, GateRef gate);
212     void DumpLiveState();
213     GateRef MergeValue(const BytecodeRegion &bb,
214         GateRef stateMerge, GateRef currentValue, GateRef nextValue, size_t index);
215     void NewMerge(const BytecodeRegion &bbNext);
216     void MergeStateDepend(const BytecodeRegion &bb, const BytecodeRegion &bbNext);
217     void CopyLiveoutValues(const BytecodeRegion &bbNext, FrameContext* dest, FrameContext* src);
218     void SaveCurrentContext(const BytecodeRegion &bb);
219 
220     void NewLoopExit(const BytecodeRegion &bbNext, BitSet *loopAssignment);
221     size_t ComputeLoopDepth(size_t loopHead);
222     void TryInsertLoopExit(const BytecodeRegion &bb, const BytecodeRegion &bbNext);
223     void ComputeLoopInfo();
224     void ResizeLoopBody();
225     void MergeAssignment(const BytecodeRegion &bbNext);
226     BitSet *GetLoopAssignment(const BytecodeRegion &bb);
227     LoopInfo& GetLoopInfo(const BytecodeRegion &bb);
228     LoopInfo& GetLoopInfo(BytecodeRegion &bb);
229     LoopInfo* GetLoopInfoByLoopBody(const BytecodeRegion &bb);
230     bool IsLoopBackEdge(const BytecodeRegion &bb, const BytecodeRegion &bbNext);
231 
232     GateRef BuildFrameContext(FrameContext* frameContext);
233     void BindStateSplitBefore(const BytecodeInfo &bytecodeInfo, FrameLiveOut* liveout, uint32_t bcId);
234     void BindStateSplitAfter(const BytecodeInfo &bytecodeInfo, uint32_t bcId, GateRef gate);
235     GateRef BuildFrameValues(FrameContext* frameContext, FrameLiveOut* liveout);
236     GateRef BuildStateSplit(FrameContext* frameContext, FrameLiveOut* liveout, size_t bcIndex);
237     GateRef BuildFrameState(FrameContext* frameContext, FrameLiveOut* liveout, size_t bcIndex);
238     void AddEmptyBlock(BytecodeRegion* bb);
239     FrameContext *GetCachedContext();
240 
241     BytecodeCircuitBuilder *bcBuilder_ {nullptr};
242     TSManager *tsManager_ {nullptr};
243     const TypeRecorder *typeRecorder_ {nullptr};
244     const PGOTypeRecorder *pgoTypeRecorder_ {nullptr};
245     FrameLiveOut *liveOutResult_ {nullptr};
246     FrameLiveOut *currentBBliveOut_ {nullptr};
247     FrameContext *liveContext_ {nullptr};
248     FrameContext *cachedContext_ {nullptr};
249     FrameContext *cachedContextBackup_ {nullptr};
250     size_t numVregs_ {0};
251     size_t accumulatorIndex_ {0};
252     size_t envIndex_ {0};
253     size_t numLoops_ {0};
254     size_t sortIndx_ {0};
255     GateRef frameStateCache_ {Circuit::NullGate()};
256     Circuit *circuit_ {nullptr};
257     GateAccessor acc_;
258     ChunkVector<FrameLiveOut *> bcEndStateLiveouts_;
259     ChunkVector<FrameLiveOut *> bbBeginStateLiveouts_;
260     ChunkVector<FrameContext *> bbFrameContext_;
261     ChunkVector<LoopInfo> loops_;
262     ChunkDeque<size_t> rpoList_;
263     ChunkVector<size_t> postOrderList_;
264 
265     friend class BlockLoopAnalysis;
266     friend class SubContextScope;
267 };
268 }  // panda::ecmascript::kungfu
269 #endif  // ECMASCRIPT_COMPILER_FRAME_STATE_H
270