2022-01-06 02:26:19 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2022-06-16 09:27:35 +00:00
|
|
|
#include "ecmascript/compiler/bytecode_circuit_builder.h"
|
|
|
|
|
2022-04-24 07:14:09 +00:00
|
|
|
#include "ecmascript/base/number_helper.h"
|
2022-06-10 07:22:21 +00:00
|
|
|
#include "ecmascript/compiler/gate_accessor.h"
|
2022-07-21 17:37:55 +00:00
|
|
|
#include "ecmascript/ts_types/ts_manager.h"
|
2022-09-20 15:17:00 +00:00
|
|
|
#include "libpandafile/bytecode_instruction-inl.h"
|
2022-08-26 01:06:59 +00:00
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
namespace panda::ecmascript::kungfu {
|
2022-03-07 02:58:13 +00:00
|
|
|
void BytecodeCircuitBuilder::BytecodeToCircuit()
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-11-02 01:32:55 +00:00
|
|
|
ExceptionInfo exceptionInfo = {};
|
2022-01-06 02:26:19 +00:00
|
|
|
|
|
|
|
// collect try catch block info
|
2022-08-02 08:38:18 +00:00
|
|
|
CollectTryCatchBlockInfo(exceptionInfo);
|
2022-11-28 01:26:23 +00:00
|
|
|
hasTryCatch_ = exceptionInfo.size() != 0;
|
2022-11-02 07:10:09 +00:00
|
|
|
BuildRegionInfo();
|
2022-01-06 02:26:19 +00:00
|
|
|
// Building the basic block diagram of bytecode
|
2022-11-02 07:10:09 +00:00
|
|
|
BuildRegions(exceptionInfo);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-11-02 07:10:09 +00:00
|
|
|
void BytecodeCircuitBuilder::BuildRegionInfo()
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-11-02 01:32:55 +00:00
|
|
|
uint32_t size = pcOffsets_.size();
|
2023-09-07 02:16:14 +00:00
|
|
|
uint32_t end = size - 1; // 1: end
|
2022-11-02 01:32:55 +00:00
|
|
|
BytecodeIterator iterator(this, 0, end);
|
|
|
|
|
|
|
|
infoData_.resize(size);
|
2023-04-28 08:37:17 +00:00
|
|
|
byteCodeToJSGates_.resize(size, std::vector<GateRef>(0));
|
2022-11-02 07:10:09 +00:00
|
|
|
regionsInfo_.InsertHead(0); // 0: start pc
|
2023-11-06 01:19:36 +00:00
|
|
|
iterator.GotoStart();
|
|
|
|
while (!iterator.Done()) {
|
2022-11-02 01:32:55 +00:00
|
|
|
auto index = iterator.Index();
|
|
|
|
auto &info = infoData_[index];
|
|
|
|
auto pc = pcOffsets_[index];
|
|
|
|
info.metaData_ = bytecodes_->GetBytecodeMetaData(pc);
|
2023-04-03 08:33:32 +00:00
|
|
|
ASSERT(!info.metaData_.IsInvalid());
|
2022-11-02 01:32:55 +00:00
|
|
|
BytecodeInfo::InitBytecodeInfo(this, info, pc);
|
2022-11-02 07:10:09 +00:00
|
|
|
CollectRegionInfo(index);
|
2023-11-06 01:19:36 +00:00
|
|
|
++iterator;
|
2022-11-02 01:32:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-02 07:10:09 +00:00
|
|
|
void BytecodeCircuitBuilder::CollectRegionInfo(uint32_t bcIndex)
|
2022-11-02 01:32:55 +00:00
|
|
|
{
|
|
|
|
auto pc = pcOffsets_[bcIndex];
|
|
|
|
auto &info = infoData_[bcIndex];
|
2022-11-25 07:22:42 +00:00
|
|
|
int32_t offset = 0;
|
2022-11-02 01:32:55 +00:00
|
|
|
if (info.IsJump()) {
|
|
|
|
switch (info.GetOpcode()) {
|
|
|
|
case EcmaOpcode::JEQZ_IMM8:
|
|
|
|
case EcmaOpcode::JNEZ_IMM8:
|
|
|
|
case EcmaOpcode::JMP_IMM8:
|
|
|
|
offset = static_cast<int8_t>(READ_INST_8_0());
|
|
|
|
break;
|
|
|
|
case EcmaOpcode::JNEZ_IMM16:
|
|
|
|
case EcmaOpcode::JEQZ_IMM16:
|
|
|
|
case EcmaOpcode::JMP_IMM16:
|
|
|
|
offset = static_cast<int16_t>(READ_INST_16_0());
|
|
|
|
break;
|
|
|
|
case EcmaOpcode::JMP_IMM32:
|
|
|
|
case EcmaOpcode::JNEZ_IMM32:
|
|
|
|
case EcmaOpcode::JEQZ_IMM32:
|
|
|
|
offset = static_cast<int32_t>(READ_INST_32_0());
|
|
|
|
break;
|
|
|
|
default:
|
2022-12-01 07:29:41 +00:00
|
|
|
LOG_ECMA(FATAL) << "this branch is unreachable";
|
2022-11-02 01:32:55 +00:00
|
|
|
UNREACHABLE();
|
|
|
|
break;
|
2022-09-08 01:37:53 +00:00
|
|
|
}
|
2022-11-02 01:32:55 +00:00
|
|
|
auto nextIndex = bcIndex + 1; // 1: next pc
|
|
|
|
auto targetIndex = FindBcIndexByPc(pc + offset);
|
|
|
|
// condition branch current basic block end
|
|
|
|
if (info.IsCondJump()) {
|
2022-11-02 07:10:09 +00:00
|
|
|
regionsInfo_.InsertSplit(nextIndex);
|
|
|
|
regionsInfo_.InsertJump(targetIndex, bcIndex, false);
|
2022-11-02 01:32:55 +00:00
|
|
|
} else {
|
2023-04-18 02:56:21 +00:00
|
|
|
if (bcIndex != GetLastBcIndex()) {
|
|
|
|
regionsInfo_.InsertHead(nextIndex);
|
|
|
|
}
|
2022-11-02 07:10:09 +00:00
|
|
|
regionsInfo_.InsertJump(targetIndex, bcIndex, true);
|
2022-08-16 15:48:09 +00:00
|
|
|
}
|
2022-11-02 01:32:55 +00:00
|
|
|
} else if (info.IsReturn() || info.IsThrow()) {
|
|
|
|
if (bcIndex != GetLastBcIndex()) {
|
|
|
|
auto nextIndex = bcIndex + 1; // 1: next pc
|
2022-11-02 07:10:09 +00:00
|
|
|
regionsInfo_.InsertHead(nextIndex);
|
2022-04-01 06:33:39 +00:00
|
|
|
}
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-02 01:32:55 +00:00
|
|
|
void BytecodeCircuitBuilder::CollectTryCatchBlockInfo(ExceptionInfo &byteCodeException)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-12-03 14:03:40 +00:00
|
|
|
auto pf = file_->GetPandaFile();
|
|
|
|
panda_file::MethodDataAccessor mda(*pf, method_->GetMethodId());
|
|
|
|
panda_file::CodeDataAccessor cda(*pf, mda.GetCodeId().value());
|
2022-08-02 08:38:18 +00:00
|
|
|
|
|
|
|
cda.EnumerateTryBlocks([this, &byteCodeException](
|
2022-11-02 01:32:55 +00:00
|
|
|
panda_file::CodeDataAccessor::TryBlock &tryBlock) {
|
|
|
|
auto tryStartOffset = tryBlock.GetStartPc();
|
|
|
|
auto tryEndOffset = tryBlock.GetStartPc() + tryBlock.GetLength();
|
|
|
|
|
2022-03-07 02:58:13 +00:00
|
|
|
auto tryStartPc = const_cast<uint8_t *>(method_->GetBytecodeArray() + tryStartOffset);
|
|
|
|
auto tryEndPc = const_cast<uint8_t *>(method_->GetBytecodeArray() + tryEndOffset);
|
2022-08-23 02:33:21 +00:00
|
|
|
// skip try blocks with same pc in start and end label
|
|
|
|
if (tryStartPc == tryEndPc) {
|
|
|
|
return true;
|
|
|
|
}
|
2022-11-02 01:32:55 +00:00
|
|
|
|
|
|
|
auto tryStartBcIndex = FindBcIndexByPc(tryStartPc);
|
2022-11-02 07:10:09 +00:00
|
|
|
regionsInfo_.InsertSplit(tryStartBcIndex);
|
2022-11-02 01:32:55 +00:00
|
|
|
if (tryEndPc <= GetLastPC()) {
|
|
|
|
auto tryEndBcIndex = FindBcIndexByPc(tryEndPc);
|
2022-11-02 07:10:09 +00:00
|
|
|
regionsInfo_.InsertSplit(tryEndBcIndex);
|
2022-11-02 01:32:55 +00:00
|
|
|
}
|
|
|
|
byteCodeException.emplace_back(ExceptionItem { tryStartPc, tryEndPc, {} });
|
|
|
|
tryBlock.EnumerateCatchBlocks([&](panda_file::CodeDataAccessor::CatchBlock &catchBlock) {
|
|
|
|
auto pcOffset = catchBlock.GetHandlerPc();
|
2022-03-07 02:58:13 +00:00
|
|
|
auto catchBlockPc = const_cast<uint8_t *>(method_->GetBytecodeArray() + pcOffset);
|
2022-11-02 01:32:55 +00:00
|
|
|
auto catchBlockBcIndex = FindBcIndexByPc(catchBlockPc);
|
2022-11-02 07:10:09 +00:00
|
|
|
regionsInfo_.InsertHead(catchBlockBcIndex);
|
2022-01-06 02:26:19 +00:00
|
|
|
// try block associate catch block
|
2023-11-06 01:19:36 +00:00
|
|
|
byteCodeException.back().catches.emplace_back(catchBlockPc);
|
2022-01-06 02:26:19 +00:00
|
|
|
return true;
|
|
|
|
});
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2023-04-23 09:21:01 +00:00
|
|
|
void BytecodeCircuitBuilder::BuildEntryBlock()
|
|
|
|
{
|
2023-11-06 01:19:36 +00:00
|
|
|
BytecodeRegion &entryBlock = RegionAt(0);
|
|
|
|
BytecodeRegion &nextBlock = RegionAt(1);
|
2023-04-23 09:21:01 +00:00
|
|
|
entryBlock.succs.emplace_back(&nextBlock);
|
|
|
|
nextBlock.preds.emplace_back(&entryBlock);
|
2023-11-06 01:19:36 +00:00
|
|
|
entryBlock.bytecodeIterator_.Reset(this, 0, BytecodeIterator::INVALID_INDEX);
|
2023-04-23 09:21:01 +00:00
|
|
|
}
|
|
|
|
|
2022-11-02 07:10:09 +00:00
|
|
|
void BytecodeCircuitBuilder::BuildRegions(const ExceptionInfo &byteCodeException)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-11-02 07:10:09 +00:00
|
|
|
auto &items = regionsInfo_.GetBlockItems();
|
2022-11-02 01:32:55 +00:00
|
|
|
auto blockSize = items.size();
|
2023-04-23 09:21:01 +00:00
|
|
|
|
|
|
|
// 1 : entry block. if the loop head is in the first bb block, the variables used in the head cannot correctly
|
|
|
|
// generate Phi nodes through the dominator-tree algorithm, resulting in an infinite loop. Therefore, an empty
|
|
|
|
// BB block is generated as an entry block
|
2023-11-06 01:19:36 +00:00
|
|
|
graph_.resize(blockSize + 1, nullptr);
|
|
|
|
for (size_t i = 0; i < graph_.size(); i++) {
|
|
|
|
graph_[i] = circuit_->chunk()->New<BytecodeRegion>(circuit_->chunk());
|
|
|
|
}
|
2023-04-23 09:21:01 +00:00
|
|
|
|
|
|
|
// build entry block
|
|
|
|
BuildEntryBlock();
|
|
|
|
|
2022-11-02 01:32:55 +00:00
|
|
|
// build basic block
|
2023-04-23 09:21:01 +00:00
|
|
|
size_t blockId = 1;
|
2022-11-02 01:32:55 +00:00
|
|
|
for (const auto &item : items) {
|
|
|
|
auto &curBlock = GetBasicBlockById(blockId);
|
|
|
|
curBlock.id = blockId;
|
|
|
|
curBlock.start = item.GetStartBcIndex();
|
2023-04-23 09:21:01 +00:00
|
|
|
if (blockId != 1) {
|
2023-11-06 01:19:36 +00:00
|
|
|
auto &prevBlock = RegionAt(blockId - 1);
|
2022-11-02 01:32:55 +00:00
|
|
|
prevBlock.end = curBlock.start - 1;
|
|
|
|
prevBlock.bytecodeIterator_.Reset(this, prevBlock.start, prevBlock.end);
|
|
|
|
// fall through
|
|
|
|
if (!item.IsHeadBlock()) {
|
|
|
|
curBlock.preds.emplace_back(&prevBlock);
|
|
|
|
prevBlock.succs.emplace_back(&curBlock);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-02 01:32:55 +00:00
|
|
|
blockId++;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
auto &lastBlock = RegionAt(blockId - 1); // 1: last block
|
2022-11-02 01:32:55 +00:00
|
|
|
lastBlock.end = GetLastBcIndex();
|
|
|
|
lastBlock.bytecodeIterator_.Reset(this, lastBlock.start, lastBlock.end);
|
|
|
|
|
2022-11-02 07:10:09 +00:00
|
|
|
auto &splitItems = regionsInfo_.GetSplitItems();
|
2022-11-02 01:32:55 +00:00
|
|
|
for (const auto &item : splitItems) {
|
2022-11-02 07:10:09 +00:00
|
|
|
auto curIndex = regionsInfo_.FindBBIndexByBcIndex(item.startBcIndex);
|
2022-11-02 01:32:55 +00:00
|
|
|
auto &curBlock = GetBasicBlockById(curIndex);
|
2022-11-02 07:10:09 +00:00
|
|
|
auto predIndex = regionsInfo_.FindBBIndexByBcIndex(item.predBcIndex);
|
2022-11-02 01:32:55 +00:00
|
|
|
auto &predBlock = GetBasicBlockById(predIndex);
|
|
|
|
curBlock.preds.emplace_back(&predBlock);
|
|
|
|
predBlock.succs.emplace_back(&curBlock);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-11-02 01:32:55 +00:00
|
|
|
if (byteCodeException.size() != 0) {
|
|
|
|
BuildCatchBlocks(byteCodeException);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
UpdateCFG();
|
|
|
|
if (HasTryCatch()) {
|
|
|
|
CollectTryPredsInfo();
|
|
|
|
}
|
|
|
|
RemoveUnreachableRegion();
|
2022-11-02 01:32:55 +00:00
|
|
|
if (IsLogEnabled()) {
|
2023-11-06 01:19:36 +00:00
|
|
|
PrintGraph("Update CFG");
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
BuildCircuit();
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-11-02 01:32:55 +00:00
|
|
|
void BytecodeCircuitBuilder::BuildCatchBlocks(const ExceptionInfo &byteCodeException)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
|
|
|
// try catch block associate
|
2022-04-24 17:17:29 +00:00
|
|
|
for (size_t i = 0; i < graph_.size(); i++) {
|
2023-11-06 01:19:36 +00:00
|
|
|
auto &bb = RegionAt(i);
|
2022-11-02 01:32:55 +00:00
|
|
|
auto startIndex = bb.start;
|
|
|
|
const auto pc = pcOffsets_[startIndex];
|
|
|
|
for (auto it = byteCodeException.cbegin(); it != byteCodeException.cend(); it++) {
|
|
|
|
if (pc < it->startPc || pc >= it->endPc) {
|
2022-01-18 04:02:20 +00:00
|
|
|
continue;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-11-02 01:32:55 +00:00
|
|
|
// try block interval
|
2023-11-06 01:19:36 +00:00
|
|
|
const auto &catches = it->catches; // catches start pc
|
2022-04-24 17:17:29 +00:00
|
|
|
for (size_t j = i + 1; j < graph_.size(); j++) {
|
2023-11-06 01:19:36 +00:00
|
|
|
auto &catchBB = RegionAt(j);
|
2022-11-02 01:32:55 +00:00
|
|
|
const auto catchStart = pcOffsets_[catchBB.start];
|
2023-11-06 01:19:36 +00:00
|
|
|
if (std::find(catches.cbegin(), catches.cend(), catchStart) != catches.cend()) {
|
|
|
|
bb.catches.insert(bb.catches.cbegin(), &catchBB);
|
2022-11-02 01:32:55 +00:00
|
|
|
bb.succs.emplace_back(&catchBB);
|
|
|
|
catchBB.preds.emplace_back(&bb);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-21 02:14:57 +00:00
|
|
|
|
|
|
|
// When there are multiple catch blocks in the current block, the set of catch blocks
|
|
|
|
// needs to be sorted to satisfy the order of execution of catch blocks.
|
2022-07-15 02:35:25 +00:00
|
|
|
bb.SortCatches();
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-06 01:19:36 +00:00
|
|
|
void BytecodeCircuitBuilder::CollectTryPredsInfo()
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2023-11-06 01:19:36 +00:00
|
|
|
for (size_t i = 0; i < graph_.size(); i++) {
|
|
|
|
auto &bb = RegionAt(i);
|
|
|
|
if (bb.catches.empty()) {
|
|
|
|
continue;
|
|
|
|
} else if (bb.catches.size() > 1) { // 1: cache size
|
|
|
|
for (auto it = bb.catches.begin() + 1; it != bb.catches.end();) { // 1: invalid catch bb
|
|
|
|
bb.EraseThisBlock((*it)->trys);
|
|
|
|
it = bb.catches.erase(it);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-06 01:19:36 +00:00
|
|
|
EnumerateBlock(bb, [&bb](const BytecodeInfo &bytecodeInfo) -> bool {
|
|
|
|
if (bytecodeInfo.IsGeneral()) {
|
|
|
|
// if block which can throw exception has serval catchs block,
|
|
|
|
// only the innermost catch block is useful
|
|
|
|
ASSERT(bb.catches.size() == 1); // 1: cache size
|
|
|
|
if (!bytecodeInfo.NoThrow()) {
|
|
|
|
bb.catches.at(0)->numOfStatePreds++;
|
2022-08-01 09:13:57 +00:00
|
|
|
}
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
return true;
|
|
|
|
});
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-06 01:19:36 +00:00
|
|
|
void BytecodeCircuitBuilder::RemoveUnusedPredsInfo(BytecodeRegion& bb)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2023-11-06 01:19:36 +00:00
|
|
|
EnumerateBlock(bb, [&bb](const BytecodeInfo &bytecodeInfo) -> bool {
|
|
|
|
if (bytecodeInfo.IsGeneral()) {
|
|
|
|
ASSERT(bb.catches.size() == 1); // 1: cache size
|
|
|
|
if (!bytecodeInfo.NoThrow()) {
|
|
|
|
bb.catches.at(0)->numOfStatePreds--;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
return true;
|
|
|
|
});
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2023-11-06 01:19:36 +00:00
|
|
|
void BytecodeCircuitBuilder::ClearUnreachableRegion(ChunkVector<BytecodeRegion*>& pendingList)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2023-11-06 01:19:36 +00:00
|
|
|
auto bb = pendingList.back();
|
|
|
|
pendingList.pop_back();
|
|
|
|
for (auto it = bb->preds.begin(); it != bb->preds.end(); it++) {
|
|
|
|
if ((*it)->numOfStatePreds != 0) {
|
|
|
|
bb->EraseThisBlock((*it)->succs);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
for (auto it = bb->succs.begin(); it != bb->succs.end(); it++) {
|
|
|
|
auto bbNext = *it;
|
|
|
|
if (bbNext->numOfStatePreds != 0) {
|
|
|
|
bb->EraseThisBlock(bbNext->preds);
|
|
|
|
bbNext->numOfStatePreds--;
|
|
|
|
if (bbNext->numOfStatePreds == 0) {
|
|
|
|
pendingList.emplace_back(bbNext);
|
|
|
|
}
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
for (auto it = bb->trys.begin(); it != bb->trys.end(); it++) {
|
|
|
|
if ((*it)->numOfStatePreds != 0) {
|
|
|
|
bb->EraseThisBlock((*it)->catches);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
for (auto it = bb->catches.begin(); it != bb->catches.end(); it++) {
|
|
|
|
auto bbNext = *it;
|
|
|
|
if (bbNext->numOfStatePreds != 0) {
|
|
|
|
RemoveUnusedPredsInfo(*bb);
|
|
|
|
bb->EraseThisBlock(bbNext->trys);
|
|
|
|
if (bbNext->numOfStatePreds == 0) {
|
|
|
|
pendingList.emplace_back(bbNext);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
bb->preds.clear();
|
|
|
|
bb->succs.clear();
|
|
|
|
bb->trys.clear();
|
|
|
|
bb->catches.clear();
|
|
|
|
numOfLiveBB_--;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2023-11-06 01:19:36 +00:00
|
|
|
void BytecodeCircuitBuilder::RemoveUnreachableRegion()
|
2022-07-15 02:35:25 +00:00
|
|
|
{
|
2023-11-06 01:19:36 +00:00
|
|
|
numOfLiveBB_ = graph_.size();
|
|
|
|
ChunkVector<BytecodeRegion*> pendingList(circuit_->chunk());
|
|
|
|
for (size_t i = 1; i < graph_.size(); i++) { // 1: skip entry bb
|
|
|
|
auto &bb = RegionAt(i);
|
|
|
|
if (bb.numOfStatePreds == 0) {
|
|
|
|
pendingList.emplace_back(&bb);
|
2022-07-15 02:35:25 +00:00
|
|
|
}
|
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
while (!pendingList.empty()) {
|
|
|
|
ClearUnreachableRegion(pendingList);
|
|
|
|
}
|
2022-07-15 02:35:25 +00:00
|
|
|
}
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
// Update CFG's predecessor, successor and try catch associations
|
2022-04-24 17:17:29 +00:00
|
|
|
void BytecodeCircuitBuilder::UpdateCFG()
|
2022-01-19 01:11:02 +00:00
|
|
|
{
|
2023-11-06 01:19:36 +00:00
|
|
|
for (size_t i = 0; i < graph_.size(); i++) {
|
|
|
|
auto &bb = RegionAt(i);
|
2022-01-19 01:11:02 +00:00
|
|
|
bb.preds.clear();
|
|
|
|
bb.trys.clear();
|
2023-11-06 01:19:36 +00:00
|
|
|
ChunkVector<BytecodeRegion *> newSuccs(circuit_->chunk());
|
2022-01-19 01:11:02 +00:00
|
|
|
for (const auto &succ: bb.succs) {
|
2023-11-06 01:19:36 +00:00
|
|
|
if (std::count(bb.catches.cbegin(), bb.catches.cend(), succ)) {
|
2022-01-19 01:11:02 +00:00
|
|
|
continue;
|
|
|
|
}
|
2022-10-27 09:12:44 +00:00
|
|
|
newSuccs.emplace_back(succ);
|
2022-01-19 01:11:02 +00:00
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
bb.succs.clear();
|
|
|
|
bb.succs.insert(bb.succs.end(), newSuccs.begin(), newSuccs.end());
|
2022-01-19 01:11:02 +00:00
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
for (size_t i = 0; i < graph_.size(); i++) {
|
|
|
|
auto &bb = RegionAt(i);
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto &succ: bb.succs) {
|
2022-10-27 09:12:44 +00:00
|
|
|
succ->preds.emplace_back(&bb);
|
2023-11-06 01:19:36 +00:00
|
|
|
succ->numOfStatePreds++;
|
2022-01-19 01:11:02 +00:00
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
for (auto &catchBlock: bb.catches) {
|
2022-10-27 09:12:44 +00:00
|
|
|
catchBlock->trys.emplace_back(&bb);
|
2022-01-19 01:11:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-24 17:17:29 +00:00
|
|
|
// build circuit
|
|
|
|
void BytecodeCircuitBuilder::BuildCircuitArgs()
|
|
|
|
{
|
2022-06-16 09:27:35 +00:00
|
|
|
argAcc_.NewCommonArg(CommonArgIdx::GLUE, MachineType::I64, GateType::NJSValue());
|
2023-05-18 11:13:51 +00:00
|
|
|
if (!method_->IsFastCall()) {
|
|
|
|
argAcc_.NewCommonArg(CommonArgIdx::ACTUAL_ARGC, MachineType::I64, GateType::NJSValue());
|
|
|
|
auto funcIdx = static_cast<size_t>(CommonArgIdx::FUNC);
|
|
|
|
const size_t actualNumArgs = argAcc_.GetActualNumArgs();
|
|
|
|
// new actual argument gates
|
|
|
|
for (size_t argIdx = funcIdx; argIdx < actualNumArgs; argIdx++) {
|
|
|
|
argAcc_.NewArg(argIdx);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
auto funcIdx = static_cast<size_t>(FastCallArgIdx::FUNC);
|
|
|
|
size_t actualNumArgs = static_cast<size_t>(FastCallArgIdx::NUM_OF_ARGS) + method_->GetNumArgsWithCallField();
|
|
|
|
for (size_t argIdx = funcIdx; argIdx < actualNumArgs; argIdx++) {
|
|
|
|
argAcc_.NewArg(argIdx);
|
|
|
|
}
|
2022-04-24 17:17:29 +00:00
|
|
|
}
|
2022-07-19 12:44:46 +00:00
|
|
|
argAcc_.CollectArgs();
|
2022-10-22 07:59:53 +00:00
|
|
|
if (HasTypes()) {
|
2022-07-05 07:24:00 +00:00
|
|
|
argAcc_.FillArgsGateType(&typeRecorder_);
|
|
|
|
}
|
2023-03-27 09:23:59 +00:00
|
|
|
|
|
|
|
BuildFrameArgs();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BytecodeCircuitBuilder::BuildFrameArgs()
|
|
|
|
{
|
2023-09-14 09:06:56 +00:00
|
|
|
UInt32PairAccessor accessor(0, 0);
|
|
|
|
auto metaData = circuit_->FrameArgs(accessor.ToValue());
|
|
|
|
size_t numArgs = metaData->GetNumIns();
|
2023-03-27 09:23:59 +00:00
|
|
|
std::vector<GateRef> args(numArgs, Circuit::NullGate());
|
|
|
|
size_t idx = 0;
|
|
|
|
args[idx++] = argAcc_.GetCommonArgGate(CommonArgIdx::FUNC);
|
|
|
|
args[idx++] = argAcc_.GetCommonArgGate(CommonArgIdx::NEW_TARGET);
|
|
|
|
args[idx++] = argAcc_.GetCommonArgGate(CommonArgIdx::THIS_OBJECT);
|
|
|
|
args[idx++] = argAcc_.GetCommonArgGate(CommonArgIdx::ACTUAL_ARGC);
|
2023-09-14 09:06:56 +00:00
|
|
|
args[idx++] = GetPreFrameArgs();
|
2023-05-18 03:24:10 +00:00
|
|
|
GateRef frameArgs = circuit_->NewGate(metaData, args);
|
2023-03-27 09:23:59 +00:00
|
|
|
argAcc_.SetFrameArgs(frameArgs);
|
2022-04-24 17:17:29 +00:00
|
|
|
}
|
|
|
|
|
2022-11-29 09:25:20 +00:00
|
|
|
std::vector<GateRef> BytecodeCircuitBuilder::CreateGateInList(
|
|
|
|
const BytecodeInfo &info, const GateMetaData *meta)
|
2022-04-24 17:17:29 +00:00
|
|
|
{
|
2022-11-29 09:25:20 +00:00
|
|
|
auto numValues = meta->GetNumIns();
|
|
|
|
const size_t length = meta->GetInValueStarts();
|
2022-11-10 09:58:04 +00:00
|
|
|
std::vector<GateRef> inList(numValues, Circuit::NullGate());
|
2022-11-28 01:26:23 +00:00
|
|
|
auto inputSize = info.inputs.size();
|
|
|
|
for (size_t i = 0; i < inputSize; i++) {
|
2022-10-27 03:56:58 +00:00
|
|
|
auto &input = info.inputs[i];
|
2022-10-17 11:41:53 +00:00
|
|
|
if (std::holds_alternative<ConstDataId>(input)) {
|
2023-06-06 09:13:57 +00:00
|
|
|
inList[i + length] = circuit_->GetConstantGate(MachineType::I64,
|
|
|
|
std::get<ConstDataId>(input).GetId(),
|
|
|
|
GateType::NJSValue());
|
2022-04-24 17:17:29 +00:00
|
|
|
} else if (std::holds_alternative<Immediate>(input)) {
|
2022-11-09 02:05:55 +00:00
|
|
|
inList[i + length] = circuit_->GetConstantGate(MachineType::I64,
|
2022-11-23 08:58:08 +00:00
|
|
|
std::get<Immediate>(input).GetValue(),
|
|
|
|
GateType::NJSValue());
|
2022-10-24 11:32:00 +00:00
|
|
|
} else if (std::holds_alternative<ICSlotId>(input)) {
|
2022-11-09 02:05:55 +00:00
|
|
|
inList[i + length] = circuit_->GetConstantGate(MachineType::I16,
|
2022-11-23 08:58:08 +00:00
|
|
|
std::get<ICSlotId>(input).GetId(),
|
|
|
|
GateType::NJSValue());
|
2022-04-24 17:17:29 +00:00
|
|
|
} else {
|
|
|
|
ASSERT(std::holds_alternative<VirtualRegister>(input));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2022-11-28 01:26:23 +00:00
|
|
|
if (info.AccIn()) {
|
|
|
|
inputSize++;
|
|
|
|
}
|
2023-06-09 02:13:24 +00:00
|
|
|
if (meta->HasFrameState()) {
|
|
|
|
inList[inputSize + length] = GetFrameArgs();
|
2022-11-28 01:26:23 +00:00
|
|
|
}
|
2022-04-24 17:17:29 +00:00
|
|
|
return inList;
|
|
|
|
}
|
|
|
|
|
|
|
|
GateRef BytecodeCircuitBuilder::NewConst(const BytecodeInfo &info)
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
{
|
2022-10-27 03:56:58 +00:00
|
|
|
auto opcode = info.GetOpcode();
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
GateRef gate = 0;
|
|
|
|
switch (opcode) {
|
2022-09-08 01:37:53 +00:00
|
|
|
case EcmaOpcode::LDNAN:
|
2022-11-09 02:05:55 +00:00
|
|
|
gate = circuit_->GetConstantGate(MachineType::I64,
|
2022-11-23 08:58:08 +00:00
|
|
|
base::NumberHelper::GetNaN(),
|
2022-11-29 09:25:20 +00:00
|
|
|
GateType::NumberType());
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
break;
|
2022-09-08 01:37:53 +00:00
|
|
|
case EcmaOpcode::LDINFINITY:
|
2022-11-09 02:05:55 +00:00
|
|
|
gate = circuit_->GetConstantGate(MachineType::I64,
|
2022-11-23 08:58:08 +00:00
|
|
|
base::NumberHelper::GetPositiveInfinity(),
|
2022-11-29 09:25:20 +00:00
|
|
|
GateType::NumberType());
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
break;
|
2022-09-08 01:37:53 +00:00
|
|
|
case EcmaOpcode::LDUNDEFINED:
|
2022-11-09 02:05:55 +00:00
|
|
|
gate = circuit_->GetConstantGate(MachineType::I64,
|
2022-11-23 08:58:08 +00:00
|
|
|
JSTaggedValue::VALUE_UNDEFINED,
|
2022-11-29 09:25:20 +00:00
|
|
|
GateType::UndefinedType());
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
break;
|
2022-09-08 01:37:53 +00:00
|
|
|
case EcmaOpcode::LDNULL:
|
2022-11-09 02:05:55 +00:00
|
|
|
gate = circuit_->GetConstantGate(MachineType::I64,
|
2022-11-23 08:58:08 +00:00
|
|
|
JSTaggedValue::VALUE_NULL,
|
2022-11-29 09:25:20 +00:00
|
|
|
GateType::NullType());
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
break;
|
2022-09-08 01:37:53 +00:00
|
|
|
case EcmaOpcode::LDTRUE:
|
2022-11-09 02:05:55 +00:00
|
|
|
gate = circuit_->GetConstantGate(MachineType::I64,
|
2022-11-23 08:58:08 +00:00
|
|
|
JSTaggedValue::VALUE_TRUE,
|
2022-11-29 09:25:20 +00:00
|
|
|
GateType::BooleanType());
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
break;
|
2022-09-08 01:37:53 +00:00
|
|
|
case EcmaOpcode::LDFALSE:
|
2022-11-09 02:05:55 +00:00
|
|
|
gate = circuit_->GetConstantGate(MachineType::I64,
|
2022-11-23 08:58:08 +00:00
|
|
|
JSTaggedValue::VALUE_FALSE,
|
2022-11-29 09:25:20 +00:00
|
|
|
GateType::BooleanType());
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
break;
|
2022-09-08 01:37:53 +00:00
|
|
|
case EcmaOpcode::LDHOLE:
|
2022-11-09 02:05:55 +00:00
|
|
|
gate = circuit_->GetConstantGate(MachineType::I64,
|
2022-11-23 08:58:08 +00:00
|
|
|
JSTaggedValue::VALUE_HOLE,
|
|
|
|
GateType::TaggedValue());
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
break;
|
2022-09-08 01:37:53 +00:00
|
|
|
case EcmaOpcode::LDAI_IMM32:
|
2022-11-09 02:05:55 +00:00
|
|
|
gate = circuit_->GetConstantGate(MachineType::I64,
|
2022-11-23 08:58:08 +00:00
|
|
|
std::get<Immediate>(info.inputs[0]).ToJSTaggedValueInt(),
|
2022-11-29 09:25:20 +00:00
|
|
|
GateType::IntType());
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
break;
|
2022-09-08 01:37:53 +00:00
|
|
|
case EcmaOpcode::FLDAI_IMM64:
|
2022-11-09 02:05:55 +00:00
|
|
|
gate = circuit_->GetConstantGate(MachineType::I64,
|
2022-11-23 08:58:08 +00:00
|
|
|
std::get<Immediate>(info.inputs.at(0)).ToJSTaggedValueDouble(),
|
2022-11-29 09:25:20 +00:00
|
|
|
GateType::DoubleType());
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
break;
|
2022-09-08 01:37:53 +00:00
|
|
|
case EcmaOpcode::LDFUNCTION:
|
2022-06-16 09:27:35 +00:00
|
|
|
gate = argAcc_.GetCommonArgGate(CommonArgIdx::FUNC);
|
2022-04-06 07:17:04 +00:00
|
|
|
break;
|
2022-09-09 07:35:02 +00:00
|
|
|
case EcmaOpcode::LDNEWTARGET:
|
|
|
|
gate = argAcc_.GetCommonArgGate(CommonArgIdx::NEW_TARGET);
|
|
|
|
break;
|
|
|
|
case EcmaOpcode::LDTHIS:
|
2022-10-15 04:09:38 +00:00
|
|
|
gate = argAcc_.GetCommonArgGate(CommonArgIdx::THIS_OBJECT);
|
2022-09-09 07:35:02 +00:00
|
|
|
break;
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
default:
|
2022-12-01 07:29:41 +00:00
|
|
|
LOG_ECMA(FATAL) << "this branch is unreachable";
|
2022-04-11 02:41:49 +00:00
|
|
|
UNREACHABLE();
|
Add information such as instruction immediate, method_id, string_id, etc.
The lowering slow path requires not only the vreg information of the
instruction, but also other information such as string id, method id, etc.
For each bytecode instruction, collect the various information stored in
the instruction, and use the information as the input of the gate, and
in the lowering stage, take out the required information from the gate.
issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4WQR5
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I42ef36554b0b88ce3e1cd0f593e8ce9e924b83e0
2022-03-04 07:52:07 +00:00
|
|
|
}
|
|
|
|
return gate;
|
|
|
|
}
|
|
|
|
|
2023-11-06 01:19:36 +00:00
|
|
|
void BytecodeCircuitBuilder::MergeThrowGate(BytecodeRegion &bb, uint32_t bcIndex)
|
|
|
|
{
|
|
|
|
auto state = frameStateBuilder_.GetCurrentState();
|
|
|
|
auto depend = frameStateBuilder_.GetCurrentDepend();
|
|
|
|
if (!bb.catches.empty()) {
|
|
|
|
auto ifSuccess = circuit_->NewGate(circuit_->IfSuccess(), {state});
|
|
|
|
auto ifException = circuit_->NewGate(circuit_->IfException(), {state, depend});
|
|
|
|
frameStateBuilder_.UpdateStateDepend(ifException, ifException);
|
|
|
|
ASSERT(bb.catches.size() == 1); // 1: one catch
|
|
|
|
auto bbNext = bb.catches.at(0);
|
|
|
|
frameStateBuilder_.MergeIntoSuccessor(bb, *bbNext);
|
|
|
|
bbNext->expandedPreds.push_back({bb.id, bcIndex, true});
|
|
|
|
state = ifSuccess;
|
|
|
|
}
|
|
|
|
auto constant = circuit_->GetConstantGate(MachineType::I64,
|
|
|
|
JSTaggedValue::VALUE_EXCEPTION,
|
|
|
|
GateType::TaggedValue());
|
|
|
|
circuit_->NewGate(circuit_->Return(),
|
|
|
|
{ state, depend, constant, circuit_->GetReturnRoot() });
|
|
|
|
}
|
|
|
|
|
|
|
|
void BytecodeCircuitBuilder::MergeExceptionGete(BytecodeRegion &bb,
|
|
|
|
const BytecodeInfo& bytecodeInfo, uint32_t bcIndex)
|
|
|
|
{
|
|
|
|
auto state = frameStateBuilder_.GetCurrentState();
|
|
|
|
auto depend = frameStateBuilder_.GetCurrentDepend();
|
|
|
|
auto ifSuccess = circuit_->NewGate(circuit_->IfSuccess(), {state});
|
|
|
|
ASSERT(bb.catches.size() == 1); // 1: one catch
|
|
|
|
auto bbNext = bb.catches.at(0);
|
|
|
|
auto ifException = circuit_->NewGate(circuit_->IfException(), {state, depend});
|
|
|
|
frameStateBuilder_.UpdateStateDepend(ifException, ifException);
|
|
|
|
frameStateBuilder_.MergeIntoSuccessor(bb, *bbNext);
|
|
|
|
if (bytecodeInfo.GetOpcode() == EcmaOpcode::CREATEASYNCGENERATOROBJ_V8) {
|
|
|
|
bbNext->expandedPreds.push_back({bb.id, bcIndex + 1, true}); // 1: next pc
|
|
|
|
} else {
|
|
|
|
bbNext->expandedPreds.push_back({bb.id, bcIndex, true});
|
|
|
|
}
|
|
|
|
frameStateBuilder_.UpdateStateDepend(ifSuccess, depend);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb)
|
2022-01-18 04:02:20 +00:00
|
|
|
{
|
2022-10-27 03:56:58 +00:00
|
|
|
auto &iterator = bb.GetBytecodeIterator();
|
|
|
|
const BytecodeInfo& bytecodeInfo = iterator.GetBytecodeInfo();
|
2023-11-06 01:19:36 +00:00
|
|
|
GateRef state = frameStateBuilder_.GetCurrentState();
|
|
|
|
GateRef depend = frameStateBuilder_.GetCurrentDepend();
|
2022-11-02 07:10:09 +00:00
|
|
|
size_t numValueInputs = bytecodeInfo.ComputeValueInputCount();
|
2022-04-24 17:17:29 +00:00
|
|
|
GateRef gate = 0;
|
2023-01-06 10:04:16 +00:00
|
|
|
bool writable = !bytecodeInfo.NoSideEffects();
|
2023-09-14 09:06:56 +00:00
|
|
|
bool hasFrameState = bytecodeInfo.HasFrameState();
|
2023-03-02 12:09:04 +00:00
|
|
|
size_t pcOffset = GetPcOffset(iterator.Index());
|
2023-03-27 09:23:59 +00:00
|
|
|
auto meta = circuit_->JSBytecode(numValueInputs, bytecodeInfo.GetOpcode(), pcOffset, writable, hasFrameState);
|
2022-11-29 09:25:20 +00:00
|
|
|
std::vector<GateRef> inList = CreateGateInList(bytecodeInfo, meta);
|
2022-10-07 23:56:43 +00:00
|
|
|
if (bytecodeInfo.IsDef()) {
|
2022-11-29 09:25:20 +00:00
|
|
|
gate = circuit_->NewGate(meta, MachineType::I64, inList.size(),
|
|
|
|
inList.data(), GateType::AnyType());
|
2022-04-24 17:17:29 +00:00
|
|
|
} else {
|
2022-11-29 09:25:20 +00:00
|
|
|
gate = circuit_->NewGate(meta, MachineType::NOVALUE, inList.size(),
|
|
|
|
inList.data(), GateType::Empty());
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2023-04-28 08:37:17 +00:00
|
|
|
byteCodeToJSGates_[iterator.Index()].emplace_back(gate);
|
|
|
|
jsGatesToByteCode_[gate] = iterator.Index();
|
2023-04-27 12:26:51 +00:00
|
|
|
gateAcc_.NewIn(gate, 0, state);
|
|
|
|
gateAcc_.NewIn(gate, 1, depend);
|
2023-11-06 01:19:36 +00:00
|
|
|
frameStateBuilder_.UpdateStateDepend(gate, gate);
|
|
|
|
frameStateBuilder_.UpdateFrameValues(bytecodeInfo, iterator.Index(), gate);
|
2023-02-13 05:46:34 +00:00
|
|
|
if (bytecodeInfo.IsThrow()) {
|
2023-11-06 01:19:36 +00:00
|
|
|
MergeThrowGate(bb, iterator.Index());
|
2023-02-13 05:46:34 +00:00
|
|
|
return;
|
|
|
|
}
|
2023-01-13 01:18:36 +00:00
|
|
|
|
2023-11-06 01:19:36 +00:00
|
|
|
if (!bb.catches.empty() && !bytecodeInfo.NoThrow()) {
|
|
|
|
MergeExceptionGete(bb, bytecodeInfo, iterator.Index());
|
2022-02-12 08:15:41 +00:00
|
|
|
}
|
2022-06-06 09:41:17 +00:00
|
|
|
if (bytecodeInfo.IsGeneratorRelative()) {
|
|
|
|
suspendAndResumeGates_.emplace_back(gate);
|
|
|
|
}
|
2022-04-24 17:17:29 +00:00
|
|
|
}
|
|
|
|
|
2023-11-06 01:19:36 +00:00
|
|
|
void BytecodeCircuitBuilder::NewJump(BytecodeRegion &bb)
|
2022-04-24 17:17:29 +00:00
|
|
|
{
|
2022-10-27 03:56:58 +00:00
|
|
|
auto &iterator = bb.GetBytecodeIterator();
|
|
|
|
const BytecodeInfo& bytecodeInfo = iterator.GetBytecodeInfo();
|
2023-11-06 01:19:36 +00:00
|
|
|
GateRef state = frameStateBuilder_.GetCurrentState();
|
|
|
|
GateRef depend = frameStateBuilder_.GetCurrentDepend();
|
2022-06-10 07:22:21 +00:00
|
|
|
size_t numValueInputs = bytecodeInfo.ComputeValueInputCount();
|
2023-11-06 01:19:36 +00:00
|
|
|
if (bytecodeInfo.IsCondJump() && bb.succs.size() == 2) { // 2: two succ
|
2023-03-02 12:09:04 +00:00
|
|
|
size_t pcOffset = GetPcOffset(iterator.Index());
|
2023-03-27 09:23:59 +00:00
|
|
|
auto meta = circuit_->JSBytecode(numValueInputs, bytecodeInfo.GetOpcode(), pcOffset, false, false);
|
2022-11-29 09:25:20 +00:00
|
|
|
auto numValues = meta->GetNumIns();
|
|
|
|
GateRef gate = circuit_->NewGate(meta, std::vector<GateRef>(numValues, Circuit::NullGate()));
|
2022-07-19 12:44:46 +00:00
|
|
|
gateAcc_.NewIn(gate, 0, state);
|
|
|
|
gateAcc_.NewIn(gate, 1, depend);
|
2023-11-06 01:19:36 +00:00
|
|
|
frameStateBuilder_.UpdateStateDepend(gate, gate);
|
|
|
|
frameStateBuilder_.UpdateFrameValues(bytecodeInfo, iterator.Index(), gate);
|
|
|
|
|
2022-11-29 09:25:20 +00:00
|
|
|
auto ifTrue = circuit_->NewGate(circuit_->IfTrue(), {gate});
|
|
|
|
auto trueRelay = circuit_->NewGate(circuit_->DependRelay(), {ifTrue, gate});
|
|
|
|
auto ifFalse = circuit_->NewGate(circuit_->IfFalse(), {gate});
|
|
|
|
auto falseRelay = circuit_->NewGate(circuit_->DependRelay(), {ifFalse, gate});
|
2023-11-06 01:19:36 +00:00
|
|
|
for (auto &bbNext: bb.succs) {
|
|
|
|
if (bbNext->id == bb.id + 1) {
|
|
|
|
frameStateBuilder_.UpdateStateDepend(ifFalse, falseRelay);
|
|
|
|
frameStateBuilder_.MergeIntoSuccessor(bb, *bbNext);
|
|
|
|
bbNext->expandedPreds.push_back({bb.id, iterator.Index(), false});
|
|
|
|
} else {
|
|
|
|
frameStateBuilder_.UpdateStateDepend(ifTrue, trueRelay);
|
|
|
|
frameStateBuilder_.MergeIntoSuccessor(bb, *bbNext);
|
|
|
|
bbNext->expandedPreds.push_back({bb.id, iterator.Index(), false});
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
2023-04-28 08:37:17 +00:00
|
|
|
byteCodeToJSGates_[iterator.Index()].emplace_back(gate);
|
|
|
|
jsGatesToByteCode_[gate] = iterator.Index();
|
2022-04-24 17:17:29 +00:00
|
|
|
} else {
|
|
|
|
ASSERT(bb.succs.size() == 1);
|
|
|
|
auto &bbNext = bb.succs.at(0);
|
2023-11-06 01:19:36 +00:00
|
|
|
frameStateBuilder_.MergeIntoSuccessor(bb, *bbNext);
|
2022-10-27 03:56:58 +00:00
|
|
|
bbNext->expandedPreds.push_back({bb.id, iterator.Index(), false});
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-04-24 17:17:29 +00:00
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
|
2023-11-06 01:19:36 +00:00
|
|
|
GateRef BytecodeCircuitBuilder::NewReturn(BytecodeRegion &bb)
|
2022-04-24 17:17:29 +00:00
|
|
|
{
|
|
|
|
ASSERT(bb.succs.empty());
|
2022-10-27 03:56:58 +00:00
|
|
|
auto &iterator = bb.GetBytecodeIterator();
|
|
|
|
const BytecodeInfo& bytecodeInfo = iterator.GetBytecodeInfo();
|
2023-11-06 01:19:36 +00:00
|
|
|
GateRef state = frameStateBuilder_.GetCurrentState();
|
|
|
|
GateRef depend = frameStateBuilder_.GetCurrentDepend();
|
|
|
|
GateRef gate = Circuit::NullGate();
|
2022-10-27 03:56:58 +00:00
|
|
|
if (bytecodeInfo.GetOpcode() == EcmaOpcode::RETURN) {
|
2022-09-06 05:27:19 +00:00
|
|
|
// handle return.dyn bytecode
|
2023-11-06 01:19:36 +00:00
|
|
|
gate = circuit_->NewGate(circuit_->Return(),
|
2023-04-27 12:26:51 +00:00
|
|
|
{ state, depend, Circuit::NullGate(), circuit_->GetReturnRoot() });
|
2023-04-28 08:37:17 +00:00
|
|
|
byteCodeToJSGates_[iterator.Index()].emplace_back(gate);
|
|
|
|
jsGatesToByteCode_[gate] = iterator.Index();
|
2022-10-27 03:56:58 +00:00
|
|
|
} else if (bytecodeInfo.GetOpcode() == EcmaOpcode::RETURNUNDEFINED) {
|
2022-04-24 17:17:29 +00:00
|
|
|
// handle returnundefined bytecode
|
2022-11-09 02:05:55 +00:00
|
|
|
auto constant = circuit_->GetConstantGate(MachineType::I64,
|
2022-11-23 08:58:08 +00:00
|
|
|
JSTaggedValue::VALUE_UNDEFINED,
|
|
|
|
GateType::TaggedValue());
|
2023-11-06 01:19:36 +00:00
|
|
|
gate = circuit_->NewGate(circuit_->Return(),
|
2023-04-27 12:26:51 +00:00
|
|
|
{ state, depend, constant, circuit_->GetReturnRoot() });
|
2023-04-28 08:37:17 +00:00
|
|
|
byteCodeToJSGates_[iterator.Index()].emplace_back(gate);
|
|
|
|
jsGatesToByteCode_[gate] = iterator.Index();
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
return gate;
|
2022-04-24 17:17:29 +00:00
|
|
|
}
|
|
|
|
|
2023-11-06 01:19:36 +00:00
|
|
|
void BytecodeCircuitBuilder::NewByteCode(BytecodeRegion &bb)
|
2022-04-24 17:17:29 +00:00
|
|
|
{
|
2022-10-27 03:56:58 +00:00
|
|
|
auto &iterator = bb.GetBytecodeIterator();
|
|
|
|
const BytecodeInfo& bytecodeInfo = iterator.GetBytecodeInfo();
|
2023-11-01 09:18:44 +00:00
|
|
|
FrameLiveOut* liveout;
|
|
|
|
auto bcId = iterator.Index();
|
|
|
|
if (iterator.IsInRange(bcId - 1)) {
|
|
|
|
liveout = frameStateBuilder_.GetOrOCreateBCEndLiveOut(bcId - 1);
|
|
|
|
} else {
|
|
|
|
liveout = frameStateBuilder_.GetOrOCreateBBLiveOut(bb.id);
|
|
|
|
}
|
|
|
|
frameStateBuilder_.AdvanceToNextBc(bytecodeInfo, liveout, bcId);
|
2023-11-06 01:19:36 +00:00
|
|
|
GateRef gate = Circuit::NullGate();
|
2022-02-17 03:48:40 +00:00
|
|
|
if (bytecodeInfo.IsSetConstant()) {
|
2022-04-24 17:17:29 +00:00
|
|
|
// handle bytecode command to get constants
|
2023-11-06 01:19:36 +00:00
|
|
|
gate = NewConst(bytecodeInfo);
|
2023-04-28 08:37:17 +00:00
|
|
|
byteCodeToJSGates_[iterator.Index()].emplace_back(gate);
|
|
|
|
jsGatesToByteCode_[gate] = iterator.Index();
|
2022-02-17 03:48:40 +00:00
|
|
|
} else if (bytecodeInfo.IsGeneral()) {
|
2022-04-24 17:17:29 +00:00
|
|
|
// handle general ecma.* bytecodes
|
2023-11-06 01:19:36 +00:00
|
|
|
NewJSGate(bb);
|
2022-02-17 03:48:40 +00:00
|
|
|
} else if (bytecodeInfo.IsJump()) {
|
2022-04-24 17:17:29 +00:00
|
|
|
// handle conditional jump and unconditional jump bytecodes
|
2023-11-06 01:19:36 +00:00
|
|
|
NewJump(bb);
|
2022-02-17 03:48:40 +00:00
|
|
|
} else if (bytecodeInfo.IsReturn()) {
|
2022-09-06 05:27:19 +00:00
|
|
|
// handle return.dyn and returnundefined bytecodes
|
2023-11-06 01:19:36 +00:00
|
|
|
gate = NewReturn(bb);
|
|
|
|
} else if (bytecodeInfo.IsMov()) {
|
|
|
|
frameStateBuilder_.UpdateMoveValues(bytecodeInfo, iterator.Index());
|
|
|
|
} else if (!bytecodeInfo.IsDiscarded()) {
|
2022-12-01 07:29:41 +00:00
|
|
|
LOG_ECMA(FATAL) << "this branch is unreachable";
|
2022-04-24 17:17:29 +00:00
|
|
|
UNREACHABLE();
|
|
|
|
}
|
2023-11-06 01:19:36 +00:00
|
|
|
if (gate != Circuit::NullGate()) {
|
|
|
|
frameStateBuilder_.UpdateFrameValues(bytecodeInfo, iterator.Index(), gate);
|
|
|
|
}
|
2022-04-24 17:17:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BytecodeCircuitBuilder::BuildSubCircuit()
|
|
|
|
{
|
2023-11-06 01:19:36 +00:00
|
|
|
auto &entryBlock = RegionAt(0);
|
|
|
|
frameStateBuilder_.InitEntryBB(entryBlock);
|
|
|
|
auto& rpoList = frameStateBuilder_.GetRpoList();
|
|
|
|
for (auto &bbId: rpoList) {
|
|
|
|
auto &bb = RegionAt(bbId);
|
|
|
|
frameStateBuilder_.AdvanceToNextBB(bb);
|
2023-04-23 09:21:01 +00:00
|
|
|
if (IsEntryBlock(bb.id)) {
|
2023-08-07 08:24:38 +00:00
|
|
|
if (NeedCheckSafePointAndStackOver()) {
|
2023-11-06 01:19:36 +00:00
|
|
|
GateRef state = frameStateBuilder_.GetCurrentState();
|
|
|
|
GateRef depend = frameStateBuilder_.GetCurrentDepend();
|
|
|
|
auto stackCheck = circuit_->NewGate(circuit_->CheckSafePointAndStackOver(), {state, depend});
|
|
|
|
bb.dependCache = stackCheck;
|
|
|
|
frameStateBuilder_.UpdateStateDepend(stackCheck, stackCheck);
|
|
|
|
}
|
|
|
|
auto &bbNext = RegionAt(bb.id + 1);
|
|
|
|
frameStateBuilder_.MergeIntoSuccessor(bb, bbNext);
|
2023-04-23 09:21:01 +00:00
|
|
|
bbNext.expandedPreds.push_back({bb.id, bb.end, false});
|
|
|
|
continue;
|
|
|
|
}
|
2022-02-10 02:03:48 +00:00
|
|
|
if (!bb.trys.empty()) {
|
2023-11-06 01:19:36 +00:00
|
|
|
GateRef state = frameStateBuilder_.GetCurrentState();
|
|
|
|
GateRef depend = frameStateBuilder_.GetCurrentDepend();
|
|
|
|
auto getException = circuit_->NewGate(circuit_->GetException(),
|
|
|
|
MachineType::I64, {state, depend}, GateType::AnyType());
|
|
|
|
frameStateBuilder_.UpdateAccumulator(getException);
|
|
|
|
frameStateBuilder_.UpdateStateDepend(state, getException);
|
|
|
|
}
|
|
|
|
EnumerateBlock(bb, [this, &bb]
|
2022-10-27 03:56:58 +00:00
|
|
|
(const BytecodeInfo &bytecodeInfo) -> bool {
|
2023-11-06 01:19:36 +00:00
|
|
|
NewByteCode(bb);
|
2022-02-17 03:48:40 +00:00
|
|
|
if (bytecodeInfo.IsJump() || bytecodeInfo.IsThrow()) {
|
2022-06-30 02:22:52 +00:00
|
|
|
return false;
|
2022-04-24 17:17:29 +00:00
|
|
|
}
|
2022-06-30 02:22:52 +00:00
|
|
|
return true;
|
|
|
|
});
|
2023-11-06 01:19:36 +00:00
|
|
|
bool needFallThrough = true;
|
|
|
|
if (!bb.IsEmptryBlock()) {
|
|
|
|
const BytecodeInfo& bytecodeInfo = GetBytecodeInfo(bb.end);
|
|
|
|
needFallThrough = bytecodeInfo.needFallThrough();
|
|
|
|
}
|
|
|
|
// fallThrough or empty merge bb
|
|
|
|
if (needFallThrough) {
|
|
|
|
ASSERT(bb.succs.size() == 1); // 1: fall through
|
|
|
|
auto &bbNext = RegionAt(bb.succs[0]->id);
|
|
|
|
frameStateBuilder_.MergeIntoSuccessor(bb, bbNext);
|
2023-04-03 08:33:32 +00:00
|
|
|
bbNext.expandedPreds.push_back({bb.id, bb.end, false});
|
|
|
|
}
|
2022-04-24 17:17:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void BytecodeCircuitBuilder::BuildCircuit()
|
|
|
|
{
|
|
|
|
// create arg gates array
|
|
|
|
BuildCircuitArgs();
|
2023-11-06 01:19:36 +00:00
|
|
|
frameStateBuilder_.DoBytecodeAnalysis();
|
2022-04-24 17:17:29 +00:00
|
|
|
// build states sub-circuit of each block
|
|
|
|
BuildSubCircuit();
|
2022-04-14 08:14:34 +00:00
|
|
|
if (IsLogEnabled()) {
|
2022-10-03 04:31:39 +00:00
|
|
|
PrintGraph("Bytecode2Gate");
|
2022-10-09 07:53:21 +00:00
|
|
|
LOG_COMPILER(INFO) << "\033[34m" << "============= "
|
|
|
|
<< "After bytecode2circuit lowering ["
|
|
|
|
<< methodName_ << "]"
|
|
|
|
<< " =============" << "\033[0m";
|
2022-11-09 02:05:55 +00:00
|
|
|
circuit_->PrintAllGatesWithBytecode();
|
2022-10-03 04:31:39 +00:00
|
|
|
LOG_COMPILER(INFO) << "\033[34m" << "=========================== End ===========================" << "\033[0m";
|
2022-04-14 08:14:34 +00:00
|
|
|
}
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-10-03 04:31:39 +00:00
|
|
|
void BytecodeCircuitBuilder::PrintGraph(const char* title)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-10-03 04:31:39 +00:00
|
|
|
LOG_COMPILER(INFO) << "======================== " << title << " ========================";
|
2022-04-24 17:17:29 +00:00
|
|
|
for (size_t i = 0; i < graph_.size(); i++) {
|
2023-11-06 01:19:36 +00:00
|
|
|
BytecodeRegion& bb = RegionAt(i);
|
|
|
|
if (!IsEntryBlock(bb.id) && bb.numOfStatePreds == 0) {
|
2022-10-03 04:31:39 +00:00
|
|
|
LOG_COMPILER(INFO) << "B" << bb.id << ": ;preds= invalid BB";
|
2022-11-02 01:32:55 +00:00
|
|
|
LOG_COMPILER(INFO) << "\tBytecodePC: [" << std::to_string(bb.start) << ", "
|
|
|
|
<< std::to_string(bb.end) << ")";
|
2022-01-06 02:26:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
2022-10-03 04:31:39 +00:00
|
|
|
std::string log("B" + std::to_string(bb.id) + ": ;preds= ");
|
|
|
|
for (size_t k = 0; k < bb.preds.size(); ++k) {
|
|
|
|
log += std::to_string(bb.preds[k]->id) + ", ";
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-07-06 06:12:54 +00:00
|
|
|
LOG_COMPILER(INFO) << log;
|
2023-04-23 09:21:01 +00:00
|
|
|
if (IsEntryBlock(bb.id)) {
|
|
|
|
LOG_COMPILER(INFO) << "\tBytecodePC: Empty";
|
|
|
|
} else {
|
|
|
|
LOG_COMPILER(INFO) << "\tBytecodePC: [" << std::to_string(bb.start) << ", "
|
|
|
|
<< std::to_string(bb.end) << ")";
|
|
|
|
}
|
2022-01-06 02:26:19 +00:00
|
|
|
|
2022-10-03 04:31:39 +00:00
|
|
|
std::string log1("\tSucces: ");
|
|
|
|
for (size_t j = 0; j < bb.succs.size(); j++) {
|
|
|
|
log1 += std::to_string(bb.succs[j]->id) + ", ";
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-10-03 04:31:39 +00:00
|
|
|
LOG_COMPILER(INFO) << log1;
|
2022-01-06 02:26:19 +00:00
|
|
|
|
2023-11-06 01:19:36 +00:00
|
|
|
for (size_t j = 0; j < bb.catches.size(); j++) {
|
|
|
|
LOG_COMPILER(INFO) << "\tcatch [: " << std::to_string(bb.catches[j]->start) << ", "
|
|
|
|
<< std::to_string(bb.catches[j]->end) << ")";
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-10-03 04:31:39 +00:00
|
|
|
std::string log2("\tTrys: ");
|
|
|
|
for (auto tryBlock: bb.trys) {
|
|
|
|
log2 += std::to_string(tryBlock->id) + " , ";
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-10-03 04:31:39 +00:00
|
|
|
LOG_COMPILER(INFO) << log2;
|
2022-01-06 02:26:19 +00:00
|
|
|
|
2022-11-02 01:32:55 +00:00
|
|
|
PrintBytecodeInfo(bb);
|
2022-10-03 04:31:39 +00:00
|
|
|
LOG_COMPILER(INFO) << "";
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-02 01:32:55 +00:00
|
|
|
void BytecodeCircuitBuilder::PrintBytecodeInfo(BytecodeRegion& bb)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2023-04-23 09:21:01 +00:00
|
|
|
if (IsEntryBlock(bb.id)) {
|
|
|
|
LOG_COMPILER(INFO) << "\tBytecode[] = Empty";
|
|
|
|
return;
|
|
|
|
}
|
2022-10-03 04:31:39 +00:00
|
|
|
LOG_COMPILER(INFO) << "\tBytecode[] = ";
|
2022-10-27 03:56:58 +00:00
|
|
|
EnumerateBlock(bb, [&](const BytecodeInfo &bytecodeInfo) -> bool {
|
2022-10-27 09:12:44 +00:00
|
|
|
auto &iterator = bb.GetBytecodeIterator();
|
2022-10-03 04:31:39 +00:00
|
|
|
std::string log;
|
2022-10-27 09:12:44 +00:00
|
|
|
log += std::string("\t\t< ") + std::to_string(iterator.Index()) + ": ";
|
2022-11-02 01:32:55 +00:00
|
|
|
log += GetEcmaOpcodeStr(iterator.GetBytecodeInfo().GetOpcode()) + ", " + "In=[";
|
2022-10-27 03:56:58 +00:00
|
|
|
if (bytecodeInfo.AccIn()) {
|
2022-10-03 04:31:39 +00:00
|
|
|
log += "acc,";
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-10-03 04:31:39 +00:00
|
|
|
for (const auto &in: bytecodeInfo.inputs) {
|
|
|
|
if (std::holds_alternative<VirtualRegister>(in)) {
|
|
|
|
log += std::to_string(std::get<VirtualRegister>(in).GetId()) + ",";
|
|
|
|
}
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-10-03 04:31:39 +00:00
|
|
|
log += "], Out=[";
|
2022-10-27 03:56:58 +00:00
|
|
|
if (bytecodeInfo.AccOut()) {
|
2022-10-03 04:31:39 +00:00
|
|
|
log += "acc,";
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-10-03 04:31:39 +00:00
|
|
|
for (const auto &out: bytecodeInfo.vregOut) {
|
2022-11-29 03:14:12 +00:00
|
|
|
log += std::to_string(out) + ",";
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-10-03 04:31:39 +00:00
|
|
|
log += "] >";
|
|
|
|
LOG_COMPILER(INFO) << log;
|
2022-07-15 02:35:25 +00:00
|
|
|
|
2023-04-28 08:37:17 +00:00
|
|
|
auto gate = GetGateByBcIndex(iterator.Index());
|
2022-11-02 01:32:55 +00:00
|
|
|
if (gate != Circuit::NullGate()) {
|
|
|
|
this->gateAcc_.ShortPrint(gate);
|
2022-07-15 02:35:25 +00:00
|
|
|
}
|
2022-10-03 04:31:39 +00:00
|
|
|
return true;
|
|
|
|
});
|
2022-07-15 02:35:25 +00:00
|
|
|
}
|
2022-04-22 03:03:38 +00:00
|
|
|
} // namespace panda::ecmascript::kungfu
|