mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2025-02-26 15:28:33 +00:00
!3550 Simplifield circuit graph
Merge pull request !3550 from 孙哲/master
This commit is contained in:
commit
6d3c60682d
@ -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",
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
|
@ -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_;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -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
|
||||
|
@ -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); }},
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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) ? "" : ", ");
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
133
ecmascript/compiler/graph_editor.cpp
Normal file
133
ecmascript/compiler/graph_editor.cpp
Normal 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
|
47
ecmascript/compiler/graph_editor.h
Normal file
47
ecmascript/compiler/graph_editor.h
Normal 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
|
@ -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
@ -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};
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -30,6 +30,9 @@ for (x in mycars) {
|
||||
finally {
|
||||
fin = 1;
|
||||
}
|
||||
for (x in mycars) {
|
||||
fin = -1;
|
||||
}
|
||||
fin = -1;
|
||||
}
|
||||
print(fin)
|
||||
|
Loading…
x
Reference in New Issue
Block a user