mirror of
https://github.com/openharmony/ark_js_runtime.git
synced 2026-08-28 04:49:56 -04:00
fb4de0245a
Replace all JS_BYTECODE in HIR. In order to simplify the code implementation, no type judgment is made on the input, and the slowpath is directly implemented by calling the trampoline function without affecting the original function. For complex function implementation, directly encapsulate the entire interpreted code as a trampoline function. Signed-off-by: xujie <xujie101@huawei.com> Change-Id: Icd24f7cebb496e4376170784ce1e2e2ef1a7ee71
209 lines
7.1 KiB
C++
209 lines
7.1 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/ecma_vm.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
|
|
uint64_t imm {0};
|
|
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
|
|
};
|
|
|
|
enum CommonArgIdx : uint8_t {
|
|
GLUE = 0,
|
|
FUNC,
|
|
NEW_TARGET,
|
|
THIS,
|
|
NUM_OF_ARGS,
|
|
};
|
|
|
|
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()
|
|
{
|
|
return &circuit_;
|
|
}
|
|
|
|
[[nodiscard]] const std::map<kungfu::GateRef, std::pair<size_t, uint8_t *>>& GetGateToBytecode() const
|
|
{
|
|
return jsgateToBytecode_;
|
|
}
|
|
|
|
[[nodiscard]] const 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));
|
|
}
|
|
|
|
[[nodiscard]] uint8_t* GetJSBytecode(GateRef gate) const
|
|
{
|
|
return jsgateToBytecode_.at(gate).second;
|
|
}
|
|
|
|
[[nodiscard]] GateRef GetCommonArgByIndex(CommonArgIdx idx)
|
|
{
|
|
return commonArgs_[idx];
|
|
}
|
|
|
|
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<int32_t> &immDom, BytecodeGraph &byteCodeGraph);
|
|
void ComputeDomFrontiers(std::vector<int32_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);
|
|
static bool IsSetConstant(EcmaOpcode opcode);
|
|
size_t GetActualNumArgs(size_t numArgs)
|
|
{
|
|
return numArgs + CommonArgIdx::NUM_OF_ARGS;
|
|
}
|
|
|
|
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_;
|
|
std::array<GateRef, CommonArgIdx::NUM_OF_ARGS> commonArgs_ {};
|
|
};
|
|
} // namespace panda::ecmascript::kungfu
|
|
#endif // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H
|