• 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 #include "ecmascript/compiler/bytecode_circuit_builder.h"
16 #include "ecmascript/compiler/frame_states.h"
17 #include <cstddef>
18 
19 namespace panda::ecmascript::kungfu {
FrameStateBuilder(BytecodeCircuitBuilder * builder,Circuit * circuit,const MethodLiteral * literal)20 FrameStateBuilder::FrameStateBuilder(BytecodeCircuitBuilder *builder,
21     Circuit *circuit, const MethodLiteral *literal)
22     : builder_(builder),
23       numVregs_(literal->GetNumberVRegs() + FIXED_ARGS),
24       accumulatorIndex_(literal->GetNumberVRegs() + 1), // 1: acc
25       circuit_(circuit),
26       gateAcc_(circuit),
27       bcEndStateInfos_(circuit->chunk()),
28       bbBeginStateInfos_(circuit->chunk()),
29       postOrderList_(circuit->chunk())
30 {
31 }
32 
~FrameStateBuilder()33 FrameStateBuilder::~FrameStateBuilder()
34 {
35     liveOutResult_ = nullptr;
36     bcEndStateInfos_.clear();
37     bbBeginStateInfos_.clear();
38     builder_ = nullptr;
39 }
40 
BuildFrameValues(FrameStateInfo * stateInfo)41 GateRef FrameStateBuilder::BuildFrameValues(FrameStateInfo *stateInfo)
42 {
43     size_t frameStateInputs = numVregs_;
44     std::vector<GateRef> inList(frameStateInputs, Circuit::NullGate());
45     auto optimizedGate = circuit_->GetConstantGate(MachineType::I64,
46                                                    JSTaggedValue::VALUE_OPTIMIZED_OUT,
47                                                    GateType::TaggedValue());
48     for (size_t i = 0; i < numVregs_; i++) {
49         auto value = stateInfo->ValuesAt(i);
50         if (value == Circuit::NullGate()) {
51             value = optimizedGate;
52         }
53         inList[i] = value;
54     }
55     return circuit_->NewGate(circuit_->FrameValues(frameStateInputs), inList);
56 }
57 
BuildFrameStateGate(size_t pcOffset,GateRef frameValues,FrameStateOutput output)58 GateRef FrameStateBuilder::BuildFrameStateGate(size_t pcOffset, GateRef frameValues, FrameStateOutput output)
59 {
60     GateRef frameArgs = builder_->GetFrameArgs();
61     GateRef preFrameState = builder_->GetPreFrameState();
62     UInt32PairAccessor accessor(static_cast<uint32_t>(pcOffset), output.GetValue());
63     return circuit_->NewGate(circuit_->FrameState(accessor.ToValue()),
64         {frameArgs, frameValues, preFrameState});
65 }
66 
BindStateSplit(GateRef state,GateRef depend,GateRef frameState)67 void FrameStateBuilder::BindStateSplit(GateRef state, GateRef depend, GateRef frameState)
68 {
69     GateRef stateSplit = circuit_->NewGate(circuit_->StateSplit(), {state, depend, frameState});
70     auto uses = gateAcc_.Uses(depend);
71     for (auto useIt = uses.begin(); useIt != uses.end();) {
72         if (gateAcc_.IsDependIn(useIt) && *useIt != stateSplit) {
73             useIt = gateAcc_.ReplaceIn(useIt, stateSplit);
74         } else {
75             useIt++;
76         }
77     }
78     if (builder_->IsLogEnabled()) {
79         gateAcc_.ShortPrint(frameState);
80     }
81 }
82 
BindStateSplit(GateRef gate,GateRef frameState)83 void FrameStateBuilder::BindStateSplit(GateRef gate, GateRef frameState)
84 {
85     auto state = gateAcc_.GetState(gate);
86     auto depend = gateAcc_.GetDep(gate);
87     if (gateAcc_.GetOpCode(state) == OpCode::IF_SUCCESS) {
88         state = gateAcc_.GetState(state);
89     }
90     GateRef stateSplit = circuit_->NewGate(circuit_->StateSplit(), {state, depend, frameState});
91     gateAcc_.ReplaceDependIn(gate, stateSplit);
92     if (builder_->IsLogEnabled()) {
93         gateAcc_.ShortPrint(frameState);
94     }
95 }
96 
CreateEmptyStateInfo()97 FrameStateInfo *FrameStateBuilder::CreateEmptyStateInfo()
98 {
99     auto chunk = circuit_->chunk();
100     auto frameInfo = chunk->New<FrameStateInfo>(chunk, numVregs_);
101     for (size_t i = 0; i < numVregs_; i++) {
102         frameInfo->SetValuesAt(i, Circuit::NullGate());
103     }
104     return frameInfo;
105 }
106 
BuildPostOrderList(size_t size)107 void FrameStateBuilder::BuildPostOrderList(size_t size)
108 {
109     postOrderList_.clear();
110     std::deque<size_t> pendingList;
111     std::vector<bool> visited(size, false);
112     // entry block (bbid=0) is a empty block, need skip
113     auto firstBlockId = 1;
114     pendingList.emplace_back(firstBlockId);
115 
116     while (!pendingList.empty()) {
117         size_t curBlockId = pendingList.back();
118         visited[curBlockId] = true;
119 
120         bool change = false;
121         auto &bb = builder_->GetBasicBlockById(curBlockId);
122         for (const auto &succBlock: bb.succs) {
123             if (!visited[succBlock->id]) {
124                 pendingList.emplace_back(succBlock->id);
125                 change = true;
126                 break;
127             }
128         }
129         if (change) {
130             continue;
131         }
132         for (const auto &succBlock: bb.catchs) {
133             if (!visited[succBlock->id]) {
134                 pendingList.emplace_back(succBlock->id);
135                 change = true;
136                 break;
137             }
138         }
139         if (!change) {
140             postOrderList_.emplace_back(curBlockId);
141             pendingList.pop_back();
142         }
143     }
144 }
145 
MergeIntoPredBC(uint32_t predPc,size_t diff)146 bool FrameStateBuilder::MergeIntoPredBC(uint32_t predPc, size_t diff)
147 {
148     // liveout next
149     auto frameInfo = GetOrOCreateBCEndStateInfo(predPc);
150     FrameStateInfo *predFrameInfo = liveOutResult_;
151     bool changed = frameInfo->MergeLiveout(predFrameInfo);
152     if (!changed) {
153         return changed;
154     }
155     for (size_t i = 0; i < numVregs_; i++) {
156         auto predValue = predFrameInfo->ValuesAt(i);
157         auto value = frameInfo->ValuesAt(i);
158         // if value not null, merge pred
159         if (value == Circuit::NullGate() && predValue != Circuit::NullGate()) {
160             predValue = TryGetLoopExitValue(predValue, diff);
161             frameInfo->SetValuesAt(i, predValue);
162             changed = true;
163         }
164     }
165     return changed;
166 }
167 
GetPreBBInput(BytecodeRegion * bb,BytecodeRegion * predBb,GateRef gate)168 GateRef FrameStateBuilder::GetPreBBInput(BytecodeRegion *bb, BytecodeRegion *predBb, GateRef gate)
169 {
170     if (gateAcc_.GetOpCode(gate) == OpCode::VALUE_SELECTOR) {
171         return GetPhiComponent(bb, predBb, gate);
172     }
173     return gate;
174 }
175 
GetPhiComponent(BytecodeRegion * bb,BytecodeRegion * predBb,GateRef phi)176 GateRef FrameStateBuilder::GetPhiComponent(BytecodeRegion *bb, BytecodeRegion *predBb, GateRef phi)
177 {
178     ASSERT(gateAcc_.GetOpCode(phi) == OpCode::VALUE_SELECTOR);
179 
180     if (bb->phiGate.find(phi) == bb->phiGate.end()) {
181         return Circuit::NullGate();
182     }
183 
184     if (bb->numOfLoopBacks != 0) {
185         ASSERT(bb->loopbackBlocks.size() != 0);
186         auto forwardValue = gateAcc_.GetValueIn(phi, 0); // 0: fowward
187         auto loopBackValue = gateAcc_.GetValueIn(phi, 1); // 1: back
188         size_t backIndex = 0;
189         size_t forwardIndex = 0;
190         for (size_t i = 0; i < bb->numOfStatePreds; ++i) {
191             auto predId = std::get<0>(bb->expandedPreds.at(i));
192             if (bb->loopbackBlocks.count(predId)) {
193                 if (predId == predBb->id) {
194                     if (bb->numOfLoopBacks == 1) {
195                         return loopBackValue;
196                     }
197                     return gateAcc_.GetValueIn(loopBackValue, backIndex);
198                 }
199                 backIndex++;
200             } else {
201                 if (predId == predBb->id) {
202                     auto mergeCount = bb->numOfStatePreds - bb->numOfLoopBacks;
203                     if (mergeCount == 1) {
204                         return forwardValue;
205                     }
206                     return gateAcc_.GetValueIn(forwardValue, forwardIndex);
207                 }
208                 forwardIndex++;
209             }
210         }
211         return Circuit::NullGate();
212     }
213 
214     ASSERT(gateAcc_.GetNumValueIn(phi) == bb->numOfStatePreds);
215     // The phi input nodes need to be traversed in reverse order, because there is a bb with multiple def points
216     for (size_t i = bb->numOfStatePreds - 1; i >= 0; --i) {
217         auto predId = std::get<0>(bb->expandedPreds.at(i));
218         if (predId == predBb->id) {
219             return gateAcc_.GetValueIn(phi, i);
220         }
221     }
222     return Circuit::NullGate();
223 }
224 
MergeIntoPredBB(BytecodeRegion * bb,BytecodeRegion * predBb)225 bool FrameStateBuilder::MergeIntoPredBB(BytecodeRegion *bb, BytecodeRegion *predBb)
226 {
227     bool changed = MergeIntoPredBC(predBb->end, LoopExitCount(predBb, bb));
228     if (!changed) {
229         return changed;
230     }
231     auto predLiveout = GetOrOCreateBCEndStateInfo(predBb->end);
232     // replace phi
233     if (bb->valueSelectorAccGate != Circuit::NullGate()) {
234         auto phi = bb->valueSelectorAccGate;
235         auto value = predLiveout->ValuesAt(accumulatorIndex_);
236         if (value == phi) {
237             auto target = GetPreBBInput(bb, predBb, phi);
238             if (target != Circuit::NullGate()) {
239                 auto diff = LoopExitCount(predBb, bb);
240                 target = TryGetLoopExitValue(target, diff);
241                 predLiveout->SetValuesAt(accumulatorIndex_, target);
242             }
243         }
244     }
245     for (auto &it : bb->vregToValueGate) {
246         auto reg = it.first;
247         auto gate = it.second;
248         auto value = predLiveout->ValuesAt(reg);
249         if (value == gate) {
250             auto target = GetPreBBInput(bb, predBb, gate);
251             if (target == Circuit::NullGate()) {
252                 continue;
253             }
254             auto diff = LoopExitCount(predBb, bb);
255             target = TryGetLoopExitValue(target, diff);
256             predLiveout->SetValuesAt(reg, target);
257         }
258     }
259     return changed;
260 }
261 
ComputeLiveOut(size_t bbId)262 bool FrameStateBuilder::ComputeLiveOut(size_t bbId)
263 {
264     auto &bb = builder_->GetBasicBlockById(bbId);
265     bool changed = false;
266     ASSERT(!bb.isDead);
267     // iterator bc
268     auto &iterator = bb.GetBytecodeIterator();
269     iterator.GotoEnd();
270     ASSERT(bb.end == iterator.Index());
271     auto liveout = GetOrOCreateBCEndStateInfo(bb.end);
272     liveOutResult_->CopyFrom(liveout);
273     while (true) {
274         auto &bytecodeInfo = iterator.GetBytecodeInfo();
275         ComputeLiveOutBC(iterator.Index(), bytecodeInfo, bbId);
276         --iterator;
277         if (iterator.Done()) {
278             break;
279         }
280         auto prevPc = iterator.Index();
281         changed |= MergeIntoPredBC(prevPc, 0);
282     }
283 
284     SaveBBBeginStateInfo(bbId);
285 
286     bool defPhi = bb.valueSelectorAccGate != Circuit::NullGate() ||
287         bb.vregToValueGate.size() != 0;
288     // merge current into pred bb
289     for (auto bbPred : bb.preds) {
290         if (bbPred->isDead) {
291             continue;
292         }
293         if (defPhi) {
294             changed |= MergeIntoPredBB(&bb, bbPred);
295         } else {
296             changed |= MergeIntoPredBC(bbPred->end, LoopExitCount(bbPred, &bb));
297         }
298     }
299     if (!bb.trys.empty()) {
300         // clear GET_EXCEPTION gate if this is a catch block
301         UpdateAccumulator(Circuit::NullGate());
302         for (auto bbPred : bb.trys) {
303             if (bbPred->isDead) {
304                 continue;
305             }
306             if (defPhi) {
307                 changed |= MergeIntoPredBB(&bb, bbPred);
308             } else {
309                 changed |= MergeIntoPredBC(bbPred->end, LoopExitCount(bbPred, &bb));
310             }
311         }
312     }
313 
314     return changed;
315 }
316 
ComputeLiveState()317 void FrameStateBuilder::ComputeLiveState()
318 {
319     // recompute liveout
320     bool changed = true;
321     while (changed) {
322         changed = false;
323         for (size_t i = 0; i < postOrderList_.size(); i++) {
324             changed |= ComputeLiveOut(postOrderList_[i]);
325         }
326     }
327 }
328 
BuildFrameState()329 void FrameStateBuilder::BuildFrameState()
330 {
331     bcEndStateInfos_.resize(builder_->GetLastBcIndex() + 1, nullptr); // 1: +1 pcOffsets size
332     auto size = builder_->GetBasicBlockCount();
333     bbBeginStateInfos_.resize(size, nullptr);
334     liveOutResult_ = CreateEmptyStateInfo();
335     BuildPostOrderList(size);
336     ComputeLiveState();
337     BindBBStateSplit();
338 }
339 
ComputeLiveOutBC(uint32_t index,const BytecodeInfo & bytecodeInfo,size_t bbId)340 void FrameStateBuilder::ComputeLiveOutBC(uint32_t index, const BytecodeInfo &bytecodeInfo, size_t bbId)
341 {
342     if (bytecodeInfo.IsMov()) {
343         auto gate = Circuit::NullGate();
344         // variable kill
345         if (bytecodeInfo.AccOut()) {
346             gate = ValuesAtAccumulator();
347             UpdateAccumulator(Circuit::NullGate());
348         } else if (bytecodeInfo.vregOut.size() != 0) {
349             auto out = bytecodeInfo.vregOut[0];
350             gate = ValuesAt(out);
351             UpdateVirtualRegister(out, Circuit::NullGate());
352         }
353         // variable use
354         // when alive gate is null, find def
355         if (bytecodeInfo.AccIn()) {
356             if (gate == Circuit::NullGate()) {
357                 gate = builder_->ResolveDef(bbId, index, 0, true);
358             }
359             UpdateAccumulator(gate);
360         } else if (bytecodeInfo.inputs.size() != 0) {
361             auto vreg = std::get<VirtualRegister>(bytecodeInfo.inputs.at(0)).GetId();
362             if (gate == Circuit::NullGate()) {
363                 gate = builder_->ResolveDef(bbId, index, vreg, false);
364             }
365             UpdateVirtualRegister(vreg, gate);
366         }
367         return;
368     }
369     if (!bytecodeInfo.IsGeneral() && !bytecodeInfo.IsReturn() && !bytecodeInfo.IsCondJump()) {
370         return;
371     }
372     GateRef gate = builder_->GetGateByBcIndex(index);
373     // variable kill
374     if (bytecodeInfo.AccOut()) {
375         UpdateAccumulator(Circuit::NullGate());
376     }
377     for (const auto &out: bytecodeInfo.vregOut) {
378         UpdateVirtualRegister(out, Circuit::NullGate());
379     }
380     if (bytecodeInfo.GetOpcode() == EcmaOpcode::RESUMEGENERATOR) {
381         UpdateVirtualRegistersOfResume(gate);
382     }
383 
384     // variable use
385     if (bytecodeInfo.AccIn()) {
386         auto id = bytecodeInfo.inputs.size();
387         GateRef def = gateAcc_.GetValueIn(gate, id);
388         UpdateAccumulator(def);
389     }
390     for (size_t i = 0; i < bytecodeInfo.inputs.size(); i++) {
391         auto in = bytecodeInfo.inputs[i];
392         if (std::holds_alternative<VirtualRegister>(in)) {
393             auto vreg = std::get<VirtualRegister>(in).GetId();
394             GateRef def = gateAcc_.GetValueIn(gate, i);
395             UpdateVirtualRegister(vreg, def);
396         }
397     }
398     if (IsAsyncResolveOrSusp(bytecodeInfo)) {
399         UpdateVirtualRegistersOfSuspend(gate);
400     }
401 }
402 
IsAsyncResolveOrSusp(const BytecodeInfo & bytecodeInfo)403 bool FrameStateBuilder::IsAsyncResolveOrSusp(const BytecodeInfo &bytecodeInfo)
404 {
405     EcmaOpcode opcode = bytecodeInfo.GetOpcode();
406     return opcode == EcmaOpcode::SUSPENDGENERATOR_V8 || opcode == EcmaOpcode::ASYNCGENERATORRESOLVE_V8_V8_V8;
407 }
408 
BuildStateSplitAfter(size_t index,BytecodeRegion & bb)409 void FrameStateBuilder::BuildStateSplitAfter(size_t index, BytecodeRegion& bb)
410 {
411     auto gate = builder_->GetGateByBcIndex(index);
412     ASSERT(gateAcc_.GetOpCode(gate) == OpCode::JS_BYTECODE);
413     auto nextIndex = GetNearestNextIndex(index, bb);
414     if (builder_->GetBytecodeInfo(nextIndex).IsCall()) {
415         return;
416     }
417     auto pcOffset = builder_->GetPcOffset(nextIndex);
418     auto stateInfo = GetFrameInfoAfter(nextIndex - 1); // 1: after prev bc
419     GateRef frameValues = BuildFrameValues(stateInfo);
420     GateRef frameStateAfter = BuildFrameStateGate(
421         pcOffset, frameValues, FrameStateOutput::Invalid());
422     BindStateSplit(gate, gate, frameStateAfter);
423 }
424 
GetNearestNextIndex(size_t index,BytecodeRegion & bb) const425 size_t FrameStateBuilder::GetNearestNextIndex(size_t index, BytecodeRegion& bb) const
426 {
427     index++;
428     auto gate = builder_->GetGateByBcIndex(index);
429     while ((gate == Circuit::NullGate() || gateAcc_.IsConstant(gate)) && index < bb.end) {
430         index++;
431         gate = builder_->GetGateByBcIndex(index);
432     }
433     return index;
434 }
435 
BuildStateSplitBefore(BytecodeRegion & bb,size_t index)436 void FrameStateBuilder::BuildStateSplitBefore(BytecodeRegion& bb, size_t index)
437 {
438     auto pcOffset = builder_->GetPcOffset(index);
439     auto stateInfo = GetFrameInfoBefore(bb, index);
440     GateRef frameValues = BuildFrameValues(stateInfo);
441     GateRef frameStateBefore = BuildFrameStateGate(
442         pcOffset, frameValues, FrameStateOutput::Invalid());
443     if (index == bb.start) {
444         BindStateSplit(bb.stateCurrent, bb.dependCurrent, frameStateBefore);
445     } else {
446         auto gate = builder_->GetGateByBcIndex(index);
447         BindStateSplit(gate, frameStateBefore);
448     }
449 }
450 
ShouldInsertFrameStateBefore(BytecodeRegion & bb,size_t index)451 bool FrameStateBuilder::ShouldInsertFrameStateBefore(BytecodeRegion& bb, size_t index)
452 {
453     auto gate = builder_->GetGateByBcIndex(index);
454     if (index == bb.start) {
455         if (bb.numOfStatePreds > 1) { // 1: > 1 is merge
456             return true;
457         } else if (bb.numOfStatePreds == 1) {   // 1: == 1 maybe loopexit
458             auto predBb = (bb.preds.size() > 0) ? bb.preds.at(0) : bb.trys.at(0);
459             if (LoopExitCount(predBb, &bb) > 0) {
460                 return true;
461             }
462         }
463         if (gateAcc_.GetOpCode(bb.dependCurrent) == OpCode::GET_EXCEPTION) {
464             return true;
465         }
466     } else {
467         if (gate == Circuit::NullGate() || gateAcc_.GetStateCount(gate) != 1) {
468             return false;
469         }
470         auto state = gateAcc_.GetState(gate);
471         if (gateAcc_.GetOpCode(state) == OpCode::IF_SUCCESS) {
472             return true;
473         }
474     }
475     return false;
476 }
477 
BuildFrameState(BytecodeRegion & bb,const BytecodeInfo & bytecodeInfo,size_t index)478 void FrameStateBuilder::BuildFrameState(BytecodeRegion& bb,
479     const BytecodeInfo &bytecodeInfo, size_t index)
480 {
481     // Not bind state split for Call
482     if (bytecodeInfo.IsCall()) {
483         BuildCallFrameState(index, bb);
484     }
485 
486     bool needStateSplitBefore = ShouldInsertFrameStateBefore(bb, index);
487     auto gate = builder_->GetGateByBcIndex(index);
488     if (needStateSplitBefore && index != bb.start) {
489         auto depend = gateAcc_.GetDep(gate);
490         if (gateAcc_.GetOpCode(depend) == OpCode::STATE_SPLIT) {
491             needStateSplitBefore = false;
492         }
493     }
494     if (needStateSplitBefore) {
495         BuildStateSplitBefore(bb, index);
496     }
497 
498     if (!bytecodeInfo.NoSideEffects() && !bytecodeInfo.IsThrow()) {
499         if (!gateAcc_.HasIfExceptionUse(gate)) {
500             BuildStateSplitAfter(index, bb);
501         }
502     }
503 }
504 
BuildCallFrameState(size_t index,BytecodeRegion & bb)505 void FrameStateBuilder::BuildCallFrameState(size_t index, BytecodeRegion& bb)
506 {
507     auto pcOffset = builder_->GetPcOffset(index);
508     auto stateInfo = GetFrameInfoBefore(bb, index);
509     GateRef frameValues = BuildFrameValues(stateInfo);
510     GateRef frameState = BuildFrameStateGate(pcOffset, frameValues, FrameStateOutput::Invalid());
511     auto gate = builder_->GetGateByBcIndex(index);
512     gateAcc_.ReplaceFrameStateIn(gate, frameState);
513 }
514 
BindBBStateSplit()515 void FrameStateBuilder::BindBBStateSplit()
516 {
517     auto& dfsList = builder_->GetDfsList();
518     for (auto &bbId: dfsList) {
519         auto &bb = builder_->GetBasicBlockById(bbId);
520         if (builder_->IsFirstBasicBlock(bb.id)) {
521             BuildStateSplitBefore(bb, bb.start);
522         }
523         if (builder_->IsEntryBlock(bb.id)) {
524             BuildStateSplitBefore(bb, bb.start);
525         }
526         ASSERT(!bb.isDead);
527         builder_->EnumerateBlock(bb, [&](const BytecodeInfo &bytecodeInfo) -> bool {
528             auto &iterator = bb.GetBytecodeIterator();
529             auto index = iterator.Index();
530             BuildFrameState(bb, bytecodeInfo, index);
531             return true;
532         });
533     }
534 }
535 
GetFrameInfoBefore(BytecodeRegion & bb,uint32_t bcId)536 FrameStateInfo *FrameStateBuilder::GetFrameInfoBefore(BytecodeRegion &bb, uint32_t bcId)
537 {
538     if (bcId == bb.start) {
539         return GetBBBeginStateInfo(bb.id);
540     } else {
541         return GetOrOCreateBCEndStateInfo(bcId - 1); // 1: prev pc
542     }
543 }
544 
GetFrameInfoAfter(uint32_t bcId)545 FrameStateInfo *FrameStateBuilder::GetFrameInfoAfter(uint32_t bcId)
546 {
547     return GetOrOCreateBCEndStateInfo(bcId);
548 }
549 
SaveBBBeginStateInfo(size_t bbId)550 void FrameStateBuilder::SaveBBBeginStateInfo(size_t bbId)
551 {
552     if (bbBeginStateInfos_[bbId] == nullptr) {
553         bbBeginStateInfos_[bbId] = CreateEmptyStateInfo();
554     }
555     bbBeginStateInfos_[bbId]->CopyFrom(liveOutResult_);
556 }
557 
UpdateVirtualRegistersOfSuspend(GateRef gate)558 void FrameStateBuilder::UpdateVirtualRegistersOfSuspend(GateRef gate)
559 {
560     auto saveRegsGate = gateAcc_.GetDep(gate);
561     size_t numOfRegs = gateAcc_.GetNumValueIn(saveRegsGate);
562     for (size_t i = 0; i < numOfRegs; i++) {
563         GateRef def = gateAcc_.GetValueIn(saveRegsGate, i);
564         UpdateVirtualRegister(i, def);
565     }
566 }
567 
UpdateVirtualRegistersOfResume(GateRef gate)568 void FrameStateBuilder::UpdateVirtualRegistersOfResume(GateRef gate)
569 {
570     auto uses = gateAcc_.Uses(gate);
571     for (auto it = uses.begin(); it != uses.end(); it++) {
572         if (gateAcc_.IsValueIn(it) && gateAcc_.GetOpCode(*it) == OpCode::RESTORE_REGISTER) {
573             auto vreg = static_cast<size_t>(gateAcc_.GetVirtualRegisterIndex(*it));
574             UpdateVirtualRegister(vreg, Circuit::NullGate());
575         }
576     }
577 }
578 
LoopExitCount(BytecodeRegion * bb,BytecodeRegion * bbNext)579 size_t FrameStateBuilder::LoopExitCount(BytecodeRegion* bb, BytecodeRegion* bbNext)
580 {
581     size_t headDep = ((bbNext->numOfLoopBacks > 0) && (bbNext->loopbackBlocks.count(bb->id) == 0)) ? 1 : 0;
582     if (bbNext->loopDepth < headDep) {
583         // loop optimization disabled.
584         return 0;
585     }
586     size_t nextDep = bbNext->loopDepth - headDep;
587     ASSERT(bb->loopDepth >= nextDep);
588     return bb->loopDepth > nextDep;
589 }
590 
TryGetLoopExitValue(GateRef value,size_t diff)591 GateRef FrameStateBuilder::TryGetLoopExitValue(GateRef value, size_t diff)
592 {
593     if ((gateAcc_.GetOpCode(value) != OpCode::LOOP_EXIT_VALUE) || (diff == 0)) {
594         return value;
595     }
596     for (size_t i = 0; i < diff; ++i) {
597         ASSERT(gateAcc_.GetOpCode(value) == OpCode::LOOP_EXIT_VALUE);
598         value = gateAcc_.GetValueIn(value);
599     }
600     return value;
601 }
602 }
603