Refactor Split basic block for BytecodeCircuitBuilder

issues:I5YX50

Signed-off-by: sunzhe23 <sunzhe23@huawei.com>
This commit is contained in:
sunzhe23 2022-11-02 09:32:55 +08:00
parent 34f86c36e7
commit a3d46e2748
10 changed files with 449 additions and 585 deletions

View File

@ -23,370 +23,198 @@
namespace panda::ecmascript::kungfu {
void BytecodeCircuitBuilder::BytecodeToCircuit()
{
std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> exceptionInfo;
BuildBytecodeBlockInfo();
ExceptionInfo exceptionInfo = {};
// collect try catch block info
CollectTryCatchBlockInfo(exceptionInfo);
// Complete bytecode block Information
CompleteBytecodeBlockInfo();
// Building the basic block diagram of bytecode
BuildBasicBlocks(exceptionInfo);
}
void BytecodeCircuitBuilder::CollectBytecodeBlockInfo(uint8_t *pc, std::vector<CfgInfo> &bytecodeBlockInfos)
void BytecodeCircuitBuilder::BuildBytecodeBlockInfo()
{
BytecodeInstruction inst(pc);
auto opcode = inst.GetOpcode();
auto bytecodeOffset = BytecodeInstruction::Size(opcode);
switch (static_cast<EcmaOpcode>(opcode)) {
case EcmaOpcode::JMP_IMM8: {
int8_t offset = static_cast<int8_t>(READ_INST_8_0());
std::vector<uint8_t *> temp;
temp.emplace_back(pc + offset);
// current basic block end
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
bytecodeBlockInfos.emplace_back(pc + bytecodeOffset, SplitKind::START,
std::vector<uint8_t *>(1, pc + bytecodeOffset));
// jump basic block start
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
}
break;
case EcmaOpcode::JMP_IMM16: {
int16_t offset = static_cast<int16_t>(READ_INST_16_0());
std::vector<uint8_t *> temp;
temp.emplace_back(pc + offset);
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
bytecodeBlockInfos.emplace_back(pc + bytecodeOffset, SplitKind::START,
std::vector<uint8_t *>(1, pc + bytecodeOffset));
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
}
break;
case EcmaOpcode::JMP_IMM32: {
int32_t offset = static_cast<int32_t>(READ_INST_32_0());
std::vector<uint8_t *> temp;
temp.emplace_back(pc + offset);
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
bytecodeBlockInfos.emplace_back(pc + bytecodeOffset, SplitKind::START,
std::vector<uint8_t *>(1, pc + bytecodeOffset));
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
}
break;
case EcmaOpcode::JEQZ_IMM8: {
std::vector<uint8_t *> temp;
temp.emplace_back(pc + bytecodeOffset); // first successor
int8_t offset = static_cast<int8_t>(READ_INST_8_0());
temp.emplace_back(pc + offset); // second successor
// condition branch current basic block end
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
// first branch basic block start
bytecodeBlockInfos.emplace_back(pc + bytecodeOffset, SplitKind::START,
std::vector<uint8_t *>(1, pc + bytecodeOffset));
// second branch basic block start
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
}
break;
case EcmaOpcode::JEQZ_IMM16: {
std::vector<uint8_t *> temp;
temp.emplace_back(pc + bytecodeOffset); // first successor
int16_t offset = static_cast<int16_t>(READ_INST_16_0());
temp.emplace_back(pc + offset); // second successor
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp); // end
bytecodeBlockInfos.emplace_back(pc + bytecodeOffset, SplitKind::START,
std::vector<uint8_t *>(1, pc + bytecodeOffset));
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
}
break;
case EcmaOpcode::JEQZ_IMM32: {
std::vector<uint8_t *> temp;
temp.emplace_back(pc + bytecodeOffset); // first successor
int16_t offset = static_cast<int16_t>(READ_INST_32_0());
temp.emplace_back(pc + offset); // second successor
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp); // end
bytecodeBlockInfos.emplace_back(pc + bytecodeOffset, SplitKind::START,
std::vector<uint8_t *>(1, pc + bytecodeOffset));
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
}
break;
case EcmaOpcode::JNEZ_IMM8: {
std::vector<uint8_t *> temp;
temp.emplace_back(pc + bytecodeOffset); // first successor
int8_t offset = static_cast<int8_t>(READ_INST_8_0());
temp.emplace_back(pc + offset); // second successor
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
bytecodeBlockInfos.emplace_back(pc + bytecodeOffset, SplitKind::START,
std::vector<uint8_t *>(1, pc + bytecodeOffset));
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
}
break;
case EcmaOpcode::JNEZ_IMM16: {
std::vector<uint8_t *> temp;
temp.emplace_back(pc + bytecodeOffset); // first successor
int16_t offset = static_cast<int16_t>(READ_INST_16_0());
temp.emplace_back(pc + offset); // second successor
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
bytecodeBlockInfos.emplace_back(pc + bytecodeOffset, SplitKind::START,
std::vector<uint8_t *>(1, pc + bytecodeOffset));
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
}
break;
case EcmaOpcode::JNEZ_IMM32: {
std::vector<uint8_t *> temp;
temp.emplace_back(pc + bytecodeOffset); // first successor
int16_t offset = static_cast<int16_t>(READ_INST_32_0());
temp.emplace_back(pc + offset); // second successor
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
bytecodeBlockInfos.emplace_back(pc + bytecodeOffset, SplitKind::START,
std::vector<uint8_t *>(1, pc + bytecodeOffset));
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
}
break;
case EcmaOpcode::RETURN:
case EcmaOpcode::RETURNUNDEFINED:
case EcmaOpcode::THROW_PREF_NONE:
case EcmaOpcode::THROW_CONSTASSIGNMENT_PREF_V8:
case EcmaOpcode::THROW_NOTEXISTS_PREF_NONE:
case EcmaOpcode::THROW_PATTERNNONCOERCIBLE_PREF_NONE:
case EcmaOpcode::THROW_DELETESUPERPROPERTY_PREF_NONE: {
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, std::vector<uint8_t *>(1, pc));
break;
}
default:
break;
uint32_t size = pcOffsets_.size();
uint32_t end = size - 1; // 1: end
BytecodeIterator iterator(this, 0, end);
infoData_.resize(size);
byteCodeToJSGate_.resize(size, Circuit::NullGate());
bytecodeBlocksInfo_.InsertHead(0); // 0: start pc
for (iterator.GotoStart(); !iterator.Done(); ++iterator) {
auto index = iterator.Index();
auto &info = infoData_[index];
auto pc = pcOffsets_[index];
info.metaData_ = bytecodes_->GetBytecodeMetaData(pc);
BytecodeInfo::InitBytecodeInfo(this, info, pc);
CollectBytecodeBlockInfo(index);
}
}
void BytecodeCircuitBuilder::CollectTryCatchBlockInfo(std::map<std::pair<uint8_t *, uint8_t *>,
std::vector<uint8_t *>> &byteCodeException)
void BytecodeCircuitBuilder::CollectBytecodeBlockInfo(uint32_t bcIndex)
{
auto pc = pcOffsets_[bcIndex];
auto &info = infoData_[bcIndex];
int32_t offset;
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:
UNREACHABLE();
break;
}
auto nextIndex = bcIndex + 1; // 1: next pc
auto targetIndex = FindBcIndexByPc(pc + offset);
// condition branch current basic block end
if (info.IsCondJump()) {
bytecodeBlocksInfo_.InsertSplit(nextIndex);
bytecodeBlocksInfo_.InsertJump(targetIndex, bcIndex, false);
} else {
bytecodeBlocksInfo_.InsertHead(nextIndex);
bytecodeBlocksInfo_.InsertJump(targetIndex, bcIndex, true);
}
} else if (info.IsReturn() || info.IsThrow()) {
if (bcIndex != GetLastBcIndex()) {
auto nextIndex = bcIndex + 1; // 1: next pc
bytecodeBlocksInfo_.InsertHead(nextIndex);
}
}
}
void BytecodeCircuitBuilder::CollectTryCatchBlockInfo(ExceptionInfo &byteCodeException)
{
// try contains many catch
panda_file::MethodDataAccessor mda(*pf_, method_->GetMethodId());
panda_file::CodeDataAccessor cda(*pf_, mda.GetCodeId().value());
cda.EnumerateTryBlocks([this, &byteCodeException](
panda_file::CodeDataAccessor::TryBlock &try_block) {
auto tryStartOffset = try_block.GetStartPc();
auto tryEndOffset = try_block.GetStartPc() + try_block.GetLength();
panda_file::CodeDataAccessor::TryBlock &tryBlock) {
auto tryStartOffset = tryBlock.GetStartPc();
auto tryEndOffset = tryBlock.GetStartPc() + tryBlock.GetLength();
auto tryStartPc = const_cast<uint8_t *>(method_->GetBytecodeArray() + tryStartOffset);
auto tryEndPc = const_cast<uint8_t *>(method_->GetBytecodeArray() + tryEndOffset);
// skip try blocks with same pc in start and end label
if (tryStartPc == tryEndPc) {
return true;
}
byteCodeException[std::make_pair(tryStartPc, tryEndPc)] = {};
uint32_t pcOffset = panda_file::INVALID_OFFSET;
try_block.EnumerateCatchBlocks([&](panda_file::CodeDataAccessor::CatchBlock &catch_block) {
pcOffset = catch_block.GetHandlerPc();
auto tryStartBcIndex = FindBcIndexByPc(tryStartPc);
bytecodeBlocksInfo_.InsertSplit(tryStartBcIndex);
if (tryEndPc <= GetLastPC()) {
auto tryEndBcIndex = FindBcIndexByPc(tryEndPc);
bytecodeBlocksInfo_.InsertSplit(tryEndBcIndex);
}
byteCodeException.emplace_back(ExceptionItem { tryStartPc, tryEndPc, {} });
tryBlock.EnumerateCatchBlocks([&](panda_file::CodeDataAccessor::CatchBlock &catchBlock) {
auto pcOffset = catchBlock.GetHandlerPc();
auto catchBlockPc = const_cast<uint8_t *>(method_->GetBytecodeArray() + pcOffset);
auto catchBlockBcIndex = FindBcIndexByPc(catchBlockPc);
bytecodeBlocksInfo_.InsertHead(catchBlockBcIndex);
// try block associate catch block
byteCodeException[std::make_pair(tryStartPc, tryEndPc)].emplace_back(catchBlockPc);
byteCodeException.back().catchs.emplace_back(catchBlockPc);
return true;
});
// Check whether the previous block of the try block exists.
// If yes, add the current block; otherwise, create a new block.
bool flag = false;
for (size_t i = 0; i < bytecodeBlockInfos_.size(); i++) {
if (bytecodeBlockInfos_[i].splitKind == SplitKind::START) {
continue;
}
if (bytecodeBlockInfos_[i].pc == byteCodeCurPrePc_.at(tryStartPc)) {
flag = true;
break;
}
}
if (!flag) {
// pre block
if (byteCodeCurPrePc_.at(tryStartPc) != tryStartPc) {
bytecodeBlockInfos_.emplace_back(byteCodeCurPrePc_.at(tryStartPc), SplitKind::END,
std::vector<uint8_t *>(1, tryStartPc));
}
}
// try block
bytecodeBlockInfos_.emplace_back(tryStartPc, SplitKind::START, std::vector<uint8_t *>(1, tryStartPc));
flag = false;
for (size_t i = 0; i < bytecodeBlockInfos_.size(); i++) {
if (bytecodeBlockInfos_[i].splitKind == SplitKind::START) {
continue;
}
if (bytecodeBlockInfos_[i].pc == byteCodeCurPrePc_.at(tryEndPc)) {
auto &succs = bytecodeBlockInfos_[i].succs;
auto iter = std::find(succs.cbegin(), succs.cend(), bytecodeBlockInfos_[i].pc);
if (iter == succs.cend()) {
auto opcode = PcToOpcode(bytecodeBlockInfos_[i].pc);
switch (opcode) {
case EcmaOpcode::JMP_IMM8:
case EcmaOpcode::JMP_IMM16:
case EcmaOpcode::JMP_IMM32:
case EcmaOpcode::JEQZ_IMM8:
case EcmaOpcode::JEQZ_IMM16:
case EcmaOpcode::JEQZ_IMM32:
case EcmaOpcode::JNEZ_IMM8:
case EcmaOpcode::JNEZ_IMM16:
case EcmaOpcode::JNEZ_IMM32:
case EcmaOpcode::RETURN:
case EcmaOpcode::RETURNUNDEFINED:
case EcmaOpcode::THROW_PREF_NONE: {
break;
}
default: {
succs.emplace_back(tryEndPc);
break;
}
}
}
flag = true;
break;
}
}
if (!flag) {
bytecodeBlockInfos_.emplace_back(byteCodeCurPrePc_.at(tryEndPc), SplitKind::END,
std::vector<uint8_t *>(1, tryEndPc));
}
bytecodeBlockInfos_.emplace_back(tryEndPc, SplitKind::START, std::vector<uint8_t *>(1, tryEndPc)); // next block
return true;
});
}
void BytecodeCircuitBuilder::CompleteBytecodeBlockInfo()
void BytecodeCircuitBuilder::BuildBasicBlocks(const ExceptionInfo &byteCodeException)
{
std::sort(bytecodeBlockInfos_.begin(), bytecodeBlockInfos_.end());
// Deduplicate
auto deduplicateIndex = std::unique(bytecodeBlockInfos_.begin(), bytecodeBlockInfos_.end());
bytecodeBlockInfos_.erase(deduplicateIndex, bytecodeBlockInfos_.end());
// Supplementary block information
// endBlockPc: Pairs occur, with odd indexes indicating endPc, and even indexes indicating startPc.
std::vector<uint8_t *> endBlockPc;
std::vector<uint8_t *> startBlockPc; //
for (size_t i = 0; i < bytecodeBlockInfos_.size() - 1; i++) {
if (bytecodeBlockInfos_[i].splitKind == bytecodeBlockInfos_[i + 1].splitKind &&
bytecodeBlockInfos_[i].splitKind == SplitKind::START) {
auto prePc = byteCodeCurPrePc_.at(bytecodeBlockInfos_[i + 1].pc);
endBlockPc.emplace_back(prePc); // Previous instruction of current instruction
endBlockPc.emplace_back(bytecodeBlockInfos_[i + 1].pc); // current instruction
continue;
}
if (bytecodeBlockInfos_[i].splitKind == bytecodeBlockInfos_[i + 1].splitKind &&
bytecodeBlockInfos_[i].splitKind == SplitKind::END) {
auto tempPc = bytecodeBlockInfos_[i].pc;
auto findItem = std::find_if(byteCodeCurPrePc_.cbegin(), byteCodeCurPrePc_.cend(),
[tempPc](const std::map<uint8_t *, uint8_t *>::value_type item) {
return item.second == tempPc;
});
if (findItem != byteCodeCurPrePc_.cend()) {
startBlockPc.emplace_back((*findItem).first);
}
}
}
// Supplementary end block info
for (auto iter = endBlockPc.cbegin(); iter != endBlockPc.cend(); iter += 2) { // 2: index
bytecodeBlockInfos_.emplace_back(*iter, SplitKind::END, std::vector<uint8_t *>(1, *(iter + 1)));
}
// Supplementary start block info
for (auto iter = startBlockPc.cbegin(); iter != startBlockPc.cend(); iter++) {
bytecodeBlockInfos_.emplace_back(*iter, SplitKind::START, std::vector<uint8_t *>(1, *iter));
}
// Deduplicate successor
for (size_t i = 0; i < bytecodeBlockInfos_.size(); i++) {
if (bytecodeBlockInfos_[i].splitKind == SplitKind::END) {
std::set<uint8_t *> tempSet(bytecodeBlockInfos_[i].succs.cbegin(),
bytecodeBlockInfos_[i].succs.cend());
bytecodeBlockInfos_[i].succs.assign(tempSet.cbegin(), tempSet.cend());
}
}
std::sort(bytecodeBlockInfos_.begin(), bytecodeBlockInfos_.end());
// handling jumps to an empty block
auto endPc = bytecodeBlockInfos_[bytecodeBlockInfos_.size() - 1].pc;
auto iter = --byteCodeCurPrePc_.cend();
if (endPc == iter->first) {
bytecodeBlockInfos_.emplace_back(endPc, SplitKind::END, std::vector<uint8_t *>(1, endPc));
}
// Deduplicate
deduplicateIndex = std::unique(bytecodeBlockInfos_.begin(), bytecodeBlockInfos_.end());
bytecodeBlockInfos_.erase(deduplicateIndex, bytecodeBlockInfos_.end());
}
void BytecodeCircuitBuilder::BuildBasicBlocks(std::map<std::pair<uint8_t *, uint8_t *>,
std::vector<uint8_t *>> &exception)
{
std::map<uint8_t *, BytecodeRegion *> startPcToBB; // [start, bb]
std::map<uint8_t *, BytecodeRegion *> endPcToBB; // [end, bb]
graph_.resize(bytecodeBlockInfos_.size() / 2); // 2 : half size
auto &items = bytecodeBlocksInfo_.GetBlockItems();
auto blockSize = items.size();
graph_.resize(blockSize);
// build basic block
int blockId = 0;
int index = 0;
for (size_t i = 0; i < bytecodeBlockInfos_.size() - 1; i += 2) { // 2:index
auto startPc = bytecodeBlockInfos_[i].pc;
auto endPc = bytecodeBlockInfos_[i + 1].pc;
auto block = &graph_[index++];
block->id = blockId++;
block->start = startPc;
block->end = endPc;
block->preds = {};
block->succs = {};
startPcToBB[startPc] = block;
endPcToBB[endPc] = block;
block->bytecodeIterator_.Reset(this, startPc, endPc);
}
// add block associate
for (size_t i = 0; i < bytecodeBlockInfos_.size(); i++) {
if (bytecodeBlockInfos_[i].splitKind == SplitKind::START) {
continue;
}
auto curPc = bytecodeBlockInfos_[i].pc;
auto &successors = bytecodeBlockInfos_[i].succs;
for (size_t j = 0; j < successors.size(); j++) {
if (successors[j] == curPc) {
continue;
}
auto curBlock = endPcToBB[curPc];
auto succsBlock = startPcToBB[successors[j]];
curBlock->succs.emplace_back(succsBlock);
succsBlock->preds.emplace_back(curBlock);
}
}
// try catch block associate
for (size_t i = 0; i < graph_.size(); i++) {
const auto pc = graph_[i].start;
auto it = exception.cbegin();
for (; it != exception.cend(); it++) {
if (pc < it->first.first || pc >= it->first.second) { // try block interval
continue;
}
auto catchs = exception[it->first]; // catchs start pc
for (size_t j = i + 1; j < graph_.size(); j++) {
if (std::find(catchs.cbegin(), catchs.cend(), graph_[j].start) != catchs.cend()) {
graph_[i].catchs.insert(graph_[i].catchs.cbegin(), &graph_[j]);
graph_[i].succs.emplace_back(&graph_[j]);
graph_[j].preds.emplace_back(&graph_[i]);
}
for (const auto &item : items) {
auto &curBlock = GetBasicBlockById(blockId);
curBlock.id = blockId;
curBlock.start = item.GetStartBcIndex();
if (blockId != 0) {
auto &prevBlock = graph_[blockId - 1];
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);
}
}
blockId++;
}
auto &lastBlock = graph_[blockId - 1]; // 1: last block
lastBlock.end = GetLastBcIndex();
lastBlock.bytecodeIterator_.Reset(this, lastBlock.start, lastBlock.end);
// 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.
BytecodeRegion& bb = graph_[i];
bb.SortCatches();
auto &splitItems = bytecodeBlocksInfo_.GetSplitItems();
for (const auto &item : splitItems) {
auto curIndex = bytecodeBlocksInfo_.FindBBIndexByBcIndex(item.startBcIndex);
auto &curBlock = GetBasicBlockById(curIndex);
auto predIndex = bytecodeBlocksInfo_.FindBBIndexByBcIndex(item.predBcIndex);
auto &predBlock = GetBasicBlockById(predIndex);
curBlock.preds.emplace_back(&predBlock);
predBlock.succs.emplace_back(&curBlock);
}
if (byteCodeException.size() != 0) {
BuildCatchBlocks(byteCodeException);
}
if (IsLogEnabled()) {
PrintGraph("Build Basic Block");
}
ComputeDominatorTree();
}
void BytecodeCircuitBuilder::BuildCatchBlocks(const ExceptionInfo &byteCodeException)
{
// try catch block associate
for (size_t i = 0; i < graph_.size(); i++) {
auto &bb = graph_[i];
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) {
continue;
}
// try block interval
const auto &catchs = it->catchs; // catchs start pc
for (size_t j = i + 1; j < graph_.size(); j++) {
auto &catchBB = graph_[j];
const auto catchStart = pcOffsets_[catchBB.start];
if (std::find(catchs.cbegin(), catchs.cend(), catchStart) != catchs.cend()) {
bb.catchs.insert(bb.catchs.cbegin(), &catchBB);
bb.succs.emplace_back(&catchBB);
catchBB.preds.emplace_back(&bb);
}
}
}
// 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.
bb.SortCatches();
}
}
void BytecodeCircuitBuilder::ComputeDominatorTree()
{
// Construct graph backward order
std::map<size_t, size_t> bbIdToDfsTimestamp;
std::unordered_map<size_t, size_t> bbIdToDfsTimestamp;
std::unordered_map<size_t, size_t> dfsFatherIdx;
std::unordered_map<size_t, size_t> bbDfsTimestampToIdx;
std::vector<size_t> basicBlockList;
@ -528,7 +356,7 @@ void BytecodeCircuitBuilder::ComputeDomFrontiers(const std::vector<size_t> &immD
}
}
void BytecodeCircuitBuilder::RemoveDeadRegions(const std::map<size_t, size_t> &bbIdToDfsTimestamp)
void BytecodeCircuitBuilder::RemoveDeadRegions(const std::unordered_map<size_t, size_t> &bbIdToDfsTimestamp)
{
for (auto &block: graph_) {
std::vector<BytecodeRegion *> newPreds;
@ -550,7 +378,7 @@ void BytecodeCircuitBuilder::RemoveDeadRegions(const std::map<size_t, size_t> &b
void BytecodeCircuitBuilder::InsertPhi()
{
std::map<uint16_t, std::set<size_t>> defsitesInfo; // <vreg, bbs>
std::unordered_map<uint16_t, std::set<size_t>> defsitesInfo; // <vreg, bbs>
for (auto &bb : graph_) {
if (bb.isDead) {
continue;
@ -597,7 +425,7 @@ void BytecodeCircuitBuilder::InsertPhi()
}
}
void BytecodeCircuitBuilder::InsertExceptionPhi(std::map<uint16_t, std::set<size_t>> &defsitesInfo)
void BytecodeCircuitBuilder::InsertExceptionPhi(std::unordered_map<uint16_t, std::set<size_t>> &defsitesInfo)
{
// handle try catch defsite
for (auto &bb : graph_) {
@ -968,7 +796,6 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, GateRef &state, GateR
{
auto &iterator = bb.GetBytecodeIterator();
const BytecodeInfo& bytecodeInfo = iterator.GetBytecodeInfo();
auto pc = bytecodeInfo.GetPC();
size_t numValueInputs = bytecodeInfo.ComputeTotalValueCount();
GateRef gate = 0;
std::vector<GateRef> inList = CreateGateInList(bytecodeInfo);
@ -980,7 +807,7 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, GateRef &state, GateR
inList, GateType::Empty());
}
// 1: store bcoffset in the end.
AddBytecodeOffsetInfo(gate, bytecodeInfo, numValueInputs + 1, const_cast<uint8_t *>(pc));
AddBytecodeOffsetInfo(gate, bytecodeInfo, numValueInputs + 1, iterator.Index());
gateAcc_.NewIn(gate, 0, state);
gateAcc_.NewIn(gate, 1, depend);
auto ifSuccess = circuit_.NewGate(OpCode(OpCode::IF_SUCCESS), 0, {gate}, GateType::Empty());
@ -1003,8 +830,8 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, GateRef &state, GateR
Circuit::GetCircuitRoot(OpCode(OpCode::RETURN_LIST))},
GateType::Empty());
}
jsgateToBytecode_[gate] = { bb.id, iterator.Index() };
byteCodeToJSGate_[pc] = gate;
jsgateToBytecode_[gate] = iterator.Index();
byteCodeToJSGate_[iterator.Index()] = gate;
if (bytecodeInfo.IsGeneratorRelative()) {
suspendAndResumeGates_.emplace_back(gate);
}
@ -1020,7 +847,7 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, GateRef &state, GateR
}
state = ifSuccess;
depend = gate;
if (pc == bb.end) {
if (iterator.Index() == bb.end) {
auto &bbNext = graph_[bb.id + 1];
auto isLoopBack = bbNext.loopbackBlocks.count(bb.id);
SetBlockPred(bbNext, state, depend, isLoopBack);
@ -1032,7 +859,6 @@ void BytecodeCircuitBuilder::NewJump(BytecodeRegion &bb, GateRef &state, GateRef
{
auto &iterator = bb.GetBytecodeIterator();
const BytecodeInfo& bytecodeInfo = iterator.GetBytecodeInfo();
auto pc = bytecodeInfo.GetPC();
size_t numValueInputs = bytecodeInfo.ComputeValueInputCount();
if (bytecodeInfo.IsCondJump()) {
GateRef gate = 0;
@ -1071,8 +897,8 @@ void BytecodeCircuitBuilder::NewJump(BytecodeRegion &bb, GateRef &state, GateRef
}
ASSERT(bitSet == 3); // 3:Verify the number of successor blocks
}
jsgateToBytecode_[gate] = { bb.id, iterator.Index() };
byteCodeToJSGate_[pc] = gate;
jsgateToBytecode_[gate] = iterator.Index();
byteCodeToJSGate_[iterator.Index()] = gate;
} else {
ASSERT(bb.succs.size() == 1);
auto &bbNext = bb.succs.at(0);
@ -1087,15 +913,14 @@ void BytecodeCircuitBuilder::NewReturn(BytecodeRegion &bb, GateRef &state, GateR
ASSERT(bb.succs.empty());
auto &iterator = bb.GetBytecodeIterator();
const BytecodeInfo& bytecodeInfo = iterator.GetBytecodeInfo();
auto pc = bytecodeInfo.GetPC();
if (bytecodeInfo.GetOpcode() == EcmaOpcode::RETURN) {
// handle return.dyn bytecode
auto gate = circuit_.NewGate(OpCode(OpCode::RETURN), 0,
{ state, depend, Circuit::NullGate(),
Circuit::GetCircuitRoot(OpCode(OpCode::RETURN_LIST)) },
GateType::Empty());
jsgateToBytecode_[gate] = { bb.id, iterator.Index() };
byteCodeToJSGate_[pc] = gate;
jsgateToBytecode_[gate] = iterator.Index();
byteCodeToJSGate_[iterator.Index()] = gate;
} else if (bytecodeInfo.GetOpcode() == EcmaOpcode::RETURNUNDEFINED) {
// handle returnundefined bytecode
auto constant = circuit_.GetConstantGate(MachineType::I64,
@ -1105,8 +930,8 @@ void BytecodeCircuitBuilder::NewReturn(BytecodeRegion &bb, GateRef &state, GateR
{ state, depend, constant,
Circuit::GetCircuitRoot(OpCode(OpCode::RETURN_LIST)) },
GateType::Empty());
jsgateToBytecode_[gate] = { bb.id, iterator.Index() };
byteCodeToJSGate_[pc] = gate;
jsgateToBytecode_[gate] = iterator.Index();
byteCodeToJSGate_[iterator.Index()] = gate;
}
}
@ -1114,13 +939,12 @@ void BytecodeCircuitBuilder::NewByteCode(BytecodeRegion &bb, GateRef &state, Gat
{
auto &iterator = bb.GetBytecodeIterator();
const BytecodeInfo& bytecodeInfo = iterator.GetBytecodeInfo();
auto pc = bytecodeInfo.GetPC();
if (bytecodeInfo.IsSetConstant()) {
// handle bytecode command to get constants
GateRef gate = NewConst(bytecodeInfo);
jsgateToBytecode_[gate] = { bb.id, iterator.Index() };
byteCodeToJSGate_[pc] = gate;
if (pc == bb.end) {
jsgateToBytecode_[gate] = iterator.Index();
byteCodeToJSGate_[iterator.Index()] = gate;
if (iterator.Index() == bb.end) {
auto &bbNext = graph_[bb.id + 1];
auto isLoopBack = bbNext.loopbackBlocks.count(bb.id);
SetBlockPred(bbNext, state, depend, isLoopBack);
@ -1137,7 +961,7 @@ void BytecodeCircuitBuilder::NewByteCode(BytecodeRegion &bb, GateRef &state, Gat
NewReturn(bb, state, depend);
} else if (bytecodeInfo.IsMov()) {
// handle mov.dyn lda.dyn sta.dyn bytecodes
if (pc == bb.end) {
if (iterator.Index() == bb.end) {
auto &bbNext = graph_[bb.id + 1];
auto isLoopBack = bbNext.loopbackBlocks.count(bb.id);
SetBlockPred(bbNext, state, depend, isLoopBack);
@ -1229,7 +1053,6 @@ GateRef BytecodeCircuitBuilder::ResolveDef(const size_t bbId, int32_t bcId,
auto &iterator = bb.GetBytecodeIterator();
for (iterator.Goto(bcId); !iterator.Done(); --iterator) {
const BytecodeInfo& curInfo = iterator.GetBytecodeInfo();
auto pcIter = curInfo.GetPC();
// original bc use acc as input && current bc use acc as output
bool isTransByAcc = tmpAcc && curInfo.AccOut();
// 0 : the index in vreg-out list
@ -1243,10 +1066,10 @@ GateRef BytecodeCircuitBuilder::ResolveDef(const size_t bbId, int32_t bcId,
tmpReg = std::get<VirtualRegister>(curInfo.inputs.at(0)).GetId();
}
if (HasTypes()) {
type = typeRecorder_.UpdateType(pcToBCOffset_.at(pcIter) - 1, type);
type = typeRecorder_.UpdateType(iterator.Index(), type);
}
} else {
ans = byteCodeToJSGate_.at(pcIter);
ans = byteCodeToJSGate_.at(iterator.Index());
if (HasTypes() && !type.IsAnyType()) {
gateAcc_.SetGateType(ans, type);
}
@ -1258,7 +1081,7 @@ GateRef BytecodeCircuitBuilder::ResolveDef(const size_t bbId, int32_t bcId,
}
// New RESTORE_REGISTER HIR, used to restore the register content when processing resume instruction.
// New SAVE_REGISTER HIR, used to save register content when processing suspend instruction.
auto resumeGate = byteCodeToJSGate_.at(pcIter);
auto resumeGate = byteCodeToJSGate_.at(iterator.Index());
ans = GetExistingRestore(resumeGate, tmpReg);
if (ans != Circuit::NullGate()) {
break;
@ -1271,9 +1094,8 @@ GateRef BytecodeCircuitBuilder::ResolveDef(const size_t bbId, int32_t bcId,
bcId = iterator.Index();
auto saveRegGate = ResolveDef(bbId, iterator.Index() - 1, tmpReg, tmpAcc);
iterator.Goto(bcId);
auto nextPcIter = iterator.PeekPrevPc(2); // 2: skip 2
ASSERT(Bytecodes::GetOpcode(nextPcIter) == EcmaOpcode::SUSPENDGENERATOR_V8);
GateRef suspendGate = byteCodeToJSGate_.at(nextPcIter);
ASSERT(Bytecodes::GetOpcode(iterator.PeekPrevPc(2)) == EcmaOpcode::SUSPENDGENERATOR_V8); // 2: prev bc
GateRef suspendGate = byteCodeToJSGate_.at(iterator.Index() - 2); // 2: prev bc
auto dependGate = gateAcc_.GetDep(suspendGate);
auto newDependGate = circuit_.NewGate(OpCode(OpCode::SAVE_REGISTER), tmpReg, {dependGate, saveRegGate},
GateType::Empty());
@ -1313,9 +1135,7 @@ GateRef BytecodeCircuitBuilder::ResolveDef(const size_t bbId, int32_t bcId,
}
if (ans == Circuit::NullGate()) {
// recursively find def-site in dominator block
auto dom = bb.iDominator;
auto &domIterator = dom->GetBytecodeIterator();
return ResolveDef(dom->id, domIterator.GetEndBcIndex(), tmpReg, tmpAcc);
return ResolveDef(bb.iDominator->id, bb.iDominator->end, tmpReg, tmpAcc);
} else {
// def-site already found
return ans;
@ -1353,11 +1173,11 @@ void BytecodeCircuitBuilder::BuildCircuit()
if (gateAcc_.IsConstant(gate)) {
continue;
}
const auto &[bbIndex, bcIndex] = it->second;
const BytecodeInfo& bytecodeInfo = GetBytecodeInfo(bbIndex, bcIndex);
const auto bcIndex = it->second;
auto bbIndex = bytecodeBlocksInfo_.FindBBIndexByBcIndex(bcIndex);
const BytecodeInfo& bytecodeInfo = GetBytecodeInfo(bcIndex);
if (HasTypes()) {
auto pc = bytecodeInfo.GetPC();
auto type = typeRecorder_.GetType(pcToBCOffset_.at(pc) - 1);
auto type = typeRecorder_.GetType(bcIndex);
if (!type.IsAnyType()) {
gateAcc_.SetGateType(gate, type);
}
@ -1399,11 +1219,11 @@ void BytecodeCircuitBuilder::BuildCircuit()
}
void BytecodeCircuitBuilder::AddBytecodeOffsetInfo(GateRef &gate, const BytecodeInfo &info, size_t bcOffsetIndex,
uint8_t *pc)
uint32_t index)
{
if (info.IsCall()) {
auto bcOffset = circuit_.GetConstantGate(MachineType::I64,
pcToBCOffset_.at(pc),
index,
GateType::NJSValue());
gateAcc_.NewIn(gate, bcOffsetIndex, bcOffset);
}
@ -1426,19 +1246,13 @@ void BytecodeCircuitBuilder::SetExistingRestore(GateRef resumeGate, uint16_t tmp
void BytecodeCircuitBuilder::PrintGraph(const char* title)
{
std::map<const uint8_t *, GateRef> bcToGate;
for (const auto &[key, value]: jsgateToBytecode_) {
auto pc = GetBytecodeInfo(value.first, value.second).GetPC();
bcToGate[pc] = key;
}
LOG_COMPILER(INFO) << "======================== " << title << " ========================";
for (size_t i = 0; i < graph_.size(); i++) {
BytecodeRegion& bb = graph_[i];
if (bb.isDead) {
LOG_COMPILER(INFO) << "B" << bb.id << ": ;preds= invalid BB";
LOG_COMPILER(INFO) << "\tBytecodePC: [" << reinterpret_cast<void*>(bb.start) << ", "
<< reinterpret_cast<void*>(bb.end) << ")";
LOG_COMPILER(INFO) << "\tBytecodePC: [" << std::to_string(bb.start) << ", "
<< std::to_string(bb.end) << ")";
continue;
}
std::string log("B" + std::to_string(bb.id) + ": ;preds= ");
@ -1446,8 +1260,8 @@ void BytecodeCircuitBuilder::PrintGraph(const char* title)
log += std::to_string(bb.preds[k]->id) + ", ";
}
LOG_COMPILER(INFO) << log;
LOG_COMPILER(INFO) << "\tBytecodePC: [" << reinterpret_cast<void*>(bb.start) << ", "
<< reinterpret_cast<void*>(bb.end) << ")";
LOG_COMPILER(INFO) << "\tBytecodePC: [" << std::to_string(bb.start) << ", "
<< std::to_string(bb.end) << ")";
std::string log1("\tSucces: ");
for (size_t j = 0; j < bb.succs.size(); j++) {
@ -1456,8 +1270,8 @@ void BytecodeCircuitBuilder::PrintGraph(const char* title)
LOG_COMPILER(INFO) << log1;
for (size_t j = 0; j < bb.catchs.size(); j++) {
LOG_COMPILER(INFO) << "\tcatch [: " << reinterpret_cast<void*>(bb.catchs[j]->start) << ", "
<< reinterpret_cast<void*>(bb.catchs[j]->end) << ")";
LOG_COMPILER(INFO) << "\tcatch [: " << std::to_string(bb.catchs[j]->start) << ", "
<< std::to_string(bb.catchs[j]->end) << ")";
}
std::string log2("\tTrys: ");
@ -1488,12 +1302,12 @@ void BytecodeCircuitBuilder::PrintGraph(const char* title)
}
LOG_COMPILER(INFO) << log5;
PrintBytecodeInfo(bb, bcToGate);
PrintBytecodeInfo(bb);
LOG_COMPILER(INFO) << "";
}
}
void BytecodeCircuitBuilder::PrintBytecodeInfo(BytecodeRegion& bb, const std::map<const uint8_t *, GateRef>& bcToGate)
void BytecodeCircuitBuilder::PrintBytecodeInfo(BytecodeRegion& bb)
{
if (bb.isDead) {
return;
@ -1501,10 +1315,9 @@ void BytecodeCircuitBuilder::PrintBytecodeInfo(BytecodeRegion& bb, const std::ma
LOG_COMPILER(INFO) << "\tBytecode[] = ";
EnumerateBlock(bb, [&](const BytecodeInfo &bytecodeInfo) -> bool {
auto &iterator = bb.GetBytecodeIterator();
auto pc = bytecodeInfo.GetPC();
std::string log;
log += std::string("\t\t< ") + std::to_string(iterator.Index()) + ": ";
log += GetEcmaOpcodeStr(static_cast<EcmaOpcode>(*pc)) + ", " + "In=[";
log += GetEcmaOpcodeStr(iterator.GetBytecodeInfo().GetOpcode()) + ", " + "In=[";
if (bytecodeInfo.AccIn()) {
log += "acc,";
}
@ -1523,9 +1336,9 @@ void BytecodeCircuitBuilder::PrintBytecodeInfo(BytecodeRegion& bb, const std::ma
log += "] >";
LOG_COMPILER(INFO) << log;
auto r = bcToGate.find(pc);
if (r != bcToGate.end()) {
this->gateAcc_.ShortPrint(r->second);
auto gate = byteCodeToJSGate_[iterator.Index()];
if (gate != Circuit::NullGate()) {
this->gateAcc_.ShortPrint(gate);
}
return true;
});

View File

@ -16,6 +16,7 @@
#ifndef ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
#define ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
#include <algorithm>
#include <numeric>
#include <tuple>
#include <utility>
@ -34,11 +35,6 @@
#include "ecmascript/jspandafile/method_literal.h"
namespace panda::ecmascript::kungfu {
enum class SplitKind : uint8_t {
DEFAULT,
START,
END
};
enum class VisitState : uint8_t {
UNVISITED,
@ -46,32 +42,129 @@ enum class VisitState : uint8_t {
VISITED
};
struct CfgInfo {
uint8_t *pc {nullptr};
SplitKind splitKind {SplitKind::DEFAULT};
std::vector<uint8_t *> succs {};
CfgInfo(uint8_t *startOrEndPc, SplitKind kind, std::vector<uint8_t *> successors)
: pc(startOrEndPc), splitKind(kind), succs(successors) {}
struct ExceptionItem {
uint8_t* startPc;
uint8_t* endPc;
std::vector<uint8_t*> catchs;
bool operator<(const CfgInfo &rhs) const
ExceptionItem(uint8_t* startPc, uint8_t* endPc, std::vector<uint8_t*> catchs)
: startPc(startPc), endPc(endPc), catchs(catchs) {}
};
using ExceptionInfo = std::vector<ExceptionItem>;
class BytecodeBlockItem {
public:
static constexpr uint32_t INVALID_BC_INDEX = static_cast<uint32_t>(-1);
bool operator<(const BytecodeBlockItem &rhs) const
{
if (this->pc != rhs.pc) {
return this->pc < rhs.pc;
} else {
return this->splitKind < rhs.splitKind;
return this->startBcIndex_ < rhs.startBcIndex_;
}
bool operator>(const BytecodeBlockItem &rhs) const
{
return this->startBcIndex_ > rhs.startBcIndex_;
}
bool operator==(const BytecodeBlockItem &rhs) const
{
return this->startBcIndex_ == rhs.startBcIndex_;
}
BytecodeBlockItem(uint32_t startBcIndex, bool isHeadBlock)
: startBcIndex_(startBcIndex), isHeadBlock_(isHeadBlock) {}
uint32_t GetStartBcIndex() const
{
return startBcIndex_;
}
uint32_t IsHeadBlock() const
{
return isHeadBlock_;
}
private:
uint32_t startBcIndex_ { INVALID_BC_INDEX };
bool isHeadBlock_ { false };
friend class BytecodeBlocksInfo;
};
struct BytecodeSplitItem
{
BytecodeSplitItem(uint32_t start, uint32_t pred)
: startBcIndex(start), predBcIndex(pred) {}
uint32_t startBcIndex { BytecodeBlockItem::INVALID_BC_INDEX };
uint32_t predBcIndex { BytecodeBlockItem::INVALID_BC_INDEX };
};
class BytecodeBlocksInfo {
public:
void InsertJump(uint32_t bcIndex, uint32_t predBcIndex, bool isJumpImm)
{
InsertBlockItem(bcIndex, false);
auto fallThrogth = bcIndex - 1; // 1: fall through
// isJumpImm will not generate fall through
if (isJumpImm || fallThrogth != predBcIndex) {
InsertSplitItem(bcIndex, predBcIndex);
}
}
bool operator==(const CfgInfo &rhs) const
void InsertHead(uint32_t bcIndex)
{
return this->pc == rhs.pc && this->splitKind == rhs.splitKind;
InsertBlockItem(bcIndex, true);
}
void InsertSplit(uint32_t bcIndex)
{
InsertBlockItem(bcIndex, false);
}
size_t FindBBIndexByBcIndex(uint32_t bcIndex)
{
auto findFunc = [] (uint32_t value, const BytecodeBlockItem &item)
{
return value < item.startBcIndex_;
};
const auto &it = std::upper_bound(blockItems_.begin(),
blockItems_.end(), bcIndex, findFunc);
if (it == blockItems_.end()) {
return blockItems_.size() - 1; // 1: last bb
}
// blockItems_[0]'s value is 0, bcIndex must be: bcIndex > blockItems_.begin()
return std::distance(blockItems_.begin(), it) - 1; // 1: -1 for bbIndx
}
const std::vector<BytecodeSplitItem> &GetSplitItems() const
{
return splitItems_;
}
const std::set<BytecodeBlockItem> &GetBlockItems() const
{
return blockItems_;
}
private:
void InsertBlockItem(uint32_t bcIndex, bool isHeadBlock)
{
auto result = blockItems_.insert(BytecodeBlockItem { bcIndex, isHeadBlock });
if (!result.second && isHeadBlock) {
blockItems_.erase(result.first);
blockItems_.insert(BytecodeBlockItem { bcIndex, isHeadBlock });
}
}
void InsertSplitItem(uint32_t bcIndex, uint32_t predBcIndex)
{
splitItems_.emplace_back(BytecodeSplitItem { bcIndex, predBcIndex });
}
std::set<BytecodeBlockItem> blockItems_ {};
std::vector<BytecodeSplitItem> splitItems_ {};
};
struct BytecodeRegion {
size_t id {0};
uint8_t *start {nullptr};
uint8_t *end {nullptr};
uint32_t start {0};
uint32_t end {0};
std::vector<BytecodeRegion *> preds {}; // List of predessesor blocks
std::vector<BytecodeRegion *> succs {}; // List of successors blocks
std::vector<BytecodeRegion *> trys {}; // List of trys blocks
@ -95,7 +188,7 @@ struct BytecodeRegion {
GateRef mergeLoopBackEdges {Circuit::NullGate()};
GateRef depForward {Circuit::NullGate()};
GateRef depLoopBack {Circuit::NullGate()};
std::map<uint16_t, GateRef> vregToValSelectorGate {}; // corresponding ValueSelector gates of vregs
std::unordered_map<uint16_t, GateRef> vregToValSelectorGate {}; // corresponding ValueSelector gates of vregs
GateRef valueSelectorAccGate {Circuit::NullGate()};
BytecodeIterator bytecodeIterator_ {};
@ -175,8 +268,8 @@ public:
: tsManager_(tsManager), circuit_(cconfig->Is64Bit()), file_(jsPandaFile), pf_(jsPandaFile->GetPandaFile()),
method_(methodLiteral), gateAcc_(&circuit_), argAcc_(&circuit_, method_),
typeRecorder_(jsPandaFile, method_, tsManager), hasTypes_(hasTypes),
enableLog_(enableLog), enableTypeLowering_(enableTypeLowering), pcToBCOffset_(methodPCInfo.pcToBCOffset),
byteCodeCurPrePc_(methodPCInfo.byteCodeCurPrePc), bytecodeBlockInfos_(methodPCInfo.bytecodeBlockInfos),
enableLog_(enableLog), enableTypeLowering_(enableTypeLowering),
pcOffsets_(methodPCInfo.pcOffsets),
frameStateBuilder_(this, &circuit_, methodLiteral), methodName_(name), recordName_(recordName),
bytecodes_(bytecodes)
{
@ -185,21 +278,23 @@ public:
NO_COPY_SEMANTIC(BytecodeCircuitBuilder);
NO_MOVE_SEMANTIC(BytecodeCircuitBuilder);
void PUBLIC_API BytecodeToCircuit();
static void PUBLIC_API CollectBytecodeBlockInfo(uint8_t *pc, std::vector<CfgInfo> &bytecodeBlockInfos);
void CollectBytecodeBlockInfo(uint32_t bcIndex);
[[nodiscard]] Circuit* GetCircuit()
{
return &circuit_;
}
[[nodiscard]] const std::map<GateRef, std::pair<size_t, size_t>>& GetGateToBytecode() const
const std::unordered_map<GateRef, uint32_t>& GetGateToBytecode() const
{
return jsgateToBytecode_;
}
[[nodiscard]] const std::map<const uint8_t *, GateRef>& GetBytecodeToGate() const
GateRef GetGateByBcIndex(uint32_t bcIndex) const
{
return byteCodeToJSGate_;
ASSERT(bcIndex < byteCodeToJSGate_.size());
ASSERT(byteCodeToJSGate_[bcIndex] != Circuit::NullGate());
return byteCodeToJSGate_[bcIndex];
}
[[nodiscard]] EcmaOpcode PcToOpcode(const uint8_t *pc) const
@ -209,7 +304,8 @@ public:
[[nodiscard]] const uint8_t* GetJSBytecode(GateRef gate)
{
return GetByteCodeInfo(gate).GetPC();
const auto bcIndex = jsgateToBytecode_.at(gate);
return GetPCByIndex(bcIndex);
}
[[nodiscard]] EcmaOpcode GetByteCodeOpcode(GateRef gate)
@ -239,19 +335,11 @@ public:
return methodName_;
}
const BytecodeInfo &GetBytecodeInfo(size_t bbIndex, size_t bcIndex)
{
auto &bb = graph_[bbIndex];
auto &iterator = bb.GetBytecodeIterator();
iterator.Goto(static_cast<int32_t>(bcIndex));
return iterator.GetBytecodeInfo();
}
// for external users, circuit must be built
const BytecodeInfo &GetByteCodeInfo(const GateRef gate)
{
const auto &[bbIndex, bcIndex] = jsgateToBytecode_.at(gate);
return GetBytecodeInfo(bbIndex, bcIndex);
const auto bcIndex = jsgateToBytecode_.at(gate);
return GetBytecodeInfo(bcIndex);
}
bool IsLogEnabled() const
@ -287,13 +375,9 @@ public:
}
}
const std::map<const uint8_t *, int32_t> &GetPcToBCOffset() const
{
return pcToBCOffset_;
}
BytecodeRegion &GetBasicBlockById(size_t id)
{
ASSERT(id < graph_.size());
return graph_[id];
}
@ -302,11 +386,17 @@ public:
return graph_.size();
}
size_t GetPcOffset(const uint8_t* pc) const
size_t GetPcOffset(const uint8_t *pc) const
{
return static_cast<size_t>(pc - method_->GetBytecodeArray());
}
size_t GetPcOffset(uint32_t bcIndex) const
{
const uint8_t* pc = GetPCByIndex(bcIndex);
return GetPcOffset(pc);
}
size_t GetNumberVRegs() const
{
return static_cast<size_t>(method_->GetNumberVRegs());
@ -316,16 +406,48 @@ public:
{
return bytecodes_;
}
uint32_t GetLastBcIndex() const
{
return static_cast<uint32_t>(pcOffsets_.size() - 1);
}
const uint8_t *GetPCByIndex(uint32_t index) const
{
ASSERT(index <= GetLastBcIndex());
return pcOffsets_[index];
}
const uint8_t *GetLastPC() const
{
return GetPCByIndex(GetLastBcIndex());
}
uint32_t FindBcIndexByPc(const uint8_t *pc) const
{
auto begin = pcOffsets_.begin();
auto end = pcOffsets_.end();
auto it = std::lower_bound(begin, end, pc);
ASSERT(it != end);
ASSERT(*it == pc);
return std::distance(begin, it);
}
const BytecodeInfo &GetBytecodeInfo(uint32_t index) const
{
return infoData_[index];
}
private:
void CollectTryCatchBlockInfo(std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> &Exception);
void CompleteBytecodeBlockInfo();
void BuildBasicBlocks(std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> &Exception);
void CollectTryCatchBlockInfo(ExceptionInfo &Exception);
void BuildCatchBlocks(const ExceptionInfo &Exception);
void BuildBasicBlocks(const ExceptionInfo &Exception);
void ComputeDominatorTree();
void BuildImmediateDominator(const std::vector<size_t> &immDom);
void ComputeDomFrontiers(const std::vector<size_t> &immDom);
void RemoveDeadRegions(const std::map<size_t, size_t> &bbIdToDfsTimestamp);
void RemoveDeadRegions(const std::unordered_map<size_t, size_t> &bbIdToDfsTimestamp);
void InsertPhi();
void InsertExceptionPhi(std::map<uint16_t, std::set<size_t>> &defsitesInfo);
void InsertExceptionPhi(std::unordered_map<uint16_t, std::set<size_t>> &defsitesInfo);
void UpdateCFG();
bool ShouldBeDead(BytecodeRegion &curBlock);
// build circuit
@ -341,7 +463,7 @@ private:
void NewJump(BytecodeRegion &bb, GateRef &state, GateRef &depend);
void NewReturn(BytecodeRegion &bb, GateRef &state, GateRef &depend);
void NewByteCode(BytecodeRegion &bb, GateRef &state, GateRef &depend);
void AddBytecodeOffsetInfo(GateRef &gate, const BytecodeInfo &info, size_t bcOffsetIndex, uint8_t *pc);
void AddBytecodeOffsetInfo(GateRef &gate, const BytecodeInfo &info, size_t bcOffsetIndex, uint32_t index);
void BuildSubCircuit();
void NewPhi(BytecodeRegion &bb, uint16_t reg, bool acc, GateRef &currentPhi);
GateRef ResolveDef(const size_t bbId, int32_t bcId, const uint16_t reg, const bool acc);
@ -351,8 +473,9 @@ private:
void PrintGraph();
void PrintBBInfo();
void PrintGraph(const char* title);
void PrintBytecodeInfo(BytecodeRegion& region, const std::map<const uint8_t *, GateRef>& bcToGate);
void PrintDefsitesInfo(const std::map<uint16_t, std::set<size_t>> &defsitesInfo);
void PrintBytecodeInfo(BytecodeRegion& region);
void PrintDefsitesInfo(const std::unordered_map<uint16_t, std::set<size_t>> &defsitesInfo);
void BuildBytecodeBlockInfo();
inline bool IsEntryBlock(const size_t bbId) const
{
@ -361,8 +484,8 @@ private:
TSManager *tsManager_;
Circuit circuit_;
std::map<GateRef, std::pair<size_t, size_t>> jsgateToBytecode_;
std::map<const uint8_t *, GateRef> byteCodeToJSGate_;
std::unordered_map<GateRef, uint32_t> jsgateToBytecode_ {};
std::vector<GateRef> byteCodeToJSGate_;
BytecodeGraph graph_;
const JSPandaFile *file_ {nullptr};
const panda_file::File *pf_ {nullptr};
@ -374,14 +497,14 @@ private:
bool enableLog_ {false};
bool enableTypeLowering_ {false};
std::vector<GateRef> suspendAndResumeGates_ {};
const std::map<const uint8_t *, int32_t> &pcToBCOffset_;
const std::map<uint8_t *, uint8_t *> &byteCodeCurPrePc_;
std::vector<CfgInfo> &bytecodeBlockInfos_;
std::map<std::pair<kungfu::GateRef, uint16_t>, kungfu::GateRef> resumeRegToRestore_;
std::vector<const uint8_t*> pcOffsets_;
std::map<std::pair<kungfu::GateRef, uint16_t>, kungfu::GateRef> resumeRegToRestore_ {};
FrameStateBuilder frameStateBuilder_;
std::string methodName_;
const CString &recordName_;
Bytecodes *bytecodes_;
BytecodeBlocksInfo bytecodeBlocksInfo_{};
std::vector<BytecodeInfo> infoData_ {};
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H

View File

@ -119,39 +119,17 @@ void BytecodeInfoCollector::CollectMethodPcsFromNewBc(const uint32_t insSz, cons
{
auto bcIns = BytecodeInst(insArr);
auto bcInsLast = bcIns.JumpTo(insSz);
bytecodeInfo_.methodPcInfos.emplace_back(MethodPcInfo { {}, {}, {}, insSz });
int32_t offsetIndex = 1;
uint8_t *curPc = nullptr;
uint8_t *prePc = nullptr;
bytecodeInfo_.methodPcInfos.emplace_back(MethodPcInfo { {}, insSz });
auto &pcOffsets = bytecodeInfo_.methodPcInfos.back().pcOffsets;
const uint8_t *curPc = bcIns.GetAddress();
while (bcIns.GetAddress() != bcInsLast.GetAddress()) {
CollectMethodInfoFromNewBC(bcIns, method);
auto pc = const_cast<uint8_t *>(bcIns.GetAddress());
curPc = bcIns.GetAddress();
auto nextInst = bcIns.GetNext();
bcIns = nextInst;
auto &bytecodeBlockInfos = bytecodeInfo_.methodPcInfos.back().bytecodeBlockInfos;
auto &byteCodeCurPrePc = bytecodeInfo_.methodPcInfos.back().byteCodeCurPrePc;
auto &pcToBCOffset = bytecodeInfo_.methodPcInfos.back().pcToBCOffset;
if (offsetIndex == 1) {
curPc = prePc = pc;
bytecodeBlockInfos.emplace_back(curPc, SplitKind::START, std::vector<uint8_t *>(1, curPc));
byteCodeCurPrePc[curPc] = prePc;
pcToBCOffset[curPc] = offsetIndex++;
} else {
curPc = pc;
byteCodeCurPrePc[curPc] = prePc;
pcToBCOffset[curPc] = offsetIndex++;
prePc = curPc;
BytecodeCircuitBuilder::CollectBytecodeBlockInfo(curPc, bytecodeBlockInfos);
}
pcOffsets.emplace_back(curPc);
}
auto &bytecodeBlockInfos = bytecodeInfo_.methodPcInfos.back().bytecodeBlockInfos;
bytecodeBlockInfos.emplace_back(curPc, SplitKind::END, std::vector<uint8_t *>(1, curPc));
auto emptyPc = const_cast<uint8_t *>(bcInsLast.GetAddress());
bytecodeInfo_.methodPcInfos.back().byteCodeCurPrePc[emptyPc] = prePc;
bytecodeInfo_.methodPcInfos.back().pcToBCOffset[emptyPc] = offsetIndex++;
}
void BytecodeInfoCollector::CollectMethodPcs(const uint32_t insSz, const uint8_t *insArr,
@ -161,37 +139,17 @@ void BytecodeInfoCollector::CollectMethodPcs(const uint32_t insSz, const uint8_t
auto bcIns = OldBytecodeInst(insArr);
auto bcInsLast = bcIns.JumpTo(insSz);
bytecodeInfo_.methodPcInfos.emplace_back(MethodPcInfo { {}, {}, {}, insSz });
bytecodeInfo_.methodPcInfos.emplace_back(MethodPcInfo { {}, insSz });
auto &pcOffsets = bytecodeInfo_.methodPcInfos.back().pcOffsets;
const uint8_t *curPc = bcIns.GetAddress();
int32_t offsetIndex = 1;
uint8_t *curPc = nullptr;
uint8_t *prePc = nullptr;
while (bcIns.GetAddress() != bcInsLast.GetAddress()) {
TranslateBCIns(bcIns, method, entryPoint);
auto pc = const_cast<uint8_t *>(bcIns.GetAddress());
auto nextInst = bcIns.GetNext();
FixOpcode(const_cast<MethodLiteral *>(method), bcIns);
bcIns = nextInst;
auto &bytecodeBlockInfos = bytecodeInfo_.methodPcInfos.back().bytecodeBlockInfos;
auto &byteCodeCurPrePc = bytecodeInfo_.methodPcInfos.back().byteCodeCurPrePc;
auto &pcToBCOffset = bytecodeInfo_.methodPcInfos.back().pcToBCOffset;
if (offsetIndex == 1) {
curPc = prePc = pc;
bytecodeBlockInfos.emplace_back(curPc, SplitKind::START, std::vector<uint8_t *>(1, curPc));
byteCodeCurPrePc[curPc] = prePc;
pcToBCOffset[curPc] = offsetIndex++;
} else {
curPc = pc;
byteCodeCurPrePc[curPc] = prePc;
pcToBCOffset[curPc] = offsetIndex++;
prePc = curPc;
BytecodeCircuitBuilder::CollectBytecodeBlockInfo(curPc, bytecodeBlockInfos);
}
pcOffsets.emplace_back(curPc);
}
auto emptyPc = const_cast<uint8_t *>(bcInsLast.GetAddress());
bytecodeInfo_.methodPcInfos.back().byteCodeCurPrePc[emptyPc] = prePc;
bytecodeInfo_.methodPcInfos.back().pcToBCOffset[emptyPc] = offsetIndex++;
}
#define ADD_NOP_INST(pc, oldLen, newOpcode) \

View File

@ -22,7 +22,6 @@
#include "libpandafile/bytecode_instruction-inl.h"
namespace panda::ecmascript::kungfu {
struct CfgInfo;
// need to remove in the future
enum FixInsIndex : uint8_t { FIX_ONE = 1, FIX_TWO = 2, FIX_FOUR = 4 };
@ -79,9 +78,7 @@ struct LexEnv {
// each method in the abc file corresponds to one MethodInfo and
// methods with the same instructions share one common MethodPcInfo
struct MethodPcInfo {
std::map<uint8_t *, uint8_t *> byteCodeCurPrePc {};
std::vector<CfgInfo> bytecodeBlockInfos {};
std::map<const uint8_t *, int32_t> pcToBCOffset {};
std::vector<const uint8_t*> pcOffsets {};
uint32_t methodsSize {0};
};

View File

@ -178,12 +178,11 @@ Bytecodes::Bytecodes()
}
}
void BytecodeIterator::InitBytecodeInfo(
BytecodeCircuitBuilder *builder,
BytecodeInfo &info, const uint8_t *pc)
void BytecodeInfo::InitBytecodeInfo(BytecodeCircuitBuilder *builder,
BytecodeInfo &info, const uint8_t *pc)
{
auto opcode = Bytecodes::GetOpcode(pc);
switch (static_cast<EcmaOpcode>(opcode)) {
auto opcode = info.GetOpcode();
switch (opcode) {
case EcmaOpcode::MOV_V4_V4: {
uint16_t vdst = READ_INST_4_0();
uint16_t vsrc = READ_INST_4_1();
@ -1283,23 +1282,20 @@ void BytecodeIterator::InitBytecodeInfo(
}
}
void BytecodeIterator::Reset(BytecodeCircuitBuilder *builder, const uint8_t *start, const uint8_t *end)
const BytecodeInfo &BytecodeIterator::GetBytecodeInfo() const
{
auto pc = start;
std::vector<const uint8_t*> offsets;
while (pc <= end) {
offsets.push_back(pc);
EcmaOpcode opcode = Bytecodes::GetOpcode(pc);
pc += BytecodeInstruction::Size(opcode);
}
auto bytecodes = builder->GetBytecodes();
infoData_.resize(offsets.size());
for (size_t i = 0; i < offsets.size(); i++) {
auto info = &infoData_[i];
pc = offsets[i];
InitBytecodeInfo(builder, *info, pc);
info->pc_ = pc;
info->metaData_ = bytecodes->GetBytecodeMetaData(pc);
}
return builder_->GetBytecodeInfo(index_);
}
const uint8_t *BytecodeIterator::PeekNextPc(size_t i) const
{
ASSERT(index_ + i <= end_);
return builder_->GetPCByIndex(index_ + i);
}
const uint8_t *BytecodeIterator::PeekPrevPc(size_t i) const
{
ASSERT(index_ - i >= start_);
return builder_->GetPCByIndex(index_ - i);
}
} // panda::ecmascript::kungfu

View File

@ -172,7 +172,7 @@ private:
uint32_t value_ {0};
friend class Bytecodes;
friend class BytecodeInfo;
friend class BytecodeIterator;
friend class BytecodeCircuitBuilder;
};
class Bytecodes {
@ -520,22 +520,27 @@ public:
return metaData_.GetOpcode();
}
const uint8_t *GetPC() const
{
return pc_;
}
static void InitBytecodeInfo(BytecodeCircuitBuilder *builder,
BytecodeInfo &info, const uint8_t* pc);
private:
BytecodeMetaData metaData_ { 0 };
const uint8_t *pc_ {nullptr};
friend class BytecodeIterator;
friend class BytecodeCircuitBuilder;
};
class BytecodeIterator {
public:
BytecodeIterator() = default;
explicit BytecodeIterator(BytecodeCircuitBuilder *builder,
uint32_t start, uint32_t end)
: builder_(builder), start_(start), end_(end) {}
void Reset(BytecodeCircuitBuilder *builder,
const uint8_t *start, const uint8_t *end);
uint32_t start, uint32_t end)
{
builder_ = builder;
start_ = start;
end_ = end;
}
BytecodeIterator& operator++()
{
@ -559,19 +564,19 @@ public:
void GotoStart()
{
index_ = 0;
index_ = start_;
ASSERT(InRange());
}
void GotoEnd()
{
index_ = infoData_.size() - 1;
index_ = end_;
ASSERT(InRange());
}
bool InRange() const
{
return (index_ < static_cast<int32_t>(infoData_.size())) && (index_ >= 0);
return (index_ <= end_) && (index_ >= start_);
}
bool Done() const
@ -579,45 +584,22 @@ public:
return !InRange();
}
const BytecodeInfo &GetBytecodeInfo() const
uint32_t Index() const
{
return infoData_[index_];
return index_;
}
size_t Index() const
{
return static_cast<size_t>(index_);
}
const uint8_t* CurrentPc() const
{
return GetBytecodeInfo().GetPC();
}
const uint8_t *PeekNextPc(size_t i) const
{
ASSERT((Index() + i) < infoData_.size());
return infoData_[index_ + i].GetPC();
}
const uint8_t *PeekPrevPc(size_t i) const
{
ASSERT((index_ - i) >= 0);
return infoData_[index_ - i].GetPC();
}
size_t GetEndBcIndex() const
{
return static_cast<size_t>(infoData_.size() - 1);
}
const BytecodeInfo &GetBytecodeInfo() const;
const uint8_t *PeekNextPc(size_t i) const;
const uint8_t *PeekPrevPc(size_t i) const;
private:
void InitBytecodeInfo(BytecodeCircuitBuilder *builder,
BytecodeInfo &info, const uint8_t *pc);
static constexpr int32_t INVALID_INDEX = -1;
int32_t index_{ INVALID_INDEX };
std::vector<BytecodeInfo> infoData_ {};
BytecodeCircuitBuilder *builder_ {nullptr};
uint32_t start_ {0};
uint32_t end_ {0};
uint32_t index_{ INVALID_INDEX };
};
} // panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_BYTECODES_H

View File

@ -29,8 +29,10 @@ FrameStateBuilder::FrameStateBuilder(BytecodeCircuitBuilder *builder,
FrameStateBuilder::~FrameStateBuilder()
{
for (auto &state : stateInfos_) {
delete state.second;
for (auto state : stateInfos_) {
if (state != nullptr) {
delete state;
}
}
delete liveOutResult_;
stateInfos_.clear();
@ -122,7 +124,7 @@ void FrameStateBuilder::BuildPostOrderList(size_t size)
}
}
bool FrameStateBuilder::MergeIntoPredBC(const uint8_t* predPc)
bool FrameStateBuilder::MergeIntoPredBC(uint32_t predPc)
{
// liveout next
auto frameInfo = GetOrOCreateStateInfo(predPc);
@ -214,17 +216,17 @@ bool FrameStateBuilder::ComputeLiveOut(size_t bbId)
// iterator bc
auto &iterator = bb.GetBytecodeIterator();
iterator.GotoEnd();
ASSERT(bb.end == iterator.CurrentPc());
ASSERT(bb.end == iterator.Index());
auto liveout = GetOrOCreateStateInfo(bb.end);
liveOutResult_->CopyFrom(liveout);
while (true) {
auto &bytecodeInfo = iterator.GetBytecodeInfo();
ComputeLiveOutBC(bytecodeInfo);
ComputeLiveOutBC(iterator.Index(), bytecodeInfo);
--iterator;
if (iterator.Done()) {
break;
}
auto prevPc = iterator.CurrentPc();
auto prevPc = iterator.Index();
changed |= MergeIntoPredBC(prevPc);
}
@ -263,6 +265,7 @@ void FrameStateBuilder::ComputeLiveState()
void FrameStateBuilder::BuildFrameState()
{
argAcc_.CollectArgs();
stateInfos_.resize(builder_->GetLastBcIndex() + 1, nullptr); // 1: +1 pcOffsets size
auto size = builder_->GetBasicBlockCount();
liveOutResult_ = CreateEmptyStateInfo();
BuildPostOrderList(size);
@ -270,10 +273,8 @@ void FrameStateBuilder::BuildFrameState()
BindGuard(size);
}
void FrameStateBuilder::ComputeLiveOutBC(const BytecodeInfo &bytecodeInfo)
void FrameStateBuilder::ComputeLiveOutBC(uint32_t index, const BytecodeInfo &bytecodeInfo)
{
auto pc = bytecodeInfo.GetPC();
auto byteCodeToJSGate = builder_->GetBytecodeToGate();
if (bytecodeInfo.IsMov()) {
auto gate = Circuit::NullGate();
// variable kill
@ -297,7 +298,7 @@ void FrameStateBuilder::ComputeLiveOutBC(const BytecodeInfo &bytecodeInfo)
if (!bytecodeInfo.IsGeneral() && !bytecodeInfo.IsReturn() && !bytecodeInfo.IsCondJump()) {
return;
}
GateRef gate = byteCodeToJSGate.at(pc);
GateRef gate = builder_->GetGateByBcIndex(index);
// variable kill
if (bytecodeInfo.AccOut()) {
UpdateAccumulator(Circuit::NullGate());
@ -323,7 +324,6 @@ void FrameStateBuilder::ComputeLiveOutBC(const BytecodeInfo &bytecodeInfo)
void FrameStateBuilder::BindGuard(size_t size)
{
auto byteCodeToJSGate = builder_->GetBytecodeToGate();
for (size_t i = 0; i < size; i++) {
auto &bb = builder_->GetBasicBlockById(i);
if (bb.isDead) {
@ -332,16 +332,14 @@ void FrameStateBuilder::BindGuard(size_t size)
builder_->EnumerateBlock(bb, [&](const BytecodeInfo &bytecodeInfo) -> bool {
if (bytecodeInfo.Deopt()) {
auto &iterator = bb.GetBytecodeIterator();
auto pc = bytecodeInfo.GetPC();
auto gate = byteCodeToJSGate.at(pc);
auto pcOffset = builder_->GetPcOffset(pc);
auto prevPc = iterator.PeekPrevPc(1); // 1: prev pc
auto stateInfo = GetOrOCreateStateInfo(prevPc);
auto index = iterator.Index();
auto gate = builder_->GetGateByBcIndex(index);
auto pcOffset = builder_->GetPcOffset(index);
auto stateInfo = GetOrOCreateStateInfo(index - 1); // 1: prev pc
BindGuard(gate, pcOffset, stateInfo);
}
return true;
});
}
}
}

View File

@ -85,15 +85,15 @@ private:
void BuildPostOrderList(size_t size);
bool ComputeLiveOut(size_t bbId);
void ComputeLiveState();
void ComputeLiveOutBC(const BytecodeInfo &bytecodeInfo);
bool MergeIntoPredBC(const uint8_t* predPc);
void ComputeLiveOutBC(uint32_t index, const BytecodeInfo &bytecodeInfo);
bool MergeIntoPredBC(uint32_t predPc);
bool MergeIntoPredBB(BytecodeRegion *bb, BytecodeRegion *predBb);
FrameStateInfo *GetOrOCreateStateInfo(const uint8_t * pc)
FrameStateInfo *GetOrOCreateStateInfo(uint32_t bcIndex)
{
auto currentInfo = stateInfos_[pc];
auto currentInfo = stateInfos_[bcIndex];
if (currentInfo == nullptr) {
currentInfo = CreateEmptyStateInfo();
stateInfos_[pc] = currentInfo;
stateInfos_[bcIndex] = currentInfo;
}
return currentInfo;
}
@ -106,7 +106,7 @@ private:
Circuit *circuit_ {nullptr};
GateAccessor gateAcc_;
ArgumentAccessor argAcc_;
std::map<const uint8_t *, FrameStateInfo *> stateInfos_;
std::vector<FrameStateInfo *> stateInfos_;
std::vector<size_t> postOrderList_;
};
} // panda::ecmascript::kungfu

View File

@ -801,17 +801,14 @@ void TypeInfer::PrintAllByteCodesTypes() const
const MethodLiteral *methodLiteral = builder_->GetMethod();
const std::string functionName = methodLiteral->ParseFunctionName(jsPandaFile, methodLiteral->GetMethodId());
auto &pcToBCOffset = builder_->GetPcToBCOffset();
auto &bytecodeToGate = builder_->GetBytecodeToGate();
LOG_COMPILER(INFO) << "print bytecode types:";
LOG_COMPILER(INFO) << ".function " + functionName + "() {";
for (auto it = pcToBCOffset.begin(); std::next(it) != pcToBCOffset.end(); it++) { // ignore last element
const uint8_t *pc = it->first;
uint32_t lastBcIndex = builder_->GetLastBcIndex();
for (uint32_t bcIndex = 0; bcIndex < lastBcIndex; bcIndex++) { // ignore last element
const uint8_t *pc = builder_->GetPCByIndex(bcIndex);
BytecodeInstruction inst(pc);
auto findIt = bytecodeToGate.find(pc);
if (findIt != bytecodeToGate.end()) {
GateRef gate = bytecodeToGate.at(pc);
GateRef gate = builder_->GetGateByBcIndex(bcIndex);
if (gate != Circuit::NullGate()) {
GateType type = gateAccessor_.GetGateType(gate);
if (!tsManager_->IsPrimitiveTypeKind(type)) {
GlobalTSTypeRef gt = type.GetGTRef();

View File

@ -12,5 +12,5 @@
# limitations under the License.
SyntaxError: Unexpected Array in JSON
Exception at function foo: 8
Exception at function func_main_0: 10
Exception at function foo: 7
Exception at function func_main_0: 9