• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #include "ecmascript/compiler/state_split_linearizer.h"
17 #include "ecmascript/compiler/scheduler.h"
18 
19 namespace panda::ecmascript::kungfu {
Run()20 void StateSplitLinearizer::Run()
21 {
22     graphLinearizer_.SetScheduleJSOpcode();
23     graphLinearizer_.LinearizeGraph();
24     LinearizeStateSplit();
25     if (IsLogEnabled()) {
26         LOG_COMPILER(INFO) << "";
27         LOG_COMPILER(INFO) << "\033[34m"
28                            << "===================="
29                            << " After state split linearizer "
30                            << "[" << GetMethodName() << "]"
31                            << "===================="
32                            << "\033[0m";
33         circuit_->PrintAllGatesWithBytecode();
34         LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
35     }
36 #ifndef NDEBUG
37     graphLinearizer_.Reset();
38     graphLinearizer_.EnableScheduleUpperBound();
39     graphLinearizer_.SetScheduleJSOpcode();
40     graphLinearizer_.LinearizeGraph();
41     if (IsLogEnabled()) {
42         LOG_COMPILER(INFO) << "";
43         LOG_COMPILER(INFO) << "\033[34m"
44                            << "===================="
45                            << " verify split linearizer "
46                            << "[" << GetMethodName() << "]"
47                            << "===================="
48                            << "\033[0m";
49         graphLinearizer_.PrintGraph("Build Basic Block");
50         LOG_COMPILER(INFO) << "\033[34m" << "========================= End ==========================" << "\033[0m";
51     }
52 #endif
53 }
54 
55 struct RegionEdge {
56     GateRef stateOut {Circuit::NullGate()};
57     GateRef dependOut {Circuit::NullGate()};
58     GateRef frameStateOut {Circuit::NullGate()};
59 };
60 
61 struct PendingGateRegionEdge {
PendingGateRegionEdgepanda::ecmascript::kungfu::PendingGateRegionEdge62     explicit PendingGateRegionEdge(GateRegion* from, GateRegion* to,
63         GateRef dependStart, size_t index) : from(from), to(to),
64         dependStart(dependStart), index(index) {}
65 
66     GateRegion* from;
67     GateRegion* to;
68     GateRef dependStart;
69     size_t index;
70 };
71 
72 class RegionStateDependMap {
73 public:
RegionStateDependMap(Chunk * chunk)74     explicit RegionStateDependMap(Chunk* chunk) : regionMap_(chunk) {}
GetEdge(GateRegion * from,GateRegion * to)75     RegionEdge& GetEdge(GateRegion* from, GateRegion* to)
76     {
77         return regionMap_[std::make_pair(from->GetId(), to->GetId())];
78     }
79 private:
80     ChunkMap<std::pair<size_t, size_t>, RegionEdge> regionMap_;
81 };
82 
83 class StateDependBuilder {
84 public:
StateDependBuilder(StateSplitLinearizer * linearizer,Chunk * chunk)85     explicit StateDependBuilder(StateSplitLinearizer* linearizer, Chunk* chunk)
86         : linearizer_(linearizer), pendingList_(chunk),
87         acc_(linearizer->circuit_), map_(chunk), pendingEdges_(chunk) {}
88 
Run(ChunkVector<GateRegion * > & regionList)89     void Run(ChunkVector<GateRegion*>& regionList)
90     {
91         replacement_.SetDepend(acc_.GetDependRoot());
92         dependStart_ = replacement_.Depend();
93         auto entry = regionList.front();
94         linearizer_->circuit_->AdvanceTime();
95         entry->SetVisited(acc_);
96         ASSERT(pendingList_.empty());
97         pendingList_.emplace_back(entry);
98         while (!pendingList_.empty()) {
99             auto curRegion = pendingList_.back();
100             pendingList_.pop_back();
101             VisitRegion(curRegion);
102             for (auto succ : curRegion->succs_) {
103                 if (!succ->IsVisited(acc_)) {
104                     succ->SetVisited(acc_);
105                     pendingList_.emplace_back(succ);
106                 }
107             }
108         }
109         ConnectPendingRegionEdges();
110     }
111 
VisitFixedGate(GateRef curGate)112     void VisitFixedGate(GateRef curGate)
113     {
114         auto op = acc_.GetOpCode(curGate);
115         if (op == OpCode::DEPEND_SELECTOR || op == OpCode::DEPEND_RELAY) {
116             replacement_.SetDepend(curGate);
117             dependStart_ = curGate;
118         } else {
119             VisitGate(curGate);
120         }
121     }
122 
VisitRegion(GateRegion * curRegion)123     void VisitRegion(GateRegion* curRegion)
124     {
125         replacement_.SetState(curRegion->GetState());
126         currentIndex_ = static_cast<int32_t>(curRegion->gateList_.size() - 1); // 1: -1 for size
127         TryLoadDependStart(curRegion);
128         // 0: is state
129         for (; currentIndex_ > 0; currentIndex_--) {
130             auto curGate = curRegion->gateList_[currentIndex_];
131             VisitFixedGate(curGate);
132             if (dependStart_ != Circuit::NullGate()) {
133                 currentIndex_--;
134                 break;
135             }
136         }
137         ConnectStateDepend(curRegion);
138         for (; currentIndex_ > 0; currentIndex_--) {
139             auto curGate = curRegion->gateList_[currentIndex_];
140             VisitGate(curGate);
141         }
142         StoreStateDepend(curRegion);
143     }
144 
ProcessStateDepend(GateRef currentGate)145     void ProcessStateDepend(GateRef currentGate)
146     {
147         auto currentState = replacement_.State();
148         auto currentDepend = replacement_.Depend();
149         if (acc_.GetStateCount(currentGate) > 0) {
150             ASSERT(acc_.GetStateCount(currentGate) == 1);
151             auto stateInput = acc_.GetState(currentGate);
152             if (currentState != stateInput) {
153                 acc_.ReplaceStateIn(currentGate, currentState);
154             }
155             if (!acc_.IsVirtualState(currentGate) && !acc_.IsFixed(currentGate)) {
156                 replacement_.SetState(currentGate);
157             }
158         }
159         if (acc_.GetDependCount(currentGate) > 0) {
160             ASSERT(acc_.GetDependCount(currentGate) == 1);
161             auto dependInput = acc_.GetDep(currentGate);
162             if (currentDepend != dependInput) {
163                 acc_.ReplaceDependIn(currentGate, currentDepend);
164             }
165             replacement_.SetDepend(currentGate);
166         }
167     }
168 
VisitGate(GateRef gate)169     void VisitGate(GateRef gate)
170     {
171         auto& lowering = linearizer_->lcrLowering_;
172         auto op = acc_.GetOpCode(gate);
173         switch (op) {
174             case OpCode::FRAME_STATE:
175                 frameState_ = gate;
176                 break;
177             case OpCode::STATE_SPLIT:
178                 return;
179             case OpCode::CONVERT:
180                 ASSERT(replacement_.State() != Circuit::NullGate());
181                 replacement_ = lowering.LowerConvert(replacement_, gate);
182                 break;
183             default:
184                 break;
185         }
186         ProcessStateDepend(gate);
187     }
188 
TryLoadDependStart(GateRegion * curRegion)189     void TryLoadDependStart(GateRegion* curRegion)
190     {
191         auto currentState = curRegion->GetState();
192         if (dependStart_ == Circuit::NullGate()) {
193             if (acc_.GetOpCode(currentState) == OpCode::IF_EXCEPTION) {
194                 dependStart_ = currentState;
195                 replacement_.SetDepend(dependStart_);
196             } else if (curRegion->preds_.size() == 1) {
197                 auto &edge = map_.GetEdge(curRegion->preds_[0], curRegion);
198                 ASSERT(edge.dependOut != Circuit::NullGate());
199                 replacement_.SetDepend(edge.dependOut);
200                 frameState_ = edge.frameStateOut;
201             }
202         }
203     }
204 
ConnectStateDepend(GateRegion * curRegion)205     void ConnectStateDepend(GateRegion* curRegion)
206     {
207         auto currentState = curRegion->GetState();
208         ASSERT(dependStart_ == Circuit::NullGate() ||
209                curRegion->preds_.size() == acc_.GetDependCount(dependStart_));
210         ASSERT(curRegion->preds_.size() == acc_.GetStateCount(currentState));
211         for (size_t i = 0; i < curRegion->preds_.size(); i++) {
212             auto pred = curRegion->preds_[i];
213             auto &edge = map_.GetEdge(pred, curRegion);
214             auto stateInput = acc_.GetState(currentState, i);
215             if (edge.stateOut == Circuit::NullGate()) {
216                 ASSERT(edge.dependOut == Circuit::NullGate());
217                 pendingEdges_.emplace_back(PendingGateRegionEdge(pred, curRegion, dependStart_, i));
218             } else {
219                 ConnectEdge(edge, currentState, stateInput, i);
220             }
221         }
222     }
223 
ConnectEdge(RegionEdge & edge,GateRef currentState,GateRef stateInput,size_t i)224     void ConnectEdge(RegionEdge& edge, GateRef currentState, GateRef stateInput, size_t i)
225     {
226         if (edge.stateOut != stateInput) {
227             acc_.ReplaceStateIn(currentState, edge.stateOut, i);
228         }
229         if (frameState_ == Circuit::NullGate()) {
230             frameState_ = edge.frameStateOut;
231         }
232         if (dependStart_ != Circuit::NullGate()) {
233             auto dependInput = acc_.GetDep(dependStart_, i);
234             if (edge.dependOut != dependInput) {
235                 acc_.ReplaceDependIn(dependStart_, edge.dependOut, i);
236             }
237         }
238     }
239 
ConnectPendingRegionEdges()240     void ConnectPendingRegionEdges()
241     {
242         for (auto regionEdge : pendingEdges_) {
243             auto currentState = regionEdge.to->GetState();
244             auto stateInput = acc_.GetState(currentState, regionEdge.index);
245             auto &edge = map_.GetEdge(regionEdge.from, regionEdge.to);
246             if (edge.stateOut != stateInput) {
247                 acc_.ReplaceStateIn(currentState, edge.stateOut, regionEdge.index);
248             }
249             auto dependInput = acc_.GetDep(regionEdge.dependStart, regionEdge.index);
250             if (edge.dependOut != dependInput) {
251                 acc_.ReplaceDependIn(regionEdge.dependStart, edge.dependOut, regionEdge.index);
252             }
253         }
254     }
255 
StoreStateDepend(GateRegion * curRegion)256     void StoreStateDepend(GateRegion* curRegion)
257     {
258         for (auto succ : curRegion->succs_) {
259             auto &edge = map_.GetEdge(curRegion, succ);
260             if (edge.stateOut == Circuit::NullGate()) {
261                 edge.stateOut = replacement_.State();
262             }
263             if (edge.dependOut == Circuit::NullGate()) {
264                 edge.dependOut = replacement_.Depend();
265             }
266             if (edge.frameStateOut == Circuit::NullGate()) {
267                 edge.frameStateOut = frameState_;
268             }
269         }
270         replacement_.Reset();
271         frameState_ = Circuit::NullGate();
272         dependStart_ = Circuit::NullGate();
273         currentIndex_ = -1;
274     }
275 
276 private:
277     GateRef dependStart_ {Circuit::NullGate()};
278     GateRef frameState_ {Circuit::NullGate()};
279     StateDepend replacement_;
280     int32_t currentIndex_ {-1};
281     StateSplitLinearizer* linearizer_ {nullptr};
282     ChunkDeque<GateRegion*> pendingList_;
283     GateAccessor acc_;
284     RegionStateDependMap map_;
285     ChunkVector<PendingGateRegionEdge> pendingEdges_;
286 };
287 
LinearizeStateSplit()288 void StateSplitLinearizer::LinearizeStateSplit()
289 {
290     StateDependBuilder builder(this, graphLinearizer_.chunk_);
291     builder.Run(graphLinearizer_.regionList_);
292 }
293 
294 }  // namespace panda::ecmascript::kungfu
295