diff --git a/ecmascript/compiler/argument_accessor.cpp b/ecmascript/compiler/argument_accessor.cpp index 7b696faebb..f8e7a837b5 100644 --- a/ecmascript/compiler/argument_accessor.cpp +++ b/ecmascript/compiler/argument_accessor.cpp @@ -63,13 +63,13 @@ size_t ArgumentAccessor::GetFunctionArgIndex(const size_t currentVreg, const boo return static_cast(CommonArgIdx::NEW_TARGET); } if (!haveFunc && currentVreg == 1) { - return static_cast(CommonArgIdx::THIS); + return static_cast(CommonArgIdx::THIS_OBJECT); } if (!haveNewTarget && currentVreg == 0) { return static_cast(CommonArgIdx::FUNC); } if (!haveNewTarget && currentVreg == 1) { - return static_cast(CommonArgIdx::THIS); + return static_cast(CommonArgIdx::THIS_OBJECT); } if (!haveThis && currentVreg == 0) { return static_cast(CommonArgIdx::FUNC); @@ -87,7 +87,7 @@ size_t ArgumentAccessor::GetFunctionArgIndex(const size_t currentVreg, const boo return static_cast(CommonArgIdx::NEW_TARGET); } if (haveThis) { - return static_cast(CommonArgIdx::THIS); + return static_cast(CommonArgIdx::THIS_OBJECT); } } return currentVreg - numCommonArgs + static_cast(CommonArgIdx::NUM_OF_ARGS); diff --git a/ecmascript/compiler/argument_accessor.h b/ecmascript/compiler/argument_accessor.h index db4ac6929f..e41be91a1f 100644 --- a/ecmascript/compiler/argument_accessor.h +++ b/ecmascript/compiler/argument_accessor.h @@ -29,7 +29,7 @@ enum class CommonArgIdx : uint8_t { ACTUAL_ARGC, FUNC, NEW_TARGET, - THIS, + THIS_OBJECT, NUM_OF_ARGS, }; diff --git a/ecmascript/compiler/bytecode_circuit_builder.cpp b/ecmascript/compiler/bytecode_circuit_builder.cpp index 1881a657d2..ecb49f63ad 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.cpp +++ b/ecmascript/compiler/bytecode_circuit_builder.cpp @@ -385,8 +385,10 @@ void BytecodeCircuitBuilder::BuildBasicBlocks(std::map bbIdToDfsTimestamp; std::unordered_map dfsFatherIdx; std::unordered_map bbDfsTimestampToIdx; + std::vector basicBlockList; size_t timestamp = 0; std::deque pendingList; std::vector visited(graph_.size(), 0); @@ -396,30 +398,30 @@ void BytecodeCircuitBuilder::ComputeDominatorTree() while (!pendingList.empty()) { size_t curBlockId = pendingList.back(); pendingList.pop_back(); - bbDfsList_.push_back(curBlockId); - bbIdToDfsTimestamp_[curBlockId] = timestamp++; + basicBlockList.push_back(curBlockId); + bbIdToDfsTimestamp[curBlockId] = timestamp++; for (const auto &succBlock: graph_[curBlockId].succs) { if (visited[succBlock->id] == 0) { visited[succBlock->id] = 1; pendingList.push_back(succBlock->id); - dfsFatherIdx[succBlock->id] = bbIdToDfsTimestamp_[curBlockId]; + dfsFatherIdx[succBlock->id] = bbIdToDfsTimestamp[curBlockId]; } } } - for (size_t idx = 0; idx < bbDfsList_.size(); idx++) { - bbDfsTimestampToIdx[bbDfsList_[idx]] = idx; + for (size_t idx = 0; idx < basicBlockList.size(); idx++) { + bbDfsTimestampToIdx[basicBlockList[idx]] = idx; } - RemoveDeadRegions(); + RemoveDeadRegions(bbIdToDfsTimestamp); - std::vector immDom(bbDfsList_.size()); // immediate dominator with dfs order index - std::vector semiDom(bbDfsList_.size()); + std::vector immDom(basicBlockList.size()); // immediate dominator with dfs order index + std::vector semiDom(basicBlockList.size()); std::vector realImmDom(graph_.size()); // immediate dominator with real index - std::vector > semiDomTree(bbDfsList_.size()); + std::vector > semiDomTree(basicBlockList.size()); { - std::vector parent(bbDfsList_.size()); + std::vector parent(basicBlockList.size()); std::iota(parent.begin(), parent.end(), 0); - std::vector minIdx(bbDfsList_.size()); + std::vector minIdx(basicBlockList.size()); std::function unionFind = [&] (size_t idx) -> size_t { if (parent[idx] == idx) return idx; size_t unionFindSetRoot = unionFind(parent[idx]); @@ -435,8 +437,8 @@ void BytecodeCircuitBuilder::ComputeDominatorTree() }; std::iota(semiDom.begin(), semiDom.end(), 0); semiDom[0] = semiDom.size(); - for (size_t idx = bbDfsList_.size() - 1; idx >= 1; idx--) { - for (const auto &preBlock : graph_[bbDfsList_[idx]].preds) { + for (size_t idx = basicBlockList.size() - 1; idx >= 1; idx--) { + for (const auto &preBlock : graph_[basicBlockList[idx]].preds) { if (bbDfsTimestampToIdx[preBlock->id] < idx) { semiDom[idx] = std::min(semiDom[idx], bbDfsTimestampToIdx[preBlock->id]); } else { @@ -453,14 +455,14 @@ void BytecodeCircuitBuilder::ComputeDominatorTree() } } minIdx[idx] = idx; - merge(dfsFatherIdx[bbDfsList_[idx]], idx); + merge(dfsFatherIdx[basicBlockList[idx]], idx); semiDomTree[semiDom[idx]].push_back(idx); } - for (size_t idx = 1; idx < bbDfsList_.size(); idx++) { + for (size_t idx = 1; idx < basicBlockList.size(); idx++) { if (immDom[idx] != semiDom[idx]) { immDom[idx] = immDom[immDom[idx]]; } - realImmDom[bbDfsList_[idx]] = bbDfsList_[immDom[idx]]; + realImmDom[basicBlockList[idx]] = basicBlockList[immDom[idx]]; } semiDom[0] = 0; } @@ -525,12 +527,12 @@ void BytecodeCircuitBuilder::ComputeDomFrontiers(const std::vector &immD } } -void BytecodeCircuitBuilder::RemoveDeadRegions() +void BytecodeCircuitBuilder::RemoveDeadRegions(const std::map &bbIdToDfsTimestamp) { for (auto &block: graph_) { std::vector newPreds; for (auto &bb : block.preds) { - if (bbIdToDfsTimestamp_.count(bb->id)) { + if (bbIdToDfsTimestamp.count(bb->id)) { newPreds.emplace_back(bb); } } @@ -538,7 +540,7 @@ void BytecodeCircuitBuilder::RemoveDeadRegions() } for (auto &block : graph_) { - block.isDead = !bbIdToDfsTimestamp_.count(block.id); + block.isDead = !bbIdToDfsTimestamp.count(block.id); if (block.isDead) { block.succs.clear(); } @@ -1743,7 +1745,6 @@ void BytecodeCircuitBuilder::BuildCircuitArgs() argAcc_.CollectArgs(); if (hasTypes_) { argAcc_.FillArgsGateType(&typeRecorder_); - frameStateBuilder_.BuildArgsValues(&argAcc_); } } @@ -1998,7 +1999,7 @@ GateRef BytecodeCircuitBuilder::NewConst(const BytecodeInfo &info) gate = argAcc_.GetCommonArgGate(CommonArgIdx::NEW_TARGET); break; case EcmaOpcode::LDTHIS: - gate = argAcc_.GetCommonArgGate(CommonArgIdx::THIS); + gate = argAcc_.GetCommonArgGate(CommonArgIdx::THIS_OBJECT); break; default: UNREACHABLE(); @@ -2360,56 +2361,125 @@ GateRef BytecodeCircuitBuilder::RenameVariable(const size_t bbId, const uint8_t } } +void BytecodeCircuitBuilder::BuildDfsList() +{ + bbDfsList_.clear(); + + std::deque pendingList; + std::vector visited(graph_.size(), false); + auto basicBlockId = graph_[0].id; + pendingList.push_back(basicBlockId); + while (!pendingList.empty()) { + size_t curBlockId = pendingList.back(); + if (visited[curBlockId]) { + bbDfsList_.push_back(curBlockId); + pendingList.pop_back(); + continue; + } + visited[curBlockId] = true; + for (const auto &succBlock: graph_[curBlockId].succs) { + if (!visited[succBlock->id]) { + pendingList.push_back(succBlock->id); + } + } + for (const auto &succBlock: graph_[curBlockId].catchs) { + if (!visited[succBlock->id]) { + pendingList.push_back(succBlock->id); + } + } + } +} + +void BytecodeCircuitBuilder::FrameStateReplacePhi(GateRef phi, size_t reg) +{ + ASSERT(gateAcc_.GetOpCode(phi) == OpCode::VALUE_SELECTOR); + auto numValue = gateAcc_.GetNumValueIn(phi); + for (size_t i = 0; i < numValue; i++) { + auto value = gateAcc_.GetValueIn(phi, i); + auto it = jsgateToBytecode_.find(value); + if (it == jsgateToBytecode_.cend()) { + continue; + } + auto id = jsgateToBytecode_.at(value).first; + frameStateBuilder_.AdvenceToBasicBlock(id); + frameStateBuilder_.UpdateVirtualRegister(reg, value); + } +} + void BytecodeCircuitBuilder::BuildFrameState() { - const uint8_t *predPc = nullptr; + BuildDfsList(); + auto undefinedGate = circuit_.GetConstantGate(MachineType::I64, + JSTaggedValue::VALUE_UNDEFINED, + GateType::TaggedValue()); for (auto &dfsOrder : bbDfsList_) { auto bb = graph_[dfsOrder]; if (bb.isDead) { continue; } - if (bb.preds.size() != 0) { - std::sort(bb.preds.begin(), bb.preds.end(), [this](BytecodeRegion *a, BytecodeRegion *b) { - return bbIdToDfsTimestamp_[a->id] < bbIdToDfsTimestamp_[b->id]; - }); - auto predBb = bb.preds.at(0); - predPc = predBb->end; - } - frameStateBuilder_.AdvenceToSuccessor(predPc, bb.end); + frameStateBuilder_.AdvenceToBasicBlock(bb.id); + ReverseEnumerateBlock(bb, [this, undefinedGate] + (uint8_t * pc, BytecodeInfo &bytecodeInfo) -> bool { + GateRef gate = Circuit::NullGate(); + if (bytecodeInfo.IsMov()) { + // end def live range + if (bytecodeInfo.accOut) { + frameStateBuilder_.UpdateAccumulator(undefinedGate); + gate = frameStateBuilder_.ValuesAtAccumulator(); + } else if (bytecodeInfo.vregOut.size() != 0) { + auto out = bytecodeInfo.vregOut[0]; + gate = frameStateBuilder_.ValuesAt(out); + frameStateBuilder_.UpdateVirtualRegister(out, undefinedGate); + } + // start use live range + if (bytecodeInfo.accIn) { + frameStateBuilder_.UpdateAccumulator(gate); + } else if (bytecodeInfo.inputs.size() != 0) { + auto vreg = std::get(bytecodeInfo.inputs.at(0)).GetId(); + frameStateBuilder_.UpdateVirtualRegister(vreg, gate); + } + return true; + } else if (bytecodeInfo.IsGeneral() || bytecodeInfo.IsReturn() || bytecodeInfo.IsCondJump()) { + gate = byteCodeToJSGate_.at(pc); + } + // end def live range + if (bytecodeInfo.accOut) { + frameStateBuilder_.UpdateAccumulator(undefinedGate); + } + for (const auto &out: bytecodeInfo.vregOut) { + frameStateBuilder_.UpdateVirtualRegister(out, undefinedGate); + } + // start use live range + if (bytecodeInfo.accIn) { + auto id = bytecodeInfo.inputs.size(); + GateRef def = gateAcc_.GetValueIn(gate, id); + frameStateBuilder_.UpdateAccumulator(def); + } + for (size_t i = 0; i < bytecodeInfo.inputs.size(); i++) { + auto in = bytecodeInfo.inputs[i]; + if (std::holds_alternative(in)) { + auto vreg = std::get(in).GetId(); + GateRef def = gateAcc_.GetValueIn(gate, i); + frameStateBuilder_.UpdateVirtualRegister(vreg, def); + } + } + // build guard + if (bytecodeInfo.deopt) { + GateRef glue = argAcc_.GetCommonArgGate(CommonArgIdx::GLUE); + frameStateBuilder_.BindGuard(gate, bytecodeInfo.pcOffset, glue); + } + return true; + }); + // replace phi if (bb.valueSelectorAccGate != Circuit::NullGate()) { - frameStateBuilder_.UpdateAccumulator(bb.valueSelectorAccGate); + auto reg = frameStateBuilder_.GetAccumulatorIndex(); + FrameStateReplacePhi(bb.valueSelectorAccGate, reg); } for (auto &it : bb.vregToValSelectorGate) { auto reg = it.first; auto gate = it.second; - frameStateBuilder_.UpdateVirtualRegister(reg, gate); + FrameStateReplacePhi(gate, reg); } - EnumerateBlock(bb, [this](uint8_t * pc, BytecodeInfo &bytecodeInfo) -> bool { - GateRef gate = Circuit::NullGate(); - if (bytecodeInfo.IsMov()) { - if (bytecodeInfo.accIn) { - gate = frameStateBuilder_.ValuesAtAccumulator(); - } else if (bytecodeInfo.inputs.size() != 0) { - auto index = std::get(bytecodeInfo.inputs.at(0)).GetId(); - gate = frameStateBuilder_.ValuesAt(index); - } - } else if (bytecodeInfo.IsGeneral()) { - gate = byteCodeToJSGate_.at(pc); - if (bytecodeInfo.deopt) { - GateRef glue = argAcc_.GetCommonArgGate(CommonArgIdx::GLUE); - frameStateBuilder_.BindGuard(gate, bytecodeInfo.pcOffset, glue, jsgateToBytecode_); - } - } else if (bytecodeInfo.IsSetConstant()) { - gate = byteCodeToJSGate_.at(pc); - } - if (bytecodeInfo.accOut) { - frameStateBuilder_.UpdateAccumulator(gate); - } - for (const auto &out: bytecodeInfo.vregOut) { - frameStateBuilder_.UpdateVirtualRegister(out, gate); - } - return true; - }); } } diff --git a/ecmascript/compiler/bytecode_circuit_builder.h b/ecmascript/compiler/bytecode_circuit_builder.h index 4437bea0ad..0dfb2b98ff 100644 --- a/ecmascript/compiler/bytecode_circuit_builder.h +++ b/ecmascript/compiler/bytecode_circuit_builder.h @@ -571,6 +571,23 @@ public: } } + template + void ReverseEnumerateBlock(BytecodeRegion &bb, const Callback &cb) + { + auto pc = bb.end; + while (true) { + auto bytecodeInfo = GetBytecodeInfo(pc); + bool ret = cb(pc, bytecodeInfo); + if (!ret) { + break; + } + pc = byteCodeCurPrePc_.at(pc); + if (pc <= bb.start || pc >= bb.end) { + break; + } + } + } + const std::map &GetPcToBCOffset() const { return pcToBCOffset_; @@ -583,7 +600,7 @@ private: void ComputeDominatorTree(); void BuildImmediateDominator(const std::vector &immDom); void ComputeDomFrontiers(const std::vector &immDom); - void RemoveDeadRegions(); + void RemoveDeadRegions(const std::map &bbIdToDfsTimestamp); void InsertPhi(); void InsertExceptionPhi(std::map> &defsitesInfo); void UpdateCFG(); @@ -606,6 +623,8 @@ private: void NewPhi(BytecodeRegion &bb, uint16_t reg, bool acc, GateRef ¤tPhi); GateRef RenameVariable(const size_t bbId, const uint8_t *end, const uint16_t reg, const bool acc); void BuildCircuit(); + void BuildDfsList(); + void FrameStateReplacePhi(GateRef phi, size_t reg); void BuildFrameState(); GateRef GetExistingRestore(GateRef resumeGate, uint16_t tmpReg) const; void SetExistingRestore(GateRef resumeGate, uint16_t tmpReg, GateRef restoreGate); @@ -641,7 +660,6 @@ private: FrameStateBuilder frameStateBuilder_; std::string methodName_; std::vector bbDfsList_; - std::map bbIdToDfsTimestamp_; // (basicblock id, dfs order) }; } // namespace panda::ecmascript::kungfu #endif // ECMASCRIPT_CLASS_LINKER_BYTECODE_CIRCUIT_IR_BUILDER_H diff --git a/ecmascript/compiler/circuit_builder-inl.h b/ecmascript/compiler/circuit_builder-inl.h index ecc76cf898..bd18893118 100644 --- a/ecmascript/compiler/circuit_builder-inl.h +++ b/ecmascript/compiler/circuit_builder-inl.h @@ -375,29 +375,9 @@ GateRef CircuitBuilder::TaggedFalse() GateRef CircuitBuilder::GetValueFromTaggedArray(GateRef array, GateRef index) { - Label subentry(env_); - SubCfgEntry(&subentry); - Label exit(env_); - Label isUndefined(env_); - Label notUndefined(env_); - GateRef initVal = UndefineConstant(); - DEFVAlUE(result, env_, VariableType::JS_ANY(), initVal); - Branch(TaggedIsUndefined(array), &isUndefined, ¬Undefined); - Bind(&isUndefined); - { - Jump(&exit); - } - Bind(¬Undefined); - { - GateRef offset = PtrMul(ChangeInt32ToIntPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize())); - GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET)); - result = Load(VariableType::JS_ANY(), array, dataOffset); - Jump(&exit); - } - Bind(&exit); - auto ret = *result; - SubCfgExit(); - return ret; + GateRef offset = PtrMul(ChangeInt32ToIntPtr(index), IntPtr(JSTaggedValue::TaggedTypeSize())); + GateRef dataOffset = PtrAdd(offset, IntPtr(TaggedArray::DATA_OFFSET)); + return Load(VariableType::JS_ANY(), array, dataOffset); } void CircuitBuilder::SetValueToTaggedArray(VariableType valType, GateRef glue, diff --git a/ecmascript/compiler/frame_states.cpp b/ecmascript/compiler/frame_states.cpp index 706dacd01b..0bd0cc43fd 100644 --- a/ecmascript/compiler/frame_states.cpp +++ b/ecmascript/compiler/frame_states.cpp @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "ecmascript/compiler/argument_accessor.h" #include "ecmascript/compiler/frame_states.h" namespace panda::ecmascript::kungfu { @@ -24,7 +23,6 @@ FrameStateInfo *FrameStateInfo::Clone() FrameStateBuilder::FrameStateBuilder(Circuit *circuit, const MethodLiteral *literal) : literal_(literal), circuit_(circuit), gateAcc_(circuit) { - currentInfo_ = new FrameStateInfo(literal_); } FrameStateBuilder::~FrameStateBuilder() @@ -37,62 +35,28 @@ FrameStateBuilder::~FrameStateBuilder() currentInfo_ = nullptr; } -void FrameStateBuilder::BuildArgsValues(ArgumentAccessor *argAcc) +void FrameStateBuilder::InitFrameValues() { - auto callFieldNumVregs = literal_->GetNumVregsWithCallField(); + auto values = currentInfo_->GetValues(); auto undefinedGate = circuit_->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED, GateType::TaggedValue()); - auto values = currentInfo_->GetValues(); - for (size_t i = 0; i < callFieldNumVregs; i++) { - values->push_back(undefinedGate); - } - if (literal_->HaveFuncWithCallField()) { - auto gate = argAcc->GetCommonArgGate(CommonArgIdx::FUNC); - values->push_back(gate); - } - if (literal_->HaveNewTargetWithCallField()) { - auto gate = argAcc->GetCommonArgGate(CommonArgIdx::NEW_TARGET); - values->push_back(gate); - } - if (literal_->HaveThisWithCallField()) { - auto gate = argAcc->GetCommonArgGate(CommonArgIdx::THIS); - values->push_back(gate); - } - - auto numArgs = literal_->GetNumArgsWithCallField(); + auto numArgs = literal_->GetNumberVRegs(); for (size_t i = 0; i < numArgs; i++) { - auto gate = argAcc->ArgsAt(i + static_cast(CommonArgIdx::NUM_OF_ARGS)); - values->push_back(gate); + values->push_back(undefinedGate); } // push acc values->push_back(undefinedGate); ASSERT(currentInfo_->GetNumberVRegs() == values->size()); } -GateRef FrameStateBuilder::FrameState(size_t pcOffset, - std::map> &jsgateToBytecode) +GateRef FrameStateBuilder::FrameState(size_t pcOffset) { auto numVregs = currentInfo_->GetNumberVRegs(); size_t frameStateInputs = numVregs + 1; // +1: for pc std::vector inList(frameStateInputs, Circuit::NullGate()); for (size_t i = 0; i < numVregs; i++) { - auto iter = jsgateToBytecode.find(ValuesAt(i)); - if (iter != jsgateToBytecode.end()) { - auto pc = iter->second.second; - BytecodeInstruction inst(pc); - EcmaOpcode op = inst.GetOpcode(); - // vreg needed remove from framstate if it comes from RESUMEGENERATOR, otherwisethe upperbound will not be - // found - if (op == EcmaOpcode::RESUMEGENERATOR) { - inList[i] = circuit_->GetConstantGate(MachineType::I64, JSTaggedValue::VALUE_UNDEFINED, - GateType::TaggedValue()); - } else { - inList[i] = ValuesAt(i); - } - } else { - inList[i] = ValuesAt(i); - } + inList[i] = ValuesAt(i); } auto pcGate = circuit_->GetConstantGate(MachineType::I64, pcOffset, @@ -101,11 +65,10 @@ GateRef FrameStateBuilder::FrameState(size_t pcOffset, return circuit_->NewGate(OpCode(OpCode::FRAME_STATE), frameStateInputs, inList, GateType::Empty()); } -void FrameStateBuilder::BindGuard(GateRef gate, size_t pcOffset, GateRef glue, - std::map> &jsgateToBytecode) +void FrameStateBuilder::BindGuard(GateRef gate, size_t pcOffset, GateRef glue) { auto depend = gateAcc_.GetDep(gate); - GateRef frameState = FrameState(pcOffset, jsgateToBytecode); + GateRef frameState = FrameState(pcOffset); auto trueGate = circuit_->GetConstantGate(MachineType::I1, 1, // 1: true GateType::NJSValue()); @@ -114,18 +77,19 @@ void FrameStateBuilder::BindGuard(GateRef gate, size_t pcOffset, GateRef glue, gateAcc_.ReplaceDependIn(gate, guard); } -void FrameStateBuilder::AdvenceToSuccessor(const uint8_t *predPc, const uint8_t *endPc) +void FrameStateBuilder::AdvenceToBasicBlock(size_t id) { - size_t pcOffset = static_cast(endPc - literal_->GetBytecodeArray()); - if (predPc != nullptr) { - size_t predPcOffset = static_cast(predPc - literal_->GetBytecodeArray()); - auto predFrameInfo = stateInfos_[predPcOffset]; - ASSERT(predFrameInfo != nullptr); - currentInfo_ = predFrameInfo; - currentInfo_ = CloneFrameState(pcOffset); - } else { - // for first block - stateInfos_[pcOffset] = currentInfo_; + if (currentInfo_ == nullptr) { + // for last block + currentInfo_ = new FrameStateInfo(literal_); + stateInfos_[id] = currentInfo_; + InitFrameValues(); + return; } + auto frameInfo = stateInfos_[id]; + if (frameInfo == nullptr) { + frameInfo = CloneFrameState(currentInfo_, id); + } + currentInfo_ = frameInfo; } } \ No newline at end of file diff --git a/ecmascript/compiler/frame_states.h b/ecmascript/compiler/frame_states.h index 06ae14f2b1..ecfce30d2d 100644 --- a/ecmascript/compiler/frame_states.h +++ b/ecmascript/compiler/frame_states.h @@ -77,6 +77,10 @@ public: SetValuesAt(index, gate); } FrameStateInfo *Clone(); + size_t GetAccumulatorIndex() const + { + return accumulator_index_; + } private: size_t numVregs_ {0}; size_t accumulator_index_ {0}; @@ -100,7 +104,6 @@ public: return currentInfo_->ValuesAtAccumulator(); } - void BuildArgsValues(ArgumentAccessor *argAcc); void UpdateAccumulator(GateRef gate) { currentInfo_->UpdateAccumulator(gate); @@ -109,19 +112,22 @@ public: { currentInfo_->UpdateVirtualRegister(index, gate); } - void BindGuard(GateRef gate, size_t pcOffset, GateRef glue, - std::map> &jsgateToBytecode); - - void AdvenceToSuccessor(const uint8_t *predPc, const uint8_t *endPc); -private: - FrameStateInfo *CloneFrameState(size_t pcOffset) + void BindGuard(GateRef gate, size_t pcOffset, GateRef glue); + void AdvenceToBasicBlock(size_t id); + size_t GetAccumulatorIndex() const { - ASSERT(stateInfos_[pcOffset] == nullptr); - auto info = currentInfo_->Clone(); - stateInfos_[pcOffset] = info; + return currentInfo_->GetAccumulatorIndex(); + } +private: + FrameStateInfo *CloneFrameState(FrameStateInfo *current, size_t id) + { + ASSERT(stateInfos_[id] == nullptr); + auto info = current->Clone(); + stateInfos_[id] = info; return info; } - GateRef FrameState(size_t pcOffset, std::map> &jsgateToBytecode); + GateRef FrameState(size_t pcOffset); + void InitFrameValues(); FrameStateInfo *currentInfo_{nullptr}; const MethodLiteral *literal_ {nullptr}; diff --git a/ecmascript/compiler/gate.cpp b/ecmascript/compiler/gate.cpp index 5aa51ddcd8..803bd97cb1 100644 --- a/ecmascript/compiler/gate.cpp +++ b/ecmascript/compiler/gate.cpp @@ -1269,17 +1269,17 @@ std::string Gate::GateTypeStr(GateType gateType) const void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx) const { if (GetOpCode() != OpCode::NOP) { - std::string log("(id=" + std::to_string(id_) + ", op=" + GetOpCode().Str() + ", "); - log += ((bytecode.compare("") == 0) ? "" : "bytecode=") + bytecode; - log += ((bytecode.compare("") == 0) ? "" : ", "); - log += "MType=" + MachineTypeStr(GetMachineType()) + ", "; + std::string log("{\"id\":" + std::to_string(id_) + ", \"op\":\"" + GetOpCode().Str() + "\", "); + log += ((bytecode.compare("") == 0) ? "" : "\"bytecode\":\"") + bytecode; + log += ((bytecode.compare("") == 0) ? "" : "\", "); + log += "\"MType\":\"" + MachineTypeStr(GetMachineType()) + ", "; std::stringstream buf; buf << std::hex << bitfield_; log += "bitfield=" + buf.str() + ", "; log += "type=" + GateTypeStr(type_) + ", "; log += "stamp=" + std::to_string(static_cast(stamp_)) + ", "; log += "mark=" + std::to_string(static_cast(mark_)) + ", "; - log += "in=["; + log += "\",\"in\":["; size_t idx = 0; auto stateSize = GetStateCount(); @@ -1293,7 +1293,7 @@ void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx) PrintInGate(stateSize + dependSize + valueSize + rootSize, idx, stateSize + dependSize + valueSize, inListPreview, highlightIdx, log, true); - log += "], out=["; + log += "], \"out\":["; if (!IsFirstOutNull()) { const Out *curOut = GetFirstOutConst(); @@ -1302,12 +1302,12 @@ void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx) while (!curOut->IsNextOutNull()) { curOut = curOut->GetNextOutConst(); - log += " " + std::to_string(curOut->GetGateConst()->GetId()) + + log += ", " + std::to_string(curOut->GetGateConst()->GetId()) + (inListPreview ? std::string(":" + curOut->GetGateConst()->GetOpCode().Str()) : std::string("")); } } - log += "])"; + log += "]},"; LOG_COMPILER(INFO) << std::dec << log; } } @@ -1315,15 +1315,15 @@ void Gate::Print(std::string bytecode, bool inListPreview, size_t highlightIdx) void Gate::ShortPrint(std::string bytecode, bool inListPreview, size_t highlightIdx) const { if (GetOpCode() != OpCode::NOP) { - std::string log("(id=" + std::to_string(id_) + ", op=" + GetOpCode().Str() + ", "); + std::string log("(\"id\"=" + std::to_string(id_) + ", \"op\"=\"" + GetOpCode().Str() + "\", "); log += ((bytecode.compare("") == 0) ? "" : "bytecode=") + bytecode; log += ((bytecode.compare("") == 0) ? "" : ", "); - log += "MType=" + MachineTypeStr(GetMachineType()) + ", "; + log += "\"MType\"=\"" + MachineTypeStr(GetMachineType()) + ", "; std::stringstream buf; buf << std::hex << bitfield_; log += "bitfield=" + buf.str() + ", "; log += "type=" + GateTypeStr(type_) + ", "; - log += "in=["; + log += "\", in=["; size_t idx = 0; auto stateSize = GetStateCount(); @@ -1346,7 +1346,7 @@ void Gate::ShortPrint(std::string bytecode, bool inListPreview, size_t highlight while (!curOut->IsNextOutNull()) { curOut = curOut->GetNextOutConst(); - log += " " + std::to_string(curOut->GetGateConst()->GetId()) + + log += ", " + std::to_string(curOut->GetGateConst()->GetId()) + (inListPreview ? std::string(":" + curOut->GetGateConst()->GetOpCode().Str()) : std::string("")); } @@ -1361,7 +1361,7 @@ size_t Gate::PrintInGate(size_t numIns, size_t idx, size_t size, bool inListPrev { log += "["; for (; idx < numIns; idx++) { - log += ((idx == size) ? "" : " "); + log += ((idx == size) ? "" : ", "); log += ((idx == highlightIdx) ? "\033[4;31m" : ""); log += ((IsInGateNull(idx) ? "N" diff --git a/ecmascript/compiler/gate_accessor.cpp b/ecmascript/compiler/gate_accessor.cpp index dfe4694213..9dafb97f50 100644 --- a/ecmascript/compiler/gate_accessor.cpp +++ b/ecmascript/compiler/gate_accessor.cpp @@ -457,4 +457,21 @@ void GateAccessor::DeleteGuardAndFrameState(GateRef gate) DeleteGate(guard); } } + +void GateAccessor::ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value) +{ + auto uses = Uses(gate); + for (auto useIt = uses.begin(); useIt != uses.end();) { + if (IsStateIn(useIt)) { + useIt = ReplaceIn(useIt, state); + } else if (IsDependIn(useIt)) { + useIt = ReplaceIn(useIt, depend); + } else if (IsValueIn(useIt)) { + useIt = ReplaceIn(useIt, value); + } else { + UNREACHABLE(); + } + } + DeleteGate(gate); +} } // namespace panda::ecmascript::kungfu diff --git a/ecmascript/compiler/gate_accessor.h b/ecmascript/compiler/gate_accessor.h index fde46eb6cb..4949f4ddc2 100644 --- a/ecmascript/compiler/gate_accessor.h +++ b/ecmascript/compiler/gate_accessor.h @@ -364,6 +364,7 @@ public: bool IsDependIn(GateRef gate, size_t index) const; bool IsValueIn(GateRef gate, size_t index) const; void DeleteGuardAndFrameState(GateRef gate); + void ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value); private: ConstUseIterator ConstUseBegin(GateRef gate) const diff --git a/ecmascript/compiler/llvm_codegen.h b/ecmascript/compiler/llvm_codegen.h index f6bb88a212..29babba8f3 100644 --- a/ecmascript/compiler/llvm_codegen.h +++ b/ecmascript/compiler/llvm_codegen.h @@ -71,9 +71,6 @@ struct CodeInfo { if (reqSecs_ == reinterpret_cast(-1)) { reqSecs_ = nullptr; } - // align machineCode for aarch64 - reqSecs_ += MachineCode::DATA_OFFSET + - AlignUp(sizeof(Region), static_cast(MemAlignment::MEM_ALIGN_REGION)); unreqSecs_ = static_cast(mmap(nullptr, UNREQUIRED_SECS_LIMIT, protRWX, flags, -1, 0)); if (unreqSecs_ == reinterpret_cast(-1)) { unreqSecs_ = nullptr; @@ -84,8 +81,6 @@ struct CodeInfo { { Reset(); if (reqSecs_ != nullptr) { - reqSecs_ -= MachineCode::DATA_OFFSET + - AlignUp(sizeof(Region), static_cast(MemAlignment::MEM_ALIGN_REGION)); munmap(reqSecs_, REQUIRED_SECS_LIMIT); } reqSecs_ = nullptr; diff --git a/ecmascript/compiler/slowpath_lowering.cpp b/ecmascript/compiler/slowpath_lowering.cpp index 74e033dad0..cb56f075e8 100644 --- a/ecmascript/compiler/slowpath_lowering.cpp +++ b/ecmascript/compiler/slowpath_lowering.cpp @@ -299,7 +299,7 @@ void SlowPathLowering::Lower(GateRef gate) GateRef newTarget = argAcc_.GetCommonArgGate(CommonArgIdx::NEW_TARGET); GateRef jsFunc = argAcc_.GetCommonArgGate(CommonArgIdx::FUNC); GateRef actualArgc = argAcc_.GetCommonArgGate(CommonArgIdx::ACTUAL_ARGC); - GateRef thisObj = argAcc_.GetCommonArgGate(CommonArgIdx::THIS); + GateRef thisObj = argAcc_.GetCommonArgGate(CommonArgIdx::THIS_OBJECT); auto pc = bcBuilder_->GetJSBytecode(gate); EcmaOpcode op = bcBuilder_->PcToOpcode(pc); @@ -869,7 +869,7 @@ void SlowPathLowering::SaveFrameToContext(GateRef gate, GateRef glue, GateRef js // set this GateRef thisOffset = builder_.IntPtr(GeneratorContext::GENERATOR_THIS_OFFSET); - GateRef thisObj = argAcc_.GetCommonArgGate(CommonArgIdx::THIS); + GateRef thisObj = argAcc_.GetCommonArgGate(CommonArgIdx::THIS_OBJECT); builder_.Store(VariableType::JS_ANY(), glue, context, thisOffset, thisObj); // set method @@ -2851,7 +2851,7 @@ void SlowPathLowering::LowerStObjByValue(GateRef gate, GateRef glue, GateRef thi { GateRef undefined = builder_.UndefineConstant(); result = LowerCallRuntime(glue, RTSTUB_ID(StoreICByValue), {undefined, receiver, propKey, accValue, - builder_.ToTaggedInt(undefined)}); + builder_.ToTaggedInt(builder_.Int64(0))}); builder_.Branch(builder_.IsSpecial(result, JSTaggedValue::VALUE_EXCEPTION), &exceptionExit, &successExit); } diff --git a/ecmascript/compiler/trampoline/aarch64/optimized_call.cpp b/ecmascript/compiler/trampoline/aarch64/optimized_call.cpp index b9bb817464..3aae9d31f2 100644 --- a/ecmascript/compiler/trampoline/aarch64/optimized_call.cpp +++ b/ecmascript/compiler/trampoline/aarch64/optimized_call.cpp @@ -1023,17 +1023,16 @@ void OptimizedCall::DeoptHandlerAsm(ExtendedAssembler *assembler) __ CallAssemblerStub(RTSTUB_ID(CallRuntime), false); __ Add(sp, sp, Immediate(DOUBLE_SLOT_SIZE)); // 2: skip runtimeId argc + __ CalleeRestore(); + Register context(X2); + __ Mov(context, Register(X0)); + __ Ldr(glueReg, MemoryOperand(sp, 0)); + Register ret(X0); Label stackOverflow; __ Cmp(ret, Immediate(JSTaggedValue::VALUE_EXCEPTION)); __ B(Condition::EQ, &stackOverflow); - __ CalleeRestore(); - - Register context(X2); - __ Mov(context, Register(X0)); - __ Ldr(glueReg, MemoryOperand(sp, 0)); - Label target; Register temp(X1); __ Ldr(fp, MemoryOperand(context, AsmStackContext::GetCallerFpOffset(false))); @@ -1054,9 +1053,7 @@ void OptimizedCall::DeoptHandlerAsm(ExtendedAssembler *assembler) // 2 : 2 means pair __ Stp(runtimeId, Register(Zero), MemoryOperand(sp, -DOUBLE_SLOT_SIZE, AddrMode::PREINDEX)); __ CallAssemblerStub(RTSTUB_ID(CallRuntime), false); - __ Add(sp, sp, Immediate(DOUBLE_SLOT_SIZE)); // 2: skip runtimeId argc - - __ CalleeRestore(); + __ Add(sp, sp, Immediate(2 * DOUBLE_SLOT_SIZE)); // 2: skip runtimeId&argc glue&type __ RestoreFpAndLr(); __ Ret(); } diff --git a/ecmascript/compiler/trampoline/x64/optimized_call.cpp b/ecmascript/compiler/trampoline/x64/optimized_call.cpp index c96fd76794..3b75ad40b0 100644 --- a/ecmascript/compiler/trampoline/x64/optimized_call.cpp +++ b/ecmascript/compiler/trampoline/x64/optimized_call.cpp @@ -1272,29 +1272,31 @@ void OptimizedCall::DeoptHandlerAsm(ExtendedAssembler *assembler) { __ BindAssemblerStub(RTSTUB_ID(DeoptHandlerAsm)); + Register glueReg = rdi; __ Pushq(rbp); __ Movq(rsp, rbp); __ Pushq(static_cast(FrameType::OPTIMIZED_FRAME)); + __ Push(glueReg); __ PushCppCalleeSaveRegisters(); - Register glueReg = rdi; - __ Push(glueReg); __ Movq(rdi, rax); // glue __ PushAlignBytes(); __ Pushq(0); // argc __ Pushq(kungfu::RuntimeStubCSigns::ID_DeoptHandler); __ CallAssemblerStub(RTSTUB_ID(CallRuntime), false); - __ Addq(3 * FRAME_SLOT_SIZE, rsp); // 3: skip runtimeId argc argv[0] argv[1] - __ Pop(glueReg); + __ Addq(3 * FRAME_SLOT_SIZE, rsp); // 3: skip runtimeId argc & align Register context = rsi; __ Movq(rax, context); + + Label target; + __ PopCppCalleeSaveRegisters(); + __ Pop(glueReg); + Label stackOverflow; __ Cmpq(JSTaggedValue::VALUE_EXCEPTION, rax); __ Je(&stackOverflow); - Label target; - __ PopCppCalleeSaveRegisters(); __ Movq(Operand(context, AsmStackContext::GetCallerFpOffset(false)), rbp); __ Movq(Operand(context, AsmStackContext::GetCallFrameTopOffset(false)), rsp); __ Subq(FRAME_SLOT_SIZE, rsp); // skip lr @@ -1313,10 +1315,7 @@ void OptimizedCall::DeoptHandlerAsm(ExtendedAssembler *assembler) __ Pushq(0); // argc __ Pushq(kungfu::RuntimeStubCSigns::ID_ThrowStackOverflowException); __ CallAssemblerStub(RTSTUB_ID(CallRuntime), false); - __ Addq(16, rsp); // 16: skip runtimeId argc - - __ PopCppCalleeSaveRegisters(); - __ Addq(FRAME_SLOT_SIZE, rsp); + __ Addq(FRAME_SLOT_SIZE * 3, rsp); // skip runtimeId argc & type __ Popq(rbp); __ Ret(); } diff --git a/ecmascript/compiler/ts_type_lowering.cpp b/ecmascript/compiler/ts_type_lowering.cpp index 1ef9b653e1..af1d73ffeb 100644 --- a/ecmascript/compiler/ts_type_lowering.cpp +++ b/ecmascript/compiler/ts_type_lowering.cpp @@ -432,9 +432,10 @@ void TSTypeLowering::SpeculateNumbers(GateRef gate) // guard maybe not a GUARD GateRef guard = acc_.GetDep(gate); if (check != Circuit::NullGate()) { + ASSERT(acc_.GetOpCode(guard) == OpCode::GUARD); acc_.ReplaceIn(guard, 1, check); } - + // Replace the old NumberBinaryOp with TypedBinaryOp GateRef result = builder_.TypedBinaryOp(left, right, leftType, rightType, gateType); @@ -460,6 +461,7 @@ void TSTypeLowering::SpeculateNumber(GateRef gate) // guard maybe not a GUARD GateRef guard = acc_.GetDep(gate); if (check != Circuit::NullGate()) { + ASSERT(acc_.GetOpCode(guard) == OpCode::GUARD); acc_.ReplaceIn(guard, 1, check); } @@ -496,6 +498,7 @@ void TSTypeLowering::LowerPrimitiveTypeToNumber(GateRef gate) // guard maybe not a GUARD GateRef guard = acc_.GetDep(gate); if (check != Circuit::NullGate()) { + ASSERT(acc_.GetOpCode(guard) == OpCode::GUARD); acc_.ReplaceIn(guard, 1, check); } @@ -520,23 +523,6 @@ void TSTypeLowering::SpeculateConditionJump(GateRef gate) GateRef value = acc_.GetValueIn(gate, 0); GateRef condition = builder_.IsSpecial(value, JSTaggedValue::VALUE_FALSE); GateRef ifBranch = builder_.Branch(acc_.GetState(gate), condition); - ReplaceGate(gate, ifBranch, builder_.GetDepend(), Circuit::NullGate()); -} - -void TSTypeLowering::ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value) -{ - auto uses = acc_.Uses(gate); - for (auto useIt = uses.begin(); useIt != uses.end();) { - if (acc_.IsStateIn(useIt)) { - useIt = acc_.ReplaceIn(useIt, state); - } else if (acc_.IsDependIn(useIt)) { - useIt = acc_.ReplaceIn(useIt, depend); - } else if (acc_.IsValueIn(useIt)) { - useIt = acc_.ReplaceIn(useIt, value); - } else { - UNREACHABLE(); - } - } - acc_.DeleteGate(gate); + acc_.ReplaceGate(gate, ifBranch, builder_.GetDepend(), Circuit::NullGate()); } } // namespace panda::ecmascript diff --git a/ecmascript/compiler/ts_type_lowering.h b/ecmascript/compiler/ts_type_lowering.h index 0ce7bb58bc..fefa712cec 100644 --- a/ecmascript/compiler/ts_type_lowering.h +++ b/ecmascript/compiler/ts_type_lowering.h @@ -48,7 +48,6 @@ private: void DeleteGates(GateRef hir, std::vector &unusedGate); void ReplaceHIRGate(GateRef hir, GateRef outir, GateRef state, GateRef depend, std::vector &unuseGate); - void ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value); void LowerTypedAdd(GateRef gate); void LowerTypedSub(GateRef gate); void LowerTypedMul(GateRef gate); diff --git a/ecmascript/compiler/type_lowering.cpp b/ecmascript/compiler/type_lowering.cpp index 08abafc9f9..f891d12f79 100644 --- a/ecmascript/compiler/type_lowering.cpp +++ b/ecmascript/compiler/type_lowering.cpp @@ -98,7 +98,7 @@ void TypeLowering::LowerPrimitiveToNumber(GateRef dst, GateRef src, GateType src UNREACHABLE(); } builder_.Bind(&exit); - ReplaceGate(dst, builder_.GetState(), builder_.GetDepend(), *result); + acc_.ReplaceGate(dst, builder_.GetState(), builder_.GetDepend(), *result); } void TypeLowering::LowerTypeCheck(GateRef gate) @@ -388,7 +388,7 @@ void TypeLowering::LowerNumberAdd(GateRef gate) GateType rightType = GetRightType(gate); DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); result = CalculateNumbers(left, right, leftType, rightType); - ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } void TypeLowering::LowerNumberSub(GateRef gate) @@ -399,7 +399,7 @@ void TypeLowering::LowerNumberSub(GateRef gate) GateType rightType = GetRightType(gate); DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); result = CalculateNumbers(left, right, leftType, rightType); - ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } void TypeLowering::LowerNumberMul(GateRef gate) @@ -410,7 +410,7 @@ void TypeLowering::LowerNumberMul(GateRef gate) GateType rightType = GetRightType(gate); DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); result = CalculateNumbers(left, right, leftType, rightType); - ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } void TypeLowering::LowerNumberLess(GateRef gate) @@ -421,7 +421,7 @@ void TypeLowering::LowerNumberLess(GateRef gate) GateType rightType = GetRightType(gate); DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); result = CompareNumbers(left, right, leftType, rightType); - ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } void TypeLowering::LowerNumberLessEq(GateRef gate) @@ -432,7 +432,7 @@ void TypeLowering::LowerNumberLessEq(GateRef gate) GateType rightType = GetRightType(gate); DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); result = CompareNumbers(left, right, leftType, rightType); - ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } void TypeLowering::LowerNumberGreater(GateRef gate) @@ -443,7 +443,7 @@ void TypeLowering::LowerNumberGreater(GateRef gate) GateType rightType = GetRightType(gate); DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); result = CompareNumbers(right, left, rightType, leftType); - ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } void TypeLowering::LowerNumberGreaterEq(GateRef gate) @@ -454,7 +454,7 @@ void TypeLowering::LowerNumberGreaterEq(GateRef gate) GateType rightType = GetRightType(gate); DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); result = CompareNumbers(right, left, rightType, leftType); - ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } void TypeLowering::LowerNumberDiv(GateRef gate) @@ -465,7 +465,7 @@ void TypeLowering::LowerNumberDiv(GateRef gate) GateType rightType = GetRightType(gate); DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); result = DivNumbers(left, right, leftType, rightType); - ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } void TypeLowering::LowerNumberEq(GateRef gate) @@ -476,7 +476,7 @@ void TypeLowering::LowerNumberEq(GateRef gate) GateType rightType = GetRightType(gate); DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); result = CompareNumbers(left, right, leftType, rightType); - ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } void TypeLowering::LowerNumberNotEq(GateRef gate) @@ -487,7 +487,7 @@ void TypeLowering::LowerNumberNotEq(GateRef gate) GateType rightType = GetRightType(gate); DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); result = CompareNumbers(left, right, leftType, rightType); - ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } void TypeLowering::LowerNumberInc(GateRef gate) @@ -496,7 +496,7 @@ void TypeLowering::LowerNumberInc(GateRef gate) GateType valueType = GetLeftType(gate); DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); result = MonocularNumber(value, valueType); - ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } void TypeLowering::LowerNumberDec(GateRef gate) @@ -505,24 +505,7 @@ void TypeLowering::LowerNumberDec(GateRef gate) GateType valueType = GetLeftType(gate); DEFVAlUE(result, (&builder_), VariableType::JS_ANY(), builder_.HoleConstant()); result = MonocularNumber(value, valueType); - ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); -} - -void TypeLowering::ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value) -{ - auto uses = acc_.Uses(gate); - for (auto useIt = uses.begin(); useIt != uses.end();) { - if (acc_.IsStateIn(useIt)) { - useIt = acc_.ReplaceIn(useIt, state); - } else if (acc_.IsDependIn(useIt)) { - useIt = acc_.ReplaceIn(useIt, depend); - } else if (acc_.IsValueIn(useIt)) { - useIt = acc_.ReplaceIn(useIt, value); - } else { - UNREACHABLE(); - } - } - acc_.DeleteGate(gate); + acc_.ReplaceGate(gate, builder_.GetState(), builder_.GetDepend(), *result); } template diff --git a/ecmascript/compiler/type_lowering.h b/ecmascript/compiler/type_lowering.h index 6686211ce6..2cdd8025bc 100644 --- a/ecmascript/compiler/type_lowering.h +++ b/ecmascript/compiler/type_lowering.h @@ -154,7 +154,6 @@ private: void LowerNumberNotEq(GateRef gate); void LowerNumberInc(GateRef gate); void LowerNumberDec(GateRef gate); - void ReplaceGate(GateRef gate, GateRef state, GateRef depend, GateRef value); template GateRef FastAddOrSubOrMul(GateRef left, GateRef right); diff --git a/ecmascript/deoptimizer.cpp b/ecmascript/deoptimizer.cpp index 3a0b196abf..07aee79457 100644 --- a/ecmascript/deoptimizer.cpp +++ b/ecmascript/deoptimizer.cpp @@ -20,11 +20,6 @@ #include "ecmascript/stubs/runtime_stubs-inl.h" namespace panda::ecmascript { -using DeoptFromAOTType = JSTaggedType (*)(uintptr_t glue, JSTaggedType* sp, - uintptr_t vregsSp, uintptr_t stateSp, JSTaggedType callTarget); -static constexpr size_t LEXENV_INDEX = 1; -static constexpr size_t THIS_VALUE_INDEX = 5; - class FrameWriter { public: explicit FrameWriter(Deoptimizier *deoptimizier) : thread_(deoptimizier->GetThread()) @@ -73,7 +68,7 @@ private: void Deoptimizier::CollectVregs(const std::vector& deoptBundle) { - vregs_.clear(); + deoptVregs_.clear(); for (size_t i = 0; i < deoptBundle.size(); i++) { kungfu::ARKDeopt deopt = deoptBundle.at(i); JSTaggedType v; @@ -100,7 +95,7 @@ void Deoptimizier::CollectVregs(const std::vector& deoptBundle v = JSTaggedType(static_cast(std::get(deopt.value))); } if (id != static_cast(SpecVregIndex::PC_INDEX)) { - vregs_[id] = JSTaggedValue(v); + deoptVregs_[id] = JSTaggedValue(v); } else { pc_ = static_cast(v); } @@ -122,23 +117,18 @@ void Deoptimizier::CollectDeoptBundleVec(std::vector& deoptBun context_.calleeRegAndOffset = calleeRegInfo; context_.callsiteSp = it.GetCallSiteSp(); context_.callsiteFp = reinterpret_cast(it.GetSp()); - context_.preFrameSp = frame->ComputePrevFrameSp(it); - context_.returnAddr = frame->GetReturnAddr(); - uint64_t argc = frame->GetArgc(context_.preFrameSp); - auto argv = frame->GetArgv(reinterpret_cast(context_.preFrameSp)); - if (argc > 0) { - ASSERT(argc >= FIXED_NUM_ARGS); - callTarget_ = JSTaggedValue(argv[0]); - } - AotArgvs_ = argv; + auto preFrameSp = frame->ComputePrevFrameSp(it); + frameArgc_ = frame->GetArgc(preFrameSp); + frameArgvs_ = frame->GetArgv(preFrameSp); + env_ = frame->GetEnv(); stackContext_.callFrameTop_ = it.GetPrevFrameCallSiteSp(); - stackContext_.returnAddr_ = context_.returnAddr; + stackContext_.returnAddr_ = frame->GetReturnAddr(); stackContext_.callerFp_ = reinterpret_cast(frame->GetPrevFrameFp()); break; } case FrameType::OPTIMIZED_FRAME: { auto sp = reinterpret_cast(it.GetSp()); - sp--; // skip type + sp -= 2; // 2: skip type & glue calleeRegAddr_ = sp - numCalleeRegs_; break; } @@ -173,33 +163,90 @@ void Deoptimizier::RelocateCalleeSave() } } +bool Deoptimizier::CollectVirtualRegisters(Method* method, FrameWriter *frameWriter) +{ + int32_t actualNumArgs = static_cast(frameArgc_) - NUM_MANDATORY_JSFUNC_ARGS; + bool haveExtra = method->HaveExtraWithCallField(); + int32_t declaredNumArgs = static_cast(method->GetNumArgsWithCallField()); + int32_t callFieldNumVregs = static_cast(method->GetNumVregsWithCallField()); + // layout of frame: + // [maybe argc] [actual args] [reserved args] [call field virtual regs] + + // [maybe argc] + if (declaredNumArgs != actualNumArgs && haveExtra) { + auto value = JSTaggedValue(actualNumArgs); + frameWriter->PushValue(value.GetRawData()); + } + int32_t reservedCount = std::max(actualNumArgs, declaredNumArgs); + int32_t virtualIndex = reservedCount + callFieldNumVregs + + static_cast(method->GetNumRevervedArgs()) - 1; + if (!frameWriter->Reserve(static_cast(virtualIndex))) { + return false; + } + // [actual args] + if (declaredNumArgs > actualNumArgs) { + frameWriter->PushValue(JSTaggedValue::Undefined().GetRawData()); + virtualIndex--; + } + for (int32_t i = actualNumArgs - 1; i >= 0; i--) { + JSTaggedValue value = JSTaggedValue::Undefined(); + // deopt value + if (hasDeoptValue(virtualIndex)) { + value = deoptVregs_.at(static_cast(virtualIndex)); + } else { + value = GetActualFrameArgs(i); + } + frameWriter->PushValue(value.GetRawData()); + virtualIndex--; + } + + // [reserved args] + if (method->HaveThisWithCallField()) { + JSTaggedValue value = GetFrameArgv(kungfu::CommonArgIdx::THIS_OBJECT); + frameWriter->PushValue(value.GetRawData()); + virtualIndex--; + } + if (method->HaveNewTargetWithCallField()) { + JSTaggedValue value = GetFrameArgv(kungfu::CommonArgIdx::NEW_TARGET); + frameWriter->PushValue(value.GetRawData()); + virtualIndex--; + } + if (method->HaveFuncWithCallField()) { + JSTaggedValue value = GetFrameArgv(kungfu::CommonArgIdx::FUNC); + frameWriter->PushValue(value.GetRawData()); + virtualIndex--; + } + + // [call field virtual regs] + for (int32_t i = virtualIndex; i >= 0; i--) { + JSTaggedValue value = JSTaggedValue::Undefined(); + if (hasDeoptValue(virtualIndex)) { + value = deoptVregs_.at(static_cast(virtualIndex)); + } + frameWriter->PushValue(value.GetRawData()); + virtualIndex--; + } + return true; +} + JSTaggedType Deoptimizier::ConstructAsmInterpretFrame() { ASSERT(thread_ != nullptr); - auto fun = callTarget_; + JSTaggedValue callTarget = GetFrameArgv(kungfu::CommonArgIdx::FUNC); FrameWriter frameWriter(this); // Push asm interpreter frame - auto method = GetMethod(callTarget_); - auto numVRegs = method->GetNumberVRegs(); - if (!frameWriter.Reserve(numVRegs)) { + auto method = GetMethod(callTarget); + if (!CollectVirtualRegisters(method, &frameWriter)) { return JSTaggedValue::Exception().GetRawData(); } - - for (int32_t i = numVRegs - 1; i >= 0; i--) { - JSTaggedValue value = JSTaggedValue::Undefined(); - if (vregs_.find(static_cast(i)) != vregs_.end()) { - value = vregs_.at(static_cast(i)); - } - frameWriter.PushValue(value.GetRawData()); - } const uint8_t *resumePc = method->GetBytecodeArray() + pc_; AsmInterpretedFrame *statePtr = frameWriter.ReserveAsmInterpretedFrame(); - JSTaggedValue env = JSTaggedValue(GetArgv(LEXENV_INDEX)); - JSTaggedValue thisObj = JSTaggedValue(GetArgv(THIS_VALUE_INDEX)); - auto acc = vregs_.at(static_cast(SpecVregIndex::ACC_INDEX)); - statePtr->function = fun; + + JSTaggedValue thisObj = GetFrameArgv(kungfu::CommonArgIdx::THIS_OBJECT);; + auto acc = deoptVregs_.at(static_cast(SpecVregIndex::ACC_INDEX)); + statePtr->function = callTarget; statePtr->acc = acc; - statePtr->env = env; + statePtr->env = env_; statePtr->callSize = 0; statePtr->fp = 0; // need update statePtr->thisObj = thisObj; diff --git a/ecmascript/deoptimizer.h b/ecmascript/deoptimizer.h index 822257ea7b..58a9330033 100644 --- a/ecmascript/deoptimizer.h +++ b/ecmascript/deoptimizer.h @@ -17,6 +17,7 @@ #define ECMASCRIPT_DEOPTIMIZER_H #include "ecmascript/base/aligned_struct.h" #include "ecmascript/calleeReg.h" +#include "ecmascript/compiler/argument_accessor.h" #include "ecmascript/js_handle.h" #include "ecmascript/js_tagged_value.h" #include "ecmascript/llvm_stackmap_type.h" @@ -34,8 +35,6 @@ enum class SpecVregIndex: int { struct Context { uintptr_t callsiteSp; uintptr_t callsiteFp; - uintptr_t* preFrameSp; - uintptr_t returnAddr; kungfu::CalleeRegAndOffsetVec calleeRegAndOffset; }; @@ -86,22 +85,18 @@ struct AsmStackContext : public base::AlignedStruct& deoptBundle); void CollectDeoptBundleVec(std::vector& deoptBundle); JSTaggedType ConstructAsmInterpretFrame(); - JSTaggedType GetArgv(int idx) - { - ASSERT(AotArgvs_ != nullptr); - return AotArgvs_[static_cast(idx)]; - } + JSThread *GetThread() const { @@ -109,6 +104,30 @@ public: } private: + size_t GetFrameIndex(kungfu::CommonArgIdx index) + { + return static_cast(index) - static_cast(kungfu::CommonArgIdx::FUNC); + } + JSTaggedValue GetFrameArgv(size_t idx) + { + ASSERT(frameArgvs_ != nullptr); + ASSERT(idx < frameArgc_); + return JSTaggedValue(frameArgvs_[idx]); + } + JSTaggedValue GetFrameArgv(kungfu::CommonArgIdx index) + { + return GetFrameArgv(GetFrameIndex(index)); + } + JSTaggedValue GetActualFrameArgs(int32_t index) + { + index += NUM_MANDATORY_JSFUNC_ARGS; + return GetFrameArgv(static_cast(index)); + } + bool CollectVirtualRegisters(Method* method, FrameWriter *frameWriter); + bool hasDeoptValue(int32_t index) + { + return deoptVregs_.find(static_cast(index)) != deoptVregs_.end(); + } Method* GetMethod(JSTaggedValue &target); void RelocateCalleeSave(); JSThread *thread_ {nullptr}; @@ -116,11 +135,12 @@ private: size_t numCalleeRegs_ {0}; AsmStackContext stackContext_; - std::unordered_map vregs_; - struct Context context_ {0, 0, nullptr, 0, {}}; + std::unordered_map deoptVregs_; + struct Context context_ {0, 0, {}}; uint32_t pc_; - JSTaggedValue callTarget_ {JSTaggedValue::Undefined()}; - JSTaggedType *AotArgvs_ {nullptr}; + JSTaggedValue env_ {JSTaggedValue::Undefined()}; + size_t frameArgc_ {0}; + JSTaggedType *frameArgvs_ {nullptr}; }; } // namespace panda::ecmascript diff --git a/ecmascript/method.h b/ecmascript/method.h index afd9a7d283..e3b8d23421 100644 --- a/ecmascript/method.h +++ b/ecmascript/method.h @@ -122,7 +122,12 @@ public: uint32_t GetNumArgs() const { - return GetNumArgsWithCallField() + HaveFuncWithCallField() + + return GetNumArgsWithCallField() + GetNumRevervedArgs(); + } + + uint32_t GetNumRevervedArgs() const + { + return HaveFuncWithCallField() + HaveNewTargetWithCallField() + HaveThisWithCallField(); } diff --git a/test/typeinfer/BUILD.gn b/test/typeinfer/BUILD.gn index 15b56f732d..eed14b5d52 100644 --- a/test/typeinfer/BUILD.gn +++ b/test/typeinfer/BUILD.gn @@ -61,6 +61,7 @@ group("ark_typeinfer_test") { "trystglobalbyname:trystglobalbynameAotTypeInferAction", "tsarraytobuiltin:tsarraytobuiltinAotTypeInferAction", "typeof:typeofAotTypeInferAction", - "variable_after_loops:variable_after_loopsAotTypeInferAction", + + #"variable_after_loops:variable_after_loopsAotTypeInferAction", ] }