diff --git a/ecmascript/compiler/codegen/maple/litecg_ir_builder.cpp b/ecmascript/compiler/codegen/maple/litecg_ir_builder.cpp index 67c63f76fb..1e27fa2905 100644 --- a/ecmascript/compiler/codegen/maple/litecg_ir_builder.cpp +++ b/ecmascript/compiler/codegen/maple/litecg_ir_builder.cpp @@ -601,8 +601,8 @@ void LiteCGIRBuilder::AssistGenPrologue(const size_t reservedSlotsSize, FrameTyp { lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize); if (circuit_->IsOsr()) { - SaveFrameTypeOnFrame(methodLiteral_->IsFastCall() ? FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME : - frameType); + auto osrFrameType = methodLiteral_->IsFastCall() ? FrameType::FASTJIT_FAST_CALL_FUNCTION_FRAME : frameType; + SaveFrameTypeOnFrame(function, osrFrameType); return; } auto ArgList = circuit_->GetArgRoot(); @@ -619,8 +619,8 @@ void LiteCGIRBuilder::AssistGenPrologue(const size_t reservedSlotsSize, FrameTyp } if (argth == funcIndex) { SaveByteCodePcOnOptJSFuncFrame(value); - SaveJSFuncOnOptJSFuncFrame(value); - SaveFrameTypeOnFrame(frameType); + SaveJSFuncOnOptJSFuncFrame(function, value, funcIndex); + SaveFrameTypeOnFrame(function, frameType); } } } @@ -636,13 +636,14 @@ void LiteCGIRBuilder::GenPrologue(maple::litecg::Function &function) if (frameType == FrameType::OPTIMIZED_FRAME) { reservedSlotsSize = OptimizedFrame::ComputeReservedSize(slotSize_); lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize); - SaveFrameTypeOnFrame(frameType); + SaveFrameTypeOnFrame(function, frameType); } else if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { reservedSlotsSize = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); lmirBuilder_->SetFuncFrameResverdSlot(reservedSlotsSize); if (circuit_->IsOsr()) { - SaveFrameTypeOnFrame(methodLiteral_->IsFastCall() ? FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME : - frameType); + auto osrFrameType = methodLiteral_->IsFastCall() ? FrameType::OPTIMIZED_JS_FAST_CALL_FUNCTION_FRAME + : frameType; + SaveFrameTypeOnFrame(function, osrFrameType); return; } auto ArgList = circuit_->GetArgRoot(); @@ -658,8 +659,8 @@ void LiteCGIRBuilder::GenPrologue(maple::litecg::Function &function) funcIndex = static_cast(CommonArgIdx::FUNC); } if (argth == funcIndex) { - SaveJSFuncOnOptJSFuncFrame(value); - SaveFrameTypeOnFrame(frameType); + SaveJSFuncOnOptJSFuncFrame(function, value, funcIndex); + SaveFrameTypeOnFrame(function, frameType); } } } else if (frameType == FrameType::FASTJIT_FUNCTION_FRAME) { @@ -701,30 +702,45 @@ void LiteCGIRBuilder::SaveByteCodePcOnOptJSFuncFrame(maple::litecg::Var &value) lmirBuilder_->AppendStmt(GetFirstBB(), stmt); } -void LiteCGIRBuilder::SaveJSFuncOnOptJSFuncFrame(maple::litecg::Var &value) +void LiteCGIRBuilder::SaveJSFuncOnOptJSFuncFrame(maple::litecg::Function &function, maple::litecg::Var &value, + int funcIndex) { ASSERT(IsOptimizedJSFunction()); - Expr fpAddr = CallingFp(false); - Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr); - size_t reservedOffset = 0; - if (circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { - reservedOffset = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); + if (compCfg_->IsAArch64()) { + auto frameType = circuit_->GetFrameType(); + if (frameType == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { + function.SetFuncInfo(OptimizedJSFunctionFrame::GetFunctionToFpDelta(), true, funcIndex); + } else if (frameType == FrameType::FASTJIT_FUNCTION_FRAME) { + function.SetFuncInfo(FASTJITFunctionFrame::GetFunctionToFpDelta(), true, funcIndex); + } } else { - reservedOffset = FASTJITFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); + Expr fpAddr = CallingFp(false); + Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr); + size_t reservedOffset = 0; + if (circuit_->GetFrameType() == FrameType::OPTIMIZED_JS_FUNCTION_FRAME) { + reservedOffset = OptimizedJSFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); + } else { + reservedOffset = FASTJITFunctionFrame::ComputeReservedJSFuncOffset(slotSize_); + } + + Expr frameJSFuncSlotAddr = + lmirBuilder_->Sub(frameAddr.GetType(), frameAddr, + lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, reservedOffset))); + Expr jsFuncAddr = + lmirBuilder_->Cvt(frameJSFuncSlotAddr.GetType(), + lmirBuilder_->CreatePtrType(slotType_), frameJSFuncSlotAddr); + Expr jsFuncValue = lmirBuilder_->Cvt(lmirBuilder_->i64PtrType, slotType_, lmirBuilder_->GenExprFromVar(value)); + auto &stmt = lmirBuilder_->Iassign(jsFuncValue, jsFuncAddr, jsFuncAddr.GetType()); + lmirBuilder_->AppendStmt(GetFirstBB(), stmt); } - - Expr frameJSFuncSlotAddr = - lmirBuilder_->Sub(frameAddr.GetType(), frameAddr, - lmirBuilder_->ConstVal(lmirBuilder_->CreateIntConst(slotType_, reservedOffset))); - Expr jsFuncAddr = - lmirBuilder_->Cvt(frameJSFuncSlotAddr.GetType(), lmirBuilder_->CreatePtrType(slotType_), frameJSFuncSlotAddr); - Expr jsFuncValue = lmirBuilder_->Cvt(lmirBuilder_->i64PtrType, slotType_, lmirBuilder_->GenExprFromVar(value)); - auto &stmt = lmirBuilder_->Iassign(jsFuncValue, jsFuncAddr, jsFuncAddr.GetType()); - lmirBuilder_->AppendStmt(GetFirstBB(), stmt); } -void LiteCGIRBuilder::SaveFrameTypeOnFrame(FrameType frameType) +void LiteCGIRBuilder::SaveFrameTypeOnFrame(maple::litecg::Function &function, FrameType frameType) { + if (compCfg_->IsAArch64()) { + function.SetFrameTypeInfo(-slotSize_, true, static_cast(frameType)); + return; + } Expr fpAddr = CallingFp(false); Expr frameAddr = lmirBuilder_->Cvt(fpAddr.GetType(), lmirBuilder_->i64Type, fpAddr); Expr frameJSFuncSlotAddr = lmirBuilder_->Sub( diff --git a/ecmascript/compiler/codegen/maple/litecg_ir_builder.h b/ecmascript/compiler/codegen/maple/litecg_ir_builder.h index 5355d1707f..b9b15f4231 100644 --- a/ecmascript/compiler/codegen/maple/litecg_ir_builder.h +++ b/ecmascript/compiler/codegen/maple/litecg_ir_builder.h @@ -207,8 +207,8 @@ private: void GenPrologue(maple::litecg::Function &function); void AssistGenPrologue(const size_t reservedSlotsSize, FrameType frameType, maple::litecg::Function &function); void SaveByteCodePcOnOptJSFuncFrame(maple::litecg::Var &value); - void SaveJSFuncOnOptJSFuncFrame(maple::litecg::Var &value); - void SaveFrameTypeOnFrame(FrameType frameType); + void SaveJSFuncOnOptJSFuncFrame(maple::litecg::Function &function, maple::litecg::Var &value, int funcIndex); + void SaveFrameTypeOnFrame(maple::litecg::Function &function, FrameType frameType); bool IsInterpreted() const; bool IsBaselineBuiltin() const; void AddFunc(); diff --git a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_proepilog.h b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_proepilog.h index ce4bdff96d..d4345a885d 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_proepilog.h +++ b/ecmascript/compiler/codegen/maple/maple_be/include/cg/aarch64/aarch64_proepilog.h @@ -63,7 +63,9 @@ private: void GeneratePushRegs(); void GeneratePushUnnamedVarargRegs(); void GenerateProlog(BB &bb); - + void GenerateSave(); + void GenerateFrameTypeSave(SaveInfo &frameInfo, int32 stackSize, int64 fpToSpDistance); + void GenerateFunctionSave(SaveInfo &funcInfo, int32 stackSize, int64 fpToSpDistance); void GenerateRet(BB &bb); void AppendInstructionDeallocateCallFrame(AArch64reg reg0, AArch64reg reg1, RegType rty); void AppendInstructionDeallocateCallFrameDebug(AArch64reg reg0, AArch64reg reg1, RegType rty); diff --git a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_proepilog.cpp b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_proepilog.cpp index 6f4ced16ab..0df85975b1 100644 --- a/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_proepilog.cpp +++ b/ecmascript/compiler/codegen/maple/maple_be/src/cg/aarch64/aarch64_proepilog.cpp @@ -328,6 +328,88 @@ void AArch64GenProEpilog::AppendInstructionAllocateCallFrameDebug(AArch64reg reg } } +void AArch64GenProEpilog::GenerateFrameTypeSave(SaveInfo& frameTypeInfo, int32 stackSize, int64 fpToSpDistance) +{ + if (!frameTypeInfo.shouldSave) { + return; + } + CHECK_FATAL(frameTypeInfo.offset < 0, "must be!!"); + auto &aarchCGFunc = static_cast(cgFunc); + //mov + auto &x10Opnd = aarchCGFunc.GetOrCreatePhysicalRegisterOperand(R10, k64BitSize, kRegTyInt); + auto immOpnd = &aarchCGFunc.CreateImmOperand(frameTypeInfo.idx, k64BitSize, true); + aarchCGFunc.SelectCopyImm(x10Opnd, *immOpnd, PTY_i64); + // store + Operand *o1 = aarchCGFunc.CreateStackMemOpnd(RSP, + static_cast(frameTypeInfo.offset) + fpToSpDistance, GetPointerBitSize()); + MemOperand *mem = static_cast(o1); + uint32 dataSize = GetPointerBitSize(); + if (mem->GetMemVaryType() == kNotVary && aarchCGFunc.IsImmediateOffsetOutOfRange(*mem, dataSize)) { + o1 = &aarchCGFunc.SplitOffsetWithAddInstruction(*mem, dataSize, R16); + } + + Insn &pushInsn = cgFunc.GetInsnBuilder()->BuildInsn(MOP_xstr, x10Opnd, *o1); + AppendInstructionTo(pushInsn, cgFunc); +} + +void AArch64GenProEpilog::GenerateFunctionSave(SaveInfo& funcInfo, int32 stackSize, int64 fpToSpDistance) +{ + if (!funcInfo.shouldSave) { + return; + } + CHECK_FATAL(funcInfo.offset < 0, "must be!!"); + auto &aarchCGFunc = static_cast(cgFunc); + auto &mirFunc = aarchCGFunc.GetFunction(); + CCLocInfo ploc; + CCImpl &parmlocator = *aarchCGFunc.GetOrCreateLocator(CCImpl::GetCallConvKind(aarchCGFunc.GetFunction())); + auto &x10Opnd = aarchCGFunc.GetOrCreatePhysicalRegisterOperand(R10, k64BitSize, kRegTyInt); + CHECK_FATAL(static_cast(funcInfo.idx) <= mirFunc.GetFormalCount(), "should be in range"); + for (size_t i = 0; i < mirFunc.GetFormalCount(); ++i) { + MIRType *ty = mirFunc.GetNthParamType(i); + parmlocator.LocateNextParm(*ty, ploc, (i == 0), mirFunc.GetMIRFuncType()); + if (i != static_cast(funcInfo.idx)) { + continue; + } + if (ploc.reg0 == kRinvalid) { + Operand* o1 = aarchCGFunc.CreateStackMemOpnd(RSP, ploc.memOffset + stackSize, k64BitSize); + uint32 dataSize = GetPointerBitSize(); + if (ploc.memOffset + stackSize > kStpLdpImm64UpperBound) { + o1 = SplitStpLdpOffsetForCalleeSavedWithAddInstruction(cgFunc, + static_cast(*o1), dataSize, R16); + } + Insn &ldrInsn = cgFunc.GetInsnBuilder()->BuildInsn(MOP_xldr, x10Opnd, *o1); + AppendInstructionTo(ldrInsn, cgFunc); + } else { + auto &funcOpnd = + aarchCGFunc.GetOrCreatePhysicalRegisterOperand((AArch64reg)ploc.GetReg0(), k64BitSize, kRegTyInt); + aarchCGFunc.SelectCopy(x10Opnd, ploc.GetPrimTypeOfReg0(), funcOpnd, ploc.GetPrimTypeOfReg0()); + } + } + Operand *o2 = aarchCGFunc.CreateStackMemOpnd(RSP, + static_cast(funcInfo.offset) + fpToSpDistance, GetPointerBitSize()); + MemOperand *mem2 = static_cast(o2); + uint32 dataSize = GetPointerBitSize(); + if (mem2->GetMemVaryType() == kNotVary && aarchCGFunc.IsImmediateOffsetOutOfRange(*mem2, dataSize)) { + o2 = &aarchCGFunc.SplitOffsetWithAddInstruction(*mem2, dataSize, R16); + } + Insn &pushInsn2 = cgFunc.GetInsnBuilder()->BuildInsn(MOP_xstr, x10Opnd, *o2); + AppendInstructionTo(pushInsn2, cgFunc); +} + +void AArch64GenProEpilog::GenerateSave() +{ + auto &aarchCGFunc = static_cast(cgFunc); + auto &mirFunc = aarchCGFunc.GetFunction(); + auto &frameTypeInfo = mirFunc.GetFrameTypeInfo(); + auto &funcInfo = mirFunc.GetFuncInfo(); + + int32 stackFrameSize = + static_cast(static_cast(cgFunc.GetMemlayout())->RealStackFrameSize()); + int64 fpToSpDistance = cgFunc.GetMemlayout()->SizeOfArgsToStackPass() + cgFunc.GetFunction().GetFrameReseverdSlot(); + GenerateFrameTypeSave(frameTypeInfo, stackFrameSize, fpToSpDistance); + GenerateFunctionSave(funcInfo, stackFrameSize, fpToSpDistance); +} + /* * From AArch64 Reference Manual * C1.3.3 Load/Store Addressing Mode @@ -366,7 +448,7 @@ void AArch64GenProEpilog::GeneratePushRegs() } else { AppendInstructionAllocateCallFrameDebug(R29, RLR, kRegTyInt); } - + GenerateSave(); if (useFP) { if (currCG->GenerateVerboseCG()) { cgFunc.GetCurBB()->AppendInsn(aarchCGFunc.CreateCommentInsn("copy SP to FP")); diff --git a/ecmascript/compiler/codegen/maple/maple_ir/include/mir_function.h b/ecmascript/compiler/codegen/maple/maple_ir/include/mir_function.h index 2fb84527fb..74da05c8db 100644 --- a/ecmascript/compiler/codegen/maple/maple_ir/include/mir_function.h +++ b/ecmascript/compiler/codegen/maple/maple_ir/include/mir_function.h @@ -30,6 +30,12 @@ namespace maple { enum PointerAttr : uint32_t { kPointerUndeiced = 0x1, kPointerNull = 0x2, kPointerNoNull = 0x3 }; +struct SaveInfo { + int offset; + bool shouldSave; + int idx; +}; + enum FuncAttrProp : uint32_t { kNoThrowException = 0x1, kNoRetNewlyAllocObj = 0x2, @@ -161,6 +167,30 @@ public: funcType->SetRetTyIdx(tyidx); } + void SetFrameTypeInfo(int offset, bool shouldSave, int idx) + { + frameTypeInfo.offset = offset; + frameTypeInfo.shouldSave = shouldSave; + frameTypeInfo.idx = idx; + } + + void SetFuncInfo(int offset, bool shouldSave, int idx) + { + funcIdxInfo.offset = offset; + funcIdxInfo.shouldSave = shouldSave; + funcIdxInfo.idx = idx; + } + + SaveInfo &GetFrameTypeInfo() + { + return frameTypeInfo; + } + + SaveInfo &GetFuncInfo() + { + return funcIdxInfo; + } + TyIdx GetClassTyIdx() const { return classTyIdx; @@ -1469,6 +1499,8 @@ private: void DumpFlavorLoweredThanMmpl() const; #endif MIRFuncType *ReconstructFormals(const std::vector &symbols, bool clearOldArgs); + SaveInfo frameTypeInfo {0, false, 0}; + SaveInfo funcIdxInfo {0, false, 0}; MapleList debugComments {module->GetMPAllocator().Adapter()}; }; } // namespace maple diff --git a/ecmascript/frames.h b/ecmascript/frames.h index 3f63d32948..909aa7bb9a 100644 --- a/ecmascript/frames.h +++ b/ecmascript/frames.h @@ -633,6 +633,17 @@ public: return slotSize * slotOffset; } + static int GetFrmaeTypeToFpDelta() + { + return -(int)sizeof(uintptr_t); + } + + static int GetFunctionToFpDelta() + { + int slotOffset = static_cast(Index::JSFuncIndex) - static_cast(Index::TypeIndex); + return slotOffset * JSTaggedValue::TaggedTypeSize() + GetFrmaeTypeToFpDelta(); + } + FrameType GetType() const { return type; @@ -1880,6 +1891,17 @@ public: return slotSize * slotOffset; } + static int GetFrmaeTypeToFpDelta() + { + return -(int)sizeof(uintptr_t); + } + + static int GetFunctionToFpDelta() + { + int slotOffset = static_cast(Index::JSFuncIndex) - static_cast(Index::TypeIndex); + return slotOffset * JSTaggedValue::TaggedTypeSize() + GetFrmaeTypeToFpDelta(); + } + FrameType GetType() const { return type;