mirror of
https://github.com/openharmony/ark_js_runtime.git
synced 2026-07-20 23:00:29 -04:00
7750051d88
The exception object is passed directly as a value inside the IR will cause acc to generate many phi nodes (other vreg rarely generate phi nodes when exceptions are handled). The current modification is to add a GET_EXCEPTION directive (placed at the beginning of the catch part) to indicate that the exception object is read after an exception occurs, in this case lowering is simpler and does not need to consider different value outputs, the logic is more concise and the number of code instructions is reduced. Replace ladi and fdai HIR with MIR: these two instructions to get the immediate number, do not need to use HIR to handle, this will increase the number of HIR instructions, simplify lowering. issue:https://gitee.com/openharmony/ark_js_runtime/issues/I4T6HX Signed-off-by: wanyanglan <wanyanglan1@huawei.com> Change-Id: I751677e11b50976af4e2fc5a6cac4457fa9a44df
452 lines
14 KiB
C++
452 lines
14 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.
|
|
*/
|
|
|
|
#include "ecmascript/compiler/circuit.h"
|
|
#include "ecmascript/compiler/compiler_macros.h"
|
|
#include "ecmascript/compiler/bytecode_circuit_builder.h"
|
|
|
|
namespace panda::ecmascript::kungfu {
|
|
Circuit::Circuit() : space_(), circuitSize_(0), gateCount_(0), time_(1), dataSection_()
|
|
{
|
|
NewGate(OpCode(OpCode::CIRCUIT_ROOT), 0, {}, GateType::EMPTY); // circuit root
|
|
auto circuitRoot = Circuit::GetCircuitRoot(OpCode(OpCode::CIRCUIT_ROOT));
|
|
NewGate(OpCode(OpCode::STATE_ENTRY), 0, {circuitRoot}, GateType::EMPTY);
|
|
NewGate(OpCode(OpCode::DEPEND_ENTRY), 0, {circuitRoot}, GateType::EMPTY);
|
|
NewGate(OpCode(OpCode::FRAMESTATE_ENTRY), 0, {circuitRoot}, GateType::EMPTY);
|
|
NewGate(OpCode(OpCode::RETURN_LIST), 0, {circuitRoot}, GateType::EMPTY);
|
|
NewGate(OpCode(OpCode::THROW_LIST), 0, {circuitRoot}, GateType::EMPTY);
|
|
NewGate(OpCode(OpCode::CONSTANT_LIST), 0, {circuitRoot}, GateType::EMPTY);
|
|
NewGate(OpCode(OpCode::ALLOCA_LIST), 0, {circuitRoot}, GateType::EMPTY);
|
|
NewGate(OpCode(OpCode::ARG_LIST), 0, {circuitRoot}, GateType::EMPTY);
|
|
}
|
|
|
|
uint8_t *Circuit::AllocateSpace(size_t gateSize)
|
|
{
|
|
circuitSize_ += gateSize;
|
|
if (UNLIKELY(GetSpaceDataSize() == 0)) {
|
|
SetSpaceDataSize(INITIAL_SPACE);
|
|
}
|
|
while (UNLIKELY(GetSpaceDataSize() < circuitSize_)) {
|
|
SetSpaceDataSize(GetSpaceDataSize() * SCALE_RATE);
|
|
}
|
|
if (UNLIKELY(GetSpaceDataSize() > MAX_SPACE)) {
|
|
return nullptr; // abort compilation
|
|
}
|
|
if (UNLIKELY(GetSpaceDataStartPtrConst() == nullptr)) {
|
|
return nullptr; // abort compilation
|
|
}
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
return GetDataPtr(circuitSize_ - gateSize);
|
|
}
|
|
|
|
Gate *Circuit::AllocateGateSpace(size_t numIns)
|
|
{
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
return reinterpret_cast<Gate *>(AllocateSpace(Gate::GetGateSize(numIns)) + Gate::GetOutListSize(numIns));
|
|
}
|
|
|
|
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
|
GateRef Circuit::NewGate(OpCode opcode, MachineType bitValue, BitField bitfield, size_t numIns, const GateRef inList[],
|
|
GateType type, MarkCode mark)
|
|
{
|
|
#ifndef NDEBUG
|
|
if (numIns != opcode.GetOpCodeNumIns(bitfield)) {
|
|
std::cerr << "Invalid input list!"
|
|
<< " op=" << opcode.Str() << " bitfield=" << bitfield
|
|
<< " expected_num_in=" << opcode.GetOpCodeNumIns(bitfield) << " actual_num_in=" << numIns
|
|
<< std::endl;
|
|
UNREACHABLE();
|
|
}
|
|
#endif
|
|
std::vector<Gate *> inPtrList(numIns);
|
|
auto gateSpace = AllocateGateSpace(numIns);
|
|
for (size_t idx = 0; idx < numIns; idx++) {
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
inPtrList[idx] = (inList[idx] == Circuit::NullGate()) ? nullptr : LoadGatePtr(inList[idx]);
|
|
}
|
|
ASSERT(opcode.GetMachineType() == MachineType::FLEX);
|
|
auto newGate = new (gateSpace) Gate(gateCount_, opcode, bitValue, bitfield, inPtrList.data(), type, mark);
|
|
gateCount_++;
|
|
return SaveGatePtr(newGate);
|
|
}
|
|
|
|
GateRef Circuit::NewGate(OpCode opcode, MachineType bitValue, BitField bitfield, const std::vector<GateRef> &inList,
|
|
GateType type, MarkCode mark)
|
|
{
|
|
return NewGate(opcode, bitValue, bitfield, inList.size(), inList.data(), type, mark);
|
|
}
|
|
|
|
// NOLINTNEXTLINE(modernize-avoid-c-arrays)
|
|
GateRef Circuit::NewGate(OpCode opcode, BitField bitfield, size_t numIns, const GateRef inList[], GateType type,
|
|
MarkCode mark)
|
|
{
|
|
#ifndef NDEBUG
|
|
if (numIns != opcode.GetOpCodeNumIns(bitfield)) {
|
|
std::cerr << "Invalid input list!"
|
|
<< " op=" << opcode.Str() << " bitfield=" << bitfield
|
|
<< " expected_num_in=" << opcode.GetOpCodeNumIns(bitfield) << " actual_num_in=" << numIns
|
|
<< std::endl;
|
|
UNREACHABLE();
|
|
}
|
|
#endif
|
|
std::vector<Gate *> inPtrList(numIns);
|
|
auto gateSpace = AllocateGateSpace(numIns);
|
|
for (size_t idx = 0; idx < numIns; idx++) {
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
inPtrList[idx] = (inList[idx] == Circuit::NullGate()) ? nullptr : LoadGatePtr(inList[idx]);
|
|
}
|
|
ASSERT(opcode.GetMachineType() != MachineType::FLEX);
|
|
auto newGate = new (gateSpace) Gate(gateCount_, opcode, opcode.GetMachineType(), bitfield, inPtrList.data(), type,
|
|
mark);
|
|
gateCount_++;
|
|
return SaveGatePtr(newGate);
|
|
}
|
|
|
|
GateRef Circuit::NewGate(OpCode opcode, BitField bitfield, const std::vector<GateRef> &inList, GateType type,
|
|
MarkCode mark)
|
|
{
|
|
return NewGate(opcode, bitfield, inList.size(), inList.data(), type, mark);
|
|
}
|
|
|
|
void Circuit::PrintAllGates() const
|
|
{
|
|
const auto &gateList = GetAllGates();
|
|
for (const auto &gate : gateList) {
|
|
LoadGatePtrConst(gate)->Print();
|
|
}
|
|
}
|
|
|
|
void Circuit::PrintAllGates(BytecodeCircuitBuilder &builder) const
|
|
{
|
|
const auto &gateList = GetAllGates();
|
|
for (const auto &gate : gateList) {
|
|
auto item = builder.GetGateToBytecode().find(gate);
|
|
if (item != builder.GetGateToBytecode().end()) {
|
|
std::string bytecodeStr = builder.GetBytecodeStr(gate);
|
|
LoadGatePtrConst(gate)->PrintByteCode(bytecodeStr);
|
|
} else {
|
|
LoadGatePtrConst(gate)->Print();
|
|
}
|
|
}
|
|
}
|
|
|
|
std::vector<GateRef> Circuit::GetAllGates() const
|
|
{
|
|
std::vector<GateRef> gateList;
|
|
gateList.push_back(0);
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
for (size_t out = sizeof(Gate); out < circuitSize_;
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
out += Gate::GetGateSize(reinterpret_cast<const Out *>(LoadGatePtrConst(GateRef(out)))->GetIndex() + 1)) {
|
|
gateList.push_back(SaveGatePtr(reinterpret_cast<const Out *>(LoadGatePtrConst(GateRef(out)))->GetGateConst()));
|
|
}
|
|
return gateList;
|
|
}
|
|
|
|
GateRef Circuit::SaveGatePtr(const Gate *gate) const
|
|
{
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
return static_cast<GateRef>(reinterpret_cast<const uint8_t *>(gate) - GetDataPtrConst(0));
|
|
}
|
|
|
|
Gate *Circuit::LoadGatePtr(GateRef shift)
|
|
{
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
return reinterpret_cast<Gate *>(GetDataPtr(shift));
|
|
}
|
|
|
|
const Gate *Circuit::LoadGatePtrConst(GateRef shift) const
|
|
{
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
return reinterpret_cast<const Gate *>(GetDataPtrConst(shift));
|
|
}
|
|
|
|
GateRef Circuit::GetCircuitRoot(OpCode opcode)
|
|
{
|
|
switch (opcode) {
|
|
case OpCode::CIRCUIT_ROOT:
|
|
return sizeof(In) * 0 + sizeof(Out) * 0 + sizeof(Gate) * 0; // 0 0 0: offset of circuit root
|
|
case OpCode::STATE_ENTRY:
|
|
return sizeof(In) * 0 + sizeof(Out) * 1 + sizeof(Gate) * 1; // 0 1 1: offset of state entry
|
|
case OpCode::DEPEND_ENTRY:
|
|
return sizeof(In) * 1 + sizeof(Out) * 2 + sizeof(Gate) * 2; // 1 2 2: offset of depend entry
|
|
case OpCode::FRAMESTATE_ENTRY:
|
|
return sizeof(In) * 2 + sizeof(Out) * 3 + sizeof(Gate) * 3; // 2 3 3: offset of framestate entry
|
|
case OpCode::RETURN_LIST:
|
|
return sizeof(In) * 3 + sizeof(Out) * 4 + sizeof(Gate) * 4; // 3 4 4: offset of return list
|
|
case OpCode::THROW_LIST:
|
|
return sizeof(In) * 4 + sizeof(Out) * 5 + sizeof(Gate) * 5; // 4 5 5: offset of throw list
|
|
case OpCode::CONSTANT_LIST:
|
|
return sizeof(In) * 5 + sizeof(Out) * 6 + sizeof(Gate) * 6; // 5 6 6: offset of constant list
|
|
case OpCode::ALLOCA_LIST:
|
|
return sizeof(In) * 6 + sizeof(Out) * 7 + sizeof(Gate) * 7; // 6 7 7: offset of alloca list
|
|
case OpCode::ARG_LIST:
|
|
return sizeof(In) * 7 + sizeof(Out) * 8 + sizeof(Gate) * 8; // 7 8 8: offset of arg list
|
|
default:
|
|
UNREACHABLE();
|
|
}
|
|
}
|
|
|
|
Circuit::~Circuit() {}
|
|
|
|
void Circuit::AdvanceTime() const
|
|
{
|
|
auto &curTime = const_cast<TimeStamp &>(time_);
|
|
curTime++;
|
|
if (curTime == 0) {
|
|
curTime = 1;
|
|
ResetAllGateTimeStamps();
|
|
}
|
|
}
|
|
|
|
void Circuit::ResetAllGateTimeStamps() const
|
|
{
|
|
const auto &gateList = GetAllGates();
|
|
for (auto &gate : gateList) {
|
|
const_cast<Gate *>(LoadGatePtrConst(gate))->SetMark(MarkCode::NO_MARK, 0);
|
|
}
|
|
}
|
|
|
|
TimeStamp Circuit::GetTime() const
|
|
{
|
|
return time_;
|
|
}
|
|
|
|
MarkCode Circuit::GetMark(GateRef gate) const
|
|
{
|
|
return LoadGatePtrConst(gate)->GetMark(GetTime());
|
|
}
|
|
|
|
void Circuit::SetMark(GateRef gate, MarkCode mark) const
|
|
{
|
|
const_cast<Gate *>(LoadGatePtrConst(gate))->SetMark(mark, GetTime());
|
|
}
|
|
|
|
bool Circuit::Verify(GateRef gate) const
|
|
{
|
|
return LoadGatePtrConst(gate)->Verify();
|
|
}
|
|
|
|
GateRef Circuit::NullGate()
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
bool Circuit::IsLoopHead(GateRef gate) const
|
|
{
|
|
if (gate != NullGate()) {
|
|
const Gate *curGate = LoadGatePtrConst(gate);
|
|
return curGate->GetOpCode().IsLoopHead();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Circuit::IsControlCase(GateRef gate) const
|
|
{
|
|
if (gate != NullGate()) {
|
|
const Gate *curGate = LoadGatePtrConst(gate);
|
|
return curGate->GetOpCode().IsControlCase();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Circuit::IsSelector(GateRef gate) const
|
|
{
|
|
if (gate != NullGate()) {
|
|
const Gate *curGate = LoadGatePtrConst(gate);
|
|
return curGate->GetOpCode() == OpCode::VALUE_SELECTOR;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
std::vector<GateRef> Circuit::GetInVector(GateRef gate) const
|
|
{
|
|
std::vector<GateRef> result;
|
|
const Gate *curGate = LoadGatePtrConst(gate);
|
|
for (size_t idx = 0; idx < curGate->GetNumIns(); idx++) {
|
|
result.push_back(SaveGatePtr(curGate->GetInGateConst(idx)));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
GateRef Circuit::GetIn(GateRef gate, size_t idx) const
|
|
{
|
|
ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
|
|
const Gate *curGate = LoadGatePtrConst(gate);
|
|
return SaveGatePtr(curGate->GetInGateConst(idx));
|
|
}
|
|
|
|
bool Circuit::IsInGateNull(GateRef gate, size_t idx) const
|
|
{
|
|
const Gate *curGate = LoadGatePtrConst(gate);
|
|
return curGate->GetInConst(idx)->IsGateNull();
|
|
}
|
|
|
|
bool Circuit::IsFirstOutNull(GateRef gate) const
|
|
{
|
|
const Gate *curGate = LoadGatePtrConst(gate);
|
|
return curGate->IsFirstOutNull();
|
|
}
|
|
|
|
std::vector<GateRef> Circuit::GetOutVector(GateRef gate) const
|
|
{
|
|
std::vector<GateRef> result;
|
|
const Gate *curGate = LoadGatePtrConst(gate);
|
|
if (!curGate->IsFirstOutNull()) {
|
|
const Out *curOut = curGate->GetFirstOutConst();
|
|
result.push_back(SaveGatePtr(curOut->GetGateConst()));
|
|
while (!curOut->IsNextOutNull()) {
|
|
curOut = curOut->GetNextOutConst();
|
|
result.push_back(SaveGatePtr(curOut->GetGateConst()));
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
void Circuit::NewIn(GateRef gate, size_t idx, GateRef in)
|
|
{
|
|
#ifndef NDEBUG
|
|
ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
|
|
ASSERT(Circuit::IsInGateNull(gate, idx));
|
|
#endif
|
|
LoadGatePtr(gate)->NewIn(idx, LoadGatePtr(in));
|
|
}
|
|
|
|
void Circuit::ModifyIn(GateRef gate, size_t idx, GateRef in)
|
|
{
|
|
#ifndef NDEBUG
|
|
ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
|
|
ASSERT(!Circuit::IsInGateNull(gate, idx));
|
|
#endif
|
|
LoadGatePtr(gate)->ModifyIn(idx, LoadGatePtr(in));
|
|
}
|
|
|
|
void Circuit::DeleteIn(GateRef gate, size_t idx)
|
|
{
|
|
ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns());
|
|
ASSERT(!Circuit::IsInGateNull(gate, idx));
|
|
LoadGatePtr(gate)->DeleteIn(idx);
|
|
}
|
|
|
|
void Circuit::DeleteGate(GateRef gate)
|
|
{
|
|
LoadGatePtr(gate)->DeleteGate();
|
|
}
|
|
|
|
void Circuit::SetOpCode(GateRef gate, OpCode opcode)
|
|
{
|
|
LoadGatePtr(gate)->SetOpCode(opcode);
|
|
}
|
|
|
|
void Circuit::SetGateType(GateRef gate, GateType type)
|
|
{
|
|
LoadGatePtr(gate)->SetGateType(type);
|
|
}
|
|
|
|
void Circuit::SetMachineType(GateRef gate, MachineType machineType)
|
|
{
|
|
LoadGatePtr(gate)->SetMachineType(machineType);
|
|
}
|
|
|
|
GateType Circuit::GetGateType(GateRef gate) const
|
|
{
|
|
return LoadGatePtrConst(gate)->GetGateType();
|
|
}
|
|
|
|
MachineType Circuit::GetMachineType(GateRef gate) const
|
|
{
|
|
return LoadGatePtrConst(gate)->GetMachineType();
|
|
}
|
|
|
|
OpCode Circuit::GetOpCode(GateRef gate) const
|
|
{
|
|
return LoadGatePtrConst(gate)->GetOpCode();
|
|
}
|
|
|
|
GateId Circuit::GetId(GateRef gate) const
|
|
{
|
|
return LoadGatePtrConst(gate)->GetId();
|
|
}
|
|
|
|
BitField Circuit::GetBitField(GateRef gate) const
|
|
{
|
|
return LoadGatePtrConst(gate)->GetBitField();
|
|
}
|
|
|
|
void Circuit::Print(GateRef gate) const
|
|
{
|
|
LoadGatePtrConst(gate)->Print();
|
|
}
|
|
|
|
std::vector<uint8_t> Circuit::GetDataSection() const
|
|
{
|
|
return dataSection_;
|
|
}
|
|
|
|
void Circuit::SetDataSection(const std::vector<uint8_t> &data)
|
|
{
|
|
dataSection_ = data;
|
|
}
|
|
|
|
size_t Circuit::GetCircuitDataSize() const
|
|
{
|
|
return circuitSize_;
|
|
}
|
|
|
|
const void *Circuit::GetSpaceDataStartPtrConst() const
|
|
{
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
return GetDataPtrConst(0);
|
|
}
|
|
|
|
const void *Circuit::GetSpaceDataEndPtrConst() const
|
|
{
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
return GetDataPtrConst(circuitSize_);
|
|
}
|
|
|
|
const uint8_t *Circuit::GetDataPtrConst(size_t offset) const
|
|
{
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
return space_.data() + offset;
|
|
}
|
|
|
|
uint8_t *Circuit::GetDataPtr(size_t offset)
|
|
{
|
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
|
|
return space_.data() + offset;
|
|
}
|
|
|
|
size_t Circuit::GetSpaceDataSize() const
|
|
{
|
|
return space_.size();
|
|
}
|
|
|
|
void Circuit::SetSpaceDataSize(size_t sz)
|
|
{
|
|
return space_.resize(sz);
|
|
}
|
|
|
|
panda::ecmascript::FrameType Circuit::GetFrameType() const
|
|
{
|
|
return frameType_;
|
|
}
|
|
|
|
void Circuit::SetFrameType(panda::ecmascript::FrameType type)
|
|
{
|
|
frameType_ = type;
|
|
}
|
|
} // namespace panda::ecmascript::kungfu
|