mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
Refactor Split basic block for BytecodeCircuitBuilder
issues:I5YX50 Signed-off-by: sunzhe23 <sunzhe23@huawei.com>
This commit is contained in:
parent
34f86c36e7
commit
a3d46e2748
@ -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;
|
||||
});
|
||||
|
@ -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 ¤tPhi);
|
||||
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
|
||||
|
@ -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) \
|
||||
|
@ -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};
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user