Files
ark_js_runtime/ecmascript/compiler/bytecode_circuit_builder.h
wanyanglan 01a613ecac independent running ts aot
ts aot should be a separate part that needs to generate the
corresponding file before executing xxx.abc and should not
depend on the execution of xxx.abc

issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4RP3H

Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: I4ed7d7ee5528dcb479e08486f332a48c16ea88d7
2022-01-26 15:22:50 +08:00

183 lines
6.5 KiB
C++

/*
* 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.
*/
#ifndef ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
#define ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
#include <numeric>
#include <tuple>
#include <utility>
#include <vector>
#include "circuit.h"
#include "ecmascript/interpreter/interpreter-inl.h"
#include "ecmascript/js_method.h"
namespace panda::ecmascript::kungfu {
using VRegIDType = uint16_t;
enum class SplitKind : uint8_t {
DEFAULT,
START,
END
};
struct CfgInfo {
uint8_t *pc {nullptr};
SplitKind splitKind {SplitKind::DEFAULT};
std::vector<uint8_t *> succs {};
CfgInfo(uint8_t *startOrEndPc, SplitKind kind, std::vector<uint8_t *> successors)
: pc(startOrEndPc), splitKind(kind), succs(successors) {};
bool operator<(const CfgInfo &rhs) const
{
if (this->pc != rhs.pc) {
return this->pc < rhs.pc;
} else {
return this->splitKind < rhs.splitKind;
}
}
bool operator==(const CfgInfo &rhs) const
{
return this->pc == rhs.pc && this->splitKind == rhs.splitKind;
}
};
struct BytecodeRegion {
int32_t id {-1};
uint8_t *start {nullptr};
uint8_t *end {nullptr};
std::vector<BytecodeRegion *> preds {}; // List of predessesor blocks
std::vector<BytecodeRegion *> succs {}; // List of successors blocks
std::vector<BytecodeRegion *> trys {}; // List of trys blocks
std::vector<BytecodeRegion *> catchs {}; // List of catches blocks
std::vector<BytecodeRegion *> immDomBlocks {}; // List of dominated blocks
BytecodeRegion *iDominator {nullptr}; // Block that dominates the current block
std::vector<BytecodeRegion *> domFrontiers {}; // List of dominace frontiers
bool isDead {false};
std::set<uint16_t> phi {}; // phi node
bool phiAcc {false};
int32_t numOfStatePreds {0};
int32_t statePredIndex {0};
std::vector<std::tuple<size_t, uint8_t *, bool>> expandedPreds {};
kungfu::GateRef stateStart {kungfu::Circuit::NullGate()};
kungfu::GateRef dependStart {kungfu::Circuit::NullGate()};
std::map<uint16_t, kungfu::GateRef> vregToValSelectorGate {}; // corresponding ValueSelector gates of vregs
kungfu::GateRef valueSelectorAccGate {kungfu::Circuit::NullGate()};
bool operator <(const BytecodeRegion &target) const
{
return id < target.id;
}
};
struct BytecodeInfo {
std::vector<VRegIDType> vregIn {}; // read register
std::vector<VRegIDType> vregOut {}; // write register
bool accIn {false}; // read acc
bool accOut {false}; // write acc
uint8_t opcode {0};
uint16_t offset {0};
};
struct BytecodeGraph {
std::vector<BytecodeRegion> graph {};
const JSMethod *method;
};
enum BytecodeOffset {
ONE = 1,
TWO,
THREE,
FOUR,
FIVE,
SIX,
SEVEN,
EIGHT,
NINE,
TEN
};
class BytecodeCircuitBuilder {
public:
explicit BytecodeCircuitBuilder() = default;
~BytecodeCircuitBuilder() = default;
NO_COPY_SEMANTIC(BytecodeCircuitBuilder);
NO_MOVE_SEMANTIC(BytecodeCircuitBuilder);
void PUBLIC_API BytecodeToCircuit(const std::vector<uint8_t *> &pcArray, const panda_file::File &pf,
const JSMethod *method);
[[nodiscard]] kungfu::Circuit GetCircuit() const
{
return circuit_;
}
[[nodiscard]] std::map<kungfu::GateRef, std::pair<size_t, uint8_t *>> GetGateToBytecode() const
{
return jsgateToBytecode_;
}
[[nodiscard]] std::map<uint8_t *, kungfu::GateRef> GetBytecodeToGate() const
{
return byteCodeToJSGate_;
}
[[nodiscard]] std::string GetBytecodeStr(kungfu::GateRef gate) const
{
auto pc = jsgateToBytecode_.at(gate).second;
return GetEcmaOpcodeStr(static_cast<EcmaOpcode>(*pc));
}
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(
const panda_file::File &file, const JSMethod *method, 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(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);
void ComputeDominatorTree(BytecodeGraph &byteCodeGraph);
void BuildImmediateDominator(std::vector<size_t> &immDom, BytecodeGraph &byteCodeGraph);
void ComputeDomFrontiers(std::vector<size_t> &immDom, BytecodeGraph &byteCodeGraph);
BytecodeInfo GetBytecodeInfo(uint8_t *pc);
void RemoveDeadRegions(const std::map<size_t, size_t> &dfsTimestamp, BytecodeGraph &byteCodeGraph);
void InsertPhi(BytecodeGraph &byteCodeGraph);
void UpdateCFG(BytecodeGraph &byteCodeGraph);
void BuildCircuit(BytecodeGraph &byteCodeGraph);
void PrintCollectBlockInfo(std::vector<CfgInfo> &bytecodeBlockInfos);
void PrintGraph(std::vector<BytecodeRegion> &graph);
void PrintBytecodeInfo(std::vector<BytecodeRegion> &graph);
void PrintBBInfo(std::vector<BytecodeRegion> &graph);
static bool IsJump(EcmaOpcode opcode);
static bool IsCondJump(EcmaOpcode opcode);
static bool IsMov(EcmaOpcode opcode);
static bool IsReturn(EcmaOpcode opcode);
static bool IsThrow(EcmaOpcode opcode);
static bool IsGeneral(EcmaOpcode opcode);
kungfu::Circuit circuit_;
std::map<kungfu::GateRef, std::pair<size_t, uint8_t *>> jsgateToBytecode_;
std::map<uint8_t *, kungfu::GateRef> byteCodeToJSGate_;
std::map<int32_t, BytecodeRegion *> bbIdToBasicBlock_;
};
} // namespace panda::ecmascript::kungfu
#endif // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H