diff --git a/ecmascript/compiler/async_function_lowering.cpp b/ecmascript/compiler/async_function_lowering.cpp index 6184d963ed..6e5692ecb3 100644 --- a/ecmascript/compiler/async_function_lowering.cpp +++ b/ecmascript/compiler/async_function_lowering.cpp @@ -67,7 +67,7 @@ void AsyncFunctionLowering::RebuildGeneratorCfg(GateRef resumeGate, GateRef rest { GateRef ifSuccess = accessor_.GetState(resumeGate); GateRef suspendGate = accessor_.GetState(ifSuccess); - GateRef firstRestoreRegGate = GetFirstRestoreRegister(resumeGate); + GateRef restoreRegGate = accessor_.GetDep(resumeGate); GateRef offsetConstantGate = accessor_.GetValueIn(suspendGate); offsetConstantGate = builder_.TruncInt64ToInt32(offsetConstantGate); auto stateInGate = accessor_.GetState(resumeGate); @@ -87,7 +87,7 @@ void AsyncFunctionLowering::RebuildGeneratorCfg(GateRef resumeGate, GateRef rest if (flag) { accessor_.ReplaceStateIn(resumeGate, ifTrue); accessor_.ReplaceValueIn(resumeGate, newTarget); - accessor_.ReplaceDependIn(firstRestoreRegGate, ifTrueDepend); + accessor_.ReplaceDependIn(restoreRegGate, ifTrueDepend); circuit_->NewGate(circuit_->Return(), MachineType::NOVALUE, { ifSuccess, suspendGate, suspendGate, circuit_->GetReturnRoot() }, GateType::AnyType()); @@ -125,7 +125,7 @@ void AsyncFunctionLowering::RebuildGeneratorCfg(GateRef resumeGate, GateRef rest if (accessor_.GetOpCode(resumeStateGate) != OpCode::IF_TRUE) { accessor_.ReplaceStateIn(resumeGate, ifTrue); accessor_.ReplaceValueIn(resumeGate, newTarget); - accessor_.ReplaceDependIn(firstRestoreRegGate, bcOffsetPhiGate); + accessor_.ReplaceDependIn(restoreRegGate, bcOffsetPhiGate); circuit_->NewGate(circuit_->Return(), MachineType::NOVALUE, { ifSuccess, suspendGate, suspendGate, circuit_->GetReturnRoot() }, GateType::AnyType()); @@ -202,16 +202,5 @@ bool AsyncFunctionLowering::IsAsyncRelated() const { return bcBuilder_->GetAsyncRelatedGates().size() > 0; } - -GateRef AsyncFunctionLowering::GetFirstRestoreRegister(GateRef gate) const -{ - GateRef firstRestoreGate = 0; - GateRef curRestoreGate = accessor_.GetDep(gate); - while (accessor_.GetOpCode(curRestoreGate) == OpCode::RESTORE_REGISTER) { - firstRestoreGate = curRestoreGate; - curRestoreGate = accessor_.GetDep(curRestoreGate); - } - return firstRestoreGate; -} } // panda::ecmascript::kungfu diff --git a/ecmascript/compiler/async_function_lowering.h b/ecmascript/compiler/async_function_lowering.h index e38e845bfa..b12fa23fe2 100644 --- a/ecmascript/compiler/async_function_lowering.h +++ b/ecmascript/compiler/async_function_lowering.h @@ -57,8 +57,6 @@ private: void UpdateValueSelector(GateRef prevLoopBeginGate, GateRef controlStateGate, GateRef prevBcOffsetPhiGate); - GateRef GetFirstRestoreRegister(GateRef gate) const; - BytecodeCircuitBuilder *bcBuilder_; Circuit *circuit_; CircuitBuilder builder_; diff --git a/ecmascript/compiler/bytecode_circuit_builder.cpp b/ecmascript/compiler/bytecode_circuit_builder.cpp index 5856b729f6..b55f15eb88 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.cpp +++ b/ecmascript/compiler/bytecode_circuit_builder.cpp @@ -817,6 +817,23 @@ void BytecodeCircuitBuilder::NewJSGate(BytecodeRegion &bb, GateRef &state, GateR } byteCodeToJSGate_[iterator.Index()] = gate; if (bytecodeInfo.IsGeneratorRelative()) { + if (bytecodeInfo.GetOpcode() == EcmaOpcode::SUSPENDGENERATOR_V8) { + auto hole = circuit_->GetConstantGate(MachineType::I64, + JSTaggedValue::VALUE_HOLE, + GateType::TaggedValue()); + uint32_t numRegs = method_->GetNumberVRegs(); + std::vector vec(numRegs + 1, hole); + vec[0] = depend; + GateRef saveRegs = + circuit_->NewGate(circuit_->SaveRegister(numRegs), vec); + gateAcc_.ReplaceDependIn(gate, saveRegs); + } else if (bytecodeInfo.GetOpcode() == EcmaOpcode::RESUMEGENERATOR) { + GateRef restoreRegs = + circuit_->NewGate(circuit_->RestoreRegister(), { depend }); + gateAcc_.ReplaceDependIn(gate, restoreRegs); + } else { + UNREACHABLE(); + } suspendAndResumeGates_.emplace_back(gate); } if (bytecodeInfo.IsThrow()) { @@ -984,7 +1001,8 @@ void BytecodeCircuitBuilder::NewPhi(BytecodeRegion &bb, uint16_t reg, bool acc, gateAcc_.NewIn(currentPhi, 0, bb.stateStart); for (size_t i = 0; i < bb.numOfStatePreds; ++i) { auto &[predId, predBcIdx, isException] = bb.expandedPreds.at(i); - gateAcc_.NewIn(currentPhi, i + 1, ResolveDef(predId, predBcIdx, reg, acc)); + std::pair needReplaceInfo(currentPhi, i + 1); + gateAcc_.NewIn(currentPhi, i + 1, ResolveDef(predId, predBcIdx, reg, acc, needReplaceInfo)); } } else { // 2: the number of value inputs and it is in accord with LOOP_BEGIN @@ -998,7 +1016,9 @@ void BytecodeCircuitBuilder::NewPhi(BytecodeRegion &bb, uint16_t reg, bool acc, for (size_t i = 0; i < bb.numOfStatePreds; ++i) { auto &[predId, predBcIdx, isException] = bb.expandedPreds.at(i); if (bb.loopbackBlocks.count(predId)) { - gateAcc_.NewIn(loopBackValue, loopBackIndex++, ResolveDef(predId, predBcIdx, reg, acc)); + std::pair needReplaceInfo(loopBackValue, loopBackIndex); + gateAcc_.NewIn(loopBackValue, loopBackIndex++, + ResolveDef(predId, predBcIdx, reg, acc, needReplaceInfo)); } } inList = std::vector(1 + bb.numOfStatePreds - bb.numOfLoopBacks, Circuit::NullGate()); @@ -1010,7 +1030,8 @@ void BytecodeCircuitBuilder::NewPhi(BytecodeRegion &bb, uint16_t reg, bool acc, for (size_t i = 0; i < bb.numOfStatePreds; ++i) { auto &[predId, predBcIdx, isException] = bb.expandedPreds.at(i); if (!bb.loopbackBlocks.count(predId)) { - gateAcc_.NewIn(forwardValue, forwardIndex++, ResolveDef(predId, predBcIdx, reg, acc)); + std::pair needReplaceInfo(forwardValue, forwardIndex); + gateAcc_.NewIn(forwardValue, forwardIndex++, ResolveDef(predId, predBcIdx, reg, acc, needReplaceInfo)); } } gateAcc_.NewIn(currentPhi, 1, forwardValue); // 1: index of forward value input @@ -1019,8 +1040,8 @@ void BytecodeCircuitBuilder::NewPhi(BytecodeRegion &bb, uint16_t reg, bool acc, } // recursive variables renaming algorithm -GateRef BytecodeCircuitBuilder::ResolveDef(const size_t bbId, int32_t bcId, - const uint16_t reg, const bool acc) +GateRef BytecodeCircuitBuilder::ResolveDef(const size_t bbId, int32_t bcId, const uint16_t reg, const bool acc, + std::pair &needReplaceInfo) { auto tmpReg = reg; // find def-site in bytecodes of basic block @@ -1062,21 +1083,19 @@ GateRef BytecodeCircuitBuilder::ResolveDef(const size_t bbId, int32_t bcId, // New RESTORE_REGISTER HIR, used to restore the register content when processing resume instruction. // New SAVE_REGISTER HIR, used to save register content when processing suspend instruction. auto resumeGate = byteCodeToJSGate_.at(iterator.Index()); - ans = GetExistingRestore(resumeGate, tmpReg); - if (ans != Circuit::NullGate()) { + ans = gateAcc_.GetDep(resumeGate); + auto regs = gateAcc_.GetRestoreRegsInfo(ans); + auto it = regs.find(needReplaceInfo); + if (it != regs.end()) { break; } - GateRef resumeDependGate = gateAcc_.GetDep(resumeGate); - ans = circuit_->NewGate(circuit_->RestoreRegister(tmpReg), MachineType::I64, - { resumeDependGate }, GateType::AnyType()); - SetExistingRestore(resumeGate, tmpReg, ans); - gateAcc_.SetDep(resumeGate, ans); - auto saveRegGate = ResolveDef(bbId, iterator.Index() - 1, tmpReg, tmpAcc); + gateAcc_.SetRestoreRegsInfo(ans, needReplaceInfo, tmpReg); + + auto saveRegGate = ResolveDef(bbId, iterator.Index() - 1, tmpReg, tmpAcc, needReplaceInfo); ASSERT(Bytecodes::GetOpcode(iterator.PeekPrevPc(2)) == EcmaOpcode::SUSPENDGENERATOR_V8); // 2: prev bc GateRef suspendGate = byteCodeToJSGate_.at(iterator.Index() - 2); // 2: prev bc - auto dependGate = gateAcc_.GetDep(suspendGate); - auto newDependGate = circuit_->NewGate(circuit_->SaveRegister(tmpReg), {dependGate, saveRegGate}); - gateAcc_.SetDep(suspendGate, newDependGate); + GateRef saveRegs = gateAcc_.GetDep(suspendGate); + gateAcc_.ReplaceValueIn(saveRegs, saveRegGate, tmpReg); break; } // find GET_EXCEPTION gate if this is a catch block @@ -1112,7 +1131,7 @@ GateRef BytecodeCircuitBuilder::ResolveDef(const size_t bbId, int32_t bcId, } if (ans == Circuit::NullGate()) { // recursively find def-site in dominator block - return ResolveDef(bb.iDominator->id, bb.iDominator->end, tmpReg, tmpAcc); + return ResolveDef(bb.iDominator->id, bb.iDominator->end, tmpReg, tmpAcc, needReplaceInfo); } else { // def-site already found return ans; @@ -1167,12 +1186,13 @@ void BytecodeCircuitBuilder::BuildCircuit() if (!gateAcc_.IsInGateNull(gate, inIdx)) { continue; } + std::pair needReplaceInfo(gate, inIdx); if (valueIdx < bytecodeInfo.inputs.size()) { auto vregId = std::get(bytecodeInfo.inputs.at(valueIdx)).GetId(); - GateRef defVreg = ResolveDef(bbIndex, bcIndex - 1, vregId, false); + GateRef defVreg = ResolveDef(bbIndex, bcIndex - 1, vregId, false, needReplaceInfo); gateAcc_.NewIn(gate, inIdx, defVreg); } else { - GateRef defAcc = ResolveDef(bbIndex, bcIndex - 1, 0, true); + GateRef defAcc = ResolveDef(bbIndex, bcIndex - 1, 0, true, needReplaceInfo); gateAcc_.NewIn(gate, inIdx, defAcc); } } diff --git a/ecmascript/compiler/bytecode_circuit_builder.h b/ecmascript/compiler/bytecode_circuit_builder.h index 8249baeabe..506ef002ae 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.h +++ b/ecmascript/compiler/bytecode_circuit_builder.h @@ -433,7 +433,8 @@ private: void NewByteCode(BytecodeRegion &bb, GateRef &state, GateRef &depend); void BuildSubCircuit(); void NewPhi(BytecodeRegion &bb, uint16_t reg, bool acc, GateRef ¤tPhi); - GateRef ResolveDef(const size_t bbId, int32_t bcId, const uint16_t reg, const bool acc); + GateRef ResolveDef(const size_t bbId, int32_t bcId, const uint16_t reg, const bool acc, + std::pair &needReplaceInfo); void BuildCircuit(); GateRef GetExistingRestore(GateRef resumeGate, uint16_t tmpReg) const; void SetExistingRestore(GateRef resumeGate, uint16_t tmpReg, GateRef restoreGate); diff --git a/ecmascript/compiler/circuit.cpp b/ecmascript/compiler/circuit.cpp index 91c1d85407..a29d82dabb 100644 --- a/ecmascript/compiler/circuit.cpp +++ b/ecmascript/compiler/circuit.cpp @@ -279,7 +279,7 @@ void Circuit::ModifyIn(GateRef gate, size_t idx, GateRef in) { #ifndef NDEBUG ASSERT(idx < LoadGatePtrConst(gate)->GetNumIns()); - ASSERT(!Circuit::IsInGateNull(gate, idx)); + ASSERT(!Circuit::IsInGateNull(gate, idx) || (GetOpCode(gate) == OpCode::SAVE_REGISTER)); #endif LoadGatePtr(gate)->ModifyIn(idx, LoadGatePtr(in)); } diff --git a/ecmascript/compiler/circuit.h b/ecmascript/compiler/circuit.h index 04505bb8c8..abc28bfb16 100644 --- a/ecmascript/compiler/circuit.h +++ b/ecmascript/compiler/circuit.h @@ -130,6 +130,16 @@ public: return metaBuilder_.TypedBinaryOp(value, binOp); } + const GateMetaData* SaveRegister(uint64_t value) + { + return metaBuilder_.SaveRegister(value); + } + + const GateMetaData* RestoreRegister() + { + return metaBuilder_.RestoreRegister(); + } + const GateMetaData *GetMetaData(GateRef gate) const { return LoadGatePtrConst(gate)->GetMetaData(); diff --git a/ecmascript/compiler/frame_states.cpp b/ecmascript/compiler/frame_states.cpp index 69d315bb6b..5a58dbaa4e 100644 --- a/ecmascript/compiler/frame_states.cpp +++ b/ecmascript/compiler/frame_states.cpp @@ -394,22 +394,21 @@ void FrameStateBuilder::SaveBBBeginStateInfo(size_t bbId) void FrameStateBuilder::UpdateVirtualRegistersOfSuspend(GateRef gate) { - auto saveGate = gateAcc_.GetDep(gate); - while (gateAcc_.GetOpCode(saveGate) == OpCode::SAVE_REGISTER) { - auto vreg = static_cast(gateAcc_.GetVirtualRegisterIndex(saveGate)); - auto def = gateAcc_.GetValueIn(saveGate, 0); - UpdateVirtualRegister(vreg, def); - saveGate = gateAcc_.GetDep(saveGate); + auto saveRegsGate = gateAcc_.GetDep(gate); + size_t numOfRegs = gateAcc_.GetNumOfSaveRegs(saveRegsGate); + for (size_t i = 0; i < numOfRegs; i++) { + GateRef def = gateAcc_.GetValueIn(saveRegsGate, i); + UpdateVirtualRegister(i, def); } } void FrameStateBuilder::UpdateVirtualRegistersOfResume(GateRef gate) { auto restoreGate = gateAcc_.GetDep(gate); - while (gateAcc_.GetOpCode(restoreGate) == OpCode::RESTORE_REGISTER) { - auto vreg = static_cast(gateAcc_.GetVirtualRegisterIndex(restoreGate)); + auto info = gateAcc_.GetRestoreRegsInfo(restoreGate); + for (auto it = info.begin(); it != info.end(); ++it) { + auto vreg = it->second; UpdateVirtualRegister(vreg, Circuit::NullGate()); - restoreGate = gateAcc_.GetDep(restoreGate); } } } diff --git a/ecmascript/compiler/gate.h b/ecmascript/compiler/gate.h index 2a1f16e4ea..91caa33a6f 100644 --- a/ecmascript/compiler/gate.h +++ b/ecmascript/compiler/gate.h @@ -233,6 +233,16 @@ public: { return JSBytecodeMegaData::Cast(meta_); } + + const RestoreRegsMetaData* GetRestoreRegsMetaData() const + { + return RestoreRegsMetaData::Cast(meta_); + } + + const SaveRegsMetaData* GetSaveRegsMetaData() const + { + return SaveRegsMetaData::Cast(meta_); + } std::string MachineTypeStr(MachineType machineType) const; std::string GateTypeStr(GateType gateType) const; ~Gate() = default; diff --git a/ecmascript/compiler/gate_accessor.cpp b/ecmascript/compiler/gate_accessor.cpp index 90f4fef1cf..e5cbe33f70 100644 --- a/ecmascript/compiler/gate_accessor.cpp +++ b/ecmascript/compiler/gate_accessor.cpp @@ -190,6 +190,27 @@ EcmaOpcode GateAccessor::GetByteCodeOpcode(GateRef gate) const return gatePtr->GetJSBytecodeMetaData()->GetByteCodeOpcode(); } +const std::map, uint32_t> &GateAccessor::GetRestoreRegsInfo(GateRef gate) const +{ + ASSERT(GetOpCode(gate) == OpCode::RESTORE_REGISTER); + Gate *gatePtr = circuit_->LoadGatePtr(gate); + return gatePtr->GetRestoreRegsMetaData()->GetRestoreRegsInfo(); +} + +void GateAccessor::SetRestoreRegsInfo(GateRef gate, std::pair &info, uint32_t index) const +{ + ASSERT(GetOpCode(gate) == OpCode::RESTORE_REGISTER); + Gate *gatePtr = circuit_->LoadGatePtr(gate); + const_cast(gatePtr->GetRestoreRegsMetaData())->SetRestoreRegsInfo(info, index); +} + +size_t GateAccessor::GetNumOfSaveRegs(GateRef gate) const +{ + ASSERT(GetOpCode(gate) == OpCode::SAVE_REGISTER); + Gate *gatePtr = circuit_->LoadGatePtr(gate); + return static_cast(gatePtr->GetSaveRegsMetaData()->GetNumValue()); +} + void GateAccessor::Print(GateRef gate) const { Gate *gatePtr = circuit_->LoadGatePtr(gate); diff --git a/ecmascript/compiler/gate_accessor.h b/ecmascript/compiler/gate_accessor.h index 1bbdc958a5..5b1594a36a 100644 --- a/ecmascript/compiler/gate_accessor.h +++ b/ecmascript/compiler/gate_accessor.h @@ -317,6 +317,9 @@ public: const std::string GetConstantString(GateRef gate) const; uint32_t GetBytecodeIndex(GateRef gate) const; EcmaOpcode GetByteCodeOpcode(GateRef gate) const; + const std::map, uint32_t> &GetRestoreRegsInfo(GateRef gate) const; + void SetRestoreRegsInfo(GateRef gate, std::pair &info, uint32_t index) const; + size_t GetNumOfSaveRegs(GateRef gate) const; void Print(GateRef gate) const; void ShortPrint(GateRef gate) const; GateId GetId(GateRef gate) const; diff --git a/ecmascript/compiler/gate_meta_data.cpp b/ecmascript/compiler/gate_meta_data.cpp index a87b8f3e19..7749aeaf73 100644 --- a/ecmascript/compiler/gate_meta_data.cpp +++ b/ecmascript/compiler/gate_meta_data.cpp @@ -52,6 +52,8 @@ std::string GateMetaData::Str(OpCode opcode) GATE_META_DATA_LIST_WITH_SIZE(GATE_NAME_MAP) GATE_META_DATA_LIST_WITH_ONE_PARAMETER(GATE_NAME_MAP) GATE_META_DATA_LIST_WITH_STRING(GATE_NAME_MAP) + GATE_META_DATA_IN_SAVE_REGISTER(GATE_NAME_MAP) + GATE_META_DATA_IN_RESTORE_REGISTER(GATE_NAME_MAP) #undef GATE_NAME_MAP #define GATE_NAME_MAP(OP) { OpCode::OP, #OP }, GATE_OPCODE_LIST(GATE_NAME_MAP) @@ -243,4 +245,13 @@ const GateMetaData* GateMetaBuilder::NAME(const std::string &str) \ } GATE_META_DATA_LIST_WITH_STRING(DECLARE_GATE_META) #undef DECLARE_GATE_META + +#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \ +const GateMetaData* GateMetaBuilder::NAME(uint64_t value) \ +{ \ + auto meta = new (chunk_) SaveRegsMetaData(OpCode::OP, R, S, D, V, value); \ + return meta; \ +} +GATE_META_DATA_IN_SAVE_REGISTER(DECLARE_GATE_META) +#undef DECLARE_GATE_META } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/gate_meta_data.h b/ecmascript/compiler/gate_meta_data.h index 91616e026b..8aa1d68f7a 100644 --- a/ecmascript/compiler/gate_meta_data.h +++ b/ecmascript/compiler/gate_meta_data.h @@ -26,6 +26,7 @@ #include "libpandabase/macros.h" namespace panda::ecmascript::kungfu { +using GateRef = int32_t; enum MachineType : uint8_t { // Bit width NOVALUE = 0, ANYVALUE, @@ -218,8 +219,6 @@ std::string MachineTypeToStr(MachineType machineType); V(SwitchBranch, SWITCH_BRANCH, false, 1, 0, 1) \ V(SwitchCase, SWITCH_CASE, false, 1, 0, 0) \ V(HeapAlloc, HEAP_ALLOC, false, 1, 1, 1) \ - V(RestoreRegister, RESTORE_REGISTER, false, 0, 1, 0) \ - V(SaveRegister, SAVE_REGISTER, false, 0, 1, 1) \ V(LoadElement, LOAD_ELEMENT, false, 1, 1, 2) \ V(StoreElement, STORE_ELEMENT, false, 1, 1, 3) \ V(ConstData, CONST_DATA, false, 0, 0, 0) \ @@ -234,6 +233,12 @@ std::string MachineTypeToStr(MachineType machineType); #define GATE_META_DATA_LIST_WITH_STRING(V) \ V(ConstString, CONSTSTRING, false, 0, 0, 0) +#define GATE_META_DATA_IN_SAVE_REGISTER(V) \ + V(SaveRegister, SAVE_REGISTER, false, 0, 1, value) + +#define GATE_META_DATA_IN_RESTORE_REGISTER(V) \ + V(RestoreRegister, RESTORE_REGISTER, false, 0, 1, 0) + #define GATE_OPCODE_LIST(V) \ V(JS_BYTECODE) \ V(TYPED_BINARY_OP) @@ -245,6 +250,8 @@ enum class OpCode : uint8_t { GATE_META_DATA_LIST_WITH_SIZE(DECLARE_GATE_OPCODE) GATE_META_DATA_LIST_WITH_ONE_PARAMETER(DECLARE_GATE_OPCODE) GATE_META_DATA_LIST_WITH_STRING(DECLARE_GATE_OPCODE) + GATE_META_DATA_IN_SAVE_REGISTER(DECLARE_GATE_OPCODE) + GATE_META_DATA_IN_RESTORE_REGISTER(DECLARE_GATE_OPCODE) #undef DECLARE_GATE_OPCODE #define DECLARE_GATE_OPCODE(NAME) NAME, GATE_OPCODE_LIST(DECLARE_GATE_OPCODE) @@ -261,6 +268,8 @@ public: MUTABLE_STRING, JSBYTECODE, TYPED_BINARY_OP, + SAVE_REGISTERS_OP, + RESTORE_REGISTERS_OP, }; GateMetaData() = default; explicit GateMetaData(OpCode opcode, bool hasRoot, @@ -324,6 +333,16 @@ public: return GetKind() == MUTABLE_STRING; } + bool IsSaveRegisterOp() const + { + return GetKind() == SAVE_REGISTERS_OP; + } + + bool IsRestoreRegisterOp() const + { + return GetKind() == RESTORE_REGISTERS_OP; + } + bool IsRoot() const; bool IsProlog() const; bool IsFixed() const; @@ -440,6 +459,55 @@ private: uint64_t value_ { 0 }; }; +class SaveRegsMetaData : public GateMetaData { +public: + explicit SaveRegsMetaData(OpCode opcode, bool hasRoot, uint32_t statesIn, uint16_t dependsIn, uint32_t valuesIn, + uint64_t value) : GateMetaData(opcode, hasRoot, statesIn, dependsIn, valuesIn), numValue_(value) + { + SetKind(GateMetaData::SAVE_REGISTERS_OP); + } + + static const SaveRegsMetaData* Cast(const GateMetaData* meta) + { + ASSERT(meta->IsSaveRegisterOp()); + return static_cast(meta); + } + + uint64_t GetNumValue() const + { + return numValue_; + } +private: + uint64_t numValue_ { 0 }; +}; + +class RestoreRegsMetaData : public GateMetaData { +public: + explicit RestoreRegsMetaData() : GateMetaData(OpCode::RESTORE_REGISTER, false, 0, 1, 0) + { + SetKind(GateMetaData::RESTORE_REGISTERS_OP); + } + + static const RestoreRegsMetaData* Cast(const GateMetaData* meta) + { + ASSERT(meta->IsRestoreRegisterOp()); + return static_cast(meta); + } + + const std::map, uint32_t> &GetRestoreRegsInfo() const + { + return restoreRegsInfo_; + } + + void SetRestoreRegsInfo(std::pair &needReplaceInfo, uint32_t regIdx) + { + restoreRegsInfo_[needReplaceInfo] = regIdx; + } +private: + std::map, uint32_t> restoreRegsInfo_; +}; + + class TypedBinaryMegaData : public OneParameterMetaData { public: explicit TypedBinaryMegaData(uint64_t value, TypedBinOp binOp) diff --git a/ecmascript/compiler/gate_meta_data_builder.h b/ecmascript/compiler/gate_meta_data_builder.h index 6607b72ae6..08f879ac22 100644 --- a/ecmascript/compiler/gate_meta_data_builder.h +++ b/ecmascript/compiler/gate_meta_data_builder.h @@ -107,6 +107,11 @@ public: GATE_META_DATA_LIST_WITH_ONE_PARAMETER(DECLARE_GATE_META) #undef DECLARE_GATE_META +#define DECLARE_GATE_META(NAME, OP, R, S, D, V) \ + const GateMetaData* NAME(uint64_t value); + GATE_META_DATA_IN_SAVE_REGISTER(DECLARE_GATE_META) +#undef DECLARE_GATE_META + explicit GateMetaBuilder(Chunk* chunk); const GateMetaData* JSBytecode(size_t valuesIn, EcmaOpcode opcode, uint32_t bcIndex) { @@ -123,6 +128,11 @@ public: return &cachedNop_; } + const GateMetaData* RestoreRegister() + { + return new (chunk_) RestoreRegsMetaData(); + } + GateMetaData* NewGateMetaData(const GateMetaData* other) { auto meta = new (chunk_) GateMetaData(other->opcode_, other->HasRoot(), diff --git a/ecmascript/compiler/slowpath_lowering.cpp b/ecmascript/compiler/slowpath_lowering.cpp index cf72d0c02f..a8195df997 100644 --- a/ecmascript/compiler/slowpath_lowering.cpp +++ b/ecmascript/compiler/slowpath_lowering.cpp @@ -798,13 +798,9 @@ void SlowPathLowering::SaveFrameToContext(GateRef gate, GateRef jsFunc) GateRef genObj = acc_.GetValueIn(gate, 1); GateRef saveRegister = acc_.GetDep(gate); ASSERT(acc_.GetOpCode(saveRegister) == OpCode::SAVE_REGISTER); - std::vector saveRegisterGates {}; - while (acc_.GetOpCode(saveRegister) == OpCode::SAVE_REGISTER) { - saveRegisterGates.emplace_back(saveRegister); - saveRegister = acc_.GetDep(saveRegister); - } - acc_.SetDep(gate, saveRegister); - builder_.SetDepend(saveRegister); + + acc_.SetDep(gate, acc_.GetDep(saveRegister)); + builder_.SetDepend(acc_.GetDep(saveRegister)); GateRef context = builder_.Load(VariableType::JS_POINTER(), genObj, builder_.IntPtr(JSGeneratorObject::GENERATOR_CONTEXT_OFFSET)); // new tagged array @@ -815,12 +811,18 @@ void SlowPathLowering::SaveFrameToContext(GateRef gate, GateRef jsFunc) const int arrayId = RTSTUB_ID(NewTaggedArray); GateRef taggedArray = LowerCallRuntime(arrayId, {taggedLength}); // setRegsArrays - for (auto item : saveRegisterGates) { - auto index = acc_.GetVirtualRegisterIndex(item); - auto valueGate = acc_.GetValueIn(item); - builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue_, taggedArray, builder_.Int32(index), valueGate); - acc_.DeleteGate(item); - } + auto hole = circuit_->GetConstantGate(MachineType::I64, + JSTaggedValue::VALUE_HOLE, + GateType::TaggedValue()); + size_t numVreg = acc_.GetNumOfSaveRegs(saveRegister); + for (size_t idx = 0; idx < numVreg; idx++) { + GateRef tmpGate = acc_.GetValueIn(saveRegister, idx); + if (tmpGate != hole) { + builder_.SetValueToTaggedArray(VariableType::JS_ANY(), glue_, taggedArray, builder_.Int32(idx), tmpGate); + } + } + + acc_.DeleteGate(saveRegister); // setRegsArrays GateRef regsArrayOffset = builder_.IntPtr(GeneratorContext::GENERATOR_REGS_ARRAY_OFFSET); @@ -3100,37 +3102,36 @@ GateRef SlowPathLowering::GetValueFromTaggedArray(GateRef arrayGate, GateRef ind void SlowPathLowering::LowerResumeGenerator(GateRef gate) { GateRef obj = acc_.GetValueIn(gate, 0); - GateRef restoreGate = acc_.GetDep(gate); - std::vector registerGates {}; + GateRef restoreRegs = acc_.GetDep(gate); + auto restoreInfo = acc_.GetRestoreRegsInfo(restoreRegs); - while (acc_.GetOpCode(restoreGate) == OpCode::RESTORE_REGISTER) { - registerGates.emplace_back(restoreGate); - restoreGate = acc_.GetDep(restoreGate); - } - - acc_.SetDep(gate, restoreGate); - builder_.SetDepend(restoreGate); + acc_.SetDep(gate, acc_.GetDep(restoreRegs)); + builder_.SetDepend(acc_.GetDep(restoreRegs)); GateRef contextOffset = builder_.IntPtr(JSGeneratorObject::GENERATOR_CONTEXT_OFFSET); GateRef contextGate = builder_.Load(VariableType::JS_POINTER(), obj, contextOffset); GateRef arrayOffset = builder_.IntPtr(GeneratorContext::GENERATOR_REGS_ARRAY_OFFSET); GateRef arrayGate = builder_.Load(VariableType::JS_POINTER(), contextGate, arrayOffset); - for (auto item : registerGates) { - auto index = acc_.GetVirtualRegisterIndex(item); - auto indexOffset = builder_.Int32(index); - GateRef value = GetValueFromTaggedArray(arrayGate, indexOffset); - auto uses = acc_.Uses(item); - for (auto use = uses.begin(); use != uses.end();) { - size_t valueStartIndex = acc_.GetStateCount(*use) + acc_.GetDependCount(*use); - size_t valueEndIndex = valueStartIndex + acc_.GetInValueCount(*use); - if (use.GetIndex() >= valueStartIndex && use.GetIndex() < valueEndIndex) { - use = acc_.ReplaceIn(use, value); - } else { - use++; - } + auto uses = acc_.Uses(restoreRegs); + for (auto use = uses.begin(); use != uses.end();) { + int32_t vregId; + if (acc_.GetOpCode(*use) == OpCode::SAVE_REGISTER) { + vregId = use.GetIndex() - 1; + } else { + std::pair info(*use, use.GetIndex()); + vregId = restoreInfo[info]; } - acc_.DeleteGate(item); - } + auto vregIdOffset = builder_.Int32(vregId); + GateRef value = GetValueFromTaggedArray(arrayGate, vregIdOffset); + size_t valueStartIndex = acc_.GetStateCount(*use) + acc_.GetDependCount(*use); + size_t valueEndIndex = valueStartIndex + acc_.GetInValueCount(*use); + if (use.GetIndex() >= valueStartIndex && use.GetIndex() < valueEndIndex) { + use = acc_.ReplaceIn(use, value); + } else { + use++; + } + } + acc_.DeleteGate(restoreRegs); // 1: number of value inputs ASSERT(acc_.GetNumValueIn(gate) == 1);