!3550 Simplifield circuit graph

Merge pull request !3550 from 孙哲/master
This commit is contained in:
openharmony_ci 2023-02-14 10:03:18 +00:00 committed by Gitee
commit 6d3c60682d
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
28 changed files with 778 additions and 928 deletions

View File

@ -92,6 +92,7 @@ source_set("libark_jsoptimizer_set") {
"gate.cpp",
"gate_accessor.cpp",
"gate_meta_data.cpp",
"graph_editor.cpp",
"ic_stub_builder.cpp",
"interpreter_stub.cpp",
"llvm_codegen.cpp",

View File

@ -37,11 +37,14 @@ void AsyncFunctionLowering::ProcessJumpTable()
{
GateRef newTarget = argAccessor_.GetCommonArgGate(CommonArgIdx::NEW_TARGET);
GateRef isEqual = builder_.Equal(newTarget, builder_.Undefined());
GateRef stateEntryState = *accessor_.ConstUses(stateEntry_).begin();
auto firstUse = accessor_.ConstUses(stateEntry_).begin();
GateRef ifBranchCondition = builder_.Branch(stateEntry_, isEqual);
GateRef ifTrueCondition = builder_.IfTrue(ifBranchCondition);
GateRef ifFalseCondition = builder_.IfFalse(ifBranchCondition);
accessor_.ReplaceStateIn(stateEntryState, ifTrueCondition);
if (accessor_.GetOpCode(*firstUse) == OpCode::STATE_SPLIT) {
firstUse++;
}
accessor_.ReplaceStateIn(*firstUse, ifTrueCondition);
GateRef contextOffset = builder_.IntPtr(JSGeneratorObject::GENERATOR_CONTEXT_OFFSET);
GateRef val = builder_.PtrAdd(newTarget, contextOffset);

View File

@ -583,8 +583,8 @@ void BytecodeCircuitBuilder::CollectPredsInfo()
EnumerateBlock(bb, [&noThrow, &bb]
(const BytecodeInfo &bytecodeInfo) -> bool {
if (bytecodeInfo.IsGeneral()) {
noThrow = false;
if (!bb.catchs.empty()) {
if (!bb.catchs.empty() && !bytecodeInfo.NoThrow()) {
noThrow = false;
bb.catchs.at(0)->numOfStatePreds++;
}
}
@ -831,6 +831,7 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, GateRef &state, GateR
gate = circuit_->NewGate(meta, MachineType::NOVALUE, inList.size(),
inList.data(), GateType::Empty());
}
byteCodeToJSGate_[iterator.Index()] = gate;
if (bytecodeInfo.IsSuspend()) {
auto offsetGate = circuit_->GetConstantGate(MachineType::I32,
GetJumpOffset(iterator.Index()),
@ -843,13 +844,30 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, GateRef &state, GateR
gateAcc_.NewIn(gate, 1, depend);
}
state = gate;
if (!bb.catchs.empty()) {
if (bytecodeInfo.IsThrow()) {
depend = gate;
if (!bb.catchs.empty()) {
auto &bbNext = bb.catchs.at(0);
auto isLoopBack = bbNext->loopbackBlocks.count(bb.id);
SetBlockPred(*bbNext, gate, gate, isLoopBack);
bbNext->expandedPreds.push_back({bb.id, iterator.Index(), true});
} else {
auto constant = circuit_->GetConstantGate(MachineType::I64,
JSTaggedValue::VALUE_EXCEPTION,
GateType::TaggedValue());
circuit_->NewGate(circuit_->Return(),
{ state, depend, constant, circuit_->GetReturnRoot() });
}
return;
}
if (!bb.catchs.empty() && !bytecodeInfo.NoThrow()) {
auto ifSuccess = circuit_->NewGate(circuit_->IfSuccess(), {gate});
auto ifException = circuit_->NewGate(circuit_->IfException(), {gate});
auto ifException = circuit_->NewGate(circuit_->IfException(), {gate, gate});
auto &bbNext = bb.catchs.at(0);
auto isLoopBack = bbNext->loopbackBlocks.count(bb.id);
SetBlockPred(*bbNext, ifException, gate, isLoopBack);
SetBlockPred(*bbNext, ifException, ifException, isLoopBack);
if (bytecodeInfo.GetOpcode() == EcmaOpcode::CREATEASYNCGENERATOROBJ_V8) {
bbNext->expandedPreds.push_back({bb.id, iterator.Index() + 1, true}); // 1: next pc
} else {
@ -857,7 +875,6 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, GateRef &state, GateR
}
state = ifSuccess;
}
byteCodeToJSGate_[iterator.Index()] = gate;
if (bytecodeInfo.IsGeneratorRelative()) {
if (bytecodeInfo.GetOpcode() == EcmaOpcode::SUSPENDGENERATOR_V8) {
auto hole = circuit_->GetConstantGate(MachineType::I64,
@ -873,14 +890,6 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, GateRef &state, GateR
suspendAndResumeGates_.emplace_back(gate);
}
depend = gate;
if (bytecodeInfo.IsThrow()) {
auto constant = circuit_->GetConstantGate(MachineType::I64,
JSTaggedValue::VALUE_EXCEPTION,
GateType::TaggedValue());
circuit_->NewGate(circuit_->Return(),
{ state, depend, constant, circuit_->GetReturnRoot() });
return;
}
if (iterator.Index() == bb.end) {
auto &bbNext = graph_[bb.id + 1];
auto isLoopBack = bbNext.loopbackBlocks.count(bb.id);
@ -1036,7 +1045,7 @@ void BytecodeCircuitBuilder::BuildSubCircuit()
ASSERT(dependCur != Circuit::NullGate());
if (!bb.trys.empty()) {
dependCur = circuit_->NewGate(circuit_->GetException(),
MachineType::I64, {dependCur}, GateType::Empty());
MachineType::I64, {stateCur, dependCur}, GateType::Empty());
}
EnumerateBlock(bb, [this, &stateCur, &dependCur, &bb]
(const BytecodeInfo &bytecodeInfo) -> bool {

View File

@ -57,6 +57,36 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
break;
}
switch (inst.GetOpcode()) {
case EcmaOpcode::TYPEOF_IMM8:
case EcmaOpcode::TYPEOF_IMM16:
case EcmaOpcode::ISTRUE:
case EcmaOpcode::ISFALSE:
case EcmaOpcode::STMODULEVAR_IMM8:
case EcmaOpcode::WIDE_STMODULEVAR_PREF_IMM16:
case EcmaOpcode::POPLEXENV:
case EcmaOpcode::NEWLEXENVWITHNAME_IMM8_ID16:
case EcmaOpcode::WIDE_NEWLEXENVWITHNAME_PREF_IMM16_ID16:
case EcmaOpcode::GETRESUMEMODE:
case EcmaOpcode::RESUMEGENERATOR:
case EcmaOpcode::LDLEXVAR_IMM4_IMM4:
case EcmaOpcode::LDLEXVAR_IMM8_IMM8:
case EcmaOpcode::WIDE_LDLEXVAR_PREF_IMM16_IMM16:
case EcmaOpcode::STLEXVAR_IMM4_IMM4:
case EcmaOpcode::STLEXVAR_IMM8_IMM8:
case EcmaOpcode::WIDE_STLEXVAR_PREF_IMM16_IMM16:
case EcmaOpcode::STRICTNOTEQ_IMM8_V8:
case EcmaOpcode::STRICTEQ_IMM8_V8:
case EcmaOpcode::CREATEEMPTYARRAY_IMM8:
case EcmaOpcode::CREATEEMPTYARRAY_IMM16:
case EcmaOpcode::CREATEEMPTYOBJECT:
case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM8_ID16:
case EcmaOpcode::CREATEARRAYWITHBUFFER_IMM16_ID16:
flags |= BytecodeFlags::NO_THROW;
default:
break;
}
switch (inst.GetOpcode()) {
case EcmaOpcode::MOV_V4_V4:
case EcmaOpcode::MOV_V8_V8:

View File

@ -41,6 +41,7 @@ enum BytecodeFlags : uint32_t {
GENERAL_BC = 1 << 3,
READ_THIS_OBJECT = 1 << 4,
NO_SIDE_EFFECTS = 1 << 5,
NO_THROW = 1 << 6,
};
enum BytecodeKind : uint32_t {
@ -60,7 +61,7 @@ class BytecodeMetaData {
public:
static constexpr uint32_t MAX_OPCODE_SIZE = 16;
static constexpr uint32_t MAX_SIZE_BITS = 4;
static constexpr uint32_t BYTECODE_FLAGS_SIZE = 6;
static constexpr uint32_t BYTECODE_FLAGS_SIZE = 7;
static constexpr uint32_t BYTECODE_KIND_SIZE = 4;
using OpcodeField = panda::BitField<EcmaOpcode, 0, MAX_OPCODE_SIZE>;
@ -78,6 +79,11 @@ public:
return HasFlag(BytecodeFlags::NO_SIDE_EFFECTS);
}
bool IsNoThrow() const
{
return HasFlag(BytecodeFlags::NO_THROW);
}
bool HasThisIn() const
{
return HasFlag(BytecodeFlags::READ_THIS_OBJECT);
@ -441,6 +447,11 @@ public:
return metaData_.IsNoSideEffects();
}
bool NoThrow() const
{
return metaData_.IsNoThrow();
}
bool ThisObjectIn() const
{
return metaData_.HasThisIn();

View File

@ -137,6 +137,11 @@ public:
return LoadGatePtrConst(gate)->GetMetaData();
}
GateRef DeadGate()
{
return dead_ != 0 ? dead_ : NewGate(Dead(), MachineType::NOVALUE, GateType::Empty());
}
private:
static const size_t CIRCUIT_SPACE = 1U << 30U; // 1GB
@ -186,6 +191,7 @@ private:
Chunk chunk_;
GateRef root_ { 0 };
GateRef dead_ { 0 };
GateMetaBuilder metaBuilder_;
#ifndef NDEBUG
ChunkVector<GateRef> allGates_;

View File

@ -877,6 +877,11 @@ GateRef CircuitBuilder::GetDepend() const
return GetCurrentLabel()->GetDepend();
}
StateDepend CircuitBuilder::GetStateDepend() const
{
return StateDepend(GetState(), GetDepend());
}
void CircuitBuilder::SetDepend(GateRef depend)
{
GetCurrentLabel()->SetDepend(depend);

View File

@ -127,11 +127,6 @@ GateRef CircuitBuilder::DependRelay(GateRef state, GateRef depend)
return circuit_->NewGate(circuit_->DependRelay(), { state, depend });
}
GateRef CircuitBuilder::DependAnd(std::initializer_list<GateRef> args)
{
return circuit_->NewGate(circuit_->DependAnd(), args);
}
GateRef CircuitBuilder::Arguments(size_t index)
{
auto argListOfCircuit = circuit_->GetArgRoot();
@ -410,7 +405,6 @@ GateRef CircuitBuilder::CallBCHandler(GateRef glue, GateRef target, const std::v
auto label = GetCurrentLabel();
auto depend = label->GetDepend();
GateRef result = Call(cs, glue, target, depend, args);
label->SetDepend(result);
return result;
}
@ -421,7 +415,6 @@ GateRef CircuitBuilder::CallBuiltin(GateRef glue, GateRef target, const std::vec
auto label = GetCurrentLabel();
auto depend = label->GetDepend();
GateRef result = Call(cs, glue, target, depend, args);
label->SetDepend(result);
return result;
}
@ -432,7 +425,6 @@ GateRef CircuitBuilder::CallBuiltinWithArgv(GateRef glue, GateRef target, const
auto label = GetCurrentLabel();
auto depend = label->GetDepend();
GateRef result = Call(cs, glue, target, depend, args);
label->SetDepend(result);
return result;
}
@ -443,7 +435,6 @@ GateRef CircuitBuilder::CallBCDebugger(GateRef glue, GateRef target, const std::
auto label = GetCurrentLabel();
auto depend = label->GetDepend();
GateRef result = Call(cs, glue, target, depend, args);
label->SetDepend(result);
return result;
}
@ -457,7 +448,6 @@ GateRef CircuitBuilder::CallRuntime(GateRef glue, int index, GateRef depend, con
depend = label->GetDepend();
}
GateRef result = Call(cs, glue, target, depend, args);
label->SetDepend(result);
return result;
}
@ -469,7 +459,6 @@ GateRef CircuitBuilder::CallRuntimeVarargs(GateRef glue, int index, GateRef argc
auto depend = label->GetDepend();
ASSERT(cs->IsRuntimeVAStub());
GateRef result = Call(cs, glue, target, depend, {argc, argv});
label->SetDepend(result);
return result;
}
@ -484,7 +473,6 @@ GateRef CircuitBuilder::CallNGCRuntime(GateRef glue, int index, GateRef depend,
depend = label->GetDepend();
}
GateRef result = Call(cs, glue, target, depend, args);
label->SetDepend(result);
return result;
}
@ -496,7 +484,6 @@ GateRef CircuitBuilder::CallStub(GateRef glue, int index, const std::vector<Gate
auto label = GetCurrentLabel();
auto depend = label->GetDepend();
GateRef result = Call(cs, glue, target, depend, args);
label->SetDepend(result);
return result;
}
@ -516,7 +503,6 @@ GateRef CircuitBuilder::CallBuiltinRuntime(GateRef glue, GateRef depend, const s
depend = label->GetDepend();
}
GateRef result = Call(cs, glue, target, depend, args);
label->SetDepend(result);
return result;
}
@ -550,6 +536,8 @@ GateRef CircuitBuilder::Call(const CallSignature* cs, GateRef glue, GateRef targ
MachineType machineType = cs->GetReturnType().GetMachineType();
GateType type = cs->GetReturnType().GetGateType();
GateRef result = GetCircuit()->NewGate(meta, machineType, inputs.size(), inputs.data(), type);
auto label = GetCurrentLabel();
label->SetDepend(result);
return result;
}
@ -1186,16 +1174,11 @@ void Label::LabelImpl::MergeAllControl()
void Label::LabelImpl::MergeAllDepend()
{
if (IsControlCase()) {
// Add depend_relay to current label
auto denpendEntry = env_->GetBuilder()->GetCircuit()->GetDependRoot();
dependRelay_ = env_->GetBuilder()->DependRelay(predeControl_, denpendEntry);
}
if (predecessors_.size() < 2) { // 2 : Loop Head only support two predecessors_
depend_ = predecessors_[0]->GetDepend();
if (dependRelay_ != -1) {
depend_ = env_->GetBuilder()->DependAnd({depend_, dependRelay_});
if (IsControlCase()) {
// Add depend_relay to current label
depend_ = env_->GetBuilder()->DependRelay(predeControl_, depend_);
}
return;
}

View File

@ -273,7 +273,6 @@ public:
GateRef SwitchCase(GateRef switchBranch, int64_t value);
GateRef DefaultCase(GateRef switchBranch);
GateRef DependRelay(GateRef state, GateRef depend);
GateRef DependAnd(std::initializer_list<GateRef> args);
GateRef BinaryArithmetic(const GateMetaData* meta, MachineType machineType,
GateRef left, GateRef right);
GateRef BinaryCmp(const GateMetaData* meta, GateRef left, GateRef right);
@ -408,7 +407,6 @@ public:
GateRef IsJSHClass(GateRef obj);
GateRef HasPendingException(GateRef glue);
// middle ir: operations with any type
template<TypedBinOp Op>
inline GateRef TypedBinaryOp(GateRef x, GateRef y, GateType xType, GateType yType, GateType gateType);
@ -510,6 +508,7 @@ public:
inline Label *GetCurrentLabel() const;
inline GateRef GetState() const;
inline GateRef GetDepend() const;
inline StateDepend GetStateDepend() const;
inline void SetDepend(GateRef depend);
inline void SetState(GateRef state);
@ -618,7 +617,6 @@ private:
Environment *env_;
GateRef control_;
GateRef predeControl_ {-1};
GateRef dependRelay_ {-1};
GateRef depend_ {-1};
GateRef loopDepend_ {-1};
std::vector<GateRef> otherPredeControls_;

View File

@ -8,7 +8,7 @@ Circuit IR splits a program into two major parts: [sequential logic](https://en.
* The **sequential logic** part is a subgraph of Circuit IR which is similar to the underlying control flow graph (CFG) of the program, and gates in this part are named **state gates** (since they acted like a [finite state machine](https://en.wikipedia.org/wiki/Finite-state_machine) (FSM)). Wires that connect two state gates represent possible state transitions of the FSM, and they are named **state wires**. Note that every gates that have output state wires are state gates.
* The **combinational logic** part is the other subgraph of Circuit IR which represents all computations in a program using a directed acyclic graph (DAG), and gates in this part are named **computation gates**. A computation gate can do simple things such as adding two integer values, or complex things such as calling a function (and thus make a change to the global memory). Most of **computation gates** will take some values as input and output a value. These values can be transferred by **data wires**. Some computation gates will load from or store to the global memory, so they should be executed non-simultaneously and in some order that will not violate memory dependencies (such as RAW, WAR and WAW). Addressing this issue, **dependency wires** are introduced to constrain the possible execution order of such computations. When a computation gate has multiple dependencies, an auxiliary gate `DEPEND_AND` is used to merge dependencies. Note that dependency wires are treated like data wires during the scheduling phase, since dependency wires can be viewed as special data wires that transfer huge values representing the whole memory.
* The **combinational logic** part is the other subgraph of Circuit IR which represents all computations in a program using a directed acyclic graph (DAG), and gates in this part are named **computation gates**. A computation gate can do simple things such as adding two integer values, or complex things such as calling a function (and thus make a change to the global memory). Most of **computation gates** will take some values as input and output a value. These values can be transferred by **data wires**. Some computation gates will load from or store to the global memory, so they should be executed non-simultaneously and in some order that will not violate memory dependencies (such as RAW, WAR and WAW). Addressing this issue, **dependency wires** are introduced to constrain the possible execution order of such computations. When a computation gate has multiple dependencies, an auxiliary gate `DEPEND_SELECTOR` is used to merge dependencies. Note that dependency wires are treated like data wires during the scheduling phase, since dependency wires can be viewed as special data wires that transfer huge values representing the whole memory.
In traditional [SSA](https://en.wikipedia.org/wiki/Static_single_assignment_form) form IR (e.g. LLVM IR), each instruction is placed inside a node of CFG (basic block), and all instructions in a basic block are [linearly ordered](https://en.wikipedia.org/wiki/Total_order). However, in Circuit IR, computation gates are not tied to state gates, and they are [partially ordered](https://en.wikipedia.org/wiki/Partially_ordered_set) by wires. Sequential logic part and combinational logic part are loosely coupled, they only interact in three ways:
@ -271,19 +271,6 @@ Represents dependency relay.
|-----------|----------|
| not used | not used |
#### DEPEND_AND
Represents dependency and operator.
| | state wires | #dependency wires | data wires |
|--------|-------------|-------------------|------------|
| input | [] | N | [] |
| output | {} | any | {} |
| Root | Bitfield |
|----------|---------------------------------|
| not used | number of dependency inputs (N) |
### HIR instructions
#### JS_BYTECODE

View File

@ -477,7 +477,6 @@ bool LatticeUpdateRuleSCCP::Run(GateRef gate)
{OpCode::VALUE_SELECTOR, [&]() -> bool { return RunValueSelector(gate); }},
{OpCode::DEPEND_SELECTOR, [&]() -> bool { return RunDependSelector(gate); }},
{OpCode::DEPEND_RELAY, [&]() -> bool { return RunDependRelay(gate); }},
{OpCode::DEPEND_AND, [&]() -> bool { return RunDependAnd(gate); }},
{OpCode::JS_BYTECODE, [&]() -> bool { return RunJSBytecode(gate); }},
{OpCode::IF_SUCCESS, [&]() -> bool { return RunIfSuccess(gate); }},
{OpCode::IF_EXCEPTION, [&]() -> bool { return RunIfException(gate); }},

View File

@ -544,9 +544,6 @@ void EarlyElimination::TryEliminate(GateRef gate)
case OpCode::DEPEND_SELECTOR:
TryEliminateDependSelector(gate);
break;
case OpCode::DEPEND_AND:
TryEliminateDependAnd(gate);
break;
case OpCode::DEPEND_ENTRY:
return;
default:
@ -755,16 +752,6 @@ void EarlyElimination::TryEliminateDependSelector(GateRef gate)
dependInfos_[acc_.GetId(gate)] = dependInfo;
}
void EarlyElimination::TryEliminateDependAnd(GateRef gate)
{
auto dep0 = acc_.GetDep(gate, 0);
auto info0 = dependInfos_[acc_.GetId(dep0)];
auto dep1 = acc_.GetDep(gate, 1);
auto info1 = dependInfos_[acc_.GetId(dep1)];
ASSERT(info0->Empty() || info1->Empty());
dependInfos_[acc_.GetId(gate)] = (!info0->Empty()) ? info0 : info1;
}
void EarlyElimination::RemoveGate(GateRef gate, GateRef value)
{
auto state = acc_.GetStateCount(gate) > 0 ? acc_.GetState(gate) : Circuit::NullGate();

View File

@ -225,7 +225,7 @@ class DependChainInfo : public ChunkObject {
public:
DependChainInfo(Chunk* chunk) : chunk_(chunk) {};
~DependChainInfo() = default;
bool operator == (const DependChainInfo& rhs) const
{
return (elementMap_ == rhs.elementMap_) &&
@ -347,7 +347,6 @@ private:
void TryEliminateTypedCallCheck(GateRef gate);
void TryEliminateStateSplitAndFrameState(GateRef gate);
void TryEliminateDependSelector(GateRef gate);
void TryEliminateDependAnd(GateRef gate);
void TryEliminateOther(GateRef gate);
bool IsTrustedType(GateRef gate) const;

View File

@ -71,9 +71,13 @@ GateRef FrameStateBuilder::FrameState(size_t pcOffset, FrameStateInfo *stateInfo
void FrameStateBuilder::BindStateSplit(GateRef gate, size_t pcOffset, FrameStateInfo *stateInfo)
{
auto state = gateAcc_.GetState(gate);
auto depend = gateAcc_.GetDep(gate);
if (gateAcc_.GetOpCode(state) == OpCode::IF_SUCCESS) {
state = gateAcc_.GetState(state);
}
GateRef frameState = FrameState(pcOffset, stateInfo);
GateRef stateSplit = circuit_->NewGate(circuit_->StateSplit(), {depend, frameState});
GateRef stateSplit = circuit_->NewGate(circuit_->StateSplit(), {state, depend, frameState});
gateAcc_.ReplaceDependIn(gate, stateSplit);
if (builder_->IsLogEnabled()) {
gateAcc_.ShortPrint(frameState);

View File

@ -275,7 +275,7 @@ void Gate::CheckBranchOutput() const
void Gate::CheckNOP() const
{
if (GetOpCode() == OpCode::NOP) {
if (GetOpCode() == OpCode::NOP || GetOpCode() == OpCode::DEAD) {
if (!IsFirstOutNull()) {
CheckFailed("NOP gate used by other gates", -1);
}
@ -696,7 +696,7 @@ std::string Gate::GateTypeStr(GateType gateType) const
void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx) const
{
auto opcode = GetOpCode();
if (opcode != OpCode::NOP) {
if (opcode != OpCode::NOP && opcode != OpCode::DEAD) {
std::string log("{\"id\":" + std::to_string(id_) + ", \"op\":\"" + GateMetaData::Str(opcode) + "\", ");
log += ((bytecode.compare("") == 0) ? "" : "\"bytecode\":\"") + bytecode;
log += ((bytecode.compare("") == 0) ? "" : "\", ");
@ -752,7 +752,7 @@ void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx)
void Gate::ShortPrint(std::string bytecode, bool inListPreview, size_t highlightIdx) const
{
auto opcode = GetOpCode();
if (opcode != OpCode::NOP) {
if (opcode != OpCode::NOP && opcode != OpCode::DEAD) {
std::string log("(\"id\"=" + std::to_string(id_) + ", \"op\"=\"" + GateMetaData::Str(opcode) + "\", ");
log += ((bytecode.compare("") == 0) ? "" : "bytecode=") + bytecode;
log += ((bytecode.compare("") == 0) ? "" : ", ");

View File

@ -16,6 +16,7 @@
#include "ecmascript/compiler/argument_accessor.h"
#include "ecmascript/compiler/circuit_builder.h"
#include "ecmascript/compiler/gate_accessor.h"
#include "ecmascript/compiler/graph_editor.h"
namespace panda::ecmascript::kungfu {
using UseIterator = GateAccessor::UseIterator;
@ -442,28 +443,142 @@ void GateAccessor::SetGateType(GateRef gate, GateType gt)
circuit_->LoadGatePtr(gate)->SetGateType(gt);
}
UseIterator GateAccessor::DeleteExceptionDep(const UseIterator &useIt)
UseIterator GateAccessor::ReplaceHirIfSuccess(const UseIterator &useIt, GateRef state)
{
auto next = useIt;
next++;
ASSERT(GetOpCode(*useIt) == OpCode::RETURN || GetOpCode(*useIt) == OpCode::DEPEND_SELECTOR);
if (GetOpCode(*useIt) == OpCode::RETURN) {
DeleteGate(useIt);
} else {
size_t idx = useIt.GetIndex();
auto merge = GetState(*useIt, 0);
circuit_->DecreaseIn(merge, idx - 1);
auto mergeUses = Uses(merge);
for (auto useGate : mergeUses) {
if (circuit_->GetOpCode(useGate) == OpCode::VALUE_SELECTOR) {
circuit_->DecreaseIn(useGate, idx);
}
}
DecreaseIn(useIt);
}
ASSERT(GetOpCode(*useIt) == OpCode::IF_SUCCESS);
auto firstUse = Uses(*useIt).begin();
ReplaceIn(*firstUse, firstUse.GetIndex(), state);
auto next = DeleteGate(useIt);
return next;
}
UseIterator GateAccessor::ReplaceHirIfException(const UseIterator &useIt, StateDepend replacement)
{
ASSERT(GetOpCode(*useIt) == OpCode::IF_EXCEPTION);
auto uses = Uses(*useIt);
for (auto it = uses.begin(); it != uses.end();) {
if (IsStateIn(it)) {
it = ReplaceIn(it, replacement.State());
} else if (IsDependIn(it)) {
it = ReplaceIn(it, replacement.Depend());
} else {
ASSERT(!IsValueIn(it));
}
}
UseIterator next = useIt;
next++;
return next;
}
void GateAccessor::ExceptionReturn(GateRef state, GateRef depend)
{
CircuitBuilder builder(circuit_);
auto constant = builder.ExceptionConstant();
builder.Return(state, depend, constant);
}
void GateAccessor::ReplaceHirWithIfBranch(GateRef hirGate, StateDepend success,
StateDepend exception, GateRef value)
{
auto uses = Uses(hirGate);
GateRef ifException = Circuit::NullGate();
for (auto it = uses.begin(); it != uses.end();) {
if (IsStateIn(it)) {
const OpCode op = GetOpCode(*it);
if (op == OpCode::IF_SUCCESS) {
it = ReplaceHirIfSuccess(it, success.State());
} else if (op == OpCode::IF_EXCEPTION) {
ifException = *it;
it = ReplaceHirIfException(it, exception);
} else {
ExceptionReturn(exception.State(), exception.Depend());
it = ReplaceIn(it, success.State());
}
} else if (IsDependIn(it)) {
const OpCode op = GetOpCode(*it);
if (op == OpCode::IF_EXCEPTION) {
// ignore it now.
it++;
} else {
it = ReplaceIn(it, success.Depend());
}
} else {
ASSERT(IsValueIn(it));
it = ReplaceIn(it, value);
}
}
if (ifException != Circuit::NullGate()) {
DeleteGate(ifException);
}
// delete old gate
DeleteGate(hirGate);
}
void GateAccessor::ReplaceHirDirectly(GateRef hirGate,
StateDepend replacement, GateRef value)
{
auto uses = Uses(hirGate);
for (auto it = uses.begin(); it != uses.end();) {
if (IsStateIn(it)) {
ASSERT(GetOpCode(*it) != OpCode::IF_SUCCESS &&
GetOpCode(*it) != OpCode::IF_EXCEPTION);
it = ReplaceIn(it, replacement.State());
} else if (IsDependIn(it)) {
it = ReplaceIn(it, replacement.Depend());
} else {
ASSERT(IsValueIn(it));
it = ReplaceIn(it, value);
}
}
// delete old gate
DeleteGate(hirGate);
}
void GateAccessor::ReplaceHirAndDeleteIfException(GateRef hirGate,
StateDepend replacement, GateRef value)
{
if (value != Circuit::NullGate()) {
auto type = GetGateType(hirGate);
if (!type.IsAnyType()) {
SetGateType(value, type);
}
}
GateRef ifException = Circuit::NullGate();
auto uses = Uses(hirGate);
for (auto it = uses.begin(); it != uses.end();) {
if (IsStateIn(it)) {
const OpCode op = GetOpCode(*it);
if (op == OpCode::IF_SUCCESS) {
it = ReplaceHirIfSuccess(it, replacement.State());
} else if (op == OpCode::IF_EXCEPTION) {
ifException = *it;
it = ReplaceIn(it, circuit_->DeadGate());
} else {
it = ReplaceIn(it, replacement.State());
}
} else if (IsDependIn(it)) {
const OpCode op = GetOpCode(*it);
if (op == OpCode::IF_EXCEPTION) {
it = ReplaceIn(it, circuit_->DeadGate());
} else {
it = ReplaceIn(it, replacement.Depend());
}
} else {
ASSERT(IsValueIn(it));
it = ReplaceIn(it, value);
}
}
// delete old gate
DeleteGate(hirGate);
if (ifException != Circuit::NullGate()) {
GraphEditor::RemoveDeadState(circuit_, ifException);
}
}
UseIterator GateAccessor::DeleteGate(const UseIterator &useIt)
{
auto next = useIt;
@ -594,13 +709,11 @@ bool GateAccessor::IsFrameStateIn(const UseIterator &useIt) const
return IsFrameStateIn(*useIt, index);
}
bool GateAccessor::IsExceptionState(const UseIterator &useIt) const
bool GateAccessor::IsStateIn(GateRef gate, size_t index) const
{
auto op = GetOpCode(*useIt);
bool isDependSelector = (op == OpCode::DEPEND_SELECTOR) &&
(GetOpCode(GetIn(GetIn(*useIt, 0), useIt.GetIndex() - 1)) == OpCode::IF_EXCEPTION);
bool isReturn = (op == OpCode::RETURN && GetOpCode(GetIn(*useIt, 0)) == OpCode::IF_EXCEPTION);
return isDependSelector || isReturn;
size_t stateStartIndex = 0;
size_t stateEndIndex = stateStartIndex + GetStateCount(gate);
return (index >= stateStartIndex && index < stateEndIndex);
}
bool GateAccessor::IsDependIn(GateRef gate, size_t index) const

View File

@ -19,6 +19,59 @@
#include "ecmascript/compiler/circuit.h"
namespace panda::ecmascript::kungfu {
class StateDepend {
public:
StateDepend()
: state_(Circuit::NullGate()), depend_(Circuit::NullGate()) {}
explicit StateDepend(GateRef state, GateRef depend)
: state_(state), depend_(depend) {}
GateRef State() const
{
return state_;
}
GateRef Depend() const
{
return depend_;
}
void SetState(GateRef state)
{
state_ = state;
}
void SetDepend(GateRef depend)
{
depend_ = depend;
}
private:
GateRef state_;
GateRef depend_;
};
class Edge {
public:
explicit Edge(GateRef gate, size_t index) : gate_(gate), index_(static_cast<uint32_t>(index)) {}
GateRef GetGate() const
{
return gate_;
}
size_t GetIndex() const
{
return static_cast<size_t>(index_);
}
private:
GateRef gate_;
uint32_t index_;
};
class GateAccessor {
public:
// do not create new gate or modify self during iteration
@ -113,6 +166,13 @@ public:
return out_->GetIndex();
}
Edge GetEdge()
{
ASSERT(out_ != nullptr);
UseIterator it = *this;
return Edge(*it, GetIndex());
}
OpCode GetOpCode() const
{
ASSERT(out_ != nullptr);
@ -331,7 +391,6 @@ public:
// Add for lowering
GateType GetGateType(GateRef gate) const;
void SetGateType(GateRef gate, GateType gt);
UseIterator DeleteExceptionDep(const UseIterator &useIt);
void DeleteIn(GateRef gate, size_t idx);
UseIterator DeleteGate(const UseIterator &useIt);
void DecreaseIn(const UseIterator &useIt);
@ -376,7 +435,7 @@ public:
bool IsDependIn(const UseIterator &useIt) const;
bool IsValueIn(const UseIterator &useIt) const;
bool IsFrameStateIn(const UseIterator &useIt) const;
bool IsExceptionState(const UseIterator &useIt) const;
bool IsStateIn(GateRef gate, size_t index) const;
bool IsDependIn(GateRef gate, size_t index) const;
bool IsValueIn(GateRef gate, size_t index) const;
void GetStateUses(GateRef gate, std::vector<GateRef>& stateUses);
@ -416,7 +475,17 @@ public:
const GateMetaData *GetMetaData(GateRef gate) const;
void SetMetaData(GateRef gate, const GateMetaData* meta);
void ReplaceHirWithIfBranch(GateRef hirGate, StateDepend success,
StateDepend exception, GateRef value);
void ReplaceHirDirectly(GateRef hirGate, StateDepend replacement, GateRef value);
void ReplaceHirAndDeleteIfException(GateRef hirGate,
StateDepend replacement, GateRef value);
private:
UseIterator ReplaceHirIfSuccess(const UseIterator &useIt, GateRef state);
UseIterator ReplaceHirIfException(const UseIterator &useIt, StateDepend replacement);
void ExceptionReturn(GateRef state, GateRef depend);
GateRef GetRoot(OpCode opcode) const;
ConstUseIterator ConstUseBegin(GateRef gate) const
{

View File

@ -94,23 +94,47 @@ bool GateMetaData::IsState() const
bool GateMetaData::IsGeneralState() const
{
return ((opcode_ == OpCode::IF_TRUE) || (opcode_ == OpCode::IF_FALSE) ||
(opcode_ == OpCode::JS_BYTECODE) || (opcode_ == OpCode::IF_SUCCESS) ||
(opcode_ == OpCode::IF_EXCEPTION) || (opcode_ == OpCode::SWITCH_CASE) ||
(opcode_ == OpCode::DEFAULT_CASE) || (opcode_ == OpCode::MERGE) ||
(opcode_ == OpCode::LOOP_BEGIN) || (opcode_ == OpCode::ORDINARY_BLOCK) ||
(opcode_ == OpCode::STATE_ENTRY) || (opcode_ == OpCode::TYPED_BINARY_OP) ||
(opcode_ == OpCode::TYPE_CONVERT) || (opcode_ == OpCode::TYPED_UNARY_OP) ||
(opcode_ == OpCode::TO_LENGTH) || (opcode_ == OpCode::HEAP_ALLOC) ||
(opcode_ == OpCode::LOAD_ELEMENT) || (opcode_ == OpCode::LOAD_PROPERTY) ||
(opcode_ == OpCode::STORE_ELEMENT) || (opcode_ == OpCode::STORE_PROPERTY) ||
(opcode_ == OpCode::TYPED_CALL)) || (opcode_ == OpCode::DEOPT_CHECK);
switch (opcode_) {
case OpCode::IF_TRUE:
case OpCode::IF_FALSE:
case OpCode::JS_BYTECODE:
case OpCode::IF_SUCCESS:
case OpCode::IF_EXCEPTION:
case OpCode::SWITCH_CASE:
case OpCode::DEFAULT_CASE:
case OpCode::MERGE:
case OpCode::LOOP_BEGIN:
case OpCode::ORDINARY_BLOCK:
case OpCode::STATE_ENTRY:
case OpCode::TYPED_BINARY_OP:
case OpCode::TYPE_CONVERT:
case OpCode::TYPED_UNARY_OP:
case OpCode::TO_LENGTH:
case OpCode::HEAP_ALLOC:
case OpCode::LOAD_ELEMENT:
case OpCode::LOAD_PROPERTY:
case OpCode::STORE_ELEMENT:
case OpCode::STORE_PROPERTY:
case OpCode::TYPED_CALL:
case OpCode::DEOPT_CHECK:
return true;
default:
return false;
}
}
bool GateMetaData::IsTerminalState() const
{
return ((opcode_ == OpCode::RETURN) || (opcode_ == OpCode::THROW) ||
(opcode_ == OpCode::RETURN_VOID));
switch (opcode_) {
case OpCode::RETURN:
case OpCode::THROW:
case OpCode::RETURN_VOID:
case OpCode::GET_EXCEPTION:
case OpCode::STATE_SPLIT:
return true;
default:
return false;
}
}
bool GateMetaData::IsCFGMerge() const
@ -121,10 +145,18 @@ bool GateMetaData::IsCFGMerge() const
bool GateMetaData::IsControlCase() const
{
ASSERT(HasFlag(GateFlags::CONTROL));
return (opcode_ == OpCode::IF_BRANCH) || (opcode_ == OpCode::SWITCH_BRANCH) ||
(opcode_ == OpCode::IF_TRUE) || (opcode_ == OpCode::IF_FALSE) ||
(opcode_ == OpCode::IF_SUCCESS) || (opcode_ == OpCode::IF_EXCEPTION) ||
(opcode_ == OpCode::SWITCH_CASE) || (opcode_ == OpCode::DEFAULT_CASE);
// should add relay
switch (opcode_) {
case OpCode::IF_BRANCH:
case OpCode::SWITCH_BRANCH:
case OpCode::IF_TRUE:
case OpCode::IF_FALSE:
case OpCode::SWITCH_CASE:
case OpCode::DEFAULT_CASE:
return true;
default:
return false;
}
}
bool GateMetaData::IsLoopHead() const
@ -134,7 +166,7 @@ bool GateMetaData::IsLoopHead() const
bool GateMetaData::IsNop() const
{
return (opcode_ == OpCode::NOP);
return (opcode_ == OpCode::NOP || opcode_ == OpCode::DEAD);
}
bool GateMetaData::IsConstant() const

View File

@ -185,11 +185,10 @@ std::string MachineTypeToStr(MachineType machineType);
V(LoopBegin, LOOP_BEGIN, GateFlags::CONTROL, 2, 0, 0) \
V(LoopBack, LOOP_BACK, GateFlags::CONTROL, 1, 0, 0) \
V(DependRelay, DEPEND_RELAY, GateFlags::FIXED, 1, 1, 0) \
V(DependAnd, DEPEND_AND, GateFlags::FIXED, 0, 2, 0) \
V(IfSuccess, IF_SUCCESS, GateFlags::CONTROL, 1, 0, 0) \
V(IfException, IF_EXCEPTION, GateFlags::CONTROL, 1, 0, 0) \
V(GetException, GET_EXCEPTION, GateFlags::NONE_FLAG, 0, 1, 0) \
V(StateSplit, STATE_SPLIT, GateFlags::CHECKABLE, 0, 1, 0) \
V(IfException, IF_EXCEPTION, GateFlags::CONTROL, 1, 1, 0) \
V(GetException, GET_EXCEPTION, GateFlags::NONE_FLAG, 1, 1, 0) \
V(StateSplit, STATE_SPLIT, GateFlags::CHECKABLE, 1, 1, 0) \
V(Deopt, DEOPT, GateFlags::NONE_FLAG, 0, 1, 3) \
V(Load, LOAD, GateFlags::NONE_FLAG, 0, 1, 1) \
V(Store, STORE, GateFlags::NONE_FLAG, 0, 1, 2) \
@ -207,6 +206,7 @@ std::string MachineTypeToStr(MachineType machineType);
V(TypedSuperAllocateThis, TYPED_SUPER_ALLOCATE_THIS, GateFlags::CHECKABLE, 1, 1, 2) \
V(GetSuperConstructor, GET_SUPER_CONSTRUCTOR, GateFlags::NO_WRITE, 1, 1, 1) \
V(UpdateHotness, UPDATE_HOTNESS, GateFlags::NO_WRITE, 1, 1, 1) \
V(Dead, DEAD, GateFlags::NONE_FLAG, 0, 0, 0) \
BINARY_GATE_META_DATA_CACHE_LIST(V) \
UNARY_GATE_META_DATA_CACHE_LIST(V)

View File

@ -0,0 +1,133 @@
/*
* Copyright (c) 2023 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 <queue>
#include <stack>
#include "ecmascript/compiler/graph_editor.h"
namespace panda::ecmascript::kungfu {
void GraphEditor::RemoveDeadState(Circuit* circuit, GateRef gate)
{
GraphEditor editor(circuit);
editor.ReplaceGate(gate);
editor.RemoveGate();
}
void GraphEditor::ReplaceGate(GateRef gate)
{
auto uses = acc_.Uses(gate);
for (auto useIt = uses.begin(); useIt != uses.end();) {
if (acc_.IsDependIn(useIt)) {
GateRef depend = acc_.GetDep(gate);
useIt = acc_.ReplaceIn(useIt, depend);
} else {
workList_.push_back(useIt.GetEdge());
useIt = acc_.ReplaceIn(useIt, circuit_->DeadGate());
}
}
acc_.DeleteGate(gate);
}
void GraphEditor::RemoveGate()
{
while (!workList_.empty()) {
Edge& edge = workList_.back();
GateRef gate = edge.GetGate();
workList_.pop_back();
auto opcode = acc_.GetOpCode(gate);
switch (opcode) {
case OpCode::NOP:
case OpCode::DEAD:
// dead op, just continue
break;
case OpCode::MERGE:
PropagateMerge(edge);
break;
case OpCode::LOOP_BACK:
PropagateLoopBack(edge);
break;
default:
PropagateGate(edge);
break;
}
}
}
void GraphEditor::PropagateGate(const Edge& edge)
{
GateRef gate = edge.GetGate();
// isStateIn
if (acc_.IsStateIn(gate, edge.GetIndex())) {
// 2: is loop begin
ASSERT(acc_.GetStateCount(gate) == 1 ||
acc_.GetStateCount(gate) == 2); // 2: LOOP_BEGIN
ReplaceGate(gate);
return;
}
// IsDependIn
if (acc_.IsValueIn(gate, edge.GetIndex())) {
// value gate
ReplaceGate(gate);
}
}
void GraphEditor::PropagateMerge(const Edge& edge)
{
GateRef gate = edge.GetGate();
auto numIns = acc_.GetNumIns(gate);
if (numIns == 1) {
ReplaceGate(gate);
} else {
auto uses = acc_.Uses(gate);
for (auto useIt = uses.begin(); useIt != uses.end(); useIt++) {
GateRef use = *useIt;
// (Gate1) (Dead) (Gate2) (Gate1) (Gate2)
// | | | | |
// ___________________ ==> __________
// | |
// (phi) (phi)
if (acc_.GetOpCode(use) == OpCode::VALUE_SELECTOR ||
acc_.GetOpCode(use) == OpCode::DEPEND_SELECTOR) {
acc_.DecreaseIn(use, edge.GetIndex() + 1); // +1 skip state input
}
}
acc_.DecreaseIn(gate, edge.GetIndex());
}
}
void GraphEditor::PropagateLoopBack(const Edge& edge)
{
GateRef gate = edge.GetGate();
auto uses = acc_.Uses(gate);
auto firstUse = uses.begin();
if (firstUse == uses.end()) {
// LoopBegin => LoopBack
ReplaceGate(gate);
} else {
// maybe Merge => LoopBack
GateRef loopBegin = *firstUse;
GateRef otherStateIn = acc_.GetState(loopBegin, 0);
firstUse = acc_.Uses(loopBegin).begin();
acc_.ReplaceIn(*firstUse, firstUse.GetIndex(), otherStateIn);
ReplaceGate(gate);
acc_.DeleteGate(loopBegin);
}
}
} // namespace panda::ecmascript::kungfu

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2023 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_GRAPH_EDITOR_H
#define ECMASCRIPT_COMPILER_GRAPH_EDITOR_H
#include "ecmascript/compiler/circuit_builder.h"
#include "ecmascript/compiler/gate_accessor.h"
#include "ecmascript/mem/chunk_containers.h"
namespace panda::ecmascript::kungfu {
class GraphEditor {
public:
GraphEditor(Circuit *circuit)
: circuit_(circuit), acc_(circuit),
chunk_(circuit->chunk()), workList_(circuit->chunk()) {}
~GraphEditor() = default;
static void RemoveDeadState(Circuit* circuit, GateRef gate);
private:
void ReplaceGate(GateRef gate);
void RemoveGate();
void PropagateGate(const Edge& edge);
void PropagateMerge(const Edge& edge);
void PropagateLoopBack(const Edge& edge);
Circuit *circuit_ {nullptr};
GateAccessor acc_;
Chunk* chunk_ {nullptr};
ChunkVector<Edge> workList_;
};
} // panda::ecmascript::kungfu
#endif // ECMASCRIPT_COMPILER_COMMON_STUBEXPRESSION_ELIMINATING_H

View File

@ -187,9 +187,9 @@ void LLVMIRBuilder::InitializeHandlers()
};
illegalOpHandlers_ = {
OpCode::NOP, OpCode::CIRCUIT_ROOT, OpCode::DEPEND_ENTRY,
OpCode::RETURN_LIST,
OpCode::DEAD, OpCode::RETURN_LIST,
OpCode::ARG_LIST, OpCode::THROW,
OpCode::DEPEND_SELECTOR, OpCode::DEPEND_RELAY, OpCode::DEPEND_AND,
OpCode::DEPEND_SELECTOR, OpCode::DEPEND_RELAY,
OpCode::FRAME_STATE, OpCode::STATE_SPLIT
};
}

File diff suppressed because it is too large Load Diff

View File

@ -116,7 +116,6 @@ public:
: tsManager_(tsManager), methodLiteral_(methodLiteral),
circuit_(circuit), acc_(circuit),
argAcc_(circuit), builder_(circuit, cmpCfg),
dependEntry_(circuit->GetDependRoot()),
enableLog_(enableLog), methodName_(name), glue_(acc_.GetGlueFromArgList())
{
traceBc_ = cmpCfg->IsTraceBC();
@ -146,16 +145,8 @@ private:
return methodName_;
}
GateAccessor::UseIterator ReplaceHirControlGate(const GateAccessor::UseIterator &useIt, GateRef newGate,
bool noThrow = false);
void ReplaceHirToSubCfg(GateRef hir, GateRef outir,
const std::vector<GateRef> &successControl,
const std::vector<GateRef> &exceptionControl,
bool noThrow = false);
void ExceptionReturn(GateRef state, GateRef depend);
void ReplaceHirWithIfBranch(GateRef hirGate, GateRef callGate, GateRef ifBranch);
void ReplaceHirToCall(GateRef hirGate, GateRef callGate, bool noThrow = false);
void ReplaceHirToJSCall(GateRef hirGate, GateRef callGate);
void ReplaceHirWithPendingException(GateRef hirGate, GateRef state, GateRef depend, GateRef value);
void ReplaceHirWithValue(GateRef hirGate, GateRef value, bool noThrow = false);
void ReplaceHirToThrowCall(GateRef hirGate, GateRef callGate);
void LowerExceptionHandler(GateRef hirGate);
// environment must be initialized
@ -311,7 +302,6 @@ private:
GateAccessor acc_;
ArgumentAccessor argAcc_;
CircuitBuilder builder_;
GateRef dependEntry_;
bool enableLog_ {false};
bool traceBc_ {false};
bool profiling_ {false};

View File

@ -51,10 +51,11 @@ HWTEST_F_L0(LoweringRelateGateTests, TypeCheckFramework)
Environment env(1, &builder);
builder.SetEnvironment(&env);
auto depend = acc.GetDependRoot();
auto state = acc.GetStateRoot();
auto arg0 = builder.Arguments(0);
auto pcGate = circuit.GetConstantGate(MachineType::I64, 0, GateType::NJSValue());
auto frameState = circuit.NewGate(circuit.FrameState(1), {pcGate});
auto stateSplit = circuit.NewGate(circuit.StateSplit(), {depend, frameState});
auto stateSplit = circuit.NewGate(circuit.StateSplit(), {state, depend, frameState});
builder.SetDepend(stateSplit);
auto check = builder.PrimitiveTypeCheck(GateType::NumberType(), arg0);
builder.ReturnVoid(check, depend);
@ -142,11 +143,12 @@ HWTEST_F_L0(LoweringRelateGateTests, TypeOpCodeFramework)
CompilationConfig config("x86_64-unknown-linux-gnu", false);
TypeLowering typeLowering(&circuit, &config, nullptr, false, "TypeOpCodeFramework");
auto depend = acc.GetDependRoot();
auto state = acc.GetStateRoot();
auto arg0 = builder.Arguments(0);
auto arg1 = builder.Arguments(1);
auto pcGate = circuit.GetConstantGate(MachineType::I64, 0, GateType::NJSValue());
auto frameState = circuit.NewGate(circuit.FrameState(1), {pcGate});
auto stateSplit = circuit.NewGate(circuit.StateSplit(), {depend, frameState});
auto stateSplit = circuit.NewGate(circuit.StateSplit(), {state, depend, frameState});
builder.SetDepend(stateSplit);
builder.PrimitiveTypeCheck(GateType::NumberType(), arg0);
auto convert = builder.PrimitiveToNumber(arg1, arg1Type);

View File

@ -244,127 +244,6 @@ void TSTypeLowering::Lower(GateRef gate)
}
}
void TSTypeLowering::DeleteGates(GateRef hir, std::vector<GateRef> &unusedGate)
{
for (auto &gate : unusedGate) {
auto uses = acc_.Uses(gate);
for (auto useIt = uses.begin(); useIt != uses.end(); ++useIt) {
if (acc_.GetOpCode(gate) == OpCode::IF_EXCEPTION && acc_.GetOpCode(*useIt) == OpCode::MERGE) {
// handle exception merge has only one input, using state entry and depend entry to replace merge and
// dependselector.
if (acc_.GetNumIns(*useIt) == 1) {
GateRef stateEntry = circuit_->GetStateRoot();
GateRef dependEntry = circuit_->GetDependRoot();
auto mergeUses = acc_.Uses(*useIt);
for (auto mergeUseIt = mergeUses.begin(); mergeUseIt != uses.end(); ++mergeUseIt) {
if (acc_.GetOpCode(*mergeUseIt) == OpCode::DEPEND_SELECTOR) {
auto dependSelectorUses = acc_.Uses(*mergeUseIt);
acc_.ReplaceIn(*dependSelectorUses.begin(), 0, dependEntry);
acc_.DeleteGate(*mergeUseIt);
break;
}
}
acc_.ReplaceIn(*useIt, 0, stateEntry);
} else {
acc_.DecreaseIn(useIt);
}
}
}
acc_.DeleteGate(gate);
}
acc_.DeleteGate(hir);
}
void TSTypeLowering::ReplaceHIRGate(GateRef hir, GateRef outir, GateRef state, GateRef depend,
std::vector<GateRef> &unusedGate)
{
if (outir != Circuit::NullGate()) {
auto type = acc_.GetGateType(hir);
if (!type.IsAnyType()) {
acc_.SetGateType(outir, type);
}
}
std::map<GateRef, size_t> deleteMap;
auto uses = acc_.Uses(hir);
bool expFound = false;
for (auto tmpUseIt = uses.begin(); tmpUseIt != uses.end(); tmpUseIt++) {
if (acc_.GetOpCode(*tmpUseIt) == OpCode::IF_EXCEPTION) {
auto expUses = acc_.Uses(*tmpUseIt);
for (auto expUseIt = expUses.begin(); expUseIt != expUses.end(); ++expUseIt) {
if (acc_.GetOpCode(*expUseIt) == OpCode::MERGE && acc_.GetNumIns(*expUseIt) == 1) {
expFound = true;
break;
}
}
}
}
if (expFound) {
GateRef ifBranch = builder_.Branch(state, builder_.Boolean(false));
for (auto it = uses.begin(); it != uses.end();) {
if (acc_.GetOpCode(*it) == OpCode::IF_SUCCESS) {
acc_.SetMetaData(*it, circuit_->IfFalse());
it = acc_.ReplaceIn(it, ifBranch);
} else {
if (acc_.GetOpCode(*it) == OpCode::IF_EXCEPTION) {
acc_.SetMetaData(*it, circuit_->IfTrue());
it = acc_.ReplaceIn(it, ifBranch);
} else {
it++;
}
}
}
}
for (auto useIt = uses.begin(); useIt != uses.end();) {
const OpCode op = acc_.GetOpCode(*useIt);
if (op == OpCode::IF_SUCCESS) {
// success path use fastpath state
unusedGate.emplace_back(*useIt);
auto successUse = acc_.Uses(*useIt).begin();
acc_.ReplaceIn(successUse, state);
++useIt;
} else if (op == OpCode::IF_EXCEPTION) {
// exception path needs to delete all related nodes
unusedGate.emplace_back(*useIt);
auto exceptionUse = acc_.Uses(*useIt);
auto exceptionUseIt = exceptionUse.begin();
if (acc_.GetOpCode(*exceptionUseIt) == OpCode::MERGE) {
auto mergeUse = acc_.Uses(*exceptionUseIt);
// handle exception->merge->value_selector/depend_selector
for (auto mergeUseIt = mergeUse.begin(); mergeUseIt != mergeUse.end();) {
if (acc_.GetOpCode(*mergeUseIt) == OpCode::VALUE_SELECTOR ||
acc_.GetOpCode(*mergeUseIt) == OpCode::DEPEND_SELECTOR) {
deleteMap[*mergeUseIt] = exceptionUseIt.GetIndex() + 1;
}
++mergeUseIt;
}
} else if (acc_.GetOpCode(*exceptionUseIt) == OpCode::RETURN) {
unusedGate.emplace_back(*exceptionUseIt);
}
++useIt;
} else if (op == OpCode::DEPEND_SELECTOR) {
if (acc_.GetOpCode(acc_.GetIn(acc_.GetIn(*useIt, 0), useIt.GetIndex() - 1)) == OpCode::IF_EXCEPTION) {
++useIt;
} else {
useIt = acc_.ReplaceIn(useIt, depend);
}
} else {
if (acc_.IsValueIn(useIt)) {
useIt = acc_.ReplaceIn(useIt, outir);
} else if (acc_.IsDependIn(useIt)) {
useIt = acc_.ReplaceIn(useIt, depend);
} else {
useIt = acc_.ReplaceIn(useIt, state);
}
}
}
for (auto it = deleteMap.begin(); it != deleteMap.end(); it++) {
acc_.DecreaseIn(it->first, it->second);
}
}
void TSTypeLowering::LowerTypedAdd(GateRef gate)
{
GateRef left = acc_.GetValueIn(gate, 0);
@ -622,10 +501,7 @@ void TSTypeLowering::SpeculateNumbers(GateRef gate)
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
GateRef result = builder_.TypedBinaryOp<Op>(left, right, leftType, rightType, gateType);
std::vector<GateRef> removedGate;
ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
DeleteGates(gate, removedGate);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
}
bool TSTypeLowering::NeedInt32OverflowCheck(TypedUnOp op) const
@ -652,9 +528,7 @@ void TSTypeLowering::SpeculateNumber(GateRef gate)
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
GateRef result = builder_.TypedUnaryOp<Op>(value, valueType, gateType);
std::vector<GateRef> removedGate;
ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
DeleteGates(gate, removedGate);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
}
void TSTypeLowering::LowerTypeToNumeric(GateRef gate)
@ -678,9 +552,7 @@ void TSTypeLowering::LowerPrimitiveTypeToNumber(GateRef gate)
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
GateRef result = builder_.PrimitiveToNumber(src, VariableType(MachineType::I64, srcType));
std::vector<GateRef> removedGate;
ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
DeleteGates(gate, removedGate);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
}
void TSTypeLowering::LowerConditionJump(GateRef gate)
@ -730,11 +602,8 @@ void TSTypeLowering::LowerTypedLdArrayLength(GateRef gate)
builder_.ArrayCheck(array);
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
GateRef loadLength = builder_.LoadArrayLength(array);
std::vector<GateRef> removedGate;
ReplaceHIRGate(gate, loadLength, builder_.GetState(), builder_.GetDepend(), removedGate);
DeleteGates(gate, removedGate);
GateRef result = builder_.LoadArrayLength(array);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
}
void TSTypeLowering::LowerTypedLdObjByName(GateRef gate)
@ -780,9 +649,7 @@ void TSTypeLowering::LowerTypedLdObjByName(GateRef gate)
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
GateRef result = builder_.LoadProperty(receiver, propertyOffsetGate);
std::vector<GateRef> removedGate;
ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
DeleteGates(gate, removedGate);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
}
void TSTypeLowering::LowerTypedStObjByName(GateRef gate, bool isThis)
@ -829,9 +696,7 @@ void TSTypeLowering::LowerTypedStObjByName(GateRef gate, bool isThis)
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
builder_.StoreProperty(receiver, propertyOffsetGate, value);
std::vector<GateRef> removedGate;
ReplaceHIRGate(gate, Circuit::NullGate(), builder_.GetState(), builder_.GetDepend(), removedGate);
DeleteGates(gate, removedGate);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate());
}
void TSTypeLowering::LowerTypedLdObjByIndex(GateRef gate)
@ -865,9 +730,7 @@ void TSTypeLowering::LowerTypedLdObjByIndex(GateRef gate)
UNREACHABLE();
}
std::vector<GateRef> removedGate;
ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
DeleteGates(gate, removedGate);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
}
void TSTypeLowering::LowerTypedStObjByIndex(GateRef gate)
@ -903,9 +766,7 @@ void TSTypeLowering::LowerTypedStObjByIndex(GateRef gate)
UNREACHABLE();
}
std::vector<GateRef> removedGate;
ReplaceHIRGate(gate, Circuit::NullGate(), builder_.GetState(), builder_.GetDepend(), removedGate);
DeleteGates(gate, removedGate);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), Circuit::NullGate());
}
void TSTypeLowering::LowerTypedLdObjByValue(GateRef gate, bool isThis)
@ -939,9 +800,7 @@ void TSTypeLowering::LowerTypedLdObjByValue(GateRef gate, bool isThis)
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
GateRef result = builder_.LoadElement<TypedLoadOp::ARRAY_LOAD_ELEMENT>(receiver, propKey);
std::vector<GateRef> removedGate;
ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
DeleteGates(gate, removedGate);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
}
void TSTypeLowering::LowerTypedIsTrueOrFalse(GateRef gate, bool flag)
@ -967,9 +826,7 @@ void TSTypeLowering::LowerTypedIsTrueOrFalse(GateRef gate, bool flag)
result = builder_.TypedUnaryOp<TypedUnOp::TYPED_ISTRUE>(value, valueType, GateType::TaggedValue());
}
std::vector<GateRef> removedGate;
ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
DeleteGates(gate, removedGate);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
}
void TSTypeLowering::LowerTypedNewObjRange(GateRef gate)
@ -1002,7 +859,6 @@ void TSTypeLowering::LowerTypedNewObjRange(GateRef gate)
args.emplace_back(bcIndex);
GateRef constructGate = builder_.Construct(args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), constructGate);
}
@ -1036,7 +892,6 @@ void TSTypeLowering::LowerTypedSuperCall(GateRef gate, GateRef ctor, GateRef new
args.emplace_back(bcIndex);
GateRef constructGate = builder_.Construct(args);
acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), constructGate);
}
@ -1049,9 +904,7 @@ void TSTypeLowering::SpeculateCallBuiltin(GateRef gate, BuiltinsStubCSigns::ID i
ASSERT(acc_.GetOpCode(acc_.GetDep(gate)) == OpCode::STATE_SPLIT);
GateRef result = builder_.TypedCallBuiltin(a0, id);
std::vector<GateRef> removedGate;
ReplaceHIRGate(gate, result, builder_.GetState(), builder_.GetDepend(), removedGate);
DeleteGates(gate, removedGate);
acc_.ReplaceHirAndDeleteIfException(gate, builder_.GetStateDepend(), result);
}
BuiltinsStubCSigns::ID TSTypeLowering::GetBuiltinId(GateRef func, GateRef receiver)

View File

@ -56,9 +56,6 @@ private:
void Lower(GateRef gate);
void VerifyGuard() const;
void DeleteGates(GateRef hir, std::vector<GateRef> &unusedGate);
void ReplaceHIRGate(GateRef hir, GateRef outir, GateRef state, GateRef depend,
std::vector<GateRef> &unuseGate);
void LowerTypedAdd(GateRef gate);
void LowerTypedSub(GateRef gate);
void LowerTypedMul(GateRef gate);

View File

@ -30,6 +30,9 @@ for (x in mycars) {
finally {
fin = 1;
}
for (x in mycars) {
fin = -1;
}
fin = -1;
}
print(fin)