2022-01-06 02:26:19 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
#include "bytecode_circuit_builder.h"
|
2022-01-06 02:26:19 +00:00
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
namespace panda::ecmascript::kungfu {
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::BytecodeToCircuit(const std::vector<uint8_t *> &pcArray, const panda_file::File &pf,
|
2022-01-18 04:02:20 +00:00
|
|
|
const JSMethod *method)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-01-19 01:11:02 +00:00
|
|
|
auto curPc = pcArray.front();
|
2022-01-06 02:26:19 +00:00
|
|
|
auto prePc = curPc;
|
2022-01-18 04:02:20 +00:00
|
|
|
std::map<uint8_t *, uint8_t *> byteCodeCurPrePc;
|
2022-01-19 01:11:02 +00:00
|
|
|
std::vector<CfgInfo> bytecodeBlockInfos;
|
2022-01-06 02:26:19 +00:00
|
|
|
auto startPc = curPc;
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(startPc, SplitKind::START, std::vector<uint8_t *>(1, startPc));
|
2022-01-06 02:26:19 +00:00
|
|
|
byteCodeCurPrePc.insert(std::pair<uint8_t *, uint8_t *>(curPc, prePc));
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t i = 1; i < pcArray.size() - 1; i++) {
|
|
|
|
curPc = pcArray[i];
|
2022-01-06 02:26:19 +00:00
|
|
|
byteCodeCurPrePc.insert(std::pair<uint8_t *, uint8_t *>(curPc, prePc));
|
|
|
|
prePc = curPc;
|
2022-01-19 01:11:02 +00:00
|
|
|
CollectBytecodeBlockInfo(curPc, bytecodeBlockInfos);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-14 09:48:52 +00:00
|
|
|
// handle empty
|
2022-01-19 01:11:02 +00:00
|
|
|
byteCodeCurPrePc.insert(std::pair<uint8_t *, uint8_t *>(pcArray[pcArray.size() - 1], prePc));
|
2022-01-06 02:26:19 +00:00
|
|
|
|
|
|
|
// collect try catch block info
|
2022-01-19 01:11:02 +00:00
|
|
|
auto exceptionInfo = CollectTryCatchBlockInfo(pf, method, byteCodeCurPrePc, bytecodeBlockInfos);
|
2022-01-06 02:26:19 +00:00
|
|
|
|
|
|
|
// Complete bytecode blcok Infomation
|
2022-01-19 01:11:02 +00:00
|
|
|
CompleteBytecodeBlockInfo(byteCodeCurPrePc, bytecodeBlockInfos);
|
2022-01-06 02:26:19 +00:00
|
|
|
|
|
|
|
// Building the basic block diagram of bytecode
|
2022-01-19 01:11:02 +00:00
|
|
|
BuildBasicBlocks(method, exceptionInfo, bytecodeBlockInfos, byteCodeCurPrePc);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::CollectBytecodeBlockInfo(uint8_t *pc, std::vector<CfgInfo> &bytecodeBlockInfos)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
|
|
|
auto opcode = static_cast<EcmaOpcode>(*pc);
|
|
|
|
switch (opcode) {
|
|
|
|
case EcmaOpcode::JMP_IMM8: {
|
|
|
|
int8_t offset = READ_INST_8_0();
|
|
|
|
std::vector<uint8_t *> temp;
|
|
|
|
temp.emplace_back(pc + offset);
|
|
|
|
// current basic block end
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
|
2022-01-22 11:09:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::TWO, SplitKind::START,
|
|
|
|
std::vector<uint8_t *>(1, pc + BytecodeOffset::TWO));
|
2022-01-06 02:26:19 +00:00
|
|
|
// jump basic block start
|
2022-01-22 11:09:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EcmaOpcode::JMP_IMM16: {
|
|
|
|
int16_t offset = READ_INST_16_0();
|
|
|
|
std::vector<uint8_t *> temp;
|
|
|
|
temp.emplace_back(pc + offset);
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
|
2022-01-22 11:09:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::THREE, SplitKind::START,
|
|
|
|
std::vector<uint8_t *>(1, pc + BytecodeOffset::THREE));
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START,
|
2022-01-22 11:09:02 +00:00
|
|
|
std::vector<uint8_t *>(1, pc + offset));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EcmaOpcode::JMP_IMM32: {
|
|
|
|
int32_t offset = READ_INST_32_0();
|
|
|
|
std::vector<uint8_t *> temp;
|
|
|
|
temp.emplace_back(pc + offset);
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
|
2022-01-22 11:09:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::FIVE, SplitKind::START,
|
|
|
|
std::vector<uint8_t *>(1, pc + BytecodeOffset::FIVE));
|
|
|
|
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EcmaOpcode::JEQZ_IMM8: {
|
|
|
|
std::vector<uint8_t *> temp;
|
2022-01-22 11:09:02 +00:00
|
|
|
temp.emplace_back(pc + BytecodeOffset::TWO); // first successor
|
2022-01-06 02:26:19 +00:00
|
|
|
int8_t offset = READ_INST_8_0();
|
|
|
|
temp.emplace_back(pc + offset); // second successor
|
|
|
|
// condition branch current basic block end
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
|
2022-01-06 02:26:19 +00:00
|
|
|
// first branch basic block start
|
2022-01-22 11:09:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::TWO, SplitKind::START,
|
|
|
|
std::vector<uint8_t *>(1, pc + BytecodeOffset::TWO));
|
2022-01-06 02:26:19 +00:00
|
|
|
// second branch basic block start
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EcmaOpcode::JEQZ_IMM16: {
|
|
|
|
std::vector<uint8_t *> temp;
|
2022-01-22 11:09:02 +00:00
|
|
|
temp.emplace_back(pc + BytecodeOffset::THREE); // first successor
|
2022-01-06 02:26:19 +00:00
|
|
|
int16_t offset = READ_INST_16_0();
|
|
|
|
temp.emplace_back(pc + offset); // second successor
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp); // end
|
2022-01-22 11:09:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::THREE, SplitKind::START,
|
|
|
|
std::vector<uint8_t *>(1, pc + BytecodeOffset::THREE));
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EcmaOpcode::JNEZ_IMM8: {
|
|
|
|
std::vector<uint8_t *> temp;
|
2022-01-22 11:09:02 +00:00
|
|
|
temp.emplace_back(pc + BytecodeOffset::TWO); // first successor
|
2022-01-06 02:26:19 +00:00
|
|
|
int8_t offset = READ_INST_8_0();
|
2022-01-19 01:11:02 +00:00
|
|
|
temp.emplace_back(pc + offset); // second successor
|
|
|
|
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
|
2022-01-22 11:09:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::TWO, SplitKind::START,
|
|
|
|
std::vector<uint8_t *>(1, pc + BytecodeOffset::TWO));
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EcmaOpcode::JNEZ_IMM16: {
|
|
|
|
std::vector<uint8_t *> temp;
|
2022-01-22 11:09:02 +00:00
|
|
|
temp.emplace_back(pc + BytecodeOffset::THREE); // first successor
|
2022-01-06 02:26:19 +00:00
|
|
|
int8_t offset = READ_INST_16_0();
|
2022-01-19 01:11:02 +00:00
|
|
|
temp.emplace_back(pc + offset); // second successor
|
|
|
|
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, temp);
|
2022-01-22 11:09:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + BytecodeOffset::THREE, SplitKind::START,
|
|
|
|
std::vector<uint8_t *>(1, pc + BytecodeOffset::THREE));
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc + offset, SplitKind::START, std::vector<uint8_t *>(1, pc + offset));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case EcmaOpcode::RETURN_DYN:
|
|
|
|
case EcmaOpcode::RETURNUNDEFINED_PREF: {
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, std::vector<uint8_t *>(1, pc));
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-01-14 09:48:52 +00:00
|
|
|
case EcmaOpcode::THROWDYN_PREF:
|
|
|
|
case EcmaOpcode::THROWCONSTASSIGNMENT_PREF_V8:
|
|
|
|
case EcmaOpcode::THROWTHROWNOTEXISTS_PREF:
|
|
|
|
case EcmaOpcode::THROWPATTERNNONCOERCIBLE_PREF:
|
|
|
|
case EcmaOpcode::THROWDELETESUPERPROPERTY_PREF: {
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(pc, SplitKind::END, std::vector<uint8_t *>(1, pc));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> BytecodeCircuitBuilder::CollectTryCatchBlockInfo(
|
2022-01-19 01:11:02 +00:00
|
|
|
const panda_file::File &file, const JSMethod *method, std::map<uint8_t *, uint8_t*> &byteCodeCurPrePc,
|
|
|
|
std::vector<CfgInfo> &bytecodeBlockInfos)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
|
|
|
// try contains many catch
|
|
|
|
std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> byteCodeException;
|
|
|
|
panda_file::MethodDataAccessor mda(file, method->GetFileId());
|
|
|
|
panda_file::CodeDataAccessor cda(file, mda.GetCodeId().value());
|
2022-01-19 01:11:02 +00:00
|
|
|
cda.EnumerateTryBlocks([method, &byteCodeCurPrePc, &bytecodeBlockInfos, &byteCodeException](
|
2022-01-18 04:02:20 +00:00
|
|
|
panda_file::CodeDataAccessor::TryBlock &try_block) {
|
2022-01-19 01:11:02 +00:00
|
|
|
auto tryStartOffset = try_block.GetStartPc();
|
|
|
|
auto tryEndOffset = try_block.GetStartPc() + try_block.GetLength();
|
|
|
|
auto tryStartPc = const_cast<uint8_t *>(method->GetBytecodeArray() + tryStartOffset);
|
|
|
|
auto tryEndPc = const_cast<uint8_t *>(method->GetBytecodeArray() + tryEndOffset);
|
2022-01-06 02:26:19 +00:00
|
|
|
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 catchBlockPc = const_cast<uint8_t *>(method->GetBytecodeArray() + pcOffset);
|
|
|
|
// try block associate catch block
|
|
|
|
byteCodeException[std::make_pair(tryStartPc, tryEndPc)].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;
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t i = 0; i < bytecodeBlockInfos.size(); i++) {
|
|
|
|
if (bytecodeBlockInfos[i].splitKind == SplitKind::START) {
|
2022-01-06 02:26:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
if (bytecodeBlockInfos[i].pc == byteCodeCurPrePc[tryStartPc]) {
|
2022-01-06 02:26:19 +00:00
|
|
|
flag = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!flag) {
|
|
|
|
// pre block
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(byteCodeCurPrePc[tryStartPc], SplitKind::END,
|
|
|
|
std::vector<uint8_t *>(1, tryStartPc));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
// try block
|
|
|
|
bytecodeBlockInfos.emplace_back(tryStartPc, SplitKind::START, std::vector<uint8_t *>(1, tryStartPc));
|
2022-01-06 02:26:19 +00:00
|
|
|
flag = false;
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t i = 0; i < bytecodeBlockInfos.size(); i++) {
|
|
|
|
if (bytecodeBlockInfos[i].splitKind == SplitKind::START) {
|
2022-01-06 02:26:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
if (bytecodeBlockInfos[i].pc == byteCodeCurPrePc[tryEndPc]) {
|
2022-01-22 11:09:02 +00:00
|
|
|
auto &succs = bytecodeBlockInfos[i].succs;
|
2022-01-19 01:11:02 +00:00
|
|
|
auto iter = std::find(succs.begin(), succs.end(), bytecodeBlockInfos[i].pc);
|
2022-01-06 02:26:19 +00:00
|
|
|
if (iter == succs.end()) {
|
2022-01-19 01:11:02 +00:00
|
|
|
auto opcode = static_cast<EcmaOpcode>(*(bytecodeBlockInfos[i].pc));
|
2022-01-06 02:26:19 +00:00
|
|
|
switch (opcode) {
|
|
|
|
case EcmaOpcode::JMP_IMM8:
|
|
|
|
case EcmaOpcode::JMP_IMM16:
|
|
|
|
case EcmaOpcode::JMP_IMM32:
|
|
|
|
case EcmaOpcode::JEQZ_IMM8:
|
|
|
|
case EcmaOpcode::JEQZ_IMM16:
|
|
|
|
case EcmaOpcode::JNEZ_IMM8:
|
|
|
|
case EcmaOpcode::JNEZ_IMM16:
|
|
|
|
case EcmaOpcode::RETURN_DYN:
|
|
|
|
case EcmaOpcode::RETURNUNDEFINED_PREF:
|
|
|
|
case EcmaOpcode::THROWDYN_PREF: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
succs.emplace_back(tryEndPc);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
flag = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!flag) {
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(byteCodeCurPrePc[tryEndPc], SplitKind::END,
|
|
|
|
std::vector<uint8_t *>(1, tryEndPc));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-22 11:09:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(tryEndPc, SplitKind::START, std::vector<uint8_t *>(1, tryEndPc)); // next block
|
2022-01-06 02:26:19 +00:00
|
|
|
return true;
|
|
|
|
});
|
|
|
|
return byteCodeException;
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::CompleteBytecodeBlockInfo(std::map<uint8_t *, uint8_t *> &byteCodeCurPrePc,
|
2022-01-19 01:11:02 +00:00
|
|
|
std::vector<CfgInfo> &bytecodeBlockInfos)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-01-19 01:11:02 +00:00
|
|
|
std::sort(bytecodeBlockInfos.begin(), bytecodeBlockInfos.end());
|
2022-01-06 02:26:19 +00:00
|
|
|
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
2022-01-19 01:11:02 +00:00
|
|
|
PrintCollectBlockInfo(bytecodeBlockInfos);
|
2022-01-06 02:26:19 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// Deduplicate
|
2022-01-19 01:11:02 +00:00
|
|
|
auto deduplicateIndex = std::unique(bytecodeBlockInfos.begin(), bytecodeBlockInfos.end());
|
|
|
|
bytecodeBlockInfos.erase(deduplicateIndex, bytecodeBlockInfos.end());
|
2022-01-06 02:26:19 +00:00
|
|
|
|
|
|
|
// Supplementary block information
|
|
|
|
std::vector<uint8_t *> endBlockPc;
|
|
|
|
std::vector<uint8_t *> startBlockPc;
|
2022-01-19 01:11:02 +00:00
|
|
|
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[bytecodeBlockInfos[i + 1].pc];
|
2022-01-06 02:26:19 +00:00
|
|
|
endBlockPc.emplace_back(prePc); // Previous instruction of current instruction
|
2022-01-19 01:11:02 +00:00
|
|
|
endBlockPc.emplace_back(bytecodeBlockInfos[i + 1].pc); // current instruction
|
2022-01-06 02:26:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
if (bytecodeBlockInfos[i].splitKind == bytecodeBlockInfos[i + 1].splitKind &&
|
|
|
|
bytecodeBlockInfos[i].splitKind == SplitKind::END) {
|
|
|
|
auto tempPc = bytecodeBlockInfos[i].pc;
|
2022-01-06 02:26:19 +00:00
|
|
|
auto findItem = std::find_if(byteCodeCurPrePc.begin(), byteCodeCurPrePc.end(),
|
2022-01-18 04:02:20 +00:00
|
|
|
[tempPc](const std::map<uint8_t *, uint8_t *>::value_type item) {
|
|
|
|
return item.second == tempPc;
|
|
|
|
});
|
|
|
|
if (findItem != byteCodeCurPrePc.end()) {
|
2022-01-06 02:26:19 +00:00
|
|
|
startBlockPc.emplace_back((*findItem).first);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Supplementary end block info
|
2022-01-22 11:09:02 +00:00
|
|
|
for (auto iter = endBlockPc.begin(); iter != endBlockPc.end(); iter += 2) { // 2: index
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(*iter, SplitKind::END,
|
|
|
|
std::vector<uint8_t *>(1, *(iter + 1)));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
// Supplementary start block info
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto iter = startBlockPc.begin(); iter != startBlockPc.end(); iter++) {
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(*iter, SplitKind::START, std::vector<uint8_t *>(1, *iter));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Deduplicate successor
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t i = 0; i < bytecodeBlockInfos.size(); i++) {
|
|
|
|
if (bytecodeBlockInfos[i].splitKind == SplitKind::END) {
|
|
|
|
std::set<uint8_t *> tempSet(bytecodeBlockInfos[i].succs.begin(),
|
|
|
|
bytecodeBlockInfos[i].succs.end());
|
|
|
|
bytecodeBlockInfos[i].succs.assign(tempSet.begin(), tempSet.end());
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
std::sort(bytecodeBlockInfos.begin(), bytecodeBlockInfos.end());
|
2022-01-06 02:26:19 +00:00
|
|
|
|
|
|
|
// handling jumps to an empty block
|
2022-01-19 01:11:02 +00:00
|
|
|
auto endPc = bytecodeBlockInfos[bytecodeBlockInfos.size() - 1].pc;
|
2022-01-06 02:26:19 +00:00
|
|
|
auto iter = --byteCodeCurPrePc.end();
|
|
|
|
if (endPc == iter->first) {
|
2022-01-19 01:11:02 +00:00
|
|
|
bytecodeBlockInfos.emplace_back(endPc, SplitKind::END, std::vector<uint8_t *>(1, endPc));
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
// Deduplicate
|
2022-01-19 01:11:02 +00:00
|
|
|
deduplicateIndex = std::unique(bytecodeBlockInfos.begin(), bytecodeBlockInfos.end());
|
|
|
|
bytecodeBlockInfos.erase(deduplicateIndex, bytecodeBlockInfos.end());
|
2022-01-06 02:26:19 +00:00
|
|
|
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
2022-01-19 01:11:02 +00:00
|
|
|
PrintCollectBlockInfo(bytecodeBlockInfos);
|
2022-01-06 02:26:19 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::BuildBasicBlocks(const JSMethod *method,
|
|
|
|
std::map<std::pair<uint8_t *, uint8_t *>,
|
|
|
|
std::vector<uint8_t *>> &exception,
|
|
|
|
std::vector<CfgInfo> &bytecodeBlockInfo,
|
|
|
|
std::map<uint8_t *, uint8_t *> &byteCodeCurPrePc)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-01-22 11:09:02 +00:00
|
|
|
std::map<uint8_t *, BytecodeRegion *> startPcToBB; // [start, bb]
|
|
|
|
std::map<uint8_t *, BytecodeRegion *> endPcToBB; // [end, bb]
|
|
|
|
BytecodeGraph byteCodeGraph;
|
2022-01-06 02:26:19 +00:00
|
|
|
auto &blocks = byteCodeGraph.graph;
|
|
|
|
byteCodeGraph.method = method;
|
2022-01-19 01:11:02 +00:00
|
|
|
blocks.resize(bytecodeBlockInfo.size() / 2); // 2 : half size
|
2022-01-06 02:26:19 +00:00
|
|
|
// build basic block
|
|
|
|
int blockId = 0;
|
|
|
|
int index = 0;
|
2022-01-22 11:09:02 +00:00
|
|
|
for (size_t i = 0; i < bytecodeBlockInfo.size() - 1; i += 2) { // 2:index
|
2022-01-19 01:11:02 +00:00
|
|
|
auto startPc = bytecodeBlockInfo[i].pc;
|
|
|
|
auto endPc = bytecodeBlockInfo[i + 1].pc;
|
2022-01-06 02:26:19 +00:00
|
|
|
auto block = &blocks[index++];
|
|
|
|
block->id = blockId++;
|
|
|
|
block->start = startPc;
|
|
|
|
block->end = endPc;
|
|
|
|
block->preds = {};
|
|
|
|
block->succs = {};
|
2022-01-19 01:11:02 +00:00
|
|
|
startPcToBB[startPc] = block;
|
|
|
|
endPcToBB[endPc] = block;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// add block associate
|
|
|
|
for (size_t i = 0; i < bytecodeBlockInfo.size(); i++) {
|
2022-01-19 01:11:02 +00:00
|
|
|
if (bytecodeBlockInfo[i].splitKind == SplitKind::START) {
|
2022-01-06 02:26:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
auto curPc = bytecodeBlockInfo[i].pc;
|
|
|
|
auto &successors = bytecodeBlockInfo[i].succs;
|
2022-01-06 02:26:19 +00:00
|
|
|
for (size_t j = 0; j < successors.size(); j++) {
|
|
|
|
if (successors[j] == curPc) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
auto curBlock = endPcToBB[curPc];
|
|
|
|
auto succsBlock = startPcToBB[successors[j]];
|
2022-01-06 02:26:19 +00:00
|
|
|
curBlock->succs.emplace_back(succsBlock);
|
|
|
|
succsBlock->preds.emplace_back(curBlock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// try catch block associate
|
|
|
|
for (size_t i = 0; i < blocks.size(); i++) {
|
|
|
|
auto pc = blocks[i].start;
|
|
|
|
auto it = exception.begin();
|
2022-01-18 04:02:20 +00:00
|
|
|
for (; it != exception.end(); it++) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (pc < it->first.first || pc >= it->first.second) { // try block interval
|
2022-01-18 04:02:20 +00:00
|
|
|
continue;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
auto catchs = exception[it->first]; // catchs start pc
|
|
|
|
for (size_t j = i + 1; j < blocks.size(); j++) {
|
|
|
|
if (std::find(catchs.begin(), catchs.end(), blocks[j].start) != catchs.end()) {
|
|
|
|
blocks[i].catchs.insert(blocks[i].catchs.begin(), &blocks[j]);
|
|
|
|
blocks[i].succs.emplace_back(&blocks[j]);
|
|
|
|
blocks[j].preds.emplace_back(&blocks[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t i = 0; i < blocks.size(); i++) {
|
|
|
|
bbIdToBasicBlock_[blocks[i].id] = &blocks[i];
|
|
|
|
}
|
|
|
|
|
2022-01-06 02:26:19 +00:00
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
|
|
|
PrintGraph(byteCodeGraph.graph);
|
|
|
|
#endif
|
|
|
|
ComputeDominatorTree(byteCodeGraph);
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::ComputeDominatorTree(BytecodeGraph &byteCodeGraph)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
|
|
|
auto &graph = byteCodeGraph.graph;
|
|
|
|
// Construct graph backward order
|
2022-01-19 01:11:02 +00:00
|
|
|
std::map<size_t, size_t> bbIdToDfsTimestamp; // (basicblock id, dfs order)
|
2022-01-06 02:26:19 +00:00
|
|
|
size_t timestamp = 0;
|
|
|
|
std::deque<size_t> pendingList;
|
|
|
|
std::vector<size_t> visited(graph.size(), 0);
|
|
|
|
auto basicBlockId = graph[0].id;
|
|
|
|
pendingList.push_back(basicBlockId);
|
|
|
|
while (!pendingList.empty()) {
|
|
|
|
auto &curBlockId = pendingList.back();
|
|
|
|
pendingList.pop_back();
|
2022-01-19 01:11:02 +00:00
|
|
|
bbIdToDfsTimestamp[curBlockId] = timestamp++;
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto &succBlock: graph[curBlockId].succs) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (visited[succBlock->id] == 0) {
|
|
|
|
visited[succBlock->id] = 1;
|
|
|
|
pendingList.push_back(succBlock->id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
RemoveDeadRegions(bbIdToDfsTimestamp, byteCodeGraph);
|
2022-01-06 02:26:19 +00:00
|
|
|
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
|
|
|
// print cfg order
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto iter : bbIdToDfsTimestamp) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << "BB_" << iter.first << " depth is : " << iter.second << std::endl;
|
|
|
|
}
|
|
|
|
#endif
|
2022-01-27 08:46:57 +00:00
|
|
|
std::vector<int32_t> immDom(graph.size()); // immediate dominator
|
2022-01-19 01:11:02 +00:00
|
|
|
std::vector<std::vector<size_t>> doms(graph.size()); // dominators set
|
|
|
|
doms[0] = {0};
|
|
|
|
for (size_t i = 1; i < doms.size(); i++) {
|
|
|
|
doms[i].resize(doms.size());
|
|
|
|
std::iota(doms[i].begin(), doms[i].end(), 0);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
bool changed = true;
|
|
|
|
while (changed) {
|
|
|
|
changed = false;
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t i = 1; i < doms.size(); i++) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (graph[i].isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
auto &curDom = doms[i];
|
2022-01-06 02:26:19 +00:00
|
|
|
size_t curDomSize = curDom.size();
|
2022-01-19 01:11:02 +00:00
|
|
|
curDom.resize(doms.size());
|
2022-01-06 02:26:19 +00:00
|
|
|
std::iota(curDom.begin(), curDom.end(), 0);
|
|
|
|
// traverse the predecessor nodes of the current node, Computing Dominators
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto &preBlock : graph[i].preds) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::vector<size_t> tmp(curDom.size());
|
2022-01-19 01:11:02 +00:00
|
|
|
auto preDom = doms[preBlock->id];
|
2022-01-22 11:09:02 +00:00
|
|
|
auto it = std::set_intersection(curDom.begin(), curDom.end(), preDom.begin(), preDom.end(),
|
|
|
|
tmp.begin());
|
2022-01-06 02:26:19 +00:00
|
|
|
tmp.resize(it - tmp.begin());
|
|
|
|
curDom = tmp;
|
|
|
|
}
|
|
|
|
auto it = std::find(curDom.begin(), curDom.end(), i);
|
|
|
|
if (it == curDom.end()) {
|
|
|
|
curDom.push_back(i);
|
|
|
|
std::sort(curDom.begin(), curDom.end());
|
|
|
|
}
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
if (doms[i].size() != curDomSize) {
|
2022-01-06 02:26:19 +00:00
|
|
|
changed = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
|
|
|
// print dominators set
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t i = 0; i < doms.size(); i++) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << "block " << i << " dominator blocks has: ";
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto j: doms[i]) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << j << " , ";
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// compute immediate dominator
|
2022-01-19 01:11:02 +00:00
|
|
|
immDom[0] = doms[0].front();
|
|
|
|
for (size_t i = 1; i < doms.size(); i++) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (graph[i].isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
auto it = std::remove(doms[i].begin(), doms[i].end(), i);
|
|
|
|
doms[i].resize(it - doms[i].begin());
|
|
|
|
immDom[i] = *std::max_element(
|
|
|
|
doms[i].begin(), doms[i].end(), [graph, bbIdToDfsTimestamp](size_t lhs, size_t rhs) -> bool {
|
|
|
|
return bbIdToDfsTimestamp.at(graph[lhs].id) < bbIdToDfsTimestamp.at(graph[rhs].id);
|
|
|
|
});
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
|
|
|
// print immediate dominator
|
2022-01-18 04:02:20 +00:00
|
|
|
for (size_t i = 0; i < immDom.size(); i++) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << i << " immediate dominator: " << immDom[i] << std::endl;
|
|
|
|
}
|
|
|
|
PrintGraph(graph);
|
|
|
|
#endif
|
|
|
|
BuildImmediateDominator(immDom, byteCodeGraph);
|
|
|
|
}
|
|
|
|
|
2022-01-27 08:46:57 +00:00
|
|
|
void BytecodeCircuitBuilder::BuildImmediateDominator(std::vector<int32_t> &immDom, BytecodeGraph &byteCodeGraph)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
|
|
|
auto &graph = byteCodeGraph.graph;
|
|
|
|
|
|
|
|
graph[0].iDominator = &graph[0];
|
2022-01-18 04:02:20 +00:00
|
|
|
for (size_t i = 1; i < immDom.size(); i++) {
|
2022-01-19 01:11:02 +00:00
|
|
|
auto dominatedBlock = bbIdToBasicBlock_.at(i);
|
2022-01-06 02:26:19 +00:00
|
|
|
if (dominatedBlock->isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
auto immDomBlock = bbIdToBasicBlock_.at(immDom[i]);
|
2022-01-06 02:26:19 +00:00
|
|
|
dominatedBlock->iDominator = immDomBlock;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto block : graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (block.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
std::cout << "current block " << block.id
|
|
|
|
<< " immediate dominator block id: " << block.iDominator->id << std::endl;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto &block : graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (block.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (block.iDominator->id != block.id) {
|
|
|
|
block.iDominator->immDomBlocks.emplace_back(&block);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto &block : graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (block.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
std::cout << "block " << block.id << " dominate block has: ";
|
2022-01-06 02:26:19 +00:00
|
|
|
for (size_t i = 0; i < block.immDomBlocks.size(); i++) {
|
|
|
|
std::cout << block.immDomBlocks[i]->id << ",";
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
ComputeDomFrontiers(immDom, byteCodeGraph);
|
|
|
|
InsertPhi(byteCodeGraph);
|
2022-01-19 01:11:02 +00:00
|
|
|
UpdateCFG(byteCodeGraph);
|
2022-01-06 02:26:19 +00:00
|
|
|
BuildCircuit(byteCodeGraph);
|
|
|
|
}
|
|
|
|
|
2022-01-27 08:46:57 +00:00
|
|
|
void BytecodeCircuitBuilder::ComputeDomFrontiers(std::vector<int32_t> &immDom, BytecodeGraph &byteCodeGraph)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
|
|
|
auto &graph = byteCodeGraph.graph;
|
2022-01-22 11:09:02 +00:00
|
|
|
std::vector<std::set<BytecodeRegion *>> domFrontiers(immDom.size());
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto &bb : graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (bb.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-22 11:09:02 +00:00
|
|
|
if (bb.preds.size() < 2) { // 2: pred num
|
2022-01-06 02:26:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < bb.preds.size(); i++) {
|
|
|
|
auto runner = bb.preds[i];
|
2022-01-18 04:02:20 +00:00
|
|
|
while (runner->id != immDom[bb.id]) {
|
2022-01-06 02:26:19 +00:00
|
|
|
domFrontiers[runner->id].insert(&bb);
|
2022-01-19 01:11:02 +00:00
|
|
|
runner = bbIdToBasicBlock_.at(immDom[runner->id]);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < domFrontiers.size(); i++) {
|
|
|
|
for (auto iter = domFrontiers[i].begin(); iter != domFrontiers[i].end(); iter++) {
|
|
|
|
graph[i].domFrontiers.emplace_back(*iter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
|
|
|
for (size_t i = 0; i < domFrontiers.size(); i++) {
|
|
|
|
std::cout << "basic block " << i << " dominate Frontiers is: ";
|
|
|
|
for (auto iter = domFrontiers[i].begin(); iter != domFrontiers[i].end(); iter++) {
|
|
|
|
std::cout << (*iter)->id << " , ";
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::RemoveDeadRegions(const std::map<size_t, size_t> &bbIdToDfsTimestamp,
|
|
|
|
BytecodeGraph &byteCodeGraph)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
|
|
|
auto &graph = byteCodeGraph.graph;
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto &block: graph) {
|
2022-01-22 11:09:02 +00:00
|
|
|
std::vector<BytecodeRegion *> newPreds;
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto &bb : block.preds) {
|
|
|
|
if (bbIdToDfsTimestamp.count(bb->id)) {
|
2022-01-06 02:26:19 +00:00
|
|
|
newPreds.emplace_back(bb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
block.preds = newPreds;
|
|
|
|
}
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto &block : graph) {
|
|
|
|
block.isDead = !bbIdToDfsTimestamp.count(block.id);
|
2022-01-06 02:26:19 +00:00
|
|
|
if (block.isDead) {
|
|
|
|
block.succs.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
BytecodeInfo BytecodeCircuitBuilder::GetBytecodeInfo(uint8_t *pc)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-01-22 11:09:02 +00:00
|
|
|
BytecodeInfo info;
|
2022-01-06 02:26:19 +00:00
|
|
|
auto opcode = static_cast<EcmaOpcode>(*pc);
|
|
|
|
info.opcode = opcode;
|
|
|
|
switch (opcode) {
|
|
|
|
case EcmaOpcode::MOV_V4_V4: {
|
|
|
|
uint16_t vdst = READ_INST_4_0();
|
|
|
|
uint16_t vsrc = READ_INST_4_1();
|
|
|
|
info.vregIn.emplace_back(vsrc);
|
|
|
|
info.vregOut.emplace_back(vdst);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::MOV_DYN_V8_V8: {
|
|
|
|
uint16_t vdst = READ_INST_8_0();
|
|
|
|
uint16_t vsrc = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(vsrc);
|
|
|
|
info.vregOut.emplace_back(vdst);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::MOV_DYN_V16_V16: {
|
|
|
|
uint16_t vdst = READ_INST_16_0();
|
|
|
|
uint16_t vsrc = READ_INST_16_2();
|
|
|
|
info.vregIn.emplace_back(vsrc);
|
|
|
|
info.vregOut.emplace_back(vdst);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDA_STR_ID32: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::JMP_IMM8: {
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::JMP_IMM16: {
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::JMP_IMM32: {
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::JEQZ_IMM8: {
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::JEQZ_IMM16: {
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::JNEZ_IMM8: {
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::JNEZ_IMM16: {
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDA_DYN_V8: {
|
|
|
|
uint16_t vsrc = READ_INST_8_0();
|
|
|
|
info.vregIn.emplace_back(vsrc);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STA_DYN_V8: {
|
|
|
|
uint16_t vdst = READ_INST_8_0();
|
|
|
|
info.vregOut.emplace_back(vdst);
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDAI_DYN_IMM32: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::FLDAI_DYN_IMM64: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::NINE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CALLARG0DYN_PREF_V8: {
|
|
|
|
uint32_t funcReg = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(funcReg);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CALLARG1DYN_PREF_V8_V8: {
|
|
|
|
uint32_t funcReg = READ_INST_8_1();
|
|
|
|
uint32_t reg = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(funcReg);
|
|
|
|
info.vregIn.emplace_back(reg);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CALLARGS2DYN_PREF_V8_V8_V8: {
|
|
|
|
uint32_t funcReg = READ_INST_8_1();
|
|
|
|
uint32_t reg = READ_INST_8_3();
|
|
|
|
info.vregIn.emplace_back(funcReg);
|
|
|
|
info.vregIn.emplace_back(reg);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CALLARGS3DYN_PREF_V8_V8_V8_V8: {
|
|
|
|
uint32_t funcReg = READ_INST_8_1();
|
|
|
|
uint32_t reg = READ_INST_8_4();
|
|
|
|
info.vregIn.emplace_back(funcReg);
|
|
|
|
info.vregIn.emplace_back(reg);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CALLITHISRANGEDYN_PREF_IMM16_V8: {
|
|
|
|
uint32_t funcReg = READ_INST_8_3();
|
|
|
|
uint32_t actualNumArgs = READ_INST_16_1() - 1;
|
2022-01-18 04:02:20 +00:00
|
|
|
size_t copyArgs = actualNumArgs + NUM_MANDATORY_JSFUNC_ARGS - 2;
|
2022-01-06 02:26:19 +00:00
|
|
|
info.vregIn.emplace_back(funcReg);
|
|
|
|
for (size_t i = 1; i <= copyArgs; i++) {
|
|
|
|
info.vregIn.emplace_back(funcReg + i);
|
|
|
|
}
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CALLSPREADDYN_PREF_V8_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v1 = READ_INST_8_2();
|
|
|
|
uint16_t v2 = READ_INST_8_3();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.vregIn.emplace_back(v2);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CALLIRANGEDYN_PREF_IMM16_V8: {
|
|
|
|
uint32_t funcReg = READ_INST_8_3();
|
|
|
|
uint32_t actualNumArgs = READ_INST_16_1();
|
2022-01-18 04:02:20 +00:00
|
|
|
size_t copyArgs = actualNumArgs + NUM_MANDATORY_JSFUNC_ARGS - 2;
|
2022-01-06 02:26:19 +00:00
|
|
|
info.vregIn.emplace_back(funcReg);
|
|
|
|
for (size_t i = 1; i <= copyArgs; i++) {
|
|
|
|
info.vregIn.emplace_back(funcReg + i);
|
|
|
|
}
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-01-18 04:02:20 +00:00
|
|
|
case EcmaOpcode::RETURN_DYN: {
|
2022-01-06 02:26:19 +00:00
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::ONE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::RETURNUNDEFINED_PREF: {
|
2022-01-18 04:02:20 +00:00
|
|
|
info.accIn = true;
|
2022-01-06 02:26:19 +00:00
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDNAN_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDINFINITY_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDGLOBALTHIS_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDUNDEFINED_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDNULL_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDSYMBOL_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDGLOBAL_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDTRUE_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDFALSE_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDLEXENVDYN_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::GETUNMAPPEDARGS_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::ASYNCFUNCTIONENTER_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::TONUMBER_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::NEGDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::NOTDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::INCDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::DECDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::THROWDYN_PREF: {
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::TYPEOFDYN_PREF: {
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::GETPROPITERATOR_PREF: {
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::RESUMEGENERATOR_PREF_V8: {
|
|
|
|
uint16_t vs = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(vs);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::GETRESUMEMODE_PREF_V8: {
|
|
|
|
uint16_t vs = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(vs);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::GETITERATOR_PREF: {
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::THROWCONSTASSIGNMENT_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::THROWTHROWNOTEXISTS_PREF: {
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::THROWPATTERNNONCOERCIBLE_PREF: {
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::THROWIFNOTOBJECT_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::ITERNEXT_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CLOSEITERATOR_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::ADD2DYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::SUB2DYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::MUL2DYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::DIV2DYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::MOD2DYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::EQDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::NOTEQDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LESSDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LESSEQDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::GREATERDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::GREATEREQDYN_PREF_V8: {
|
|
|
|
uint16_t vs = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(vs);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::SHL2DYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::SHR2DYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::ASHR2DYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::AND2DYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::OR2DYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::XOR2DYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::DELOBJPROP_PREF_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::DEFINEFUNCDYN_PREF_ID16_IMM16_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::DEFINENCFUNCDYN_PREF_ID16_IMM16_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::DEFINEMETHOD_PREF_ID16_IMM16_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::NEWOBJDYNRANGE_PREF_IMM16_V8: {
|
|
|
|
uint16_t firstArgRegIdx = READ_INST_8_3();
|
|
|
|
info.vregIn.emplace_back(firstArgRegIdx);
|
|
|
|
info.vregIn.emplace_back(firstArgRegIdx + 1);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::EXPDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::ISINDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::INSTANCEOFDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STRICTNOTEQDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STRICTEQDYN_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDLEXVARDYN_PREF_IMM16_IMM16: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDLEXVARDYN_PREF_IMM8_IMM8: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDLEXVARDYN_PREF_IMM4_IMM4: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STLEXVARDYN_PREF_IMM16_IMM16_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STLEXVARDYN_PREF_IMM8_IMM8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STLEXVARDYN_PREF_IMM4_IMM4_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::NEWLEXENVDYN_PREF_IMM16: {
|
|
|
|
uint16_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::POPLEXENVDYN_PREF: {
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CREATEITERRESULTOBJ_PREF_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::SUSPENDGENERATOR_PREF_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::ASYNCFUNCTIONAWAITUNCAUGHT_PREF_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::ASYNCFUNCTIONRESOLVE_PREF_V8_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v2 = READ_INST_8_3();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v2);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::ASYNCFUNCTIONREJECT_PREF_V8_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v2 = READ_INST_8_3();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v2);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::NEWOBJSPREADDYN_PREF_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::THROWUNDEFINEDIFHOLE_PREF_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STOWNBYNAME_PREF_ID32_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CREATEEMPTYARRAY_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CREATEEMPTYOBJECT_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CREATEOBJECTWITHBUFFER_PREF_IMM16: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::SETOBJECTWITHPROTO_PREF_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CREATEARRAYWITHBUFFER_PREF_IMM16: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::IMPORTMODULE_PREF_ID32: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STMODULEVAR_PREF_ID32: {
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::COPYMODULE_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDMODVARBYNAME_PREF_ID32_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CREATEREGEXPWITHLITERAL_PREF_ID32_IMM8: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::GETTEMPLATEOBJECT_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::GETNEXTPROPNAME_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::COPYDATAPROPERTIES_PREF_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STOWNBYINDEX_PREF_V8_IMM32: {
|
|
|
|
uint32_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STOWNBYVALUE_PREF_V8_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_1();
|
|
|
|
uint32_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CREATEOBJECTWITHEXCLUDEDKEYS_PREF_IMM16_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_3();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::DEFINEGENERATORFUNC_PREF_ID16_IMM16_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::DEFINEASYNCFUNC_PREF_ID16_IMM16_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDHOLE_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::COPYRESTARGS_PREF_IMM16: {
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::DEFINEGETTERSETTERBYVALUE_PREF_V8_V8_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v1 = READ_INST_8_2();
|
|
|
|
uint16_t v2 = READ_INST_8_3();
|
|
|
|
uint16_t v3 = READ_INST_8_4();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.vregIn.emplace_back(v2);
|
|
|
|
info.vregIn.emplace_back(v3);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDOBJBYINDEX_PREF_V8_IMM32: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STOBJBYINDEX_PREF_V8_IMM32: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDOBJBYVALUE_PREF_V8_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_1();
|
|
|
|
uint32_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STOBJBYVALUE_PREF_V8_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_1();
|
|
|
|
uint32_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDSUPERBYVALUE_PREF_V8_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_1();
|
|
|
|
uint32_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STSUPERBYVALUE_PREF_V8_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_1();
|
|
|
|
uint32_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::TRYLDGLOBALBYNAME_PREF_ID32: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::TRYSTGLOBALBYNAME_PREF_ID32: {
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STCONSTTOGLOBALRECORD_PREF_ID32: {
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STLETTOGLOBALRECORD_PREF_ID32: {
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STCLASSTOGLOBALRECORD_PREF_ID32: {
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STOWNBYVALUEWITHNAMESET_PREF_V8_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_1();
|
|
|
|
uint32_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STOWNBYNAMEWITHNAMESET_PREF_ID32_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDGLOBALVAR_PREF_ID32: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDOBJBYNAME_PREF_ID32_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STOBJBYNAME_PREF_ID32_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDSUPERBYNAME_PREF_ID32_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STSUPERBYNAME_PREF_ID32_V8: {
|
|
|
|
uint32_t v0 = READ_INST_8_5();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SEVEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STGLOBALVAR_PREF_ID32: {
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::SIX;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CREATEGENERATOROBJ_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::STARRAYSPREAD_PREF_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::GETITERATORNEXT_PREF_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
uint16_t v1 = READ_INST_8_2();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::DEFINECLASSWITHBUFFER_PREF_ID16_IMM16_IMM16_V8_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_7();
|
|
|
|
uint16_t v1 = READ_INST_8_8();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.vregIn.emplace_back(v1);
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TEN;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDFUNCTION_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::SUPERCALL_PREF_IMM16_V8: {
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FIVE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::SUPERCALLSPREAD_PREF_V8: {
|
|
|
|
uint16_t v0 = READ_INST_8_1();
|
|
|
|
info.vregIn.emplace_back(v0);
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::THREE;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::CREATEOBJECTHAVINGMETHOD_PREF_IMM16: {
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::THROWIFSUPERNOTCORRECTCALL_PREF_IMM16: {
|
|
|
|
info.accIn = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::FOUR;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::LDHOMEOBJECT_PREF: {
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::THROWDELETESUPERPROPERTY_PREF: {
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::DEBUGGER_PREF: {
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::ISTRUE_PREF: {
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case EcmaOpcode::ISFALSE_PREF: {
|
|
|
|
info.accIn = true;
|
|
|
|
info.accOut = true;
|
2022-01-22 11:09:02 +00:00
|
|
|
info.offset = BytecodeOffset::TWO;
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
std::cout << opcode << std::endl;
|
|
|
|
abort();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::InsertPhi(BytecodeGraph &byteCodeGraph)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
|
|
|
auto &graph = byteCodeGraph.graph;
|
|
|
|
std::map<uint16_t, std::set<size_t>> defsitesInfo; // <vreg, bbs>
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto &bb : graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (bb.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
auto pc = bb.start;
|
|
|
|
while (pc <= bb.end) {
|
2022-01-22 11:09:02 +00:00
|
|
|
auto bytecodeInfo = GetBytecodeInfo(pc);
|
2022-01-06 02:26:19 +00:00
|
|
|
pc = pc + bytecodeInfo.offset; // next inst start pc
|
2022-01-18 04:02:20 +00:00
|
|
|
for (const auto &vreg: bytecodeInfo.vregOut) {
|
2022-01-06 02:26:19 +00:00
|
|
|
defsitesInfo[vreg].insert(bb.id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
2022-01-19 01:11:02 +00:00
|
|
|
for (const auto&[variable, defsites] : defsitesInfo) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << "variable: " << variable << " locate block have: ";
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto id : defsites) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << id << " , ";
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
for (const auto&[variable, defsites] : defsitesInfo) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::queue<uint16_t> workList;
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto blockId: defsites) {
|
2022-01-06 02:26:19 +00:00
|
|
|
workList.push(blockId);
|
|
|
|
}
|
|
|
|
while (!workList.empty()) {
|
|
|
|
auto currentId = workList.front();
|
|
|
|
workList.pop();
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto &block : graph[currentId].domFrontiers) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (!block->phi.count(variable)) {
|
|
|
|
block->phi.insert(variable);
|
|
|
|
if (!defsitesInfo[variable].count(block->id)) {
|
|
|
|
workList.push(block->id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
|
|
|
PrintGraph(graph);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
// Update CFG's predecessor, successor and try catch associations
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::UpdateCFG(BytecodeGraph &byteCodeGraph)
|
2022-01-19 01:11:02 +00:00
|
|
|
{
|
|
|
|
auto &graph = byteCodeGraph.graph;
|
|
|
|
for (auto &bb: graph) {
|
|
|
|
if (bb.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
bb.preds.clear();
|
|
|
|
bb.trys.clear();
|
2022-01-22 11:09:02 +00:00
|
|
|
std::vector<BytecodeRegion *> newSuccs;
|
2022-01-19 01:11:02 +00:00
|
|
|
for (const auto &succ: bb.succs) {
|
|
|
|
if (std::count(bb.catchs.begin(), bb.catchs.end(), succ)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
newSuccs.push_back(succ);
|
|
|
|
}
|
|
|
|
bb.succs = newSuccs;
|
|
|
|
}
|
|
|
|
for (auto &bb: graph) {
|
|
|
|
if (bb.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
for (auto &succ: bb.succs) {
|
|
|
|
succ->preds.push_back(&bb);
|
|
|
|
}
|
|
|
|
for (auto &catchBlock: bb.catchs) {
|
|
|
|
catchBlock->trys.push_back(&bb);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
bool BytecodeCircuitBuilder::IsJump(EcmaOpcode opcode)
|
2022-01-18 04:02:20 +00:00
|
|
|
{
|
2022-01-06 02:26:19 +00:00
|
|
|
switch (opcode) {
|
|
|
|
case EcmaOpcode::JMP_IMM8:
|
|
|
|
case EcmaOpcode::JMP_IMM16:
|
|
|
|
case EcmaOpcode::JMP_IMM32:
|
|
|
|
case EcmaOpcode::JEQZ_IMM8:
|
|
|
|
case EcmaOpcode::JEQZ_IMM16:
|
|
|
|
case EcmaOpcode::JNEZ_IMM8:
|
|
|
|
case EcmaOpcode::JNEZ_IMM16:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
bool BytecodeCircuitBuilder::IsCondJump(EcmaOpcode opcode)
|
2022-01-18 04:02:20 +00:00
|
|
|
{
|
2022-01-06 02:26:19 +00:00
|
|
|
switch (opcode) {
|
|
|
|
case EcmaOpcode::JEQZ_IMM8:
|
|
|
|
case EcmaOpcode::JEQZ_IMM16:
|
|
|
|
case EcmaOpcode::JNEZ_IMM8:
|
|
|
|
case EcmaOpcode::JNEZ_IMM16:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
bool BytecodeCircuitBuilder::IsMov(EcmaOpcode opcode)
|
2022-01-18 04:02:20 +00:00
|
|
|
{
|
2022-01-06 02:26:19 +00:00
|
|
|
switch (opcode) {
|
|
|
|
case EcmaOpcode::MOV_V4_V4:
|
|
|
|
case EcmaOpcode::MOV_DYN_V8_V8:
|
|
|
|
case EcmaOpcode::MOV_DYN_V16_V16:
|
|
|
|
case EcmaOpcode::LDA_DYN_V8:
|
|
|
|
case EcmaOpcode::STA_DYN_V8:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
bool BytecodeCircuitBuilder::IsReturn(EcmaOpcode opcode)
|
2022-01-18 04:02:20 +00:00
|
|
|
{
|
2022-01-06 02:26:19 +00:00
|
|
|
switch (opcode) {
|
|
|
|
case EcmaOpcode::RETURN_DYN:
|
|
|
|
case EcmaOpcode::RETURNUNDEFINED_PREF:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
bool BytecodeCircuitBuilder::IsThrow(EcmaOpcode opcode)
|
2022-01-14 09:48:52 +00:00
|
|
|
{
|
|
|
|
switch (opcode) {
|
|
|
|
case EcmaOpcode::THROWDYN_PREF:
|
|
|
|
case EcmaOpcode::THROWCONSTASSIGNMENT_PREF_V8:
|
|
|
|
case EcmaOpcode::THROWTHROWNOTEXISTS_PREF:
|
|
|
|
case EcmaOpcode::THROWPATTERNNONCOERCIBLE_PREF:
|
|
|
|
case EcmaOpcode::THROWDELETESUPERPROPERTY_PREF:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
bool BytecodeCircuitBuilder::IsGeneral(EcmaOpcode opcode)
|
2022-01-18 04:02:20 +00:00
|
|
|
{
|
2022-01-19 01:11:02 +00:00
|
|
|
return !IsMov(opcode) && !IsJump(opcode) && !IsReturn(opcode);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::BuildCircuit(BytecodeGraph &byteCodeGraph)
|
2022-01-18 04:02:20 +00:00
|
|
|
{
|
2022-01-06 02:26:19 +00:00
|
|
|
auto &graph = byteCodeGraph.graph;
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
|
|
|
PrintBBInfo(graph);
|
|
|
|
#endif
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
// create arg gates array
|
2022-01-06 02:26:19 +00:00
|
|
|
const size_t numArgs = byteCodeGraph.method->GetNumArgs();
|
|
|
|
const size_t offsetArgs = byteCodeGraph.method->GetNumVregs();
|
2022-01-19 01:11:02 +00:00
|
|
|
std::vector<GateRef> argGates(numArgs);
|
2022-01-06 02:26:19 +00:00
|
|
|
for (size_t argIdx = 0; argIdx < numArgs; argIdx++) {
|
2022-02-09 08:51:58 +00:00
|
|
|
argGates.at(argIdx) = circuit_.NewGate(OpCode(OpCode::ARG), MachineType::I64, argIdx,
|
2022-01-19 01:11:02 +00:00
|
|
|
{Circuit::GetCircuitRoot(OpCode(OpCode::ARG_LIST))},
|
2022-01-27 08:46:57 +00:00
|
|
|
GateType::JS_ANY);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
// get number of expanded state predicates of each block
|
|
|
|
// one block-level try catch edge may correspond to multiple bytecode-level edges
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto &bb: graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (bb.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
bb.numOfStatePreds = 0;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto &bb: graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (bb.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
auto pc = bb.start;
|
|
|
|
while (pc <= bb.end) {
|
2022-01-22 11:09:02 +00:00
|
|
|
auto bytecodeInfo = GetBytecodeInfo(pc);
|
2022-01-06 02:26:19 +00:00
|
|
|
pc = pc + bytecodeInfo.offset; // next inst start pc
|
|
|
|
if (IsGeneral(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
|
|
|
|
if (!bb.catchs.empty()) {
|
2022-01-19 01:11:02 +00:00
|
|
|
bb.catchs.at(0)->numOfStatePreds++;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto &succ: bb.succs) {
|
2022-01-19 01:11:02 +00:00
|
|
|
succ->numOfStatePreds++;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
|
|
|
|
// build head of each block
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto &bb: graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (bb.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
if (bb.numOfStatePreds == 0) {
|
|
|
|
bb.stateStart = Circuit::GetCircuitRoot(OpCode(OpCode::STATE_ENTRY));
|
|
|
|
bb.dependStart = Circuit::GetCircuitRoot(OpCode(OpCode::DEPEND_ENTRY));
|
|
|
|
} else if (bb.numOfStatePreds == 1) {
|
|
|
|
bb.stateStart = circuit_.NewGate(OpCode(OpCode::ORDINARY_BLOCK), 0,
|
2022-01-27 08:46:57 +00:00
|
|
|
{Circuit::NullGate()}, GateType::EMPTY);
|
2022-01-19 01:11:02 +00:00
|
|
|
bb.dependStart = circuit_.NewGate(OpCode(OpCode::DEPEND_RELAY), 0,
|
2022-01-27 08:46:57 +00:00
|
|
|
{bb.stateStart, Circuit::NullGate()}, GateType::EMPTY);
|
2022-01-06 02:26:19 +00:00
|
|
|
} else {
|
2022-01-19 01:11:02 +00:00
|
|
|
bb.stateStart = circuit_.NewGate(OpCode(OpCode::MERGE), bb.numOfStatePreds,
|
|
|
|
std::vector<GateRef>(bb.numOfStatePreds, Circuit::NullGate()),
|
2022-01-27 08:46:57 +00:00
|
|
|
GateType::EMPTY);
|
2022-01-19 01:11:02 +00:00
|
|
|
bb.dependStart = circuit_.NewGate(OpCode(OpCode::DEPEND_SELECTOR), bb.numOfStatePreds,
|
|
|
|
std::vector<GateRef>(bb.numOfStatePreds + 1, Circuit::NullGate()),
|
2022-01-27 08:46:57 +00:00
|
|
|
GateType::EMPTY);
|
2022-01-06 02:26:19 +00:00
|
|
|
circuit_.NewIn(bb.dependStart, 0, bb.stateStart);
|
|
|
|
}
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
// build states sub-circuit of each block
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto &bb: graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (bb.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
auto stateCur = bb.stateStart;
|
|
|
|
auto dependCur = bb.dependStart;
|
2022-01-19 01:11:02 +00:00
|
|
|
ASSERT(stateCur != Circuit::NullGate());
|
|
|
|
ASSERT(dependCur != Circuit::NullGate());
|
2022-01-06 02:26:19 +00:00
|
|
|
auto pc = bb.start;
|
|
|
|
while (pc <= bb.end) {
|
|
|
|
auto pcPrev = pc;
|
2022-01-22 11:09:02 +00:00
|
|
|
auto bytecodeInfo = GetBytecodeInfo(pc);
|
2022-01-06 02:26:19 +00:00
|
|
|
pc = pc + bytecodeInfo.offset; // next inst start pc
|
|
|
|
size_t numValueInputs = (bytecodeInfo.accIn ? 1 : 0) + bytecodeInfo.vregIn.size();
|
|
|
|
if (IsGeneral(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
|
2022-01-19 01:11:02 +00:00
|
|
|
// handle general ecma.* bytecodes
|
2022-01-27 08:46:57 +00:00
|
|
|
GateRef gate = 0;
|
|
|
|
if (!bytecodeInfo.vregOut.empty() || bytecodeInfo.accOut) {
|
2022-02-09 08:51:58 +00:00
|
|
|
gate = circuit_.NewGate(OpCode(OpCode::JS_BYTECODE), MachineType::I64, numValueInputs,
|
2022-01-27 08:46:57 +00:00
|
|
|
std::vector<GateRef>(2 + numValueInputs, // 2: state and depend input
|
|
|
|
Circuit::NullGate()),
|
|
|
|
GateType::JS_ANY);
|
|
|
|
} else {
|
|
|
|
gate = circuit_.NewGate(OpCode(OpCode::JS_BYTECODE), MachineType::NOVALUE, numValueInputs,
|
|
|
|
std::vector<GateRef>(2 + numValueInputs, // 2: state and depend input
|
|
|
|
Circuit::NullGate()),
|
|
|
|
GateType::EMPTY);
|
|
|
|
}
|
2022-01-06 02:26:19 +00:00
|
|
|
circuit_.NewIn(gate, 0, stateCur);
|
|
|
|
circuit_.NewIn(gate, 1, dependCur);
|
2022-01-27 08:46:57 +00:00
|
|
|
auto ifSuccess = circuit_.NewGate(OpCode(OpCode::IF_SUCCESS), 0, {gate}, GateType::EMPTY);
|
|
|
|
auto ifException = circuit_.NewGate(OpCode(OpCode::IF_EXCEPTION), 0, {gate}, GateType::EMPTY);
|
2022-01-06 02:26:19 +00:00
|
|
|
if (!bb.catchs.empty()) {
|
|
|
|
auto bbNext = bb.catchs.at(0);
|
2022-01-19 01:11:02 +00:00
|
|
|
circuit_.NewIn(bbNext->stateStart, bbNext->statePredIndex, ifException);
|
|
|
|
circuit_.NewIn(bbNext->dependStart, bbNext->statePredIndex + 1, gate);
|
|
|
|
bbNext->statePredIndex++;
|
2022-01-22 11:09:02 +00:00
|
|
|
bbNext->expandedPreds.push_back( {bb.id, pcPrev, true} );
|
2022-01-19 01:11:02 +00:00
|
|
|
ASSERT(bbNext->statePredIndex <= bbNext->numOfStatePreds);
|
2022-01-06 02:26:19 +00:00
|
|
|
} else {
|
2022-01-19 01:11:02 +00:00
|
|
|
circuit_.NewGate(OpCode(OpCode::THROW), 0,
|
2022-01-18 04:02:20 +00:00
|
|
|
{ifException, gate, gate,
|
2022-01-19 01:11:02 +00:00
|
|
|
Circuit::GetCircuitRoot(OpCode(OpCode::THROW_LIST))},
|
2022-01-27 08:46:57 +00:00
|
|
|
GateType::JS_ANY);
|
2022-01-19 01:11:02 +00:00
|
|
|
}
|
2022-01-22 11:09:02 +00:00
|
|
|
jsgateToBytecode_[gate] = {bb.id, pcPrev};
|
2022-01-19 01:11:02 +00:00
|
|
|
if (IsThrow(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
|
|
|
|
circuit_.NewGate(OpCode(OpCode::RETURN), 0,
|
|
|
|
{ifSuccess, gate, TaggedValue::VALUE_HOLE,
|
|
|
|
Circuit::GetCircuitRoot(OpCode(OpCode::RETURN_LIST))},
|
2022-01-27 08:46:57 +00:00
|
|
|
GateType::JS_ANY);
|
2022-01-19 01:11:02 +00:00
|
|
|
break;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
stateCur = ifSuccess;
|
|
|
|
dependCur = gate;
|
|
|
|
if (pcPrev == bb.end) {
|
|
|
|
auto bbNext = &graph.at(bb.id + 1);
|
2022-01-19 01:11:02 +00:00
|
|
|
circuit_.NewIn(bbNext->stateStart, bbNext->statePredIndex, stateCur);
|
|
|
|
circuit_.NewIn(bbNext->dependStart, bbNext->statePredIndex + 1, dependCur);
|
|
|
|
bbNext->statePredIndex++;
|
2022-01-22 11:09:02 +00:00
|
|
|
bbNext->expandedPreds.push_back( {bb.id, pcPrev, false} );
|
2022-01-19 01:11:02 +00:00
|
|
|
ASSERT(bbNext->statePredIndex <= bbNext->numOfStatePreds);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
} else if (IsJump(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
|
2022-01-19 01:11:02 +00:00
|
|
|
// handle conditional jump and unconditional jump bytecodes
|
2022-01-06 02:26:19 +00:00
|
|
|
if (IsCondJump(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
|
2022-01-27 08:46:57 +00:00
|
|
|
GateRef gate = 0;
|
|
|
|
if (!bytecodeInfo.vregOut.empty() || bytecodeInfo.accOut) {
|
2022-02-09 08:51:58 +00:00
|
|
|
gate = circuit_.NewGate(OpCode(OpCode::JS_BYTECODE), MachineType::I64, numValueInputs,
|
2022-01-27 08:46:57 +00:00
|
|
|
std::vector<GateRef>(2 + numValueInputs, // 2: state and depend input
|
|
|
|
Circuit::NullGate()),
|
|
|
|
GateType::JS_ANY);
|
|
|
|
} else {
|
|
|
|
gate = circuit_.NewGate(OpCode(OpCode::JS_BYTECODE), MachineType::NOVALUE, numValueInputs,
|
|
|
|
std::vector<GateRef>(2 + numValueInputs, // 2: state and depend input
|
|
|
|
Circuit::NullGate()),
|
|
|
|
GateType::EMPTY);
|
|
|
|
}
|
2022-01-06 02:26:19 +00:00
|
|
|
circuit_.NewIn(gate, 0, stateCur);
|
|
|
|
circuit_.NewIn(gate, 1, dependCur);
|
2022-01-27 08:46:57 +00:00
|
|
|
auto ifTrue = circuit_.NewGate(OpCode(OpCode::IF_TRUE), 0, {gate}, GateType::EMPTY);
|
|
|
|
auto ifFalse = circuit_.NewGate(OpCode(OpCode::IF_FALSE), 0, {gate}, GateType::EMPTY);
|
2022-01-22 11:09:02 +00:00
|
|
|
ASSERT(bb.succs.size() == 2); // 2 : 2 num of successors
|
2022-01-06 02:26:19 +00:00
|
|
|
int bitSet = 0;
|
|
|
|
for (auto &bbNext: bb.succs) {
|
|
|
|
if (bbNext->id == bb.id + 1) {
|
2022-01-19 01:11:02 +00:00
|
|
|
circuit_.NewIn(bbNext->stateStart, bbNext->statePredIndex, ifFalse);
|
|
|
|
circuit_.NewIn(bbNext->dependStart, bbNext->statePredIndex + 1, gate);
|
|
|
|
bbNext->statePredIndex++;
|
2022-01-22 11:09:02 +00:00
|
|
|
bbNext->expandedPreds.push_back( {bb.id, pcPrev, false} );
|
2022-01-19 01:11:02 +00:00
|
|
|
ASSERT(bbNext->statePredIndex <= bbNext->numOfStatePreds);
|
2022-01-06 02:26:19 +00:00
|
|
|
bitSet |= 1;
|
|
|
|
} else {
|
2022-01-19 01:11:02 +00:00
|
|
|
circuit_.NewIn(bbNext->stateStart, bbNext->statePredIndex, ifTrue);
|
|
|
|
circuit_.NewIn(bbNext->dependStart, bbNext->statePredIndex + 1, gate);
|
|
|
|
bbNext->statePredIndex++;
|
2022-01-22 11:09:02 +00:00
|
|
|
bbNext->expandedPreds.push_back( {bb.id, pcPrev, false} );
|
2022-01-19 01:11:02 +00:00
|
|
|
ASSERT(bbNext->statePredIndex <= bbNext->numOfStatePreds);
|
2022-01-22 11:09:02 +00:00
|
|
|
bitSet |= 2; // 2:verify
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-22 11:09:02 +00:00
|
|
|
ASSERT(bitSet == 3); // 3:Verify the number of successor blocks
|
|
|
|
jsgateToBytecode_[gate] = {bb.id, pcPrev};
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
ASSERT(bb.succs.size() == 1);
|
|
|
|
auto bbNext = bb.succs.at(0);
|
2022-01-19 01:11:02 +00:00
|
|
|
circuit_.NewIn(bbNext->stateStart, bbNext->statePredIndex, stateCur);
|
|
|
|
circuit_.NewIn(bbNext->dependStart, bbNext->statePredIndex + 1, dependCur);
|
|
|
|
bbNext->statePredIndex++;
|
2022-01-22 11:09:02 +00:00
|
|
|
bbNext->expandedPreds.push_back( {bb.id, pcPrev, false} );
|
2022-01-19 01:11:02 +00:00
|
|
|
ASSERT(bbNext->statePredIndex <= bbNext->numOfStatePreds);
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-01-14 09:48:52 +00:00
|
|
|
} else if (static_cast<EcmaOpcode>(bytecodeInfo.opcode) == EcmaOpcode::RETURN_DYN) {
|
2022-01-19 01:11:02 +00:00
|
|
|
// handle return.dyn bytecode
|
2022-01-06 02:26:19 +00:00
|
|
|
ASSERT(bb.succs.empty());
|
2022-01-19 01:11:02 +00:00
|
|
|
auto gate = circuit_.NewGate(OpCode(OpCode::RETURN), 0,
|
|
|
|
{stateCur, dependCur, Circuit::NullGate(),
|
|
|
|
Circuit::GetCircuitRoot(OpCode(OpCode::RETURN_LIST))},
|
2022-01-27 08:46:57 +00:00
|
|
|
GateType::EMPTY);
|
2022-01-22 11:09:02 +00:00
|
|
|
jsgateToBytecode_[gate] = {bb.id, pcPrev};
|
2022-01-06 02:26:19 +00:00
|
|
|
break;
|
2022-01-14 09:48:52 +00:00
|
|
|
} else if (static_cast<EcmaOpcode>(bytecodeInfo.opcode) == EcmaOpcode::RETURNUNDEFINED_PREF) {
|
2022-01-19 01:11:02 +00:00
|
|
|
// handle returnundefined bytecode
|
2022-01-14 09:48:52 +00:00
|
|
|
ASSERT(bb.succs.empty());
|
2022-02-09 08:51:58 +00:00
|
|
|
auto constant = circuit_.NewGate(OpCode(OpCode::CONSTANT), MachineType::I64,
|
2022-01-19 01:11:02 +00:00
|
|
|
TaggedValue::VALUE_UNDEFINED,
|
|
|
|
{Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST))},
|
2022-01-27 08:46:57 +00:00
|
|
|
GateType::JS_ANY);
|
2022-01-19 01:11:02 +00:00
|
|
|
auto gate = circuit_.NewGate(OpCode(OpCode::RETURN), 0,
|
2022-01-14 09:48:52 +00:00
|
|
|
{stateCur, dependCur, constant,
|
2022-01-19 01:11:02 +00:00
|
|
|
Circuit::GetCircuitRoot(OpCode(OpCode::RETURN_LIST))},
|
2022-01-27 08:46:57 +00:00
|
|
|
GateType::EMPTY);
|
2022-01-22 11:09:02 +00:00
|
|
|
jsgateToBytecode_[gate] = {bb.id, pcPrev};
|
2022-01-14 09:48:52 +00:00
|
|
|
break;
|
|
|
|
} else if (IsMov(static_cast<EcmaOpcode>(bytecodeInfo.opcode))) {
|
2022-01-19 01:11:02 +00:00
|
|
|
// handle mov.dyn lda.dyn sta.dyn bytecodes
|
2022-01-06 02:26:19 +00:00
|
|
|
if (pcPrev == bb.end) {
|
|
|
|
auto bbNext = &graph.at(bb.id + 1);
|
2022-01-19 01:11:02 +00:00
|
|
|
circuit_.NewIn(bbNext->stateStart, bbNext->statePredIndex, stateCur);
|
|
|
|
circuit_.NewIn(bbNext->dependStart, bbNext->statePredIndex + 1, dependCur);
|
|
|
|
bbNext->statePredIndex++;
|
2022-01-22 11:09:02 +00:00
|
|
|
bbNext->expandedPreds.push_back( {bb.id, pcPrev, false} );
|
2022-01-19 01:11:02 +00:00
|
|
|
ASSERT(bbNext->statePredIndex <= bbNext->numOfStatePreds);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-14 09:48:52 +00:00
|
|
|
} else {
|
|
|
|
abort();
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
// verification of soundness of CFG
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto &bb: graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (bb.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
ASSERT(bb.statePredIndex == bb.numOfStatePreds);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto &bb: graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (bb.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
bb.phiAcc = (bb.numOfStatePreds > 1) || (!bb.trys.empty());
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
2022-01-22 11:09:02 +00:00
|
|
|
PrintBytecodeInfo(graph);
|
2022-01-06 02:26:19 +00:00
|
|
|
#endif
|
2022-01-22 11:09:02 +00:00
|
|
|
for (const auto &[key, value]: jsgateToBytecode_) {
|
2022-01-19 01:11:02 +00:00
|
|
|
byteCodeToJSGate_[value.second] = key;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
|
|
|
|
// resolve def-site of virtual regs and set all value inputs
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto gate: circuit_.GetAllGates()) {
|
2022-01-06 02:26:19 +00:00
|
|
|
auto numInsArray = circuit_.GetOpCode(gate).GetOpCodeNumInsArray(circuit_.GetBitField(gate));
|
2022-01-22 11:09:02 +00:00
|
|
|
auto it = jsgateToBytecode_.find(gate);
|
|
|
|
if (it == jsgateToBytecode_.end()) {
|
2022-01-06 02:26:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const auto &[id, pc] = it->second;
|
2022-01-22 11:09:02 +00:00
|
|
|
auto bytecodeInfo = GetBytecodeInfo(pc);
|
2022-01-06 02:26:19 +00:00
|
|
|
[[maybe_unused]] size_t numValueInputs = (bytecodeInfo.accIn ? 1 : 0) + bytecodeInfo.vregIn.size();
|
|
|
|
[[maybe_unused]] size_t numValueOutputs = (bytecodeInfo.accOut ? 1 : 0) + bytecodeInfo.vregOut.size();
|
2022-01-22 11:09:02 +00:00
|
|
|
ASSERT(numValueInputs == numInsArray[2]); // 2 : 2 num of input value
|
2022-01-06 02:26:19 +00:00
|
|
|
ASSERT(numValueOutputs <= 1);
|
2022-01-19 01:11:02 +00:00
|
|
|
// recursive variables renaming algorithm
|
|
|
|
std::function<GateRef(size_t, const uint8_t *, uint16_t, bool)> defSiteOfReg =
|
|
|
|
[&](size_t bbId, const uint8_t *end, uint16_t reg, bool acc) -> GateRef {
|
|
|
|
// find def-site in bytecodes of basic block
|
|
|
|
auto ans = Circuit::NullGate();
|
2022-01-18 04:02:20 +00:00
|
|
|
auto &bb = graph.at(bbId);
|
|
|
|
std::vector<uint8_t *> instList;
|
|
|
|
{
|
|
|
|
auto pcIter = bb.start;
|
|
|
|
while (pcIter <= end) {
|
|
|
|
instList.push_back(pcIter);
|
2022-01-22 11:09:02 +00:00
|
|
|
auto curInfo = GetBytecodeInfo(pcIter);
|
2022-01-18 04:02:20 +00:00
|
|
|
pcIter += curInfo.offset;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-18 04:02:20 +00:00
|
|
|
std::reverse(instList.begin(), instList.end());
|
|
|
|
for (auto pcIter: instList) {
|
2022-01-22 11:09:02 +00:00
|
|
|
auto curInfo = GetBytecodeInfo(pcIter);
|
2022-01-18 04:02:20 +00:00
|
|
|
if (acc) {
|
|
|
|
if (curInfo.accOut) {
|
|
|
|
if (IsMov(static_cast<EcmaOpcode>(curInfo.opcode))) {
|
|
|
|
acc = curInfo.accIn;
|
|
|
|
if (!curInfo.vregIn.empty()) {
|
|
|
|
ASSERT(!acc);
|
|
|
|
ASSERT(curInfo.vregIn.size() == 1);
|
|
|
|
reg = curInfo.vregIn.at(0);
|
|
|
|
}
|
|
|
|
} else {
|
2022-01-19 01:11:02 +00:00
|
|
|
ans = byteCodeToJSGate_.at(pcIter);
|
2022-01-18 04:02:20 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
} else {
|
2022-01-18 04:02:20 +00:00
|
|
|
if (!curInfo.vregOut.empty() && curInfo.vregOut.at(0) == reg) {
|
|
|
|
if (IsMov(static_cast<EcmaOpcode>(curInfo.opcode))) {
|
|
|
|
acc = curInfo.accIn;
|
|
|
|
if (!curInfo.vregIn.empty()) {
|
|
|
|
ASSERT(!acc);
|
|
|
|
ASSERT(curInfo.vregIn.size() == 1);
|
|
|
|
reg = curInfo.vregIn.at(0);
|
|
|
|
}
|
|
|
|
} else {
|
2022-01-19 01:11:02 +00:00
|
|
|
ans = byteCodeToJSGate_.at(pcIter);
|
2022-01-18 04:02:20 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
// find def-site in value selectors of vregs
|
|
|
|
if (ans == Circuit::NullGate() && !acc && bb.phi.count(reg)) {
|
|
|
|
if (!bb.vregToValSelectorGate.count(reg)) {
|
2022-02-09 08:51:58 +00:00
|
|
|
auto gate = circuit_.NewGate(OpCode(OpCode::VALUE_SELECTOR), MachineType::I64,
|
2022-01-19 01:11:02 +00:00
|
|
|
bb.numOfStatePreds,
|
|
|
|
std::vector<GateRef>(
|
|
|
|
1 + bb.numOfStatePreds, Circuit::NullGate()),
|
2022-01-27 08:46:57 +00:00
|
|
|
GateType::JS_ANY);
|
2022-01-19 01:11:02 +00:00
|
|
|
bb.vregToValSelectorGate[reg] = gate;
|
2022-01-18 04:02:20 +00:00
|
|
|
circuit_.NewIn(gate, 0, bb.stateStart);
|
2022-01-27 08:46:57 +00:00
|
|
|
for (int32_t i = 0; i < bb.numOfStatePreds; ++i) {
|
2022-01-19 01:11:02 +00:00
|
|
|
auto &[predId, predPc, isException] = bb.expandedPreds.at(i);
|
2022-01-18 04:02:20 +00:00
|
|
|
circuit_.NewIn(gate, i + 1, defSiteOfReg(predId, predPc, reg, acc));
|
|
|
|
}
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
ans = bb.vregToValSelectorGate.at(reg);
|
2022-01-18 04:02:20 +00:00
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
// find def-site in value selectors of acc
|
|
|
|
if (ans == Circuit::NullGate() && acc && bb.phiAcc) {
|
|
|
|
if (bb.valueSelectorAccGate == Circuit::NullGate()) {
|
2022-02-09 08:51:58 +00:00
|
|
|
auto gate = circuit_.NewGate(OpCode(OpCode::VALUE_SELECTOR), MachineType::I64,
|
2022-01-19 01:11:02 +00:00
|
|
|
bb.numOfStatePreds,
|
|
|
|
std::vector<GateRef>(
|
|
|
|
1 + bb.numOfStatePreds, Circuit::NullGate()),
|
2022-01-27 08:46:57 +00:00
|
|
|
GateType::JS_ANY);
|
2022-01-19 01:11:02 +00:00
|
|
|
bb.valueSelectorAccGate = gate;
|
2022-01-18 04:02:20 +00:00
|
|
|
circuit_.NewIn(gate, 0, bb.stateStart);
|
|
|
|
bool hasException = false;
|
|
|
|
bool hasNonException = false;
|
2022-01-27 08:46:57 +00:00
|
|
|
for (int32_t i = 0; i < bb.numOfStatePreds; ++i) {
|
2022-01-19 01:11:02 +00:00
|
|
|
auto &[predId, predPc, isException] = bb.expandedPreds.at(i);
|
2022-01-18 04:02:20 +00:00
|
|
|
if (isException) {
|
|
|
|
hasException = true;
|
|
|
|
} else {
|
|
|
|
hasNonException = true;
|
|
|
|
}
|
|
|
|
if (isException) {
|
2022-01-19 01:11:02 +00:00
|
|
|
// exception handler will set acc
|
2022-01-18 04:02:20 +00:00
|
|
|
auto ifExceptionGate = circuit_.GetIn(bb.stateStart, i);
|
2022-01-19 01:11:02 +00:00
|
|
|
ASSERT(circuit_.GetOpCode(ifExceptionGate) == OpCode::IF_EXCEPTION);
|
2022-01-18 04:02:20 +00:00
|
|
|
circuit_.NewIn(gate, i + 1, circuit_.GetIn(ifExceptionGate, 0));
|
|
|
|
} else {
|
|
|
|
circuit_.NewIn(gate, i + 1, defSiteOfReg(predId, predPc, reg, acc));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// catch block should have only exception entries
|
|
|
|
// normal block should have only normal entries
|
|
|
|
ASSERT(!hasException || !hasNonException);
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
ans = bb.valueSelectorAccGate;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
if (ans == Circuit::NullGate() && bbId == 0) { // entry block
|
|
|
|
// find def-site in function args
|
2022-01-18 04:02:20 +00:00
|
|
|
ASSERT(!acc && reg >= offsetArgs && reg < offsetArgs + argGates.size());
|
|
|
|
return argGates.at(reg - offsetArgs);
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
if (ans == Circuit::NullGate()) {
|
|
|
|
// recursively find def-site in dominator block
|
2022-01-18 04:02:20 +00:00
|
|
|
return defSiteOfReg(bb.iDominator->id, bb.iDominator->end, reg, acc);
|
|
|
|
} else {
|
2022-01-19 01:11:02 +00:00
|
|
|
// def-site already found
|
2022-01-18 04:02:20 +00:00
|
|
|
return ans;
|
|
|
|
}
|
|
|
|
};
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t valueIdx = 0; valueIdx < numInsArray[2]; valueIdx++) { // 2: input value num
|
2022-01-06 02:26:19 +00:00
|
|
|
auto inIdx = valueIdx + numInsArray[0] + numInsArray[1];
|
2022-01-14 09:48:52 +00:00
|
|
|
if (!circuit_.IsInGateNull(gate, inIdx)) {
|
|
|
|
continue;
|
|
|
|
}
|
2022-01-06 02:26:19 +00:00
|
|
|
if (valueIdx < bytecodeInfo.vregIn.size()) {
|
|
|
|
circuit_.NewIn(gate, inIdx, defSiteOfReg(id, pc - 1, bytecodeInfo.vregIn.at(valueIdx), false));
|
|
|
|
} else {
|
|
|
|
circuit_.NewIn(gate, inIdx, defSiteOfReg(id, pc - 1, 0, true));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if ECMASCRIPT_ENABLE_TS_AOT_PRINT
|
2022-01-18 04:02:20 +00:00
|
|
|
circuit_.PrintAllGates(*this);
|
2022-01-06 02:26:19 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::PrintCollectBlockInfo(std::vector<CfgInfo> &bytecodeBlockInfos)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-01-19 01:11:02 +00:00
|
|
|
for (auto iter = bytecodeBlockInfos.begin(); iter != bytecodeBlockInfos.end(); iter++) {
|
|
|
|
std::cout << "offset: " << static_cast<const void *>(iter->pc) << " splitKind: " <<
|
|
|
|
static_cast<int32_t>(iter->splitKind) << " successor are: ";
|
|
|
|
auto &vec = iter->succs;
|
2022-01-18 04:02:20 +00:00
|
|
|
for (size_t i = 0; i < vec.size(); i++) {
|
|
|
|
std::cout << static_cast<const void *>(vec[i]) << " , ";
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-18 04:02:20 +00:00
|
|
|
std::cout << "" << std::endl;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
std::cout << "-----------------------------------------------------------------------" << std::endl;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::PrintGraph(std::vector<BytecodeRegion> &graph)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t i = 0; i < graph.size(); i++) {
|
|
|
|
if (graph[i].isDead) {
|
|
|
|
std::cout << "BB_" << graph[i].id << ": ;predsId= invalid BB" << std::endl;
|
|
|
|
std::cout << "curStartPc: " << static_cast<const void *>(graph[i].start) <<
|
|
|
|
" curEndPc: " << static_cast<const void *>(graph[i].end) << std::endl;
|
2022-01-06 02:26:19 +00:00
|
|
|
continue;
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
std::cout << "BB_" << graph[i].id << ": ;predsId= ";
|
|
|
|
for (size_t k = 0; k < graph[i].preds.size(); ++k) {
|
|
|
|
std::cout << graph[i].preds[k]->id << ", ";
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
std::cout << "" << std::endl;
|
2022-01-19 01:11:02 +00:00
|
|
|
std::cout << "curStartPc: " << static_cast<const void *>(graph[i].start) <<
|
|
|
|
" curEndPc: " << static_cast<const void *>(graph[i].end) << std::endl;
|
2022-01-06 02:26:19 +00:00
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t j = 0; j < graph[i].preds.size(); j++) {
|
|
|
|
std::cout << "predsStartPc: " << static_cast<const void *>(graph[i].preds[j]->start) <<
|
|
|
|
" predsEndPc: " << static_cast<const void *>(graph[i].preds[j]->end) << std::endl;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t j = 0; j < graph[i].succs.size(); j++) {
|
|
|
|
std::cout << "succesStartPc: " << static_cast<const void *>(graph[i].succs[j]->start) <<
|
|
|
|
" succesEndPc: " << static_cast<const void *>(graph[i].succs[j]->end) << std::endl;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-01-18 04:02:20 +00:00
|
|
|
std::cout << "succesId: ";
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t j = 0; j < graph[i].succs.size(); j++) {
|
|
|
|
std::cout << graph[i].succs[j]->id << ", ";
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
std::cout << "" << std::endl;
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t j = 0; j < graph[i].catchs.size(); j++) {
|
|
|
|
std::cout << "catchStartPc: " << static_cast<const void *>(graph[i].catchs[j]->start) <<
|
|
|
|
" catchEndPc: " << static_cast<const void *>(graph[i].catchs[j]->end) << std::endl;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
for (size_t j = 0; j < graph[i].immDomBlocks.size(); j++) {
|
|
|
|
std::cout << "dominate block id: " << graph[i].immDomBlocks[j]->id << " startPc: " <<
|
|
|
|
static_cast<const void *>(graph[i].immDomBlocks[j]->start) << " endPc: " <<
|
|
|
|
static_cast<const void *>(graph[i].immDomBlocks[j]->end) << std::endl;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
if (graph[i].iDominator) {
|
|
|
|
std::cout << "current block " << graph[i].id <<
|
|
|
|
" immediate dominator is " << graph[i].iDominator->id << std::endl;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
std::cout << "current block " << graph[i].id << " dominace Frontiers: ";
|
|
|
|
for (const auto &frontier: graph[i].domFrontiers) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << frontier->id << " , ";
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
|
2022-01-19 01:11:02 +00:00
|
|
|
std::cout << "current block " << graph[i].id << " phi variable: ";
|
|
|
|
for (auto variable: graph[i].phi) {
|
2022-01-18 04:02:20 +00:00
|
|
|
std::cout << variable << " , ";
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
2022-01-19 01:11:02 +00:00
|
|
|
std::cout << "-------------------------------------------------------" << std::endl;
|
2022-01-06 02:26:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::PrintBytecodeInfo(std::vector<BytecodeRegion> &graph)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto &bb: graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (bb.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
auto pc = bb.start;
|
|
|
|
std::cout << "BB_" << bb.id << ": " << std::endl;
|
|
|
|
while (pc <= bb.end) {
|
2022-01-22 11:09:02 +00:00
|
|
|
auto curInfo = GetBytecodeInfo(pc);
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << "Inst_" << static_cast<int>(curInfo.opcode) << ": ";
|
|
|
|
std::cout << "In=[";
|
|
|
|
if (curInfo.accIn) {
|
|
|
|
std::cout << "acc" << ",";
|
|
|
|
}
|
2022-01-18 04:02:20 +00:00
|
|
|
for (const auto &in: curInfo.vregIn) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << in << ",";
|
|
|
|
}
|
|
|
|
std::cout << "] Out=[";
|
|
|
|
if (curInfo.accOut) {
|
|
|
|
std::cout << "acc" << ",";
|
|
|
|
}
|
2022-01-18 04:02:20 +00:00
|
|
|
for (const auto &out: curInfo.vregOut) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << out << ",";
|
|
|
|
}
|
|
|
|
std::cout << "]";
|
|
|
|
std::cout << std::endl;
|
|
|
|
pc += curInfo.offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-22 11:09:02 +00:00
|
|
|
void BytecodeCircuitBuilder::PrintBBInfo(std::vector<BytecodeRegion> &graph)
|
2022-01-06 02:26:19 +00:00
|
|
|
{
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto &bb: graph) {
|
2022-01-06 02:26:19 +00:00
|
|
|
if (bb.isDead) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
std::cout << "------------------------" << std::endl;
|
|
|
|
std::cout << "block: " << bb.id << std::endl;
|
|
|
|
std::cout << "preds: ";
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto pred: bb.preds) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << pred->id << " , ";
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
std::cout << "succs: ";
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto succ: bb.succs) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << succ->id << " , ";
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
std::cout << "catchs: ";
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto catchBlock: bb.catchs) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << catchBlock->id << " , ";
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
std::cout << "trys: ";
|
2022-01-18 04:02:20 +00:00
|
|
|
for (auto tryBlock: bb.trys) {
|
2022-01-06 02:26:19 +00:00
|
|
|
std::cout << tryBlock->id << " , ";
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
}
|
|
|
|
}
|
2022-01-19 01:11:02 +00:00
|
|
|
} // namespace panda::ecmascript::kungfu
|