• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "bytecode_circuit_builder.h"
17 
18 namespace panda::ecmascript::kungfu {
BytecodeToCircuit(const std::vector<uint8_t * > & pcArray,const panda_file::File & pf,const JSMethod * method)19 void BytecodeCircuitBuilder::BytecodeToCircuit(const std::vector<uint8_t *> &pcArray, const panda_file::File &pf,
20                                                const JSMethod *method)
21 {
22     auto curPc = pcArray.front();
23     auto prePc = curPc;
24     std::map<uint8_t *, uint8_t *> byteCodeCurPrePc;
25     std::vector<CfgInfo> bytecodeBlockInfos;
26     auto startPc = curPc;
27     bytecodeBlockInfos.emplace_back(startPc, SplitKind::START, std::vector<uint8_t *>(1, startPc));
28     byteCodeCurPrePc.insert(std::pair<uint8_t *, uint8_t *>(curPc, prePc));
29     for (size_t i = 1; i < pcArray.size() - 1; i++) {
30         curPc = pcArray[i];
31         byteCodeCurPrePc.insert(std::pair<uint8_t *, uint8_t *>(curPc, prePc));
32         prePc = curPc;
33         CollectBytecodeBlockInfo(curPc, bytecodeBlockInfos);
34     }
35     // handle empty
36     byteCodeCurPrePc.insert(std::pair<uint8_t *, uint8_t *>(pcArray[pcArray.size() - 1], prePc));
37 
38     // collect try catch block info
39     auto exceptionInfo = CollectTryCatchBlockInfo(pf, method, byteCodeCurPrePc, bytecodeBlockInfos);
40 
41     // Complete bytecode blcok Infomation
42     CompleteBytecodeBlockInfo(byteCodeCurPrePc, bytecodeBlockInfos);
43 
44     // Building the basic block diagram of bytecode
45     BuildBasicBlocks(method, exceptionInfo, bytecodeBlockInfos, byteCodeCurPrePc);
46 }
47 
CollectBytecodeBlockInfo(uint8_t * pc,std::vector<CfgInfo> & bytecodeBlockInfos)48 void BytecodeCircuitBuilder::CollectBytecodeBlockInfo(uint8_t *pc, std::vector<CfgInfo> &bytecodeBlockInfos)
49 {
50     auto opcode = static_cast<EcmaOpcode>(*pc);
51     switch (opcode) {
52         case EcmaOpcode::JMP_IMM8: {
53             int8_t offset = READ_INST_8_0();
54             std::vector<uint8_t *> temp;
55             temp.emplace_back(pc + offset);
56             // current basic block end
57             bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
58             bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::TWO, SplitKind::START,
59                                             std::vector<uint8_t *>(1, pc + BytecodeOffset::TWO));
60             // jump basic block start
61             bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
62         }
63             break;
64         case EcmaOpcode::JMP_IMM16: {
65             int16_t offset = READ_INST_16_0();
66             std::vector<uint8_t *> temp;
67             temp.emplace_back(pc + offset);
68             bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
69             bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::THREE, SplitKind::START,
70                                             std::vector<uint8_t *>(1, pc + BytecodeOffset::THREE));
71             bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START,
72                                             std::vector<uint8_t *>(1, pc + offset));
73         }
74             break;
75         case EcmaOpcode::JMP_IMM32: {
76             int32_t offset = READ_INST_32_0();
77             std::vector<uint8_t *> temp;
78             temp.emplace_back(pc + offset);
79             bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
80             bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::FIVE, SplitKind::START,
81                                             std::vector<uint8_t *>(1, pc + BytecodeOffset::FIVE));
82             bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
83         }
84             break;
85         case EcmaOpcode::JEQZ_IMM8: {
86             std::vector<uint8_t *> temp;
87             temp.emplace_back(pc + BytecodeOffset::TWO);   // first successor
88             int8_t offset = READ_INST_8_0();
89             temp.emplace_back(pc + offset);  // second successor
90             // condition branch current basic block end
91             bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
92             // first branch basic block start
93             bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::TWO, SplitKind::START,
94                                             std::vector<uint8_t *>(1, pc + BytecodeOffset::TWO));
95             // second branch basic block start
96             bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
97         }
98             break;
99         case EcmaOpcode::JEQZ_IMM16: {
100             std::vector<uint8_t *> temp;
101             temp.emplace_back(pc + BytecodeOffset::THREE);   // first successor
102             int16_t offset = READ_INST_16_0();
103             temp.emplace_back(pc + offset);  // second successor
104             bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp); // end
105             bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::THREE, SplitKind::START,
106                                             std::vector<uint8_t *>(1, pc + BytecodeOffset::THREE));
107             bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
108         }
109             break;
110         case EcmaOpcode::JNEZ_IMM8: {
111             std::vector<uint8_t *> temp;
112             temp.emplace_back(pc + BytecodeOffset::TWO); // first successor
113             int8_t offset = READ_INST_8_0();
114             temp.emplace_back(pc + offset); // second successor
115             bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
116             bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::TWO, SplitKind::START,
117                                             std::vector<uint8_t *>(1, pc + BytecodeOffset::TWO));
118             bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
119         }
120             break;
121         case EcmaOpcode::JNEZ_IMM16: {
122             std::vector<uint8_t *> temp;
123             temp.emplace_back(pc + BytecodeOffset::THREE); // first successor
124             int8_t offset = READ_INST_16_0();
125             temp.emplace_back(pc + offset); // second successor
126             bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
127             bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::THREE, SplitKind::START,
128                                             std::vector<uint8_t *>(1, pc + BytecodeOffset::THREE));
129             bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
130         }
131             break;
132         case EcmaOpcode::RETURN_DYN:
133         case EcmaOpcode::RETURNUNDEFINED_PREF: {
134             bytecodeBlockInfos.emplace_back(pc, SplitKind::END, std::vector<uint8_t *>(1, pc));
135             break;
136         }
137         case EcmaOpcode::THROWDYN_PREF:
138         case EcmaOpcode::THROWCONSTASSIGNMENT_PREF_V8:
139         case EcmaOpcode::THROWTHROWNOTEXISTS_PREF:
140         case EcmaOpcode::THROWPATTERNNONCOERCIBLE_PREF:
141         case EcmaOpcode::THROWDELETESUPERPROPERTY_PREF: {
142             bytecodeBlockInfos.emplace_back(pc, SplitKind::END, std::vector<uint8_t *>(1, pc));
143         }
144             break;
145         default:
146             break;
147     }
148 }
149 
CollectTryCatchBlockInfo(const panda_file::File & file,const JSMethod * method,std::map<uint8_t *,uint8_t * > & byteCodeCurPrePc,std::vector<CfgInfo> & bytecodeBlockInfos)150 std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> BytecodeCircuitBuilder::CollectTryCatchBlockInfo(
151     const panda_file::File &file, const JSMethod *method, std::map<uint8_t *, uint8_t*> &byteCodeCurPrePc,
152     std::vector<CfgInfo> &bytecodeBlockInfos)
153 {
154     // try contains many catch
155     std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> byteCodeException;
156     panda_file::MethodDataAccessor mda(file, method->GetFileId());
157     panda_file::CodeDataAccessor cda(file, mda.GetCodeId().value());
158     cda.EnumerateTryBlocks([method, &byteCodeCurPrePc, &bytecodeBlockInfos, &byteCodeException](
159             panda_file::CodeDataAccessor::TryBlock &try_block) {
160         auto tryStartOffset = try_block.GetStartPc();
161         auto tryEndOffset = try_block.GetStartPc() + try_block.GetLength();
162         auto tryStartPc = const_cast<uint8_t *>(method->GetBytecodeArray() + tryStartOffset);
163         auto tryEndPc = const_cast<uint8_t *>(method->GetBytecodeArray() + tryEndOffset);
164         byteCodeException[std::make_pair(tryStartPc, tryEndPc)] = {};
165         uint32_t pcOffset = panda_file::INVALID_OFFSET;
166         try_block.EnumerateCatchBlocks([&](panda_file::CodeDataAccessor::CatchBlock &catch_block) {
167             pcOffset = catch_block.GetHandlerPc();
168             auto catchBlockPc = const_cast<uint8_t *>(method->GetBytecodeArray() + pcOffset);
169             // try block associate catch block
170             byteCodeException[std::make_pair(tryStartPc, tryEndPc)].emplace_back(catchBlockPc);
171             return true;
172         });
173         // Check whether the previous block of the try block exists.
174         // If yes, add the current block; otherwise, create a new block.
175         bool flag = false;
176         for (size_t i = 0; i < bytecodeBlockInfos.size(); i++) {
177             if (bytecodeBlockInfos[i].splitKind == SplitKind::START) {
178                 continue;
179             }
180             if (bytecodeBlockInfos[i].pc == byteCodeCurPrePc[tryStartPc]) {
181                 flag = true;
182                 break;
183             }
184         }
185         if (!flag) {
186             // pre block
187             bytecodeBlockInfos.emplace_back(byteCodeCurPrePc[tryStartPc], SplitKind::END,
188                                             std::vector<uint8_t *>(1, tryStartPc));
189         }
190         // try block
191         bytecodeBlockInfos.emplace_back(tryStartPc, SplitKind::START, std::vector<uint8_t *>(1, tryStartPc));
192         flag = false;
193         for (size_t i = 0; i < bytecodeBlockInfos.size(); i++) {
194             if (bytecodeBlockInfos[i].splitKind == SplitKind::START) {
195                 continue;
196             }
197             if (bytecodeBlockInfos[i].pc == byteCodeCurPrePc[tryEndPc]) {
198                 auto &succs = bytecodeBlockInfos[i].succs;
199                 auto iter = std::find(succs.begin(), succs.end(), bytecodeBlockInfos[i].pc);
200                 if (iter == succs.end()) {
201                     auto opcode = static_cast<EcmaOpcode>(*(bytecodeBlockInfos[i].pc));
202                     switch (opcode) {
203                         case EcmaOpcode::JMP_IMM8:
204                         case EcmaOpcode::JMP_IMM16:
205                         case EcmaOpcode::JMP_IMM32:
206                         case EcmaOpcode::JEQZ_IMM8:
207                         case EcmaOpcode::JEQZ_IMM16:
208                         case EcmaOpcode::JNEZ_IMM8:
209                         case EcmaOpcode::JNEZ_IMM16:
210                         case EcmaOpcode::RETURN_DYN:
211                         case EcmaOpcode::RETURNUNDEFINED_PREF:
212                         case EcmaOpcode::THROWDYN_PREF: {
213                             break;
214                         }
215                         default: {
216                             succs.emplace_back(tryEndPc);
217                             break;
218                         }
219                     }
220                 }
221                 flag = true;
222                 break;
223             }
224         }
225         if (!flag) {
226             bytecodeBlockInfos.emplace_back(byteCodeCurPrePc[tryEndPc], SplitKind::END,
227                                             std::vector<uint8_t *>(1, tryEndPc));
228         }
229         bytecodeBlockInfos.emplace_back(tryEndPc, SplitKind::START, std::vector<uint8_t *>(1, tryEndPc)); // next block
230         return true;
231     });
232     return byteCodeException;
233 }
234 
CompleteBytecodeBlockInfo(std::map<uint8_t *,uint8_t * > & byteCodeCurPrePc,std::vector<CfgInfo> & bytecodeBlockInfos)235 void BytecodeCircuitBuilder::CompleteBytecodeBlockInfo(std::map<uint8_t *, uint8_t *> &byteCodeCurPrePc,
236                                                        std::vector<CfgInfo> &bytecodeBlockInfos)
237 {
238     std::sort(bytecodeBlockInfos.begin(), bytecodeBlockInfos.end());
239 
240 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
241     PrintCollectBlockInfo(bytecodeBlockInfos);
242 #endif
243 
244     // Deduplicate
245     auto deduplicateIndex = std::unique(bytecodeBlockInfos.begin(), bytecodeBlockInfos.end());
246     bytecodeBlockInfos.erase(deduplicateIndex, bytecodeBlockInfos.end());
247 
248     // Supplementary block information
249     std::vector<uint8_t *> endBlockPc;
250     std::vector<uint8_t *> startBlockPc;
251     for (size_t i = 0; i < bytecodeBlockInfos.size() - 1; i++) {
252         if (bytecodeBlockInfos[i].splitKind == bytecodeBlockInfos[i + 1].splitKind &&
253             bytecodeBlockInfos[i].splitKind == SplitKind::START) {
254             auto prePc = byteCodeCurPrePc[bytecodeBlockInfos[i + 1].pc];
255             endBlockPc.emplace_back(prePc); // Previous instruction of current instruction
256             endBlockPc.emplace_back(bytecodeBlockInfos[i + 1].pc); // current instruction
257             continue;
258         }
259         if (bytecodeBlockInfos[i].splitKind == bytecodeBlockInfos[i + 1].splitKind &&
260             bytecodeBlockInfos[i].splitKind == SplitKind::END) {
261             auto tempPc = bytecodeBlockInfos[i].pc;
262             auto findItem = std::find_if(byteCodeCurPrePc.begin(), byteCodeCurPrePc.end(),
263                                          [tempPc](const std::map<uint8_t *, uint8_t *>::value_type item) {
264                                              return item.second == tempPc;
265                                          });
266             if (findItem != byteCodeCurPrePc.end()) {
267                 startBlockPc.emplace_back((*findItem).first);
268             }
269         }
270     }
271 
272     // Supplementary end block info
273     for (auto iter = endBlockPc.begin(); iter != endBlockPc.end(); iter += 2) { // 2: index
274         bytecodeBlockInfos.emplace_back(*iter, SplitKind::END, std::vector<uint8_t *>(1, *(iter + 1)));
275     }
276     // Supplementary start block info
277     for (auto iter = startBlockPc.begin(); iter != startBlockPc.end(); iter++) {
278         bytecodeBlockInfos.emplace_back(*iter, SplitKind::START, std::vector<uint8_t *>(1, *iter));
279     }
280 
281     // Deduplicate successor
282     for (size_t i = 0; i < bytecodeBlockInfos.size(); i++) {
283         if (bytecodeBlockInfos[i].splitKind == SplitKind::END) {
284             std::set<uint8_t *> tempSet(bytecodeBlockInfos[i].succs.begin(),
285                                         bytecodeBlockInfos[i].succs.end());
286             bytecodeBlockInfos[i].succs.assign(tempSet.begin(), tempSet.end());
287         }
288     }
289 
290     std::sort(bytecodeBlockInfos.begin(), bytecodeBlockInfos.end());
291 
292     // handling jumps to an empty block
293     auto endPc = bytecodeBlockInfos[bytecodeBlockInfos.size() - 1].pc;
294     auto iter = --byteCodeCurPrePc.end();
295     if (endPc == iter->first) {
296         bytecodeBlockInfos.emplace_back(endPc, SplitKind::END, std::vector<uint8_t *>(1, endPc));
297     }
298     // Deduplicate
299     deduplicateIndex = std::unique(bytecodeBlockInfos.begin(), bytecodeBlockInfos.end());
300     bytecodeBlockInfos.erase(deduplicateIndex, bytecodeBlockInfos.end());
301 
302 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
303     PrintCollectBlockInfo(bytecodeBlockInfos);
304 #endif
305 }
306 
BuildBasicBlocks(const JSMethod * method,std::map<std::pair<uint8_t *,uint8_t * >,std::vector<uint8_t * >> & exception,std::vector<CfgInfo> & bytecodeBlockInfo,std::map<uint8_t *,uint8_t * > & byteCodeCurPrePc)307 void BytecodeCircuitBuilder::BuildBasicBlocks(const JSMethod *method,
308                                               std::map<std::pair<uint8_t *, uint8_t *>,
309                                               std::vector<uint8_t *>> &exception,
310                                               std::vector<CfgInfo> &bytecodeBlockInfo,
311                                               std::map<uint8_t *, uint8_t *> &byteCodeCurPrePc)
312 {
313     std::map<uint8_t *, BytecodeRegion *> startPcToBB; // [start, bb]
314     std::map<uint8_t *, BytecodeRegion *> endPcToBB; // [end, bb]
315     BytecodeGraph byteCodeGraph;
316     auto &blocks = byteCodeGraph.graph;
317     byteCodeGraph.method = method;
318     blocks.resize(bytecodeBlockInfo.size() / 2); // 2 : half size
319     // build basic block
320     int blockId = 0;
321     int index = 0;
322     for (size_t i = 0; i < bytecodeBlockInfo.size() - 1; i += 2) { // 2:index
323         auto startPc = bytecodeBlockInfo[i].pc;
324         auto endPc = bytecodeBlockInfo[i + 1].pc;
325         auto block = &blocks[index++];
326         block->id = blockId++;
327         block->start = startPc;
328         block->end = endPc;
329         block->preds = {};
330         block->succs = {};
331         startPcToBB[startPc] = block;
332         endPcToBB[endPc] = block;
333     }
334 
335     // add block associate
336     for (size_t i = 0; i < bytecodeBlockInfo.size(); i++) {
337         if (bytecodeBlockInfo[i].splitKind == SplitKind::START) {
338             continue;
339         }
340         auto curPc = bytecodeBlockInfo[i].pc;
341         auto &successors = bytecodeBlockInfo[i].succs;
342         for (size_t j = 0; j < successors.size(); j++) {
343             if (successors[j] == curPc) {
344                 continue;
345             }
346             auto curBlock = endPcToBB[curPc];
347             auto succsBlock = startPcToBB[successors[j]];
348             curBlock->succs.emplace_back(succsBlock);
349             succsBlock->preds.emplace_back(curBlock);
350         }
351     }
352 
353     // try catch block associate
354     for (size_t i = 0; i < blocks.size(); i++) {
355         auto pc = blocks[i].start;
356         auto it = exception.begin();
357         for (; it != exception.end(); it++) {
358             if (pc < it->first.first || pc >= it->first.second) { // try block interval
359                 continue;
360             }
361             auto catchs = exception[it->first]; // catchs start pc
362             for (size_t j = i + 1; j < blocks.size(); j++) {
363                 if (std::find(catchs.begin(), catchs.end(), blocks[j].start) != catchs.end()) {
364                     blocks[i].catchs.insert(blocks[i].catchs.begin(), &blocks[j]);
365                     blocks[i].succs.emplace_back(&blocks[j]);
366                     blocks[j].preds.emplace_back(&blocks[i]);
367                 }
368             }
369         }
370     }
371 
372     for (size_t i = 0; i < blocks.size(); i++) {
373         bbIdToBasicBlock_[blocks[i].id] = &blocks[i];
374     }
375 
376 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
377     PrintGraph(byteCodeGraph.graph);
378 #endif
379     ComputeDominatorTree(byteCodeGraph);
380 }
381 
ComputeDominatorTree(BytecodeGraph & byteCodeGraph)382 void BytecodeCircuitBuilder::ComputeDominatorTree(BytecodeGraph &byteCodeGraph)
383 {
384     auto &graph = byteCodeGraph.graph;
385     // Construct graph backward order
386     std::map<size_t, size_t> bbIdToDfsTimestamp; // (basicblock id, dfs order)
387     size_t timestamp = 0;
388     std::deque<size_t> pendingList;
389     std::vector<size_t> visited(graph.size(), 0);
390     auto basicBlockId = graph[0].id;
391     pendingList.push_back(basicBlockId);
392     while (!pendingList.empty()) {
393         auto &curBlockId = pendingList.back();
394         pendingList.pop_back();
395         bbIdToDfsTimestamp[curBlockId] = timestamp++;
396         for (auto &succBlock: graph[curBlockId].succs) {
397             if (visited[succBlock->id] == 0) {
398                 visited[succBlock->id] = 1;
399                 pendingList.push_back(succBlock->id);
400             }
401         }
402     }
403 
404     RemoveDeadRegions(bbIdToDfsTimestamp, byteCodeGraph);
405 
406 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
407     // print cfg order
408     for (auto iter : bbIdToDfsTimestamp) {
409         std::cout << "BB_" << iter.first << " depth is : " << iter.second << std::endl;
410     }
411 #endif
412     std::vector<int32_t> immDom(graph.size()); // immediate dominator
413     std::vector<std::vector<size_t>> doms(graph.size()); // dominators set
414     doms[0] = {0};
415     for (size_t i = 1; i < doms.size(); i++) {
416         doms[i].resize(doms.size());
417         std::iota(doms[i].begin(), doms[i].end(), 0);
418     }
419     bool changed = true;
420     while (changed) {
421         changed = false;
422         for (size_t i = 1; i < doms.size(); i++) {
423             if (graph[i].isDead) {
424                 continue;
425             }
426             auto &curDom = doms[i];
427             size_t curDomSize = curDom.size();
428             curDom.resize(doms.size());
429             std::iota(curDom.begin(), curDom.end(), 0);
430             // traverse the predecessor nodes of the current node, Computing Dominators
431             for (auto &preBlock : graph[i].preds) {
432                 std::vector<size_t> tmp(curDom.size());
433                 auto preDom = doms[preBlock->id];
434                 auto it = std::set_intersection(curDom.begin(), curDom.end(), preDom.begin(), preDom.end(),
435                                                 tmp.begin());
436                 tmp.resize(it - tmp.begin());
437                 curDom = tmp;
438             }
439             auto it = std::find(curDom.begin(), curDom.end(), i);
440             if (it == curDom.end()) {
441                 curDom.push_back(i);
442                 std::sort(curDom.begin(), curDom.end());
443             }
444 
445             if (doms[i].size() != curDomSize) {
446                 changed = true;
447             }
448         }
449     }
450 
451 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
452     // print dominators set
453     for (size_t i = 0; i < doms.size(); i++) {
454         std::cout << "block " << i << " dominator blocks has: ";
455         for (auto j: doms[i]) {
456             std::cout << j << " , ";
457         }
458         std::cout << std::endl;
459     }
460 #endif
461 
462     // compute immediate dominator
463     immDom[0] = doms[0].front();
464     for (size_t i = 1; i < doms.size(); i++) {
465         if (graph[i].isDead) {
466             continue;
467         }
468         auto it = std::remove(doms[i].begin(), doms[i].end(), i);
469         doms[i].resize(it - doms[i].begin());
470         immDom[i] = *std::max_element(
471             doms[i].begin(), doms[i].end(), [graph, bbIdToDfsTimestamp](size_t lhs, size_t rhs) -> bool {
472                 return bbIdToDfsTimestamp.at(graph[lhs].id) < bbIdToDfsTimestamp.at(graph[rhs].id);
473             });
474     }
475 
476 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
477     // print immediate dominator
478     for (size_t i = 0; i < immDom.size(); i++) {
479         std::cout << i << " immediate dominator: " << immDom[i] << std::endl;
480     }
481     PrintGraph(graph);
482 #endif
483     BuildImmediateDominator(immDom, byteCodeGraph);
484 }
485 
BuildImmediateDominator(std::vector<int32_t> & immDom,BytecodeGraph & byteCodeGraph)486 void BytecodeCircuitBuilder::BuildImmediateDominator(std::vector<int32_t> &immDom, BytecodeGraph &byteCodeGraph)
487 {
488     auto &graph = byteCodeGraph.graph;
489 
490     graph[0].iDominator = &graph[0];
491     for (size_t i = 1; i < immDom.size(); i++) {
492         auto dominatedBlock = bbIdToBasicBlock_.at(i);
493         if (dominatedBlock->isDead) {
494             continue;
495         }
496         auto immDomBlock = bbIdToBasicBlock_.at(immDom[i]);
497         dominatedBlock->iDominator = immDomBlock;
498     }
499 
500 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
501     for (auto block : graph) {
502         if (block.isDead) {
503             continue;
504         }
505         std::cout << "current block " << block.id
506                   << " immediate dominator block id: " << block.iDominator->id << std::endl;
507     }
508 #endif
509 
510     for (auto &block : graph) {
511         if (block.isDead) {
512             continue;
513         }
514         if (block.iDominator->id != block.id) {
515             block.iDominator->immDomBlocks.emplace_back(&block);
516         }
517     }
518 
519 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
520     for (auto &block : graph) {
521         if (block.isDead) {
522             continue;
523         }
524         std::cout << "block " << block.id << " dominate block has: ";
525         for (size_t i = 0; i < block.immDomBlocks.size(); i++) {
526             std::cout << block.immDomBlocks[i]->id << ",";
527         }
528         std::cout << std::endl;
529     }
530 #endif
531     ComputeDomFrontiers(immDom, byteCodeGraph);
532     InsertPhi(byteCodeGraph);
533     UpdateCFG(byteCodeGraph);
534     BuildCircuit(byteCodeGraph);
535 }
536 
ComputeDomFrontiers(std::vector<int32_t> & immDom,BytecodeGraph & byteCodeGraph)537 void BytecodeCircuitBuilder::ComputeDomFrontiers(std::vector<int32_t> &immDom, BytecodeGraph &byteCodeGraph)
538 {
539     auto &graph = byteCodeGraph.graph;
540     std::vector<std::set<BytecodeRegion *>> domFrontiers(immDom.size());
541     for (auto &bb : graph) {
542         if (bb.isDead) {
543             continue;
544         }
545         if (bb.preds.size() < 2) { // 2: pred num
546             continue;
547         }
548         for (size_t i = 0; i < bb.preds.size(); i++) {
549             auto runner = bb.preds[i];
550             while (runner->id != immDom[bb.id]) {
551                 domFrontiers[runner->id].insert(&bb);
552                 runner = bbIdToBasicBlock_.at(immDom[runner->id]);
553             }
554         }
555     }
556 
557     for (size_t i = 0; i < domFrontiers.size(); i++) {
558         for (auto iter = domFrontiers[i].begin(); iter != domFrontiers[i].end(); iter++) {
559             graph[i].domFrontiers.emplace_back(*iter);
560         }
561     }
562 
563 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
564     for (size_t i = 0; i < domFrontiers.size(); i++) {
565         std::cout << "basic block " << i << " dominate Frontiers is: ";
566         for (auto iter = domFrontiers[i].begin(); iter != domFrontiers[i].end(); iter++) {
567             std::cout << (*iter)->id << " , ";
568         }
569         std::cout << std::endl;
570     }
571 #endif
572 }
573 
RemoveDeadRegions(const std::map<size_t,size_t> & bbIdToDfsTimestamp,BytecodeGraph & byteCodeGraph)574 void BytecodeCircuitBuilder::RemoveDeadRegions(const std::map<size_t, size_t> &bbIdToDfsTimestamp,
575                                                BytecodeGraph &byteCodeGraph)
576 {
577     auto &graph = byteCodeGraph.graph;
578     for (auto &block: graph) {
579         std::vector<BytecodeRegion *> newPreds;
580         for (auto &bb : block.preds) {
581             if (bbIdToDfsTimestamp.count(bb->id)) {
582                 newPreds.emplace_back(bb);
583             }
584         }
585         block.preds = newPreds;
586     }
587 
588     for (auto &block : graph) {
589         block.isDead = !bbIdToDfsTimestamp.count(block.id);
590         if (block.isDead) {
591             block.succs.clear();
592         }
593     }
594 }
595 
GetBytecodeInfo(uint8_t * pc)596 BytecodeInfo BytecodeCircuitBuilder::GetBytecodeInfo(uint8_t *pc)
597 {
598     BytecodeInfo info;
599     auto opcode = static_cast<EcmaOpcode>(*pc);
600     info.opcode = opcode;
601     switch (opcode) {
602         case EcmaOpcode::MOV_V4_V4: {
603             uint16_t vdst = READ_INST_4_0();
604             uint16_t vsrc = READ_INST_4_1();
605             info.vregIn.emplace_back(vsrc);
606             info.vregOut.emplace_back(vdst);
607             info.offset = BytecodeOffset::TWO;
608             break;
609         }
610         case EcmaOpcode::MOV_DYN_V8_V8: {
611             uint16_t vdst = READ_INST_8_0();
612             uint16_t vsrc = READ_INST_8_1();
613             info.vregIn.emplace_back(vsrc);
614             info.vregOut.emplace_back(vdst);
615             info.offset = BytecodeOffset::THREE;
616             break;
617         }
618         case EcmaOpcode::MOV_DYN_V16_V16: {
619             uint16_t vdst = READ_INST_16_0();
620             uint16_t vsrc = READ_INST_16_2();
621             info.vregIn.emplace_back(vsrc);
622             info.vregOut.emplace_back(vdst);
623             info.offset = BytecodeOffset::FIVE;
624             break;
625         }
626         case EcmaOpcode::LDA_STR_ID32: {
627             info.accOut = true;
628             info.offset = BytecodeOffset::FIVE;
629             break;
630         }
631         case EcmaOpcode::JMP_IMM8: {
632             info.offset = BytecodeOffset::TWO;
633             break;
634         }
635         case EcmaOpcode::JMP_IMM16: {
636             info.offset = BytecodeOffset::THREE;
637             break;
638         }
639         case EcmaOpcode::JMP_IMM32: {
640             info.offset = BytecodeOffset::FIVE;
641             break;
642         }
643         case EcmaOpcode::JEQZ_IMM8: {
644             info.accIn = true;
645             info.offset = BytecodeOffset::TWO;
646             break;
647         }
648         case EcmaOpcode::JEQZ_IMM16: {
649             info.accIn = true;
650             info.offset = BytecodeOffset::THREE;
651             break;
652         }
653         case EcmaOpcode::JNEZ_IMM8: {
654             info.accIn = true;
655             info.offset = BytecodeOffset::TWO;
656             break;
657         }
658         case EcmaOpcode::JNEZ_IMM16: {
659             info.accIn = true;
660             info.offset = BytecodeOffset::THREE;
661             break;
662         }
663         case EcmaOpcode::LDA_DYN_V8: {
664             uint16_t vsrc = READ_INST_8_0();
665             info.vregIn.emplace_back(vsrc);
666             info.accOut = true;
667             info.offset = BytecodeOffset::TWO;
668             break;
669         }
670         case EcmaOpcode::STA_DYN_V8: {
671             uint16_t vdst = READ_INST_8_0();
672             info.vregOut.emplace_back(vdst);
673             info.accIn = true;
674             info.offset = BytecodeOffset::TWO;
675             break;
676         }
677         case EcmaOpcode::LDAI_DYN_IMM32: {
678             info.imm = READ_INST_32_0();
679             info.accOut = true;
680             info.offset = BytecodeOffset::FIVE;
681             break;
682         }
683         case EcmaOpcode::FLDAI_DYN_IMM64: {
684             info.imm = READ_INST_64_0();
685             info.accOut = true;
686             info.offset = BytecodeOffset::NINE;
687             break;
688         }
689         case EcmaOpcode::CALLARG0DYN_PREF_V8: {
690             uint32_t funcReg = READ_INST_8_1();
691             info.vregIn.emplace_back(funcReg);
692             info.accOut = true;
693             info.offset = BytecodeOffset::THREE;
694             break;
695         }
696         case EcmaOpcode::CALLARG1DYN_PREF_V8_V8: {
697             uint32_t funcReg = READ_INST_8_1();
698             uint32_t reg = READ_INST_8_2();
699             info.vregIn.emplace_back(funcReg);
700             info.vregIn.emplace_back(reg);
701             info.accOut = true;
702             info.offset = BytecodeOffset::FOUR;
703             break;
704         }
705         case EcmaOpcode::CALLARGS2DYN_PREF_V8_V8_V8: {
706             uint32_t funcReg = READ_INST_8_1();
707             uint32_t reg = READ_INST_8_3();
708             info.vregIn.emplace_back(funcReg);
709             info.vregIn.emplace_back(reg);
710             info.accOut = true;
711             info.offset = BytecodeOffset::FIVE;
712             break;
713         }
714         case EcmaOpcode::CALLARGS3DYN_PREF_V8_V8_V8_V8: {
715             uint32_t funcReg = READ_INST_8_1();
716             uint32_t reg = READ_INST_8_4();
717             info.vregIn.emplace_back(funcReg);
718             info.vregIn.emplace_back(reg);
719             info.accOut = true;
720             info.offset = BytecodeOffset::SIX;
721             break;
722         }
723         case EcmaOpcode::CALLITHISRANGEDYN_PREF_IMM16_V8: {
724             uint32_t funcReg = READ_INST_8_3();
725             uint32_t actualNumArgs = READ_INST_16_1() - 1;
726             size_t copyArgs = actualNumArgs + NUM_MANDATORY_JSFUNC_ARGS - 2;
727             info.vregIn.emplace_back(funcReg);
728             for (size_t i = 1; i <= copyArgs; i++) {
729                 info.vregIn.emplace_back(funcReg + i);
730             }
731             info.accOut = true;
732             info.offset = BytecodeOffset::FIVE;
733             break;
734         }
735         case EcmaOpcode::CALLSPREADDYN_PREF_V8_V8_V8: {
736             uint16_t v0 = READ_INST_8_1();
737             uint16_t v1 = READ_INST_8_2();
738             uint16_t v2 = READ_INST_8_3();
739             info.vregIn.emplace_back(v0);
740             info.vregIn.emplace_back(v1);
741             info.vregIn.emplace_back(v2);
742             info.accOut = true;
743             info.offset = BytecodeOffset::FIVE;
744             break;
745         }
746         case EcmaOpcode::CALLIRANGEDYN_PREF_IMM16_V8: {
747             uint32_t funcReg = READ_INST_8_3();
748             uint32_t actualNumArgs = READ_INST_16_1();
749             size_t copyArgs = actualNumArgs + NUM_MANDATORY_JSFUNC_ARGS - 2;
750             info.vregIn.emplace_back(funcReg);
751             for (size_t i = 1; i <= copyArgs; i++) {
752                 info.vregIn.emplace_back(funcReg + i);
753             }
754             info.accOut = true;
755             info.offset = BytecodeOffset::FIVE;
756             break;
757         }
758         case EcmaOpcode::RETURN_DYN: {
759             info.accIn = true;
760             info.accOut = true;
761             info.offset = BytecodeOffset::ONE;
762             break;
763         }
764         case EcmaOpcode::RETURNUNDEFINED_PREF: {
765             info.accIn = true;
766             info.accOut = true;
767             info.offset = BytecodeOffset::TWO;
768             break;
769         }
770         case EcmaOpcode::LDNAN_PREF: {
771             info.accOut = true;
772             info.offset = BytecodeOffset::TWO;
773             info.imm = static_cast<uint64_t>(panda::ecmascript::base::NAN_VALUE);
774             break;
775         }
776         case EcmaOpcode::LDINFINITY_PREF: {
777             info.accOut = true;
778             info.offset = BytecodeOffset::TWO;
779             info.imm = static_cast<uint64_t>(panda::ecmascript::base::POSITIVE_INFINITY);
780             break;
781         }
782         case EcmaOpcode::LDGLOBALTHIS_PREF: {
783             info.accOut = true;
784             info.offset = BytecodeOffset::TWO;
785             break;
786         }
787         case EcmaOpcode::LDUNDEFINED_PREF: {
788             info.accOut = true;
789             info.offset = BytecodeOffset::TWO;
790             info.imm = JSTaggedValue::VALUE_UNDEFINED;
791             break;
792         }
793         case EcmaOpcode::LDNULL_PREF: {
794             info.accOut = true;
795             info.offset = BytecodeOffset::TWO;
796             info.imm = JSTaggedValue::VALUE_NULL;
797             break;
798         }
799         case EcmaOpcode::LDSYMBOL_PREF: {
800             info.accOut = true;
801             info.offset = BytecodeOffset::TWO;
802             break;
803         }
804         case EcmaOpcode::LDGLOBAL_PREF: {
805             info.accOut = true;
806             info.offset = BytecodeOffset::TWO;
807             break;
808         }
809         case EcmaOpcode::LDTRUE_PREF: {
810             info.accOut = true;
811             info.offset = BytecodeOffset::TWO;
812             info.imm = JSTaggedValue::VALUE_TRUE;
813             break;
814         }
815         case EcmaOpcode::LDFALSE_PREF: {
816             info.accOut = true;
817             info.offset = BytecodeOffset::TWO;
818             info.imm = JSTaggedValue::VALUE_FALSE;
819             break;
820         }
821         case EcmaOpcode::LDLEXENVDYN_PREF: {
822             info.accOut = true;
823             info.offset = BytecodeOffset::TWO;
824             break;
825         }
826         case EcmaOpcode::GETUNMAPPEDARGS_PREF: {
827             info.accOut = true;
828             info.offset = BytecodeOffset::TWO;
829             break;
830         }
831         case EcmaOpcode::ASYNCFUNCTIONENTER_PREF: {
832             info.accOut = true;
833             info.offset = BytecodeOffset::TWO;
834             break;
835         }
836         case EcmaOpcode::TONUMBER_PREF_V8: {
837             uint16_t v0 = READ_INST_8_1();
838             info.vregIn.emplace_back(v0);
839             info.accOut = true;
840             info.offset = BytecodeOffset::THREE;
841             break;
842         }
843         case EcmaOpcode::NEGDYN_PREF_V8: {
844             uint16_t v0 = READ_INST_8_1();
845             info.vregIn.emplace_back(v0);
846             info.accOut = true;
847             info.offset = BytecodeOffset::THREE;
848             break;
849         }
850         case EcmaOpcode::NOTDYN_PREF_V8: {
851             uint16_t v0 = READ_INST_8_1();
852             info.vregIn.emplace_back(v0);
853             info.accOut = true;
854             info.offset = BytecodeOffset::THREE;
855             break;
856         }
857         case EcmaOpcode::INCDYN_PREF_V8: {
858             uint16_t v0 = READ_INST_8_1();
859             info.vregIn.emplace_back(v0);
860             info.accOut = true;
861             info.offset = BytecodeOffset::THREE;
862             break;
863         }
864         case EcmaOpcode::DECDYN_PREF_V8: {
865             uint16_t v0 = READ_INST_8_1();
866             info.vregIn.emplace_back(v0);
867             info.accOut = true;
868             info.offset = BytecodeOffset::THREE;
869             break;
870         }
871         case EcmaOpcode::THROWDYN_PREF: {
872             info.accIn = true;
873             info.offset = BytecodeOffset::TWO;
874             break;
875         }
876         case EcmaOpcode::TYPEOFDYN_PREF: {
877             info.accIn = true;
878             info.accOut = true;
879             info.offset = BytecodeOffset::TWO;
880             break;
881         }
882         case EcmaOpcode::GETPROPITERATOR_PREF: {
883             info.accIn = true;
884             info.accOut = true;
885             info.offset = BytecodeOffset::TWO;
886             break;
887         }
888         case EcmaOpcode::RESUMEGENERATOR_PREF_V8: {
889             uint16_t vs = READ_INST_8_1();
890             info.vregIn.emplace_back(vs);
891             info.accOut = true;
892             info.offset = BytecodeOffset::THREE;
893             break;
894         }
895         case EcmaOpcode::GETRESUMEMODE_PREF_V8: {
896             uint16_t vs = READ_INST_8_1();
897             info.vregIn.emplace_back(vs);
898             info.accOut = true;
899             info.offset = BytecodeOffset::THREE;
900             break;
901         }
902         case EcmaOpcode::GETITERATOR_PREF: {
903             info.accIn = true;
904             info.accOut = true;
905             info.offset = BytecodeOffset::TWO;
906             break;
907         }
908         case EcmaOpcode::THROWCONSTASSIGNMENT_PREF_V8: {
909             uint16_t v0 = READ_INST_8_1();
910             info.vregIn.emplace_back(v0);
911             info.offset = BytecodeOffset::THREE;
912             break;
913         }
914         case EcmaOpcode::THROWTHROWNOTEXISTS_PREF: {
915             info.offset = BytecodeOffset::TWO;
916             break;
917         }
918         case EcmaOpcode::THROWPATTERNNONCOERCIBLE_PREF: {
919             info.offset = BytecodeOffset::TWO;
920             break;
921         }
922         case EcmaOpcode::THROWIFNOTOBJECT_PREF_V8: {
923             uint16_t v0 = READ_INST_8_1();
924             info.vregIn.emplace_back(v0);
925             info.offset = BytecodeOffset::THREE;
926             break;
927         }
928         case EcmaOpcode::ITERNEXT_PREF_V8: {
929             uint16_t v0 = READ_INST_8_1();
930             info.vregIn.emplace_back(v0);
931             info.accOut = true;
932             info.offset = BytecodeOffset::THREE;
933             break;
934         }
935         case EcmaOpcode::CLOSEITERATOR_PREF_V8: {
936             uint16_t v0 = READ_INST_8_1();
937             info.vregIn.emplace_back(v0);
938             info.accOut = true;
939             info.offset = BytecodeOffset::THREE;
940             break;
941         }
942         case EcmaOpcode::ADD2DYN_PREF_V8: {
943             uint16_t v0 = READ_INST_8_1();
944             info.vregIn.emplace_back(v0);
945             info.accIn = true;
946             info.accOut = true;
947             info.offset = BytecodeOffset::THREE;
948             break;
949         }
950         case EcmaOpcode::SUB2DYN_PREF_V8: {
951             uint16_t v0 = READ_INST_8_1();
952             info.vregIn.emplace_back(v0);
953             info.accIn = true;
954             info.accOut = true;
955             info.offset = BytecodeOffset::THREE;
956             break;
957         }
958         case EcmaOpcode::MUL2DYN_PREF_V8: {
959             uint16_t v0 = READ_INST_8_1();
960             info.vregIn.emplace_back(v0);
961             info.accIn = true;
962             info.accOut = true;
963             info.offset = BytecodeOffset::THREE;
964             break;
965         }
966         case EcmaOpcode::DIV2DYN_PREF_V8: {
967             uint16_t v0 = READ_INST_8_1();
968             info.vregIn.emplace_back(v0);
969             info.accIn = true;
970             info.accOut = true;
971             info.offset = BytecodeOffset::THREE;
972             break;
973         }
974         case EcmaOpcode::MOD2DYN_PREF_V8: {
975             uint16_t v0 = READ_INST_8_1();
976             info.vregIn.emplace_back(v0);
977             info.accIn = true;
978             info.accOut = true;
979             info.offset = BytecodeOffset::THREE;
980             break;
981         }
982         case EcmaOpcode::EQDYN_PREF_V8: {
983             uint16_t v0 = READ_INST_8_1();
984             info.vregIn.emplace_back(v0);
985             info.accIn = true;
986             info.accOut = true;
987             info.offset = BytecodeOffset::THREE;
988             break;
989         }
990         case EcmaOpcode::NOTEQDYN_PREF_V8: {
991             uint16_t v0 = READ_INST_8_1();
992             info.vregIn.emplace_back(v0);
993             info.accIn = true;
994             info.accOut = true;
995             info.offset = BytecodeOffset::THREE;
996             break;
997         }
998         case EcmaOpcode::LESSDYN_PREF_V8: {
999             uint16_t v0 = READ_INST_8_1();
1000             info.vregIn.emplace_back(v0);
1001             info.accIn = true;
1002             info.accOut = true;
1003             info.offset = BytecodeOffset::THREE;
1004             break;
1005         }
1006         case EcmaOpcode::LESSEQDYN_PREF_V8: {
1007             uint16_t v0 = READ_INST_8_1();
1008             info.vregIn.emplace_back(v0);
1009             info.accIn = true;
1010             info.accOut = true;
1011             info.offset = BytecodeOffset::THREE;
1012             break;
1013         }
1014         case EcmaOpcode::GREATERDYN_PREF_V8: {
1015             uint16_t v0 = READ_INST_8_1();
1016             info.vregIn.emplace_back(v0);
1017             info.accIn = true;
1018             info.accOut = true;
1019             info.offset = BytecodeOffset::THREE;
1020             break;
1021         }
1022         case EcmaOpcode::GREATEREQDYN_PREF_V8: {
1023             uint16_t vs = READ_INST_8_1();
1024             info.vregIn.emplace_back(vs);
1025             info.accIn = true;
1026             info.accOut = true;
1027             info.offset = BytecodeOffset::THREE;
1028             break;
1029         }
1030         case EcmaOpcode::SHL2DYN_PREF_V8: {
1031             uint16_t v0 = READ_INST_8_1();
1032             info.vregIn.emplace_back(v0);
1033             info.accIn = true;
1034             info.accOut = true;
1035             info.offset = BytecodeOffset::THREE;
1036             break;
1037         }
1038         case EcmaOpcode::SHR2DYN_PREF_V8: {
1039             uint16_t v0 = READ_INST_8_1();
1040             info.vregIn.emplace_back(v0);
1041             info.accIn = true;
1042             info.accOut = true;
1043             info.offset = BytecodeOffset::THREE;
1044             break;
1045         }
1046         case EcmaOpcode::ASHR2DYN_PREF_V8: {
1047             uint16_t v0 = READ_INST_8_1();
1048             info.vregIn.emplace_back(v0);
1049             info.accIn = true;
1050             info.accOut = true;
1051             info.offset = BytecodeOffset::THREE;
1052             break;
1053         }
1054         case EcmaOpcode::AND2DYN_PREF_V8: {
1055             uint16_t v0 = READ_INST_8_1();
1056             info.vregIn.emplace_back(v0);
1057             info.accIn = true;
1058             info.accOut = true;
1059             info.offset = BytecodeOffset::THREE;
1060             break;
1061         }
1062         case EcmaOpcode::OR2DYN_PREF_V8: {
1063             uint16_t v0 = READ_INST_8_1();
1064             info.vregIn.emplace_back(v0);
1065             info.accIn = true;
1066             info.accOut = true;
1067             info.offset = BytecodeOffset::THREE;
1068             break;
1069         }
1070         case EcmaOpcode::XOR2DYN_PREF_V8: {
1071             uint16_t v0 = READ_INST_8_1();
1072             info.vregIn.emplace_back(v0);
1073             info.accIn = true;
1074             info.accOut = true;
1075             info.offset = BytecodeOffset::THREE;
1076             break;
1077         }
1078         case EcmaOpcode::DELOBJPROP_PREF_V8_V8: {
1079             uint16_t v0 = READ_INST_8_1();
1080             uint16_t v1 = READ_INST_8_2();
1081             info.vregIn.emplace_back(v0);
1082             info.vregIn.emplace_back(v1);
1083             info.accOut = true;
1084             info.offset = BytecodeOffset::FOUR;
1085             break;
1086         }
1087         case EcmaOpcode::DEFINEFUNCDYN_PREF_ID16_IMM16_V8: {
1088             uint16_t v0 = READ_INST_8_5();
1089             info.vregIn.emplace_back(v0);
1090             info.accOut = true;
1091             info.offset = BytecodeOffset::SEVEN;
1092             break;
1093         }
1094         case EcmaOpcode::DEFINENCFUNCDYN_PREF_ID16_IMM16_V8: {
1095             uint16_t v0 = READ_INST_8_5();
1096             info.vregIn.emplace_back(v0);
1097             info.accIn = true;
1098             info.accOut = true;
1099             info.offset = BytecodeOffset::SEVEN;
1100             break;
1101         }
1102         case EcmaOpcode::DEFINEMETHOD_PREF_ID16_IMM16_V8: {
1103             uint16_t v0 = READ_INST_8_5();
1104             info.vregIn.emplace_back(v0);
1105             info.accIn = true;
1106             info.accOut = true;
1107             info.offset = BytecodeOffset::SEVEN;
1108             break;
1109         }
1110         case EcmaOpcode::NEWOBJDYNRANGE_PREF_IMM16_V8: {
1111             uint16_t firstArgRegIdx = READ_INST_8_3();
1112             info.vregIn.emplace_back(firstArgRegIdx);
1113             info.vregIn.emplace_back(firstArgRegIdx + 1);
1114             info.accOut = true;
1115             info.offset = BytecodeOffset::FIVE;
1116             break;
1117         }
1118         case EcmaOpcode::EXPDYN_PREF_V8: {
1119             uint16_t v0 = READ_INST_8_1();
1120             info.vregIn.emplace_back(v0);
1121             info.accIn = true;
1122             info.accOut = true;
1123             info.offset = BytecodeOffset::THREE;
1124             break;
1125         }
1126         case EcmaOpcode::ISINDYN_PREF_V8: {
1127             uint16_t v0 = READ_INST_8_1();
1128             info.vregIn.emplace_back(v0);
1129             info.accIn = true;
1130             info.accOut = true;
1131             info.offset = BytecodeOffset::THREE;
1132             break;
1133         }
1134         case EcmaOpcode::INSTANCEOFDYN_PREF_V8: {
1135             uint16_t v0 = READ_INST_8_1();
1136             info.vregIn.emplace_back(v0);
1137             info.accIn = true;
1138             info.accOut = true;
1139             info.offset = BytecodeOffset::THREE;
1140             break;
1141         }
1142         case EcmaOpcode::STRICTNOTEQDYN_PREF_V8: {
1143             uint16_t v0 = READ_INST_8_1();
1144             info.vregIn.emplace_back(v0);
1145             info.accIn = true;
1146             info.accOut = true;
1147             info.offset = BytecodeOffset::THREE;
1148             break;
1149         }
1150         case EcmaOpcode::STRICTEQDYN_PREF_V8: {
1151             uint16_t v0 = READ_INST_8_1();
1152             info.vregIn.emplace_back(v0);
1153             info.accIn = true;
1154             info.accOut = true;
1155             info.offset = BytecodeOffset::THREE;
1156             break;
1157         }
1158         case EcmaOpcode::LDLEXVARDYN_PREF_IMM16_IMM16: {
1159             info.accOut = true;
1160             info.offset = BytecodeOffset::SIX;
1161             break;
1162         }
1163         case EcmaOpcode::LDLEXVARDYN_PREF_IMM8_IMM8: {
1164             info.accOut = true;
1165             info.offset = BytecodeOffset::FOUR;
1166             break;
1167         }
1168         case EcmaOpcode::LDLEXVARDYN_PREF_IMM4_IMM4: {
1169             info.accOut = true;
1170             info.offset = BytecodeOffset::THREE;
1171             break;
1172         }
1173         case EcmaOpcode::STLEXVARDYN_PREF_IMM16_IMM16_V8: {
1174             uint16_t v0 = READ_INST_8_5();
1175             info.vregIn.emplace_back(v0);
1176             info.offset = BytecodeOffset::SEVEN;
1177             break;
1178         }
1179         case EcmaOpcode::STLEXVARDYN_PREF_IMM8_IMM8_V8: {
1180             uint16_t v0 = READ_INST_8_3();
1181             info.vregIn.emplace_back(v0);
1182             info.offset = BytecodeOffset::FIVE;
1183             break;
1184         }
1185         case EcmaOpcode::STLEXVARDYN_PREF_IMM4_IMM4_V8: {
1186             uint16_t v0 = READ_INST_8_2();
1187             info.vregIn.emplace_back(v0);
1188             info.offset = BytecodeOffset::FOUR;
1189             break;
1190         }
1191         case EcmaOpcode::NEWLEXENVDYN_PREF_IMM16: {
1192             info.accOut = true;
1193             info.offset = BytecodeOffset::FOUR;
1194             break;
1195         }
1196         case EcmaOpcode::POPLEXENVDYN_PREF: {
1197             info.offset = BytecodeOffset::TWO;
1198             break;
1199         }
1200         case EcmaOpcode::CREATEITERRESULTOBJ_PREF_V8_V8: {
1201             uint16_t v0 = READ_INST_8_1();
1202             uint16_t v1 = READ_INST_8_2();
1203             info.vregIn.emplace_back(v0);
1204             info.vregIn.emplace_back(v1);
1205             info.accOut = true;
1206             info.offset = BytecodeOffset::FOUR;
1207             break;
1208         }
1209         case EcmaOpcode::SUSPENDGENERATOR_PREF_V8_V8: {
1210             uint16_t v0 = READ_INST_8_1();
1211             uint16_t v1 = READ_INST_8_2();
1212             info.vregIn.emplace_back(v0);
1213             info.vregIn.emplace_back(v1);
1214             info.accIn = true;
1215             info.accOut = true;
1216             info.offset = BytecodeOffset::FOUR;
1217             break;
1218         }
1219         case EcmaOpcode::ASYNCFUNCTIONAWAITUNCAUGHT_PREF_V8_V8: {
1220             uint16_t v0 = READ_INST_8_1();
1221             uint16_t v1 = READ_INST_8_2();
1222             info.vregIn.emplace_back(v0);
1223             info.vregIn.emplace_back(v1);
1224             info.accOut = true;
1225             info.offset = BytecodeOffset::FOUR;
1226             break;
1227         }
1228         case EcmaOpcode::ASYNCFUNCTIONRESOLVE_PREF_V8_V8_V8: {
1229             uint16_t v0 = READ_INST_8_1();
1230             uint16_t v2 = READ_INST_8_3();
1231             info.vregIn.emplace_back(v0);
1232             info.vregIn.emplace_back(v2);
1233             info.accOut = true;
1234             info.offset = BytecodeOffset::FIVE;
1235             break;
1236         }
1237         case EcmaOpcode::ASYNCFUNCTIONREJECT_PREF_V8_V8_V8: {
1238             uint16_t v0 = READ_INST_8_1();
1239             uint16_t v2 = READ_INST_8_3();
1240             info.vregIn.emplace_back(v0);
1241             info.vregIn.emplace_back(v2);
1242             info.offset = BytecodeOffset::FIVE;
1243             break;
1244         }
1245         case EcmaOpcode::NEWOBJSPREADDYN_PREF_V8_V8: {
1246             uint16_t v0 = READ_INST_8_1();
1247             uint16_t v1 = READ_INST_8_2();
1248             info.vregIn.emplace_back(v0);
1249             info.vregIn.emplace_back(v1);
1250             info.accIn = true;
1251             info.accOut = true;
1252             info.offset = BytecodeOffset::FOUR;
1253             break;
1254         }
1255         case EcmaOpcode::THROWUNDEFINEDIFHOLE_PREF_V8_V8: {
1256             uint16_t v0 = READ_INST_8_1();
1257             uint16_t v1 = READ_INST_8_2();
1258             info.vregIn.emplace_back(v0);
1259             info.vregIn.emplace_back(v1);
1260             info.offset = BytecodeOffset::FOUR;
1261             break;
1262         }
1263         case EcmaOpcode::STOWNBYNAME_PREF_ID32_V8: {
1264             uint32_t v0 = READ_INST_8_5();
1265             info.vregIn.emplace_back(v0);
1266             info.accIn = true;
1267             info.offset = BytecodeOffset::SEVEN;
1268             break;
1269         }
1270         case EcmaOpcode::CREATEEMPTYARRAY_PREF: {
1271             info.accOut = true;
1272             info.offset = BytecodeOffset::TWO;
1273             break;
1274         }
1275         case EcmaOpcode::CREATEEMPTYOBJECT_PREF: {
1276             info.accOut = true;
1277             info.offset = BytecodeOffset::TWO;
1278             break;
1279         }
1280         case EcmaOpcode::CREATEOBJECTWITHBUFFER_PREF_IMM16: {
1281             info.accOut = true;
1282             info.offset = BytecodeOffset::FOUR;
1283             break;
1284         }
1285         case EcmaOpcode::SETOBJECTWITHPROTO_PREF_V8_V8: {
1286             uint16_t v0 = READ_INST_8_1();
1287             uint16_t v1 = READ_INST_8_2();
1288             info.vregIn.emplace_back(v0);
1289             info.vregIn.emplace_back(v1);
1290             info.offset = BytecodeOffset::FOUR;
1291             break;
1292         }
1293         case EcmaOpcode::CREATEARRAYWITHBUFFER_PREF_IMM16: {
1294             info.accOut = true;
1295             info.offset = BytecodeOffset::FOUR;
1296             break;
1297         }
1298         case EcmaOpcode::IMPORTMODULE_PREF_ID32: {
1299             info.accOut = true;
1300             info.offset = BytecodeOffset::SIX;
1301             break;
1302         }
1303         case EcmaOpcode::STMODULEVAR_PREF_ID32: {
1304             info.accIn = true;
1305             info.offset = BytecodeOffset::SIX;
1306             break;
1307         }
1308         case EcmaOpcode::COPYMODULE_PREF_V8: {
1309             uint16_t v0 = READ_INST_8_1();
1310             info.vregIn.emplace_back(v0);
1311             info.offset = BytecodeOffset::THREE;
1312             break;
1313         }
1314         case EcmaOpcode::LDMODVARBYNAME_PREF_ID32_V8: {
1315             uint32_t v0 = READ_INST_8_5();
1316             info.vregIn.emplace_back(v0);
1317             info.accOut = true;
1318             info.offset = BytecodeOffset::SEVEN;
1319             break;
1320         }
1321         case EcmaOpcode::CREATEREGEXPWITHLITERAL_PREF_ID32_IMM8: {
1322             info.accOut = true;
1323             info.offset = BytecodeOffset::SEVEN;
1324             break;
1325         }
1326         case EcmaOpcode::GETTEMPLATEOBJECT_PREF_V8: {
1327             uint16_t v0 = READ_INST_8_1();
1328             info.vregIn.emplace_back(v0);
1329             info.accOut = true;
1330             info.offset = BytecodeOffset::THREE;
1331             break;
1332         }
1333         case EcmaOpcode::GETNEXTPROPNAME_PREF_V8: {
1334             uint16_t v0 = READ_INST_8_1();
1335             info.vregIn.emplace_back(v0);
1336             info.accOut = true;
1337             info.offset = BytecodeOffset::THREE;
1338             break;
1339         }
1340         case EcmaOpcode::COPYDATAPROPERTIES_PREF_V8_V8: {
1341             uint16_t v0 = READ_INST_8_1();
1342             uint16_t v1 = READ_INST_8_2();
1343             info.vregIn.emplace_back(v0);
1344             info.vregIn.emplace_back(v1);
1345             info.accOut = true;
1346             info.offset = BytecodeOffset::FOUR;
1347             break;
1348         }
1349         case EcmaOpcode::STOWNBYINDEX_PREF_V8_IMM32: {
1350             uint32_t v0 = READ_INST_8_1();
1351             info.vregIn.emplace_back(v0);
1352             info.accIn = true;
1353             info.offset = BytecodeOffset::SEVEN;
1354             break;
1355         }
1356         case EcmaOpcode::STOWNBYVALUE_PREF_V8_V8: {
1357             uint32_t v0 = READ_INST_8_1();
1358             uint32_t v1 = READ_INST_8_2();
1359             info.vregIn.emplace_back(v0);
1360             info.vregIn.emplace_back(v1);
1361             info.accIn = true;
1362             info.offset = BytecodeOffset::FOUR;
1363             break;
1364         }
1365         case EcmaOpcode::CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8: {
1366             uint16_t v0 = READ_INST_8_3();
1367             info.vregIn.emplace_back(v0);
1368             info.accOut = true;
1369             info.offset = BytecodeOffset::SIX;
1370             break;
1371         }
1372         case EcmaOpcode::DEFINEGENERATORFUNC_PREF_ID16_IMM16_V8: {
1373             uint16_t v0 = READ_INST_8_5();
1374             info.vregIn.emplace_back(v0);
1375             info.accOut = true;
1376             info.offset = BytecodeOffset::SEVEN;
1377             break;
1378         }
1379         case EcmaOpcode::DEFINEASYNCFUNC_PREF_ID16_IMM16_V8: {
1380             uint16_t v0 = READ_INST_8_5();
1381             info.vregIn.emplace_back(v0);
1382             info.accOut = true;
1383             info.offset = BytecodeOffset::SEVEN;
1384             break;
1385         }
1386         case EcmaOpcode::LDHOLE_PREF: {
1387             info.accOut = true;
1388             info.offset = BytecodeOffset::TWO;
1389             info.imm = JSTaggedValue::VALUE_HOLE;
1390             break;
1391         }
1392         case EcmaOpcode::COPYRESTARGS_PREF_IMM16: {
1393             info.offset = BytecodeOffset::FOUR;
1394             break;
1395         }
1396         case EcmaOpcode::DEFINEGETTERSETTERBYVALUE_PREF_V8_V8_V8_V8: {
1397             uint16_t v0 = READ_INST_8_1();
1398             uint16_t v1 = READ_INST_8_2();
1399             uint16_t v2 = READ_INST_8_3();
1400             uint16_t v3 = READ_INST_8_4();
1401             info.vregIn.emplace_back(v0);
1402             info.vregIn.emplace_back(v1);
1403             info.vregIn.emplace_back(v2);
1404             info.vregIn.emplace_back(v3);
1405             info.accIn = true;
1406             info.accOut = true;
1407             info.offset = BytecodeOffset::SIX;
1408             break;
1409         }
1410         case EcmaOpcode::LDOBJBYINDEX_PREF_V8_IMM32: {
1411             uint16_t v0 = READ_INST_8_1();
1412             info.vregIn.emplace_back(v0);
1413             info.accOut = true;
1414             info.offset = BytecodeOffset::SEVEN;
1415             break;
1416         }
1417         case EcmaOpcode::STOBJBYINDEX_PREF_V8_IMM32: {
1418             uint16_t v0 = READ_INST_8_1();
1419             info.vregIn.emplace_back(v0);
1420             info.accIn = true;
1421             info.offset = BytecodeOffset::SEVEN;
1422             break;
1423         }
1424         case EcmaOpcode::LDOBJBYVALUE_PREF_V8_V8: {
1425             uint32_t v0 = READ_INST_8_1();
1426             uint32_t v1 = READ_INST_8_2();
1427             info.vregIn.emplace_back(v0);
1428             info.vregIn.emplace_back(v1);
1429             info.accOut = true;
1430             info.offset = BytecodeOffset::FOUR;
1431             break;
1432         }
1433         case EcmaOpcode::STOBJBYVALUE_PREF_V8_V8: {
1434             uint32_t v0 = READ_INST_8_1();
1435             uint32_t v1 = READ_INST_8_2();
1436             info.vregIn.emplace_back(v0);
1437             info.vregIn.emplace_back(v1);
1438             info.accIn = true;
1439             info.offset = BytecodeOffset::FOUR;
1440             break;
1441         }
1442         case EcmaOpcode::LDSUPERBYVALUE_PREF_V8_V8: {
1443             uint32_t v0 = READ_INST_8_1();
1444             uint32_t v1 = READ_INST_8_2();
1445             info.vregIn.emplace_back(v0);
1446             info.vregIn.emplace_back(v1);
1447             info.accOut = true;
1448             info.offset = BytecodeOffset::FOUR;
1449             break;
1450         }
1451         case EcmaOpcode::STSUPERBYVALUE_PREF_V8_V8: {
1452             uint32_t v0 = READ_INST_8_1();
1453             uint32_t v1 = READ_INST_8_2();
1454             info.vregIn.emplace_back(v0);
1455             info.vregIn.emplace_back(v1);
1456             info.accIn = true;
1457             info.offset = BytecodeOffset::FOUR;
1458             break;
1459         }
1460         case EcmaOpcode::TRYLDGLOBALBYNAME_PREF_ID32: {
1461             info.accOut = true;
1462             info.offset = BytecodeOffset::SIX;
1463             break;
1464         }
1465         case EcmaOpcode::TRYSTGLOBALBYNAME_PREF_ID32: {
1466             info.accIn = true;
1467             info.offset = BytecodeOffset::SIX;
1468             break;
1469         }
1470         case EcmaOpcode::STCONSTTOGLOBALRECORD_PREF_ID32: {
1471             info.accIn = true;
1472             info.offset = BytecodeOffset::SIX;
1473             break;
1474         }
1475         case EcmaOpcode::STLETTOGLOBALRECORD_PREF_ID32: {
1476             info.accIn = true;
1477             info.offset = BytecodeOffset::SIX;
1478             break;
1479         }
1480         case EcmaOpcode::STCLASSTOGLOBALRECORD_PREF_ID32: {
1481             info.accIn = true;
1482             info.offset = BytecodeOffset::SIX;
1483             break;
1484         }
1485         case EcmaOpcode::STOWNBYVALUEWITHNAMESET_PREF_V8_V8: {
1486             uint32_t v0 = READ_INST_8_1();
1487             uint32_t v1 = READ_INST_8_2();
1488             info.vregIn.emplace_back(v0);
1489             info.vregIn.emplace_back(v1);
1490             info.accIn = true;
1491             info.offset = BytecodeOffset::FOUR;
1492             break;
1493         }
1494         case EcmaOpcode::STOWNBYNAMEWITHNAMESET_PREF_ID32_V8: {
1495             uint32_t v0 = READ_INST_8_5();
1496             info.vregIn.emplace_back(v0);
1497             info.accIn = true;
1498             info.offset = BytecodeOffset::SEVEN;
1499             break;
1500         }
1501         case EcmaOpcode::LDGLOBALVAR_PREF_ID32: {
1502             info.accOut = true;
1503             info.offset = BytecodeOffset::SIX;
1504             break;
1505         }
1506         case EcmaOpcode::LDOBJBYNAME_PREF_ID32_V8: {
1507             uint32_t v0 = READ_INST_8_5();
1508             info.vregIn.emplace_back(v0);
1509             info.accOut = true;
1510             info.offset = BytecodeOffset::SEVEN;
1511             break;
1512         }
1513         case EcmaOpcode::STOBJBYNAME_PREF_ID32_V8: {
1514             uint32_t v0 = READ_INST_8_5();
1515             info.vregIn.emplace_back(v0);
1516             info.accIn = true;
1517             info.offset = BytecodeOffset::SEVEN;
1518             break;
1519         }
1520         case EcmaOpcode::LDSUPERBYNAME_PREF_ID32_V8: {
1521             uint32_t v0 = READ_INST_8_5();
1522             info.vregIn.emplace_back(v0);
1523             info.accOut = true;
1524             info.offset = BytecodeOffset::SEVEN;
1525             break;
1526         }
1527         case EcmaOpcode::STSUPERBYNAME_PREF_ID32_V8: {
1528             uint32_t v0 = READ_INST_8_5();
1529             info.vregIn.emplace_back(v0);
1530             info.accIn = true;
1531             info.offset = BytecodeOffset::SEVEN;
1532             break;
1533         }
1534         case EcmaOpcode::STGLOBALVAR_PREF_ID32: {
1535             info.accIn = true;
1536             info.offset = BytecodeOffset::SIX;
1537             break;
1538         }
1539         case EcmaOpcode::CREATEGENERATOROBJ_PREF_V8: {
1540             uint16_t v0 = READ_INST_8_1();
1541             info.vregIn.emplace_back(v0);
1542             info.accOut = true;
1543             info.offset = BytecodeOffset::THREE;
1544             break;
1545         }
1546         case EcmaOpcode::STARRAYSPREAD_PREF_V8_V8: {
1547             uint16_t v0 = READ_INST_8_1();
1548             uint16_t v1 = READ_INST_8_2();
1549             info.vregIn.emplace_back(v0);
1550             info.vregIn.emplace_back(v1);
1551             info.accIn = true;
1552             info.accOut = true;
1553             info.offset = BytecodeOffset::FOUR;
1554             break;
1555         }
1556         case EcmaOpcode::GETITERATORNEXT_PREF_V8_V8: {
1557             uint16_t v0 = READ_INST_8_1();
1558             uint16_t v1 = READ_INST_8_2();
1559             info.vregIn.emplace_back(v0);
1560             info.vregIn.emplace_back(v1);
1561             info.accOut = true;
1562             info.offset = BytecodeOffset::FOUR;
1563             break;
1564         }
1565         case EcmaOpcode::DEFINECLASSWITHBUFFER_PREF_ID16_IMM16_IMM16_V8_V8: {
1566             uint16_t v0 = READ_INST_8_7();
1567             uint16_t v1 = READ_INST_8_8();
1568             info.vregIn.emplace_back(v0);
1569             info.vregIn.emplace_back(v1);
1570             info.accOut = true;
1571             info.offset = BytecodeOffset::TEN;
1572             break;
1573         }
1574         case EcmaOpcode::LDFUNCTION_PREF: {
1575             info.accOut = true;
1576             info.offset = BytecodeOffset::TWO;
1577             break;
1578         }
1579         case EcmaOpcode::SUPERCALL_PREF_IMM16_V8: {
1580             info.accIn = true;
1581             info.accOut = true;
1582             info.offset = BytecodeOffset::FIVE;
1583             break;
1584         }
1585         case EcmaOpcode::SUPERCALLSPREAD_PREF_V8: {
1586             uint16_t v0 = READ_INST_8_1();
1587             info.vregIn.emplace_back(v0);
1588             info.accIn = true;
1589             info.accOut = true;
1590             info.offset = BytecodeOffset::THREE;
1591             break;
1592         }
1593         case EcmaOpcode::CREATEOBJECTHAVINGMETHOD_PREF_IMM16: {
1594             info.accIn = true;
1595             info.accOut = true;
1596             info.offset = BytecodeOffset::FOUR;
1597             break;
1598         }
1599         case EcmaOpcode::THROWIFSUPERNOTCORRECTCALL_PREF_IMM16: {
1600             info.accIn = true;
1601             info.offset = BytecodeOffset::FOUR;
1602             break;
1603         }
1604         case EcmaOpcode::LDHOMEOBJECT_PREF: {
1605             info.accOut = true;
1606             info.offset = BytecodeOffset::TWO;
1607             break;
1608         }
1609         case EcmaOpcode::THROWDELETESUPERPROPERTY_PREF: {
1610             info.offset = BytecodeOffset::TWO;
1611             break;
1612         }
1613         case EcmaOpcode::DEBUGGER_PREF: {
1614             info.offset = BytecodeOffset::TWO;
1615             break;
1616         }
1617         case EcmaOpcode::ISTRUE_PREF: {
1618             info.accIn = true;
1619             info.accOut = true;
1620             info.offset = BytecodeOffset::TWO;
1621             break;
1622         }
1623         case EcmaOpcode::ISFALSE_PREF: {
1624             info.accIn = true;
1625             info.accOut = true;
1626             info.offset = BytecodeOffset::TWO;
1627             break;
1628         }
1629         default: {
1630             std::cout << opcode << std::endl;
1631             abort();
1632             break;
1633         }
1634     }
1635     return info;
1636 }
1637 
InsertPhi(BytecodeGraph & byteCodeGraph)1638 void BytecodeCircuitBuilder::InsertPhi(BytecodeGraph &byteCodeGraph)
1639 {
1640     auto &graph = byteCodeGraph.graph;
1641     std::map<uint16_t, std::set<size_t>> defsitesInfo; // <vreg, bbs>
1642     for (auto &bb : graph) {
1643         if (bb.isDead) {
1644             continue;
1645         }
1646         auto pc = bb.start;
1647         while (pc <= bb.end) {
1648             auto bytecodeInfo = GetBytecodeInfo(pc);
1649             pc = pc + bytecodeInfo.offset; // next inst start pc
1650             for (const auto &vreg: bytecodeInfo.vregOut) {
1651                 defsitesInfo[vreg].insert(bb.id);
1652             }
1653         }
1654     }
1655 
1656 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
1657     for (const auto&[variable, defsites] : defsitesInfo) {
1658         std::cout << "variable: " << variable << " locate block have: ";
1659         for (auto id : defsites) {
1660             std::cout << id << " , ";
1661         }
1662         std::cout << std::endl;
1663     }
1664 #endif
1665 
1666     for (const auto&[variable, defsites] : defsitesInfo) {
1667         std::queue<uint16_t> workList;
1668         for (auto blockId: defsites) {
1669             workList.push(blockId);
1670         }
1671         while (!workList.empty()) {
1672             auto currentId = workList.front();
1673             workList.pop();
1674             for (auto &block : graph[currentId].domFrontiers) {
1675                 if (!block->phi.count(variable)) {
1676                     block->phi.insert(variable);
1677                     if (!defsitesInfo[variable].count(block->id)) {
1678                         workList.push(block->id);
1679                     }
1680                 }
1681             }
1682         }
1683     }
1684 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
1685     PrintGraph(graph);
1686 #endif
1687 }
1688 
1689 // Update CFG's predecessor, successor and try catch associations
UpdateCFG(BytecodeGraph & byteCodeGraph)1690 void BytecodeCircuitBuilder::UpdateCFG(BytecodeGraph &byteCodeGraph)
1691 {
1692     auto &graph = byteCodeGraph.graph;
1693     for (auto &bb: graph) {
1694         if (bb.isDead) {
1695             continue;
1696         }
1697         bb.preds.clear();
1698         bb.trys.clear();
1699         std::vector<BytecodeRegion *> newSuccs;
1700         for (const auto &succ: bb.succs) {
1701             if (std::count(bb.catchs.begin(), bb.catchs.end(), succ)) {
1702                 continue;
1703             }
1704             newSuccs.push_back(succ);
1705         }
1706         bb.succs = newSuccs;
1707     }
1708     for (auto &bb: graph) {
1709         if (bb.isDead) {
1710             continue;
1711         }
1712         for (auto &succ: bb.succs) {
1713             succ->preds.push_back(&bb);
1714         }
1715         for (auto &catchBlock: bb.catchs) {
1716             catchBlock->trys.push_back(&bb);
1717         }
1718     }
1719 }
1720 
IsJump(EcmaOpcode opcode)1721 bool BytecodeCircuitBuilder::IsJump(EcmaOpcode opcode)
1722 {
1723     switch (opcode) {
1724         case EcmaOpcode::JMP_IMM8:
1725         case EcmaOpcode::JMP_IMM16:
1726         case EcmaOpcode::JMP_IMM32:
1727         case EcmaOpcode::JEQZ_IMM8:
1728         case EcmaOpcode::JEQZ_IMM16:
1729         case EcmaOpcode::JNEZ_IMM8:
1730         case EcmaOpcode::JNEZ_IMM16:
1731             return true;
1732         default:
1733             return false;
1734     }
1735 }
1736 
IsCondJump(EcmaOpcode opcode)1737 bool BytecodeCircuitBuilder::IsCondJump(EcmaOpcode opcode)
1738 {
1739     switch (opcode) {
1740         case EcmaOpcode::JEQZ_IMM8:
1741         case EcmaOpcode::JEQZ_IMM16:
1742         case EcmaOpcode::JNEZ_IMM8:
1743         case EcmaOpcode::JNEZ_IMM16:
1744             return true;
1745         default:
1746             return false;
1747     }
1748 }
1749 
IsMov(EcmaOpcode opcode)1750 bool BytecodeCircuitBuilder::IsMov(EcmaOpcode opcode)
1751 {
1752     switch (opcode) {
1753         case EcmaOpcode::MOV_V4_V4:
1754         case EcmaOpcode::MOV_DYN_V8_V8:
1755         case EcmaOpcode::MOV_DYN_V16_V16:
1756         case EcmaOpcode::LDA_DYN_V8:
1757         case EcmaOpcode::STA_DYN_V8:
1758             return true;
1759         default:
1760             return false;
1761     }
1762 }
1763 
IsReturn(EcmaOpcode opcode)1764 bool BytecodeCircuitBuilder::IsReturn(EcmaOpcode opcode)
1765 {
1766     switch (opcode) {
1767         case EcmaOpcode::RETURN_DYN:
1768         case EcmaOpcode::RETURNUNDEFINED_PREF:
1769             return true;
1770         default:
1771             return false;
1772     }
1773 }
1774 
IsThrow(EcmaOpcode opcode)1775 bool BytecodeCircuitBuilder::IsThrow(EcmaOpcode opcode)
1776 {
1777     switch (opcode) {
1778         case EcmaOpcode::THROWDYN_PREF:
1779         case EcmaOpcode::THROWCONSTASSIGNMENT_PREF_V8:
1780         case EcmaOpcode::THROWTHROWNOTEXISTS_PREF:
1781         case EcmaOpcode::THROWPATTERNNONCOERCIBLE_PREF:
1782         case EcmaOpcode::THROWDELETESUPERPROPERTY_PREF:
1783             return true;
1784         default:
1785             return false;
1786     }
1787 }
1788 
IsGeneral(EcmaOpcode opcode)1789 bool BytecodeCircuitBuilder::IsGeneral(EcmaOpcode opcode)
1790 {
1791     return !IsMov(opcode) && !IsJump(opcode) && !IsReturn(opcode) && !IsSetConstant(opcode);
1792 }
1793 
IsSetConstant(EcmaOpcode opcode)1794 bool BytecodeCircuitBuilder::IsSetConstant(EcmaOpcode opcode)
1795 {
1796     switch (opcode) {
1797         case EcmaOpcode::LDNAN_PREF:
1798         case EcmaOpcode::LDINFINITY_PREF:
1799         case EcmaOpcode::LDUNDEFINED_PREF:
1800         case EcmaOpcode::LDNULL_PREF:
1801         case EcmaOpcode::LDTRUE_PREF:
1802         case EcmaOpcode::LDFALSE_PREF:
1803         case EcmaOpcode::LDHOLE_PREF:
1804         case EcmaOpcode::LDAI_DYN_IMM32:
1805         case EcmaOpcode::FLDAI_DYN_IMM64:
1806             return true;
1807         default:
1808             return false;
1809     }
1810 }
1811 
BuildCircuit(BytecodeGraph & byteCodeGraph)1812 void BytecodeCircuitBuilder::BuildCircuit(BytecodeGraph &byteCodeGraph)
1813 {
1814     auto &graph = byteCodeGraph.graph;
1815 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
1816     PrintBBInfo(graph);
1817 #endif
1818 
1819     // create arg gates array
1820     const size_t numArgs = byteCodeGraph.method->GetNumArgs();
1821     const size_t offsetArgs = byteCodeGraph.method->GetNumVregs();
1822     const size_t actualNumArgs = GetActualNumArgs(numArgs);
1823     std::vector<GateRef> argGates(actualNumArgs);
1824 
1825     for (size_t argIdx = 0; argIdx < CommonArgIdx::NUM_OF_ARGS; argIdx++) {
1826         auto argGate = circuit_.NewGate(OpCode(OpCode::ARG), MachineType::I64, argIdx,
1827                                         {Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST))},
1828                                         GateType::TAGGED_VALUE);
1829         argGates.at(argIdx) = argGate;
1830         commonArgs_.at(argIdx) = argGate;
1831     }
1832 
1833     for (size_t argIdx = CommonArgIdx::NUM_OF_ARGS; argIdx < actualNumArgs; argIdx++) {
1834         argGates.at(argIdx) = circuit_.NewGate(OpCode(OpCode::ARG), MachineType::I64, argIdx,
1835                                                {Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST))},
1836                                                GateType::JS_ANY);
1837     }
1838     // get number of expanded state predicates of each block
1839     // one block-level try catch edge may correspond to multiple bytecode-level edges
1840     for (auto &bb: graph) {
1841         if (bb.isDead) {
1842             continue;
1843         }
1844         bb.numOfStatePreds = 0;
1845     }
1846     for (auto &bb: graph) {
1847         if (bb.isDead) {
1848             continue;
1849         }
1850         auto pc = bb.start;
1851         while (pc <= bb.end) {
1852             auto bytecodeInfo = GetBytecodeInfo(pc);
1853             pc = pc + bytecodeInfo.offset; // next inst start pc
1854             if (IsGeneral(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
1855                 if (!bb.catchs.empty()) {
1856                     bb.catchs.at(0)->numOfStatePreds++;
1857                 }
1858             }
1859         }
1860         for (auto &succ: bb.succs) {
1861             succ->numOfStatePreds++;
1862         }
1863     }
1864 
1865     // build head of each block
1866     for (auto &bb: graph) {
1867         if (bb.isDead) {
1868             continue;
1869         }
1870         if (bb.numOfStatePreds == 0) {
1871             bb.stateStart = Circuit::GetCircuitRoot(OpCode(OpCode::STATE_ENTRY));
1872             bb.dependStart = Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY));
1873         } else if (bb.numOfStatePreds == 1) {
1874             bb.stateStart = circuit_.NewGate(OpCode(OpCode::ORDINARY_BLOCK), 0,
1875                                              {Circuit::NullGate()}, GateType::EMPTY);
1876             bb.dependStart = circuit_.NewGate(OpCode(OpCode::DEPEND_RELAY), 0,
1877                                               {bb.stateStart, Circuit::NullGate()}, GateType::EMPTY);
1878         } else {
1879             bb.stateStart = circuit_.NewGate(OpCode(OpCode::MERGE), bb.numOfStatePreds,
1880                                              std::vector<GateRef>(bb.numOfStatePreds, Circuit::NullGate()),
1881                                              GateType::EMPTY);
1882             bb.dependStart = circuit_.NewGate(OpCode(OpCode::DEPEND_SELECTOR), bb.numOfStatePreds,
1883                                               std::vector<GateRef>(bb.numOfStatePreds + 1, Circuit::NullGate()),
1884                                               GateType::EMPTY);
1885             circuit_.NewIn(bb.dependStart, 0, bb.stateStart);
1886         }
1887     }
1888     // build states sub-circuit of each block
1889     for (auto &bb: graph) {
1890         if (bb.isDead) {
1891             continue;
1892         }
1893         auto stateCur = bb.stateStart;
1894         auto dependCur = bb.dependStart;
1895         ASSERT(stateCur != Circuit::NullGate());
1896         ASSERT(dependCur != Circuit::NullGate());
1897         if (!bb.trys.empty()) {
1898             dependCur = circuit_.NewGate(OpCode(OpCode::GET_EXCEPTION), 0, {dependCur}, GateType::EMPTY);
1899         }
1900         auto pc = bb.start;
1901         while (pc <= bb.end) {
1902             auto pcPrev = pc;
1903             auto bytecodeInfo = GetBytecodeInfo(pc);
1904             pc = pc + bytecodeInfo.offset; // next inst start pc
1905             size_t numValueInputs = (bytecodeInfo.accIn ? 1 : 0) + bytecodeInfo.vregIn.size();
1906             if (IsSetConstant(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
1907                 // handle bytecode command to get constants
1908                 auto ecmaOpcode = static_cast<EcmaOpcode>(bytecodeInfo.opcode);
1909                 GateRef gate = 0;
1910                 if (ecmaOpcode == EcmaOpcode::LDNULL_PREF || ecmaOpcode == EcmaOpcode::LDINFINITY_PREF ||
1911                     ecmaOpcode == EcmaOpcode::FLDAI_DYN_IMM64) {
1912                     gate = circuit_.NewGate(OpCode(OpCode::CONSTANT), MachineType::F64, bytecodeInfo.imm,
1913                                             {Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST))},
1914                                             GateType::JS_ANY);
1915                 } else {
1916                     gate = circuit_.NewGate(OpCode(OpCode::CONSTANT), MachineType::I64, bytecodeInfo.imm,
1917                                             {Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST))},
1918                                             GateType::JS_ANY);
1919                 }
1920                 jsgateToBytecode_[gate] = {bb.id, pcPrev};
1921             } else if (IsGeneral(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
1922                 // handle general ecma.* bytecodes
1923                 GateRef gate = 0;
1924                 if (!bytecodeInfo.vregOut.empty() || bytecodeInfo.accOut) {
1925                     gate = circuit_.NewGate(OpCode(OpCode::JS_BYTECODE), MachineType::I64, numValueInputs,
1926                                             std::vector<GateRef>(2 + numValueInputs, // 2: state and depend input
1927                                                                  Circuit::NullGate()),
1928                                             GateType::JS_ANY);
1929                 } else {
1930                     gate = circuit_.NewGate(OpCode(OpCode::JS_BYTECODE), MachineType::NOVALUE, numValueInputs,
1931                                             std::vector<GateRef>(2 + numValueInputs, // 2: state and depend input
1932                                                                  Circuit::NullGate()),
1933                                             GateType::EMPTY);
1934                 }
1935                 circuit_.NewIn(gate, 0, stateCur);
1936                 circuit_.NewIn(gate, 1, dependCur);
1937                 auto ifSuccess = circuit_.NewGate(OpCode(OpCode::IF_SUCCESS), 0, {gate}, GateType::EMPTY);
1938                 auto ifException = circuit_.NewGate(OpCode(OpCode::IF_EXCEPTION), 0, {gate}, GateType::EMPTY);
1939                 if (!bb.catchs.empty()) {
1940                     auto bbNext = bb.catchs.at(0);
1941                     circuit_.NewIn(bbNext->stateStart, bbNext->statePredIndex, ifException);
1942                     circuit_.NewIn(bbNext->dependStart, bbNext->statePredIndex + 1, gate);
1943                     bbNext->statePredIndex++;
1944                     bbNext->expandedPreds.push_back(
1945                         {bb.id, pcPrev, true}
1946                     );
1947                     ASSERT(bbNext->statePredIndex <= bbNext->numOfStatePreds);
1948                 } else {
1949                     auto constant = circuit_.NewGate(OpCode(OpCode::CONSTANT), MachineType::I64,
1950                                                      JSTaggedValue::VALUE_EXCEPTION,
1951                                                      {Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST))},
1952                                                      GateType::JS_ANY);
1953                     circuit_.NewGate(OpCode(OpCode::RETURN),
1954                                      0,
1955                                      {ifException, gate, constant,
1956                                       Circuit::GetCircuitRoot(OpCode(OpCode::RETURN_LIST))},
1957                                      GateType::JS_ANY);
1958                 }
1959                 jsgateToBytecode_[gate] = {bb.id, pcPrev};
1960                 if (IsThrow(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
1961                     circuit_.NewGate(OpCode(OpCode::RETURN), 0,
1962                                      {ifSuccess, gate, TaggedValue::VALUE_HOLE,
1963                                       Circuit::GetCircuitRoot(OpCode(OpCode::RETURN_LIST))},
1964                                      GateType::JS_ANY);
1965                     break;
1966                 }
1967                 stateCur = ifSuccess;
1968                 dependCur = gate;
1969                 if (pcPrev == bb.end) {
1970                     auto bbNext = &graph.at(bb.id + 1);
1971                     circuit_.NewIn(bbNext->stateStart, bbNext->statePredIndex, stateCur);
1972                     circuit_.NewIn(bbNext->dependStart, bbNext->statePredIndex + 1, dependCur);
1973                     bbNext->statePredIndex++;
1974                     bbNext->expandedPreds.push_back(
1975                         {bb.id, pcPrev, false}
1976                     );
1977                     ASSERT(bbNext->statePredIndex <= bbNext->numOfStatePreds);
1978                 }
1979             } else if (IsJump(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
1980                 // handle conditional jump and unconditional jump bytecodes
1981                 if (IsCondJump(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
1982                     GateRef gate = 0;
1983                     if (!bytecodeInfo.vregOut.empty() || bytecodeInfo.accOut) {
1984                         gate = circuit_.NewGate(OpCode(OpCode::JS_BYTECODE), MachineType::I64, numValueInputs,
1985                                                 std::vector<GateRef>(2 + numValueInputs, // 2: state and depend input
1986                                                                      Circuit::NullGate()),
1987                                                 GateType::JS_ANY);
1988                     } else {
1989                         gate = circuit_.NewGate(OpCode(OpCode::JS_BYTECODE), MachineType::NOVALUE, numValueInputs,
1990                                                 std::vector<GateRef>(2 + numValueInputs, // 2: state and depend input
1991                                                                      Circuit::NullGate()),
1992                                                 GateType::EMPTY);
1993                     }
1994                     circuit_.NewIn(gate, 0, stateCur);
1995                     circuit_.NewIn(gate, 1, dependCur);
1996                     auto ifTrue = circuit_.NewGate(OpCode(OpCode::IF_TRUE), 0, {gate}, GateType::EMPTY);
1997                     auto ifFalse = circuit_.NewGate(OpCode(OpCode::IF_FALSE), 0, {gate}, GateType::EMPTY);
1998                     ASSERT(bb.succs.size() == 2); // 2 : 2 num of successors
1999                     int bitSet = 0;
2000                     for (auto &bbNext: bb.succs) {
2001                         if (bbNext->id == bb.id + 1) {
2002                             circuit_.NewIn(bbNext->stateStart, bbNext->statePredIndex, ifFalse);
2003                             circuit_.NewIn(bbNext->dependStart, bbNext->statePredIndex + 1, gate);
2004                             bbNext->statePredIndex++;
2005                             bbNext->expandedPreds.push_back(
2006                                 {bb.id, pcPrev, false}
2007                             );
2008                             ASSERT(bbNext->statePredIndex <= bbNext->numOfStatePreds);
2009                             bitSet |= 1;
2010                         } else {
2011                             circuit_.NewIn(bbNext->stateStart, bbNext->statePredIndex, ifTrue);
2012                             circuit_.NewIn(bbNext->dependStart, bbNext->statePredIndex + 1, gate);
2013                             bbNext->statePredIndex++;
2014                             bbNext->expandedPreds.push_back(
2015                                 {bb.id, pcPrev, false}
2016                             );
2017                             ASSERT(bbNext->statePredIndex <= bbNext->numOfStatePreds);
2018                             bitSet |= 2; // 2:verify
2019                         }
2020                     }
2021                     ASSERT(bitSet == 3); // 3:Verify the number of successor blocks
2022                     jsgateToBytecode_[gate] = {bb.id, pcPrev};
2023                     break;
2024                 } else {
2025                     ASSERT(bb.succs.size() == 1);
2026                     auto bbNext = bb.succs.at(0);
2027                     circuit_.NewIn(bbNext->stateStart, bbNext->statePredIndex, stateCur);
2028                     circuit_.NewIn(bbNext->dependStart, bbNext->statePredIndex + 1, dependCur);
2029                     bbNext->statePredIndex++;
2030                     bbNext->expandedPreds.push_back(
2031                         {bb.id, pcPrev, false}
2032                     );
2033                     ASSERT(bbNext->statePredIndex <= bbNext->numOfStatePreds);
2034                     break;
2035                 }
2036             } else if (static_cast<EcmaOpcode>(bytecodeInfo.opcode) == EcmaOpcode::RETURN_DYN) {
2037                 // handle return.dyn bytecode
2038                 ASSERT(bb.succs.empty());
2039                 auto gate = circuit_.NewGate(OpCode(OpCode::RETURN), 0,
2040                                              {stateCur, dependCur, Circuit::NullGate(),
2041                                               Circuit::GetCircuitRoot(OpCode(OpCode::RETURN_LIST))},
2042                                              GateType::EMPTY);
2043                 jsgateToBytecode_[gate] = {bb.id, pcPrev};
2044                 break;
2045             } else if (static_cast<EcmaOpcode>(bytecodeInfo.opcode) == EcmaOpcode::RETURNUNDEFINED_PREF) {
2046                 // handle returnundefined bytecode
2047                 ASSERT(bb.succs.empty());
2048                 auto constant = circuit_.NewGate(OpCode(OpCode::CONSTANT), MachineType::I64,
2049                                                  TaggedValue::VALUE_UNDEFINED,
2050                                                  {Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST))},
2051                                                  GateType::JS_ANY);
2052                 auto gate = circuit_.NewGate(OpCode(OpCode::RETURN), 0,
2053                                              {stateCur, dependCur, constant,
2054                                               Circuit::GetCircuitRoot(OpCode(OpCode::RETURN_LIST))},
2055                                              GateType::EMPTY);
2056                 jsgateToBytecode_[gate] = {bb.id, pcPrev};
2057                 break;
2058             } else if (IsMov(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
2059                 // handle mov.dyn lda.dyn sta.dyn bytecodes
2060                 if (pcPrev == bb.end) {
2061                     auto bbNext = &graph.at(bb.id + 1);
2062                     circuit_.NewIn(bbNext->stateStart, bbNext->statePredIndex, stateCur);
2063                     circuit_.NewIn(bbNext->dependStart, bbNext->statePredIndex + 1, dependCur);
2064                     bbNext->statePredIndex++;
2065                     bbNext->expandedPreds.push_back(
2066                         {bb.id, pcPrev, false}
2067                     );
2068                     ASSERT(bbNext->statePredIndex <= bbNext->numOfStatePreds);
2069                 }
2070             } else {
2071                 abort();
2072             }
2073         }
2074     }
2075     // verification of soundness of CFG
2076     for (auto &bb: graph) {
2077         if (bb.isDead) {
2078             continue;
2079         }
2080         ASSERT(bb.statePredIndex == bb.numOfStatePreds);
2081     }
2082     for (auto &bb: graph) {
2083         if (bb.isDead) {
2084             continue;
2085         }
2086         bb.phiAcc = (bb.numOfStatePreds > 1) || (!bb.trys.empty());
2087     }
2088 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
2089     PrintBytecodeInfo(graph);
2090 #endif
2091     for (const auto &[key, value]: jsgateToBytecode_) {
2092         byteCodeToJSGate_[value.second] = key;
2093     }
2094 
2095     // resolve def-site of virtual regs and set all value inputs
2096     for (auto gate: circuit_.GetAllGates()) {
2097         auto numInsArray = circuit_.GetOpCode(gate).GetOpCodeNumInsArray(circuit_.GetBitField(gate));
2098         auto it = jsgateToBytecode_.find(gate);
2099         if (it == jsgateToBytecode_.end()) {
2100             continue;
2101         }
2102         const auto &[id, pc] = it->second;
2103         auto bytecodeInfo = GetBytecodeInfo(pc);
2104         [[maybe_unused]] size_t numValueInputs = (bytecodeInfo.accIn ? 1 : 0) + bytecodeInfo.vregIn.size();
2105         [[maybe_unused]] size_t numValueOutputs = (bytecodeInfo.accOut ? 1 : 0) + bytecodeInfo.vregOut.size();
2106         ASSERT(numValueInputs == numInsArray[2]); // 2 : 2 num of input value
2107         ASSERT(numValueOutputs <= 1);
2108         // recursive variables renaming algorithm
2109         std::function<GateRef(size_t, const uint8_t *, uint16_t, bool)> defSiteOfReg =
2110                 [&](size_t bbId, const uint8_t *end, uint16_t reg, bool acc) -> GateRef {
2111                     // find def-site in bytecodes of basic block
2112                     auto ans = Circuit::NullGate();
2113                     auto &bb = graph.at(bbId);
2114                     std::vector<uint8_t *> instList;
2115                     {
2116                         auto pcIter = bb.start;
2117                         while (pcIter <= end) {
2118                             instList.push_back(pcIter);
2119                             auto curInfo = GetBytecodeInfo(pcIter);
2120                             pcIter += curInfo.offset;
2121                         }
2122                     }
2123                     std::reverse(instList.begin(), instList.end());
2124                     for (auto pcIter: instList) { // upper bound
2125                         auto curInfo = GetBytecodeInfo(pcIter);
2126                         if (acc) {
2127                             if (curInfo.accOut) {
2128                                 if (IsMov(static_cast<EcmaOpcode>(curInfo.opcode))) {
2129                                     acc = curInfo.accIn;
2130                                     if (!curInfo.vregIn.empty()) {
2131                                         ASSERT(!acc);
2132                                         ASSERT(curInfo.vregIn.size() == 1);
2133                                         reg = curInfo.vregIn.at(0);
2134                                     }
2135                                 } else {
2136                                     ans = byteCodeToJSGate_.at(pcIter);
2137                                     break;
2138                                 }
2139                             }
2140                         } else {
2141                             if (!curInfo.vregOut.empty() && curInfo.vregOut.at(0) == reg) {
2142                                 if (IsMov(static_cast<EcmaOpcode>(curInfo.opcode))) {
2143                                     acc = curInfo.accIn;
2144                                     if (!curInfo.vregIn.empty()) {
2145                                         ASSERT(!acc);
2146                                         ASSERT(curInfo.vregIn.size() == 1);
2147                                         reg = curInfo.vregIn.at(0);
2148                                     }
2149                                 } else {
2150                                     ans = byteCodeToJSGate_.at(pcIter);
2151                                     break;
2152                                 }
2153                             }
2154                         }
2155                     }
2156                     // find GET_EXCEPTION gate if this is a catch block
2157                     if (ans == Circuit::NullGate() && acc) {
2158                         if (!bb.trys.empty()) {
2159                             const auto &outList = circuit_.GetOutVector(bb.dependStart);
2160                             ASSERT(outList.size() == 1);
2161                             const auto &getExceptionGate = outList.at(0);
2162                             ASSERT(circuit_.GetOpCode(getExceptionGate) == OpCode::GET_EXCEPTION);
2163                             ans = getExceptionGate;
2164                         }
2165                     }
2166                     // find def-site in value selectors of vregs
2167                     if (ans == Circuit::NullGate() && !acc && bb.phi.count(reg)) {
2168                         if (!bb.vregToValSelectorGate.count(reg)) {
2169                             auto gate = circuit_.NewGate(OpCode(OpCode::VALUE_SELECTOR), MachineType::I64,
2170                                                          bb.numOfStatePreds,
2171                                                          std::vector<GateRef>(
2172                                                                  1 + bb.numOfStatePreds, Circuit::NullGate()),
2173                                                          GateType::JS_ANY);
2174                             bb.vregToValSelectorGate[reg] = gate;
2175                             circuit_.NewIn(gate, 0, bb.stateStart);
2176                             for (int32_t i = 0; i < bb.numOfStatePreds; ++i) {
2177                                 auto &[predId, predPc, isException] = bb.expandedPreds.at(i);
2178                                 circuit_.NewIn(gate, i + 1, defSiteOfReg(predId, predPc, reg, acc));
2179                             }
2180                         }
2181                         ans = bb.vregToValSelectorGate.at(reg);
2182                     }
2183                     // find def-site in value selectors of acc
2184                     if (ans == Circuit::NullGate() && acc && bb.phiAcc) {
2185                         if (bb.valueSelectorAccGate == Circuit::NullGate()) {
2186                             auto gate = circuit_.NewGate(OpCode(OpCode::VALUE_SELECTOR), MachineType::I64,
2187                                                          bb.numOfStatePreds,
2188                                                          std::vector<GateRef>(
2189                                                              1 + bb.numOfStatePreds, Circuit::NullGate()),
2190                                                          GateType::JS_ANY);
2191                             bb.valueSelectorAccGate = gate;
2192                             circuit_.NewIn(gate, 0, bb.stateStart);
2193                             for (int32_t i = 0; i < bb.numOfStatePreds; ++i) {
2194                                 auto &[predId, predPc, isException] = bb.expandedPreds.at(i);
2195                                 circuit_.NewIn(gate, i + 1, defSiteOfReg(predId, predPc, reg, acc));
2196                             }
2197                         }
2198                         ans = bb.valueSelectorAccGate;
2199                     }
2200                     if (ans == Circuit::NullGate() && bbId == 0) { // entry block
2201                         // find def-site in function args
2202                         ASSERT(!acc && reg >= offsetArgs && reg < offsetArgs + argGates.size());
2203                         return argGates.at(reg - offsetArgs + CommonArgIdx::NUM_OF_ARGS);
2204                     }
2205                     if (ans == Circuit::NullGate()) {
2206                         // recursively find def-site in dominator block
2207                         return defSiteOfReg(bb.iDominator->id, bb.iDominator->end, reg, acc);
2208                     } else {
2209                         // def-site already found
2210                         return ans;
2211                     }
2212                 };
2213         for (size_t valueIdx = 0; valueIdx < numInsArray[2]; valueIdx++) { // 2: input value num
2214             auto inIdx = valueIdx + numInsArray[0] + numInsArray[1];
2215             if (!circuit_.IsInGateNull(gate, inIdx)) {
2216                 continue;
2217             }
2218             if (valueIdx < bytecodeInfo.vregIn.size()) {
2219                 circuit_.NewIn(gate, inIdx, defSiteOfReg(id, pc - 1, bytecodeInfo.vregIn.at(valueIdx), false));
2220             } else {
2221                 circuit_.NewIn(gate, inIdx, defSiteOfReg(id, pc - 1, 0, true));
2222             }
2223         }
2224     }
2225 #if ECMASCRIPT_ENABLE_TS_AOT_PRINT
2226     circuit_.PrintAllGates(*this);
2227 #endif
2228 }
2229 
PrintCollectBlockInfo(std::vector<CfgInfo> & bytecodeBlockInfos)2230 void BytecodeCircuitBuilder::PrintCollectBlockInfo(std::vector<CfgInfo> &bytecodeBlockInfos)
2231 {
2232     for (auto iter = bytecodeBlockInfos.begin(); iter != bytecodeBlockInfos.end(); iter++) {
2233         std::cout << "offset: " << static_cast<const void *>(iter->pc) << " splitKind: " <<
2234                   static_cast<int32_t>(iter->splitKind) << " successor are: ";
2235         auto &vec = iter->succs;
2236         for (size_t i = 0; i < vec.size(); i++) {
2237             std::cout << static_cast<const void *>(vec[i]) << " , ";
2238         }
2239         std::cout << "" << std::endl;
2240     }
2241     std::cout << "-----------------------------------------------------------------------" << std::endl;
2242 }
2243 
PrintGraph(std::vector<BytecodeRegion> & graph)2244 void BytecodeCircuitBuilder::PrintGraph(std::vector<BytecodeRegion> &graph)
2245 {
2246     for (size_t i = 0; i < graph.size(); i++) {
2247         if (graph[i].isDead) {
2248             std::cout << "BB_" << graph[i].id << ":                               ;predsId= invalid BB" << std::endl;
2249             std::cout << "curStartPc: " << static_cast<const void *>(graph[i].start) <<
2250                       " curEndPc: " << static_cast<const void *>(graph[i].end) << std::endl;
2251             continue;
2252         }
2253         std::cout << "BB_" << graph[i].id << ":                               ;predsId= ";
2254         for (size_t k = 0; k < graph[i].preds.size(); ++k) {
2255             std::cout << graph[i].preds[k]->id << ", ";
2256         }
2257         std::cout << "" << std::endl;
2258         std::cout << "curStartPc: " << static_cast<const void *>(graph[i].start) <<
2259                   " curEndPc: " << static_cast<const void *>(graph[i].end) << std::endl;
2260 
2261         for (size_t j = 0; j < graph[i].preds.size(); j++) {
2262             std::cout << "predsStartPc: " << static_cast<const void *>(graph[i].preds[j]->start) <<
2263                       " predsEndPc: " << static_cast<const void *>(graph[i].preds[j]->end) << std::endl;
2264         }
2265 
2266         for (size_t j = 0; j < graph[i].succs.size(); j++) {
2267             std::cout << "succesStartPc: " << static_cast<const void *>(graph[i].succs[j]->start) <<
2268                       " succesEndPc: " << static_cast<const void *>(graph[i].succs[j]->end) << std::endl;
2269         }
2270 
2271         std::cout << "succesId: ";
2272         for (size_t j = 0; j < graph[i].succs.size(); j++) {
2273             std::cout << graph[i].succs[j]->id << ", ";
2274         }
2275         std::cout << "" << std::endl;
2276 
2277         for (size_t j = 0; j < graph[i].catchs.size(); j++) {
2278             std::cout << "catchStartPc: " << static_cast<const void *>(graph[i].catchs[j]->start) <<
2279                       " catchEndPc: " << static_cast<const void *>(graph[i].catchs[j]->end) << std::endl;
2280         }
2281 
2282         for (size_t j = 0; j < graph[i].immDomBlocks.size(); j++) {
2283             std::cout << "dominate block id: " << graph[i].immDomBlocks[j]->id << " startPc: " <<
2284                       static_cast<const void *>(graph[i].immDomBlocks[j]->start) << " endPc: " <<
2285                       static_cast<const void *>(graph[i].immDomBlocks[j]->end) << std::endl;
2286         }
2287 
2288         if (graph[i].iDominator) {
2289             std::cout << "current block " << graph[i].id <<
2290                       " immediate dominator is " << graph[i].iDominator->id << std::endl;
2291         }
2292 
2293         std::cout << "current block " << graph[i].id << " dominace Frontiers: ";
2294         for (const auto &frontier: graph[i].domFrontiers) {
2295             std::cout << frontier->id << " , ";
2296         }
2297         std::cout << std::endl;
2298 
2299         std::cout << "current block " << graph[i].id << " phi variable: ";
2300         for (auto variable: graph[i].phi) {
2301             std::cout << variable << " , ";
2302         }
2303         std::cout << std::endl;
2304         std::cout << "-------------------------------------------------------" << std::endl;
2305     }
2306 }
2307 
PrintBytecodeInfo(std::vector<BytecodeRegion> & graph)2308 void BytecodeCircuitBuilder::PrintBytecodeInfo(std::vector<BytecodeRegion> &graph)
2309 {
2310     for (auto &bb: graph) {
2311         if (bb.isDead) {
2312             continue;
2313         }
2314         auto pc = bb.start;
2315         std::cout << "BB_" << bb.id << ": " << std::endl;
2316         while (pc <= bb.end) {
2317             auto curInfo = GetBytecodeInfo(pc);
2318             std::cout << "Inst_" << static_cast<int>(curInfo.opcode) << ": ";
2319             std::cout << "In=[";
2320             if (curInfo.accIn) {
2321                 std::cout << "acc" << ",";
2322             }
2323             for (const auto &in: curInfo.vregIn) {
2324                 std::cout << in << ",";
2325             }
2326             std::cout << "] Out=[";
2327             if (curInfo.accOut) {
2328                 std::cout << "acc" << ",";
2329             }
2330             for (const auto &out: curInfo.vregOut) {
2331                 std::cout << out << ",";
2332             }
2333             std::cout << "]";
2334             std::cout << std::endl;
2335             pc += curInfo.offset;
2336         }
2337     }
2338 }
2339 
PrintBBInfo(std::vector<BytecodeRegion> & graph)2340 void BytecodeCircuitBuilder::PrintBBInfo(std::vector<BytecodeRegion> &graph)
2341 {
2342     for (auto &bb: graph) {
2343         if (bb.isDead) {
2344             continue;
2345         }
2346         std::cout << "------------------------" << std::endl;
2347         std::cout << "block: " << bb.id << std::endl;
2348         std::cout << "preds: ";
2349         for (auto pred: bb.preds) {
2350             std::cout << pred->id << " , ";
2351         }
2352         std::cout << std::endl;
2353         std::cout << "succs: ";
2354         for (auto succ: bb.succs) {
2355             std::cout << succ->id << " , ";
2356         }
2357         std::cout << std::endl;
2358         std::cout << "catchs: ";
2359         for (auto catchBlock: bb.catchs) {
2360             std::cout << catchBlock->id << " , ";
2361         }
2362         std::cout << std::endl;
2363         std::cout << "trys: ";
2364         for (auto tryBlock: bb.trys) {
2365             std::cout << tryBlock->id << " , ";
2366         }
2367         std::cout << std::endl;
2368     }
2369 }
2370 }  // namespace panda::ecmascript::kungfu