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