mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2024-10-07 08:03:29 +00:00
!1970 Decouple the method of collecting MethodPc in the Compiler from the PandaFileTranslator class
Merge pull request !1970 from weng-xi/dev_remove_translator
This commit is contained in:
commit
50f5ed60a1
@ -52,6 +52,7 @@ source_set("libark_jsoptimizer_set") {
|
||||
"builtins/builtins_call_signature.cpp",
|
||||
"builtins/builtins_stubs.cpp",
|
||||
"bytecode_circuit_builder.cpp",
|
||||
"bytecode_info_collector.cpp",
|
||||
"call_signature.cpp",
|
||||
"circuit.cpp",
|
||||
"circuit_builder.cpp",
|
||||
|
@ -22,35 +22,16 @@
|
||||
namespace panda::ecmascript::kungfu {
|
||||
void BytecodeCircuitBuilder::BytecodeToCircuit()
|
||||
{
|
||||
auto curPc = pcArray_.front();
|
||||
auto prePc = curPc;
|
||||
std::map<uint8_t *, uint8_t *> byteCodeCurPrePc;
|
||||
std::vector<CfgInfo> bytecodeBlockInfos;
|
||||
int32_t offsetIndex = 1;
|
||||
auto startPc = curPc;
|
||||
bytecodeBlockInfos.emplace_back(startPc, SplitKind::START, std::vector<uint8_t *>(1, startPc));
|
||||
byteCodeCurPrePc[curPc] = prePc;
|
||||
pcToBCOffset_[curPc]=offsetIndex++;
|
||||
for (size_t i = 1; i < pcArray_.size() - 1; i++) {
|
||||
curPc = pcArray_[i];
|
||||
byteCodeCurPrePc[curPc] = prePc;
|
||||
pcToBCOffset_[curPc]=offsetIndex++;
|
||||
prePc = curPc;
|
||||
CollectBytecodeBlockInfo(curPc, bytecodeBlockInfos);
|
||||
}
|
||||
// handle empty
|
||||
uint8_t *emptyPc = pcArray_.back();
|
||||
byteCodeCurPrePc[emptyPc] = prePc;
|
||||
pcToBCOffset_[emptyPc] = offsetIndex++;
|
||||
std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> exceptionInfo;
|
||||
|
||||
// collect try catch block info
|
||||
auto exceptionInfo = CollectTryCatchBlockInfo(byteCodeCurPrePc, bytecodeBlockInfos);
|
||||
CollectTryCatchBlockInfo(exceptionInfo);
|
||||
|
||||
// Complete bytecode block Information
|
||||
CompleteBytecodeBlockInfo(byteCodeCurPrePc, bytecodeBlockInfos);
|
||||
CompleteBytecodeBlockInfo();
|
||||
|
||||
// Building the basic block diagram of bytecode
|
||||
BuildBasicBlocks(exceptionInfo, bytecodeBlockInfos, byteCodeCurPrePc);
|
||||
BuildBasicBlocks(exceptionInfo);
|
||||
}
|
||||
|
||||
void BytecodeCircuitBuilder::CollectBytecodeBlockInfo(uint8_t *pc, std::vector<CfgInfo> &bytecodeBlockInfos)
|
||||
@ -152,14 +133,14 @@ void BytecodeCircuitBuilder::CollectBytecodeBlockInfo(uint8_t *pc, std::vector<C
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> BytecodeCircuitBuilder::CollectTryCatchBlockInfo(
|
||||
std::map<uint8_t *, uint8_t*> &byteCodeCurPrePc, std::vector<CfgInfo> &bytecodeBlockInfos)
|
||||
void BytecodeCircuitBuilder::CollectTryCatchBlockInfo(std::map<std::pair<uint8_t *, uint8_t *>,
|
||||
std::vector<uint8_t *>> &byteCodeException)
|
||||
{
|
||||
// try contains many catch
|
||||
std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> byteCodeException;
|
||||
panda_file::MethodDataAccessor mda(*pf_, method_->GetMethodId());
|
||||
panda_file::CodeDataAccessor cda(*pf_, mda.GetCodeId().value());
|
||||
cda.EnumerateTryBlocks([this, &byteCodeCurPrePc, &bytecodeBlockInfos, &byteCodeException](
|
||||
|
||||
cda.EnumerateTryBlocks([this, &byteCodeException](
|
||||
panda_file::CodeDataAccessor::TryBlock &try_block) {
|
||||
auto tryStartOffset = try_block.GetStartPc();
|
||||
auto tryEndOffset = try_block.GetStartPc() + try_block.GetLength();
|
||||
@ -177,32 +158,32 @@ std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> BytecodeCircui
|
||||
// Check whether the previous block of the try block exists.
|
||||
// If yes, add the current block; otherwise, create a new block.
|
||||
bool flag = false;
|
||||
for (size_t i = 0; i < bytecodeBlockInfos.size(); i++) {
|
||||
if (bytecodeBlockInfos[i].splitKind == SplitKind::START) {
|
||||
for (size_t i = 0; i < bytecodeBlockInfos_.size(); i++) {
|
||||
if (bytecodeBlockInfos_[i].splitKind == SplitKind::START) {
|
||||
continue;
|
||||
}
|
||||
if (bytecodeBlockInfos[i].pc == byteCodeCurPrePc[tryStartPc]) {
|
||||
if (bytecodeBlockInfos_[i].pc == byteCodeCurPrePc_.at(tryStartPc)) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
// pre block
|
||||
bytecodeBlockInfos.emplace_back(byteCodeCurPrePc[tryStartPc], SplitKind::END,
|
||||
std::vector<uint8_t *>(1, tryStartPc));
|
||||
bytecodeBlockInfos_.emplace_back(byteCodeCurPrePc_.at(tryStartPc), SplitKind::END,
|
||||
std::vector<uint8_t *>(1, tryStartPc));
|
||||
}
|
||||
// try block
|
||||
bytecodeBlockInfos.emplace_back(tryStartPc, SplitKind::START, std::vector<uint8_t *>(1, tryStartPc));
|
||||
bytecodeBlockInfos_.emplace_back(tryStartPc, SplitKind::START, std::vector<uint8_t *>(1, tryStartPc));
|
||||
flag = false;
|
||||
for (size_t i = 0; i < bytecodeBlockInfos.size(); i++) {
|
||||
if (bytecodeBlockInfos[i].splitKind == SplitKind::START) {
|
||||
for (size_t i = 0; i < bytecodeBlockInfos_.size(); i++) {
|
||||
if (bytecodeBlockInfos_[i].splitKind == SplitKind::START) {
|
||||
continue;
|
||||
}
|
||||
if (bytecodeBlockInfos[i].pc == byteCodeCurPrePc[tryEndPc]) {
|
||||
auto &succs = bytecodeBlockInfos[i].succs;
|
||||
auto iter = std::find(succs.cbegin(), succs.cend(), bytecodeBlockInfos[i].pc);
|
||||
if (bytecodeBlockInfos_[i].pc == byteCodeCurPrePc_.at(tryEndPc)) {
|
||||
auto &succs = bytecodeBlockInfos_[i].succs;
|
||||
auto iter = std::find(succs.cbegin(), succs.cend(), bytecodeBlockInfos_[i].pc);
|
||||
if (iter == succs.cend()) {
|
||||
auto opcode = static_cast<EcmaOpcode>(*(bytecodeBlockInfos[i].pc));
|
||||
auto opcode = static_cast<EcmaOpcode>(*(bytecodeBlockInfos_[i].pc));
|
||||
switch (opcode) {
|
||||
case EcmaOpcode::JMP_IMM8:
|
||||
case EcmaOpcode::JMP_IMM16:
|
||||
@ -227,47 +208,45 @@ std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> BytecodeCircui
|
||||
}
|
||||
}
|
||||
if (!flag) {
|
||||
bytecodeBlockInfos.emplace_back(byteCodeCurPrePc[tryEndPc], SplitKind::END,
|
||||
std::vector<uint8_t *>(1, tryEndPc));
|
||||
bytecodeBlockInfos_.emplace_back(byteCodeCurPrePc_.at(tryEndPc), SplitKind::END,
|
||||
std::vector<uint8_t *>(1, tryEndPc));
|
||||
}
|
||||
bytecodeBlockInfos.emplace_back(tryEndPc, SplitKind::START, std::vector<uint8_t *>(1, tryEndPc)); // next block
|
||||
bytecodeBlockInfos_.emplace_back(tryEndPc, SplitKind::START, std::vector<uint8_t *>(1, tryEndPc)); // next block
|
||||
return true;
|
||||
});
|
||||
return byteCodeException;
|
||||
}
|
||||
|
||||
void BytecodeCircuitBuilder::CompleteBytecodeBlockInfo(std::map<uint8_t *, uint8_t *> &byteCodeCurPrePc,
|
||||
std::vector<CfgInfo> &bytecodeBlockInfos)
|
||||
void BytecodeCircuitBuilder::CompleteBytecodeBlockInfo()
|
||||
{
|
||||
std::sort(bytecodeBlockInfos.begin(), bytecodeBlockInfos.end());
|
||||
std::sort(bytecodeBlockInfos_.begin(), bytecodeBlockInfos_.end());
|
||||
|
||||
if (IsLogEnabled()) {
|
||||
PrintCollectBlockInfo(bytecodeBlockInfos);
|
||||
PrintCollectBlockInfo(bytecodeBlockInfos_);
|
||||
}
|
||||
|
||||
// Deduplicate
|
||||
auto deduplicateIndex = std::unique(bytecodeBlockInfos.begin(), bytecodeBlockInfos.end());
|
||||
bytecodeBlockInfos.erase(deduplicateIndex, bytecodeBlockInfos.end());
|
||||
auto deduplicateIndex = std::unique(bytecodeBlockInfos_.begin(), bytecodeBlockInfos_.end());
|
||||
bytecodeBlockInfos_.erase(deduplicateIndex, bytecodeBlockInfos_.end());
|
||||
|
||||
// Supplementary block information
|
||||
std::vector<uint8_t *> endBlockPc;
|
||||
std::vector<uint8_t *> startBlockPc;
|
||||
for (size_t i = 0; i < bytecodeBlockInfos.size() - 1; i++) {
|
||||
if (bytecodeBlockInfos[i].splitKind == bytecodeBlockInfos[i + 1].splitKind &&
|
||||
bytecodeBlockInfos[i].splitKind == SplitKind::START) {
|
||||
auto prePc = byteCodeCurPrePc[bytecodeBlockInfos[i + 1].pc];
|
||||
for (size_t i = 0; i < bytecodeBlockInfos_.size() - 1; i++) {
|
||||
if (bytecodeBlockInfos_[i].splitKind == bytecodeBlockInfos_[i + 1].splitKind &&
|
||||
bytecodeBlockInfos_[i].splitKind == SplitKind::START) {
|
||||
auto prePc = byteCodeCurPrePc_.at(bytecodeBlockInfos_[i + 1].pc);
|
||||
endBlockPc.emplace_back(prePc); // Previous instruction of current instruction
|
||||
endBlockPc.emplace_back(bytecodeBlockInfos[i + 1].pc); // current instruction
|
||||
endBlockPc.emplace_back(bytecodeBlockInfos_[i + 1].pc); // current instruction
|
||||
continue;
|
||||
}
|
||||
if (bytecodeBlockInfos[i].splitKind == bytecodeBlockInfos[i + 1].splitKind &&
|
||||
bytecodeBlockInfos[i].splitKind == SplitKind::END) {
|
||||
auto tempPc = bytecodeBlockInfos[i].pc;
|
||||
auto findItem = std::find_if(byteCodeCurPrePc.cbegin(), byteCodeCurPrePc.cend(),
|
||||
if (bytecodeBlockInfos_[i].splitKind == bytecodeBlockInfos_[i + 1].splitKind &&
|
||||
bytecodeBlockInfos_[i].splitKind == SplitKind::END) {
|
||||
auto tempPc = bytecodeBlockInfos_[i].pc;
|
||||
auto findItem = std::find_if(byteCodeCurPrePc_.cbegin(), byteCodeCurPrePc_.cend(),
|
||||
[tempPc](const std::map<uint8_t *, uint8_t *>::value_type item) {
|
||||
return item.second == tempPc;
|
||||
});
|
||||
if (findItem != byteCodeCurPrePc.cend()) {
|
||||
if (findItem != byteCodeCurPrePc_.cend()) {
|
||||
startBlockPc.emplace_back((*findItem).first);
|
||||
}
|
||||
}
|
||||
@ -275,54 +254,52 @@ void BytecodeCircuitBuilder::CompleteBytecodeBlockInfo(std::map<uint8_t *, uint8
|
||||
|
||||
// Supplementary end block info
|
||||
for (auto iter = endBlockPc.cbegin(); iter != endBlockPc.cend(); iter += 2) { // 2: index
|
||||
bytecodeBlockInfos.emplace_back(*iter, SplitKind::END,
|
||||
bytecodeBlockInfos_.emplace_back(*iter, SplitKind::END,
|
||||
std::vector<uint8_t *>(1, *(iter + 1)));
|
||||
}
|
||||
// Supplementary start block info
|
||||
for (auto iter = startBlockPc.cbegin(); iter != startBlockPc.cend(); iter++) {
|
||||
bytecodeBlockInfos.emplace_back(*iter, SplitKind::START, std::vector<uint8_t *>(1, *iter));
|
||||
bytecodeBlockInfos_.emplace_back(*iter, SplitKind::START, std::vector<uint8_t *>(1, *iter));
|
||||
}
|
||||
|
||||
// Deduplicate successor
|
||||
for (size_t i = 0; i < bytecodeBlockInfos.size(); i++) {
|
||||
if (bytecodeBlockInfos[i].splitKind == SplitKind::END) {
|
||||
std::set<uint8_t *> tempSet(bytecodeBlockInfos[i].succs.cbegin(),
|
||||
bytecodeBlockInfos[i].succs.cend());
|
||||
bytecodeBlockInfos[i].succs.assign(tempSet.cbegin(), tempSet.cend());
|
||||
for (size_t i = 0; i < bytecodeBlockInfos_.size(); i++) {
|
||||
if (bytecodeBlockInfos_[i].splitKind == SplitKind::END) {
|
||||
std::set<uint8_t *> tempSet(bytecodeBlockInfos_[i].succs.cbegin(),
|
||||
bytecodeBlockInfos_[i].succs.cend());
|
||||
bytecodeBlockInfos_[i].succs.assign(tempSet.cbegin(), tempSet.cend());
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(bytecodeBlockInfos.begin(), bytecodeBlockInfos.end());
|
||||
std::sort(bytecodeBlockInfos_.begin(), bytecodeBlockInfos_.end());
|
||||
|
||||
// handling jumps to an empty block
|
||||
auto endPc = bytecodeBlockInfos[bytecodeBlockInfos.size() - 1].pc;
|
||||
auto iter = --byteCodeCurPrePc.cend();
|
||||
auto endPc = bytecodeBlockInfos_[bytecodeBlockInfos_.size() - 1].pc;
|
||||
auto iter = --byteCodeCurPrePc_.cend();
|
||||
if (endPc == iter->first) {
|
||||
bytecodeBlockInfos.emplace_back(endPc, SplitKind::END, std::vector<uint8_t *>(1, endPc));
|
||||
bytecodeBlockInfos_.emplace_back(endPc, SplitKind::END, std::vector<uint8_t *>(1, endPc));
|
||||
}
|
||||
// Deduplicate
|
||||
deduplicateIndex = std::unique(bytecodeBlockInfos.begin(), bytecodeBlockInfos.end());
|
||||
bytecodeBlockInfos.erase(deduplicateIndex, bytecodeBlockInfos.end());
|
||||
deduplicateIndex = std::unique(bytecodeBlockInfos_.begin(), bytecodeBlockInfos_.end());
|
||||
bytecodeBlockInfos_.erase(deduplicateIndex, bytecodeBlockInfos_.end());
|
||||
|
||||
if (IsLogEnabled()) {
|
||||
PrintCollectBlockInfo(bytecodeBlockInfos);
|
||||
PrintCollectBlockInfo(bytecodeBlockInfos_);
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeCircuitBuilder::BuildBasicBlocks(std::map<std::pair<uint8_t *, uint8_t *>,
|
||||
std::vector<uint8_t *>> &exception,
|
||||
std::vector<CfgInfo> &bytecodeBlockInfo,
|
||||
[[maybe_unused]] std::map<uint8_t *, uint8_t *> &byteCodeCurPrePc)
|
||||
std::vector<uint8_t *>> &exception)
|
||||
{
|
||||
std::map<uint8_t *, BytecodeRegion *> startPcToBB; // [start, bb]
|
||||
std::map<uint8_t *, BytecodeRegion *> endPcToBB; // [end, bb]
|
||||
graph_.resize(bytecodeBlockInfo.size() / 2); // 2 : half size
|
||||
graph_.resize(bytecodeBlockInfos_.size() / 2); // 2 : half size
|
||||
// build basic block
|
||||
int blockId = 0;
|
||||
int index = 0;
|
||||
for (size_t i = 0; i < bytecodeBlockInfo.size() - 1; i += 2) { // 2:index
|
||||
auto startPc = bytecodeBlockInfo[i].pc;
|
||||
auto endPc = bytecodeBlockInfo[i + 1].pc;
|
||||
for (size_t i = 0; i < bytecodeBlockInfos_.size() - 1; i += 2) { // 2:index
|
||||
auto startPc = bytecodeBlockInfos_[i].pc;
|
||||
auto endPc = bytecodeBlockInfos_[i + 1].pc;
|
||||
auto block = &graph_[index++];
|
||||
block->id = blockId++;
|
||||
block->start = startPc;
|
||||
@ -334,12 +311,12 @@ void BytecodeCircuitBuilder::BuildBasicBlocks(std::map<std::pair<uint8_t *, uint
|
||||
}
|
||||
|
||||
// add block associate
|
||||
for (size_t i = 0; i < bytecodeBlockInfo.size(); i++) {
|
||||
if (bytecodeBlockInfo[i].splitKind == SplitKind::START) {
|
||||
for (size_t i = 0; i < bytecodeBlockInfos_.size(); i++) {
|
||||
if (bytecodeBlockInfos_[i].splitKind == SplitKind::START) {
|
||||
continue;
|
||||
}
|
||||
auto curPc = bytecodeBlockInfo[i].pc;
|
||||
auto &successors = bytecodeBlockInfo[i].succs;
|
||||
auto curPc = bytecodeBlockInfos_[i].pc;
|
||||
auto &successors = bytecodeBlockInfos_[i].succs;
|
||||
for (size_t j = 0; j < successors.size(); j++) {
|
||||
if (successors[j] == curPc) {
|
||||
continue;
|
||||
@ -2614,7 +2591,7 @@ void BytecodeCircuitBuilder::AddBytecodeOffsetInfo(GateRef &gate, const Bytecode
|
||||
{
|
||||
if (info.IsCall()) {
|
||||
auto bcOffset = circuit_.NewGate(OpCode(OpCode::CONSTANT), MachineType::I64,
|
||||
pcToBCOffset_[pc],
|
||||
pcToBCOffset_.at(pc),
|
||||
{Circuit::GetCircuitRoot(OpCode(OpCode::CONSTANT_LIST))},
|
||||
GateType::NJSValue());
|
||||
gateAcc_.NewIn(gate, bcOffsetIndex, bcOffset);
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "ecmascript/compiler/argument_accessor.h"
|
||||
#include "ecmascript/compiler/circuit.h"
|
||||
#include "ecmascript/compiler/type_recorder.h"
|
||||
#include "ecmascript/compiler/bytecode_info_collector.h"
|
||||
#include "ecmascript/interpreter/interpreter-inl.h"
|
||||
#include "ecmascript/js_method.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile.h"
|
||||
@ -443,21 +444,22 @@ enum BytecodeOffset {
|
||||
|
||||
class BytecodeCircuitBuilder {
|
||||
public:
|
||||
explicit BytecodeCircuitBuilder(const BytecodeTranslationInfo &translationInfo, size_t index,
|
||||
explicit BytecodeCircuitBuilder(const JSPandaFile *jsPandaFile,
|
||||
JSHandle<JSTaggedValue> &constantPool,
|
||||
BytecodeInfoCollector::MethodPcInfo &methodPCInfo,
|
||||
TSManager *tsManager, bool enableLog)
|
||||
: tsManager_(tsManager), file_(translationInfo.jsPandaFile), pf_(translationInfo.jsPandaFile->GetPandaFile()),
|
||||
method_(translationInfo.methodPcInfos[index].method),
|
||||
pcArray_(translationInfo.methodPcInfos[index].pcArray),
|
||||
constantPool_(translationInfo.constantPool),
|
||||
gateAcc_(&circuit_), argAcc_(&circuit_, method_),
|
||||
: tsManager_(tsManager), file_(jsPandaFile), pf_(jsPandaFile->GetPandaFile()),
|
||||
method_(methodPCInfo.method), constantPool_(constantPool), gateAcc_(&circuit_), argAcc_(&circuit_, method_),
|
||||
typeRecorder_(method_, tsManager), hasTypes_(file_->HasTSTypes()),
|
||||
enableLog_(enableLog)
|
||||
enableLog_(enableLog), pcToBCOffset_(methodPCInfo.pcToBCOffset),
|
||||
byteCodeCurPrePc_(methodPCInfo.byteCodeCurPrePc), bytecodeBlockInfos_(methodPCInfo.bytecodeBlockInfos)
|
||||
{
|
||||
}
|
||||
~BytecodeCircuitBuilder() = default;
|
||||
NO_COPY_SEMANTIC(BytecodeCircuitBuilder);
|
||||
NO_MOVE_SEMANTIC(BytecodeCircuitBuilder);
|
||||
void PUBLIC_API BytecodeToCircuit();
|
||||
static void PUBLIC_API CollectBytecodeBlockInfo(uint8_t *pc, std::vector<CfgInfo> &bytecodeBlockInfos);
|
||||
|
||||
[[nodiscard]] kungfu::Circuit* GetCircuit()
|
||||
{
|
||||
@ -534,17 +536,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void PUBLIC_API CollectBytecodeBlockInfo(uint8_t* pc, std::vector<CfgInfo> &bytecodeBlockInfos);
|
||||
|
||||
std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> CollectTryCatchBlockInfo(
|
||||
std::map<uint8_t *, uint8_t*> &byteCodeCurPrePc, std::vector<CfgInfo> &bytecodeBlockInfos);
|
||||
|
||||
void CompleteBytecodeBlockInfo(std::map<uint8_t *, uint8_t*> &byteCodeCurPrePc,
|
||||
std::vector<CfgInfo> &bytecodeBlockInfos);
|
||||
|
||||
void BuildBasicBlocks(std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> &exception,
|
||||
std::vector<CfgInfo> &bytecodeBlockInfo,
|
||||
std::map<uint8_t *, uint8_t*> &byteCodeCurPrePc);
|
||||
void CollectTryCatchBlockInfo(std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> &Exception);
|
||||
void CompleteBytecodeBlockInfo();
|
||||
void BuildBasicBlocks(std::map<std::pair<uint8_t *, uint8_t *>, std::vector<uint8_t *>> &Exception);
|
||||
void ComputeDominatorTree();
|
||||
void BuildImmediateDominator(const std::vector<size_t> &immDom);
|
||||
void ComputeDomFrontiers(const std::vector<size_t> &immDom);
|
||||
@ -590,15 +584,16 @@ private:
|
||||
const JSPandaFile *file_ {nullptr};
|
||||
const panda_file::File *pf_ {nullptr};
|
||||
const JSMethod *method_ {nullptr};
|
||||
const std::vector<uint8_t *> pcArray_;
|
||||
JSHandle<JSTaggedValue> constantPool_;
|
||||
GateAccessor gateAcc_;
|
||||
ArgumentAccessor argAcc_;
|
||||
TypeRecorder typeRecorder_;
|
||||
bool hasTypes_ {false};
|
||||
bool enableLog_ {false};
|
||||
std::map<const uint8_t *, int32_t> pcToBCOffset_;
|
||||
std::vector<kungfu::GateRef> suspendAndResumeGates_ {};
|
||||
const std::map<const uint8_t *, int32_t> &pcToBCOffset_;
|
||||
const std::map<uint8_t *, uint8_t *> &byteCodeCurPrePc_;
|
||||
std::vector<CfgInfo> &bytecodeBlockInfos_;
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
|
||||
|
395
ecmascript/compiler/bytecode_info_collector.cpp
Normal file
395
ecmascript/compiler/bytecode_info_collector.cpp
Normal file
@ -0,0 +1,395 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
#include "ecmascript/compiler/bytecode_info_collector.h"
|
||||
|
||||
#include "ecmascript/jspandafile/js_pandafile_manager.h"
|
||||
#include "ecmascript/compiler/bytecode_circuit_builder.h"
|
||||
#include "libpandafile/class_data_accessor-inl.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
const JSPandaFile *BytecodeInfoCollector::LoadInfoFromPf(const CString &filename, const std::string_view &entryPoint,
|
||||
std::vector<MethodPcInfo>& methodPcInfos)
|
||||
{
|
||||
JSPandaFileManager *jsPandaFileManager = JSPandaFileManager::GetInstance();
|
||||
JSPandaFile *jsPandaFile = jsPandaFileManager->OpenJSPandaFile(filename);
|
||||
if (jsPandaFile == nullptr) {
|
||||
LOG_ECMA(ERROR) << "open file " << filename << " error";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CString methodName;
|
||||
auto pos = entryPoint.find_last_of("::");
|
||||
if (pos != std::string_view::npos) {
|
||||
methodName = entryPoint.substr(pos + 1);
|
||||
} else {
|
||||
// default use func_main_0 as entryPoint
|
||||
methodName = JSPandaFile::ENTRY_FUNCTION_NAME;
|
||||
}
|
||||
|
||||
ProcessClasses(jsPandaFile, methodName, methodPcInfos);
|
||||
|
||||
return jsPandaFile;
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::ProcessClasses(JSPandaFile *jsPandaFile, const CString &methodName,
|
||||
std::vector<MethodPcInfo> &methodPcInfos)
|
||||
{
|
||||
ASSERT(jsPandaFile != nullptr && jsPandaFile->GetMethods() != nullptr);
|
||||
JSMethod *methods = jsPandaFile->GetMethods();
|
||||
const panda_file::File *pf = jsPandaFile->GetPandaFile();
|
||||
size_t methodIdx = 0;
|
||||
panda_file::File::StringData sd = {static_cast<uint32_t>(methodName.size()),
|
||||
reinterpret_cast<const uint8_t *>(methodName.c_str())};
|
||||
std::set<const uint8_t *> processedInsns;
|
||||
Span<const uint32_t> classIndexes = jsPandaFile->GetClasses();
|
||||
for (const uint32_t index : classIndexes) {
|
||||
panda_file::File::EntityId classId(index);
|
||||
if (pf->IsExternal(classId)) {
|
||||
continue;
|
||||
}
|
||||
panda_file::ClassDataAccessor cda(*pf, classId);
|
||||
cda.EnumerateMethods([methods, &methodIdx, pf, &processedInsns, jsPandaFile, &methodPcInfos, &sd]
|
||||
(panda_file::MethodDataAccessor &mda) {
|
||||
auto codeId = mda.GetCodeId();
|
||||
ASSERT(codeId.has_value());
|
||||
|
||||
JSMethod *method = methods + (methodIdx++);
|
||||
panda_file::CodeDataAccessor codeDataAccessor(*pf, codeId.value());
|
||||
uint32_t codeSize = codeDataAccessor.GetCodeSize();
|
||||
|
||||
uint32_t mainMethodIndex = jsPandaFile->GetMainMethodIndex();
|
||||
if (mainMethodIndex == 0 && pf->GetStringData(mda.GetNameId()) == sd) {
|
||||
jsPandaFile->UpdateMainMethodIndex(mda.GetMethodId().GetOffset());
|
||||
}
|
||||
|
||||
new (method) JSMethod(jsPandaFile, mda.GetMethodId());
|
||||
method->SetHotnessCounter(EcmaInterpreter::METHOD_HOTNESS_THRESHOLD);
|
||||
method->InitializeCallField(codeDataAccessor.GetNumVregs(), codeDataAccessor.GetNumArgs());
|
||||
const uint8_t *insns = codeDataAccessor.GetInstructions();
|
||||
if (processedInsns.find(insns) == processedInsns.end()) {
|
||||
processedInsns.insert(insns);
|
||||
CollectMethodPcs(jsPandaFile, codeSize, insns, method, methodPcInfos);
|
||||
}
|
||||
jsPandaFile->SetMethodToMap(method);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::FixOpcode(uint8_t *pc)
|
||||
{
|
||||
auto opcode = static_cast<BytecodeInstruction::Opcode>(*pc);
|
||||
|
||||
switch (opcode) {
|
||||
case BytecodeInstruction::Opcode::MOV_V4_V4:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::MOV_V4_V4);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::MOV_DYN_V8_V8:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::MOV_DYN_V8_V8);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::MOV_DYN_V16_V16:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::MOV_DYN_V16_V16);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::LDA_STR_ID32:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::LDA_STR_ID32);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::JMP_IMM8:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::JMP_IMM8);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::JMP_IMM16:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::JMP_IMM16);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::JMP_IMM32:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::JMP_IMM32);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::JEQZ_IMM8:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::JEQZ_IMM8);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::JEQZ_IMM16:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::JEQZ_IMM16);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::JNEZ_IMM8:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::JNEZ_IMM8);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::JNEZ_IMM16:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::JNEZ_IMM16);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::LDA_DYN_V8:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::LDA_DYN_V8);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::STA_DYN_V8:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::STA_DYN_V8);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::LDAI_DYN_IMM32:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::LDAI_DYN_IMM32);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::FLDAI_DYN_IMM64:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::FLDAI_DYN_IMM64);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::RETURN_DYN:
|
||||
*pc = static_cast<uint8_t>(EcmaOpcode::RETURN_DYN);
|
||||
break;
|
||||
default:
|
||||
if (*pc != static_cast<uint8_t>(BytecodeInstruction::Opcode::ECMA_LDNAN_PREF_NONE)) {
|
||||
LOG_FULL(FATAL) << "Is not an Ecma Opcode opcode: " << static_cast<uint16_t>(opcode);
|
||||
UNREACHABLE();
|
||||
}
|
||||
*pc = *(pc + 1);
|
||||
*(pc + 1) = 0xFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::UpdateICOffset(JSMethod *method, uint8_t *pc)
|
||||
{
|
||||
uint8_t offset = JSMethod::MAX_SLOT_SIZE;
|
||||
auto opcode = static_cast<EcmaOpcode>(*pc);
|
||||
switch (opcode) {
|
||||
case EcmaOpcode::TRYLDGLOBALBYNAME_PREF_ID32:
|
||||
case EcmaOpcode::TRYSTGLOBALBYNAME_PREF_ID32:
|
||||
case EcmaOpcode::LDGLOBALVAR_PREF_ID32:
|
||||
case EcmaOpcode::STGLOBALVAR_PREF_ID32:
|
||||
case EcmaOpcode::ADD2DYN_PREF_V8:
|
||||
case EcmaOpcode::SUB2DYN_PREF_V8:
|
||||
case EcmaOpcode::MUL2DYN_PREF_V8:
|
||||
case EcmaOpcode::DIV2DYN_PREF_V8:
|
||||
case EcmaOpcode::MOD2DYN_PREF_V8:
|
||||
case EcmaOpcode::SHL2DYN_PREF_V8:
|
||||
case EcmaOpcode::SHR2DYN_PREF_V8:
|
||||
case EcmaOpcode::ASHR2DYN_PREF_V8:
|
||||
case EcmaOpcode::AND2DYN_PREF_V8:
|
||||
case EcmaOpcode::OR2DYN_PREF_V8:
|
||||
case EcmaOpcode::XOR2DYN_PREF_V8:
|
||||
case EcmaOpcode::EQDYN_PREF_V8:
|
||||
case EcmaOpcode::NOTEQDYN_PREF_V8:
|
||||
case EcmaOpcode::LESSDYN_PREF_V8:
|
||||
case EcmaOpcode::LESSEQDYN_PREF_V8:
|
||||
case EcmaOpcode::GREATERDYN_PREF_V8:
|
||||
case EcmaOpcode::GREATEREQDYN_PREF_V8:
|
||||
offset = method->UpdateSlotSize(1);
|
||||
break;
|
||||
case EcmaOpcode::LDOBJBYVALUE_PREF_V8_V8:
|
||||
case EcmaOpcode::STOBJBYVALUE_PREF_V8_V8:
|
||||
case EcmaOpcode::STOWNBYVALUE_PREF_V8_V8:
|
||||
case EcmaOpcode::LDOBJBYNAME_PREF_ID32_V8:
|
||||
case EcmaOpcode::STOBJBYNAME_PREF_ID32_V8:
|
||||
case EcmaOpcode::STOWNBYNAME_PREF_ID32_V8:
|
||||
case EcmaOpcode::LDOBJBYINDEX_PREF_V8_IMM32:
|
||||
case EcmaOpcode::STOBJBYINDEX_PREF_V8_IMM32:
|
||||
case EcmaOpcode::STOWNBYINDEX_PREF_V8_IMM32:
|
||||
case EcmaOpcode::LDSUPERBYVALUE_PREF_V8_V8:
|
||||
case EcmaOpcode::STSUPERBYVALUE_PREF_V8_V8:
|
||||
case EcmaOpcode::LDSUPERBYNAME_PREF_ID32_V8:
|
||||
case EcmaOpcode::STSUPERBYNAME_PREF_ID32_V8:
|
||||
case EcmaOpcode::LDMODULEVAR_PREF_ID32_IMM8:
|
||||
case EcmaOpcode::STMODULEVAR_PREF_ID32:
|
||||
offset = method->UpdateSlotSize(2); // 2: occupy two ic slot
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
*(pc + 1) = offset;
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::FixInstructionId32(const BytecodeInstruction &inst, uint32_t index,
|
||||
uint32_t fixOrder)
|
||||
{
|
||||
// NOLINTNEXTLINE(hicpp-use-auto)
|
||||
auto pc = const_cast<uint8_t *>(inst.GetAddress());
|
||||
switch (inst.GetFormat()) {
|
||||
case BytecodeInstruction::Format::ID32: {
|
||||
uint8_t size = sizeof(uint32_t);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
if (memcpy_s(pc + FixInsIndex::FIX_ONE, size, &index, size) != EOK) {
|
||||
LOG_FULL(FATAL) << "memcpy_s failed";
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Format::PREF_ID16_IMM16_V8: {
|
||||
uint16_t u16Index = index;
|
||||
uint8_t size = sizeof(uint16_t);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
if (memcpy_s(pc + FixInsIndex::FIX_TWO, size, &u16Index, size) != EOK) {
|
||||
LOG_FULL(FATAL) << "memcpy_s failed";
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Format::PREF_ID32:
|
||||
case BytecodeInstruction::Format::PREF_ID32_V8:
|
||||
case BytecodeInstruction::Format::PREF_ID32_IMM8: {
|
||||
uint8_t size = sizeof(uint32_t);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
if (memcpy_s(pc + FixInsIndex::FIX_TWO, size, &index, size) != EOK) {
|
||||
LOG_FULL(FATAL) << "memcpy_s failed";
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Format::PREF_IMM16: {
|
||||
ASSERT(static_cast<uint16_t>(index) == index);
|
||||
uint16_t u16Index = index;
|
||||
uint8_t size = sizeof(uint16_t);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
if (memcpy_s(pc + FixInsIndex::FIX_TWO, size, &u16Index, size) != EOK) {
|
||||
LOG_FULL(FATAL) << "memcpy_s failed";
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Format::PREF_ID16_IMM16_IMM16_V8_V8: {
|
||||
// Usually, we fix one part of instruction one time. But as for instruction DefineClassWithBuffer,
|
||||
// which use both method id and literal buffer id.Using fixOrder indicates fix Location.
|
||||
if (fixOrder == 0) {
|
||||
uint8_t size = sizeof(uint16_t);
|
||||
ASSERT(static_cast<uint16_t>(index) == index);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
if (memcpy_s(pc + FixInsIndex::FIX_TWO, size, &index, size) != EOK) {
|
||||
LOG_FULL(FATAL) << "memcpy_s failed";
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (fixOrder == 1) {
|
||||
ASSERT(static_cast<uint16_t>(index) == index);
|
||||
uint16_t u16Index = index;
|
||||
uint8_t size = sizeof(uint16_t);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
||||
if (memcpy_s(pc + FixInsIndex::FIX_FOUR, size, &u16Index, size) != EOK) {
|
||||
LOG_FULL(FATAL) << "memcpy_s failed";
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::TranslateBCIns(JSPandaFile *jsPandaFile, const panda::BytecodeInstruction &bcIns,
|
||||
const JSMethod *method)
|
||||
{
|
||||
const panda_file::File *pf = jsPandaFile->GetPandaFile();
|
||||
if (bcIns.HasFlag(BytecodeInstruction::Flags::STRING_ID) &&
|
||||
BytecodeInstruction::HasId(bcIns.GetFormat(), 0)) {
|
||||
auto index = jsPandaFile->GetOrInsertConstantPool(
|
||||
ConstPoolType::STRING, bcIns.GetId().AsFileId().GetOffset());
|
||||
FixInstructionId32(bcIns, index);
|
||||
} else {
|
||||
BytecodeInstruction::Opcode opcode = static_cast<BytecodeInstruction::Opcode>(bcIns.GetOpcode());
|
||||
switch (opcode) {
|
||||
uint32_t index;
|
||||
uint32_t methodId;
|
||||
case BytecodeInstruction::Opcode::ECMA_DEFINEFUNCDYN_PREF_ID16_IMM16_V8:
|
||||
methodId = pf->ResolveMethodIndex(method->GetMethodId(), bcIns.GetId().AsIndex()).GetOffset();
|
||||
index = jsPandaFile->GetOrInsertConstantPool(ConstPoolType::BASE_FUNCTION, methodId);
|
||||
FixInstructionId32(bcIns, index);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::ECMA_DEFINENCFUNCDYN_PREF_ID16_IMM16_V8:
|
||||
methodId = pf->ResolveMethodIndex(method->GetMethodId(), bcIns.GetId().AsIndex()).GetOffset();
|
||||
index = jsPandaFile->GetOrInsertConstantPool(ConstPoolType::NC_FUNCTION, methodId);
|
||||
FixInstructionId32(bcIns, index);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::ECMA_DEFINEGENERATORFUNC_PREF_ID16_IMM16_V8:
|
||||
methodId = pf->ResolveMethodIndex(method->GetMethodId(), bcIns.GetId().AsIndex()).GetOffset();
|
||||
index = jsPandaFile->GetOrInsertConstantPool(ConstPoolType::GENERATOR_FUNCTION, methodId);
|
||||
FixInstructionId32(bcIns, index);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::ECMA_DEFINEASYNCFUNC_PREF_ID16_IMM16_V8:
|
||||
methodId = pf->ResolveMethodIndex(method->GetMethodId(), bcIns.GetId().AsIndex()).GetOffset();
|
||||
index = jsPandaFile->GetOrInsertConstantPool(ConstPoolType::ASYNC_FUNCTION, methodId);
|
||||
FixInstructionId32(bcIns, index);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::ECMA_DEFINEMETHOD_PREF_ID16_IMM16_V8:
|
||||
methodId = pf->ResolveMethodIndex(method->GetMethodId(), bcIns.GetId().AsIndex()).GetOffset();
|
||||
index = jsPandaFile->GetOrInsertConstantPool(ConstPoolType::METHOD, methodId);
|
||||
FixInstructionId32(bcIns, index);
|
||||
break;
|
||||
case BytecodeInstruction::Opcode::ECMA_CREATEOBJECTWITHBUFFER_PREF_IMM16:
|
||||
case BytecodeInstruction::Opcode::ECMA_CREATEOBJECTHAVINGMETHOD_PREF_IMM16: {
|
||||
auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16>();
|
||||
index = jsPandaFile->GetOrInsertConstantPool(ConstPoolType::OBJECT_LITERAL,
|
||||
static_cast<uint16_t>(imm));
|
||||
FixInstructionId32(bcIns, index);
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::ECMA_CREATEARRAYWITHBUFFER_PREF_IMM16: {
|
||||
auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_IMM16>();
|
||||
index = jsPandaFile->GetOrInsertConstantPool(ConstPoolType::ARRAY_LITERAL,
|
||||
static_cast<uint16_t>(imm));
|
||||
FixInstructionId32(bcIns, index);
|
||||
break;
|
||||
}
|
||||
case BytecodeInstruction::Opcode::ECMA_DEFINECLASSWITHBUFFER_PREF_ID16_IMM16_IMM16_V8_V8: {
|
||||
methodId = pf->ResolveMethodIndex(method->GetMethodId(), bcIns.GetId().AsIndex()).GetOffset();
|
||||
index = jsPandaFile->GetOrInsertConstantPool(ConstPoolType::CLASS_FUNCTION, methodId);
|
||||
FixInstructionId32(bcIns, index);
|
||||
auto imm = bcIns.GetImm<BytecodeInstruction::Format::PREF_ID16_IMM16_IMM16_V8_V8>();
|
||||
index = jsPandaFile->GetOrInsertConstantPool(ConstPoolType::CLASS_LITERAL,
|
||||
static_cast<uint16_t>(imm));
|
||||
FixInstructionId32(bcIns, index, 1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeInfoCollector::CollectMethodPcs(JSPandaFile *jsPandaFile, const uint32_t insSz, const uint8_t *insArr,
|
||||
const JSMethod *method, std::vector<MethodPcInfo> &methodPcInfos)
|
||||
{
|
||||
auto bcIns = BytecodeInstruction(insArr);
|
||||
auto bcInsLast = bcIns.JumpTo(insSz);
|
||||
methodPcInfos.emplace_back(MethodPcInfo { method, {}, {}, {} });
|
||||
|
||||
int32_t offsetIndex = 1;
|
||||
uint8_t *curPc = nullptr;
|
||||
uint8_t *prePc = nullptr;
|
||||
while (bcIns.GetAddress() != bcInsLast.GetAddress()) {
|
||||
TranslateBCIns(jsPandaFile, bcIns, method);
|
||||
|
||||
auto pc = const_cast<uint8_t *>(bcIns.GetAddress());
|
||||
bcIns = bcIns.GetNext();
|
||||
|
||||
FixOpcode(pc);
|
||||
UpdateICOffset(const_cast<JSMethod *>(method), pc);
|
||||
|
||||
auto &bytecodeBlockInfos = methodPcInfos.back().bytecodeBlockInfos;
|
||||
auto &byteCodeCurPrePc = methodPcInfos.back().byteCodeCurPrePc;
|
||||
auto &pcToBCOffset = methodPcInfos.back().pcToBCOffset;
|
||||
|
||||
if (offsetIndex == 1) {
|
||||
curPc = prePc = pc;
|
||||
bytecodeBlockInfos.emplace_back(curPc, SplitKind::START, std::vector<uint8_t *>(1, curPc));
|
||||
byteCodeCurPrePc[curPc] = prePc;
|
||||
pcToBCOffset[curPc] = offsetIndex++;
|
||||
} else {
|
||||
curPc = pc;
|
||||
byteCodeCurPrePc[curPc] = prePc;
|
||||
pcToBCOffset[curPc] = offsetIndex++;
|
||||
prePc = curPc;
|
||||
BytecodeCircuitBuilder::CollectBytecodeBlockInfo(curPc, bytecodeBlockInfos);
|
||||
}
|
||||
}
|
||||
auto emptyPc = const_cast<uint8_t *>(bcInsLast.GetAddress());
|
||||
methodPcInfos.back().byteCodeCurPrePc[emptyPc] = prePc;
|
||||
methodPcInfos.back().pcToBCOffset[emptyPc] = offsetIndex++;
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
74
ecmascript/compiler/bytecode_info_collector.h
Normal file
74
ecmascript/compiler/bytecode_info_collector.h
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2022 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.
|
||||
*/
|
||||
|
||||
#ifndef ECMASCRIPT_COMPILER_BYTECODE_INFO_COLLECTOR_H
|
||||
#define ECMASCRIPT_COMPILER_BYTECODE_INFO_COLLECTOR_H
|
||||
|
||||
#include "ecmascript/ecma_vm.h"
|
||||
|
||||
#include "libpandafile/bytecode_instruction-inl.h"
|
||||
|
||||
namespace panda::ecmascript::kungfu {
|
||||
struct CfgInfo;
|
||||
class BytecodeInfoCollector {
|
||||
public:
|
||||
// need to remove in the future
|
||||
enum FixInsIndex : uint8_t { FIX_ONE = 1, FIX_TWO = 2, FIX_FOUR = 4 };
|
||||
|
||||
struct MethodPcInfo {
|
||||
const JSMethod *method {nullptr};
|
||||
std::map<uint8_t *, uint8_t *> byteCodeCurPrePc {};
|
||||
std::vector<CfgInfo> bytecodeBlockInfos {};
|
||||
std::map<const uint8_t *, int32_t> pcToBCOffset {};
|
||||
};
|
||||
|
||||
struct BCInfo {
|
||||
const JSPandaFile *jsPandaFile {nullptr};
|
||||
JSHandle<JSTaggedValue> constantPool;
|
||||
std::vector<MethodPcInfo> methodPcInfos {};
|
||||
|
||||
template <class Callback>
|
||||
void EnumerateBCInfo(const Callback &cb)
|
||||
{
|
||||
for (size_t i = 0; i < methodPcInfos.size(); i++) {
|
||||
cb(jsPandaFile, constantPool, methodPcInfos[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const JSPandaFile *LoadInfoFromPf(const CString &filename, const std::string_view& entryPoint,
|
||||
std::vector<MethodPcInfo> &methodPcInfos);
|
||||
|
||||
private:
|
||||
static void ProcessClasses(JSPandaFile *jsPandaFile, const CString &methodName,
|
||||
std::vector<MethodPcInfo> &methodPcInfos);
|
||||
|
||||
// need to remove in the future
|
||||
static void FixOpcode(uint8_t *pc);
|
||||
|
||||
// need to remove in the future
|
||||
static void UpdateICOffset(JSMethod *method, uint8_t *pc);
|
||||
|
||||
// need to remove in the future
|
||||
static void FixInstructionId32(const BytecodeInstruction &inst, uint32_t index, uint32_t fixOrder = 0);
|
||||
|
||||
// need to remove in the future
|
||||
static void TranslateBCIns(JSPandaFile *jsPandaFile, const BytecodeInstruction &bcIns, const JSMethod *method);
|
||||
|
||||
static void CollectMethodPcs(JSPandaFile *jsPandaFile, const uint32_t insSz, const uint8_t *insArr,
|
||||
const JSMethod *method, std::vector<MethodPcInfo> &methodPcInfos);
|
||||
};
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
#endif // ECMASCRIPT_COMPILER_BYTECODE_INFO_COLLECTOR_H
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "ecmascript/compiler/file_generators.h"
|
||||
#include "ecmascript/compiler/pass.h"
|
||||
#include "ecmascript/compiler/bytecode_info_collector.h"
|
||||
#include "ecmascript/ecma_handle_scope.h"
|
||||
#include "ecmascript/js_tagged_value.h"
|
||||
#include "ecmascript/jspandafile/js_pandafile_manager.h"
|
||||
@ -26,9 +27,9 @@
|
||||
namespace panda::ecmascript::kungfu {
|
||||
bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generator)
|
||||
{
|
||||
BytecodeTranslationInfo translationInfo;
|
||||
BytecodeInfoCollector::BCInfo bytecodeInfo;
|
||||
[[maybe_unused]] EcmaHandleScope handleScope(vm_->GetJSThread());
|
||||
bool res = CollectInfoOfPandaFile(fileName, entry_, &translationInfo);
|
||||
bool res = CollectBCInfo(fileName, &bytecodeInfo);
|
||||
if (!res) {
|
||||
LOG_COMPILER(ERROR) << "Cannot execute panda file '" << fileName << "'";
|
||||
return false;
|
||||
@ -41,19 +42,21 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat
|
||||
|
||||
bool enableLog = !log_->NoneMethod();
|
||||
|
||||
for (size_t i = 0; i < translationInfo.methodPcInfos.size(); i++) {
|
||||
const JSMethod *method = translationInfo.methodPcInfos[i].method;
|
||||
const std::string methodName(method->GetMethodName());
|
||||
bytecodeInfo.EnumerateBCInfo([this, &fileName, &enableLog, aotModule, &cmpCfg, tsManager]
|
||||
(const JSPandaFile *jsPandaFile, JSHandle<JSTaggedValue> &constantPool,
|
||||
BytecodeInfoCollector::MethodPcInfo &methodPCInfo) {
|
||||
const std::string methodName(methodPCInfo.method->GetMethodName());
|
||||
if (log_->CertainMethod()) {
|
||||
enableLog = logList_->IncludesMethod(fileName, methodName);
|
||||
}
|
||||
|
||||
if (enableLog) {
|
||||
LOG_COMPILER(INFO) << "\033[34m" << "aot method [" << fileName << ":"
|
||||
<< methodName << "] log:" << "\033[0m";
|
||||
<< methodName << "] log:" << "\033[0m";
|
||||
}
|
||||
|
||||
BytecodeCircuitBuilder builder(translationInfo, i, tsManager, enableLog && log_->OutputCIR());
|
||||
BytecodeCircuitBuilder builder(jsPandaFile, constantPool, methodPCInfo, tsManager,
|
||||
enableLog && log_->OutputCIR());
|
||||
builder.BytecodeToCircuit();
|
||||
PassData data(builder.GetCircuit());
|
||||
PassRunner<PassData> pipeline(&data, enableLog && log_->OutputCIR());
|
||||
@ -63,26 +66,25 @@ bool PassManager::Compile(const std::string &fileName, AOTFileGenerator &generat
|
||||
pipeline.RunPass<SlowPathLoweringPass>(&builder, &cmpCfg);
|
||||
pipeline.RunPass<VerifierPass>();
|
||||
pipeline.RunPass<SchedulingPass>();
|
||||
pipeline.RunPass<LLVMIRGenPass>(aotModule, method);
|
||||
}
|
||||
pipeline.RunPass<LLVMIRGenPass>(aotModule, methodPCInfo.method);
|
||||
});
|
||||
|
||||
generator.AddModule(aotModule, aotModuleAssembler, translationInfo.jsPandaFile);
|
||||
generator.AddModule(aotModule, aotModuleAssembler, bytecodeInfo.jsPandaFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PassManager::CollectInfoOfPandaFile(const std::string &fileName, std::string_view entryPoint,
|
||||
BytecodeTranslationInfo *translateInfo)
|
||||
bool PassManager::CollectBCInfo(const std::string &fileName, BytecodeInfoCollector::BCInfo *bytecodeInfo)
|
||||
{
|
||||
if (translateInfo == nullptr) {
|
||||
if (bytecodeInfo == nullptr) {
|
||||
return false;
|
||||
}
|
||||
const JSPandaFile *jsPandaFile =
|
||||
JSPandaFileManager::GetInstance()->LoadAotInfoFromPf(fileName.c_str(), entryPoint,
|
||||
&(translateInfo->methodPcInfos));
|
||||
const JSPandaFile *jsPandaFile = BytecodeInfoCollector::LoadInfoFromPf(fileName.c_str(), entry_,
|
||||
bytecodeInfo->methodPcInfos);
|
||||
|
||||
if (jsPandaFile == nullptr) {
|
||||
return false;
|
||||
}
|
||||
translateInfo->jsPandaFile = jsPandaFile;
|
||||
bytecodeInfo->jsPandaFile = jsPandaFile;
|
||||
|
||||
if (jsPandaFile->HasTSTypes()) {
|
||||
TSManager *tsManager = vm_->GetTSManager();
|
||||
@ -99,7 +101,7 @@ bool PassManager::CollectInfoOfPandaFile(const std::string &fileName, std::strin
|
||||
auto program = PandaFileTranslator::GenerateProgram(vm_, jsPandaFile);
|
||||
JSHandle<JSFunction> mainFunc(vm_->GetJSThread(), program->GetMainFunction());
|
||||
JSHandle<JSTaggedValue> constPool(vm_->GetJSThread(), mainFunc->GetConstantPool());
|
||||
translateInfo->constantPool = constPool;
|
||||
bytecodeInfo->constantPool = constPool;
|
||||
return true;
|
||||
}
|
||||
} // namespace panda::ecmascript::kungfu
|
||||
|
@ -30,8 +30,7 @@ public:
|
||||
relocMode_(relocMode), log_(log), logList_(logList) {};
|
||||
PassManager() = default;
|
||||
~PassManager() = default;
|
||||
bool CollectInfoOfPandaFile(const std::string &filename, std::string_view entryPoint,
|
||||
BytecodeTranslationInfo *translateInfo);
|
||||
bool CollectBCInfo(const std::string &filename, BytecodeInfoCollector::BCInfo *bytecodeInfo);
|
||||
bool Compile(const std::string &fileName, AOTFileGenerator &generator);
|
||||
void SaveSnapshotFile();
|
||||
|
||||
|
@ -81,7 +81,7 @@ public:
|
||||
return constpoolMap_;
|
||||
}
|
||||
|
||||
uint32_t GetOrInsertConstantPool(ConstPoolType type, uint32_t offset);
|
||||
uint32_t PUBLIC_API GetOrInsertConstantPool(ConstPoolType type, uint32_t offset);
|
||||
|
||||
void UpdateMainMethodIndex(uint32_t mainMethodIndex)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user