提交 0a6764ab 编写于 作者: T TIHan

Delaying lambdas working

上级 2b1e29cf
......@@ -395,7 +395,7 @@ let SetOptimizeOn(tcConfigB: TcConfigBuilder) =
tcConfigB.optSettings <- { tcConfigB.optSettings with jitOptUser = Some true }
tcConfigB.optSettings <- { tcConfigB.optSettings with localOptUser = Some true }
tcConfigB.optSettings <- { tcConfigB.optSettings with crossModuleOptUser = Some true }
tcConfigB.optSettings <- { tcConfigB.optSettings with lambdaInlineThreshold = 6 }
tcConfigB.optSettings <- { tcConfigB.optSettings with lambdaInlineThreshold = Optimizer.LambdaInlineThresholdDefault }
tcConfigB.doDetuple <- true
tcConfigB.doTLR <- true
tcConfigB.doFinalSimplify <- true
......
......@@ -2353,9 +2353,7 @@ and CodeGenMethodForExpr cenv mgbuf (spReq, entryPointInfo, methodName, eenv, al
CodeGenMethod cenv mgbuf (entryPointInfo, methodName, eenv, alreadyUsedArgs,
(fun cgbuf eenv -> GenExpr cenv cgbuf eenv spReq expr0 sequel0),
expr0.Range)
code
code
//--------------------------------------------------------------------------
// Generate sequels
......@@ -4305,9 +4303,65 @@ and GenGenericParams cenv eenv tps =
and GenGenericArgs m (tyenv: TypeReprEnv) tps =
tps |> DropErasedTypars |> List.map (fun c -> (mkILTyvarTy tyenv.[c, m]))
and DelayGenMethodForLambda cenv mgbuf eenv args =
cenv.delayedGenMethods.Enqueue(fun cenv -> GenMethodForLambda cenv mgbuf eenv args)
and GenMethodForLambda cenv mgbuf eenv (entryPointInfo, cloinfo, eenvinner, body, isLocalTypeFunc, m) =
let g = cenv.g
let ilCloBody = CodeGenMethodForExpr cenv mgbuf (SPAlways, entryPointInfo, cloinfo.cloName, eenvinner, 1, body, Return)
let ilCloTypeRef = cloinfo.cloSpec.TypeRef
let cloTypeDefs =
if isLocalTypeFunc then
// Work out the contract type and generate a class with an abstract method for this type
let (ilContractGenericParams, ilContractMethTyargs, ilContractTySpec: ILTypeSpec, ilContractFormalRetTy) = GenNamedLocalTypeFuncContractInfo cenv eenv m cloinfo
let ilContractTypeRef = ilContractTySpec.TypeRef
let ilContractTy = mkILFormalBoxedTy ilContractTypeRef ilContractGenericParams
let ilContractCtor = mkILNonGenericEmptyCtor None g.ilg.typ_Object
let ilContractMeths = [ilContractCtor; mkILGenericVirtualMethod("DirectInvoke", ILMemberAccess.Assembly, ilContractMethTyargs, [], mkILReturn ilContractFormalRetTy, MethodBody.Abstract) ]
let ilContractTypeDef =
ILTypeDef(name = ilContractTypeRef.Name,
layout = ILTypeDefLayout.Auto,
attributes = enum 0,
genericParams = ilContractGenericParams,
customAttrs = mkILCustomAttrs [mkCompilationMappingAttr g (int SourceConstructFlags.Closure) ],
fields = emptyILFields,
events= emptyILEvents,
properties = emptyILProperties,
methods= mkILMethods ilContractMeths,
methodImpls= emptyILMethodImpls,
nestedTypes=emptyILTypeDefs,
implements = [],
extends= Some g.ilg.typ_Object,
securityDecls= emptyILSecurityDecls)
// the contract type is an abstract type and not sealed
let ilContractTypeDef =
ilContractTypeDef
.WithAbstract(true)
.WithAccess(ComputeTypeAccess ilContractTypeRef true)
.WithSerializable(true)
.WithSpecialName(true)
.WithLayout(ILTypeDefLayout.Auto)
.WithInitSemantics(ILTypeInit.BeforeField)
.WithEncoding(ILDefaultPInvokeEncoding.Auto)
mgbuf.AddTypeDef(ilContractTypeRef, ilContractTypeDef, false, false, None)
let ilCtorBody = mkILMethodBody (true, [], 8, nonBranchingInstrsToCode (mkCallBaseConstructor(ilContractTy, [])), None )
let cloMethods = [ mkILGenericVirtualMethod("DirectInvoke", ILMemberAccess.Assembly, cloinfo.localTypeFuncDirectILGenericParams, [], mkILReturn (cloinfo.cloILFormalRetTy), MethodBody.IL ilCloBody) ]
let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, cloinfo.cloILGenericParams, [], cloinfo.cloILFreeVars, cloinfo.ilCloLambdas, ilCtorBody, cloMethods, [], ilContractTy, [])
cloTypeDefs
else
GenClosureTypeDefs cenv (ilCloTypeRef, cloinfo.cloILGenericParams, [], cloinfo.cloILFreeVars, cloinfo.ilCloLambdas, ilCloBody, [], [], g.ilg.typ_Object, [])
CountClosure()
for cloTypeDef in cloTypeDefs do
mgbuf.AddTypeDef(ilCloTypeRef, cloTypeDef, false, false, None)
/// Generate the closure class for a function
and GenLambdaClosure cenv (cgbuf: CodeGenBuffer) eenv isLocalTypeFunc selfv expr =
let g = cenv.g
match expr with
| Expr.Lambda (_, _, _, _, _, m, _)
| Expr.TyLambda (_, _, _, m, _) ->
......@@ -4319,57 +4373,7 @@ and GenLambdaClosure cenv (cgbuf: CodeGenBuffer) eenv isLocalTypeFunc selfv expr
| Some v -> [(v, BranchCallClosure (cloinfo.cloArityInfo))]
| _ -> []
let ilCloBody = CodeGenMethodForExpr cenv cgbuf.mgbuf (SPAlways, entryPointInfo, cloinfo.cloName, eenvinner, 1, body, Return)
let ilCloTypeRef = cloinfo.cloSpec.TypeRef
let cloTypeDefs =
if isLocalTypeFunc then
// Work out the contract type and generate a class with an abstract method for this type
let (ilContractGenericParams, ilContractMethTyargs, ilContractTySpec: ILTypeSpec, ilContractFormalRetTy) = GenNamedLocalTypeFuncContractInfo cenv eenv m cloinfo
let ilContractTypeRef = ilContractTySpec.TypeRef
let ilContractTy = mkILFormalBoxedTy ilContractTypeRef ilContractGenericParams
let ilContractCtor = mkILNonGenericEmptyCtor None g.ilg.typ_Object
let ilContractMeths = [ilContractCtor; mkILGenericVirtualMethod("DirectInvoke", ILMemberAccess.Assembly, ilContractMethTyargs, [], mkILReturn ilContractFormalRetTy, MethodBody.Abstract) ]
let ilContractTypeDef =
ILTypeDef(name = ilContractTypeRef.Name,
layout = ILTypeDefLayout.Auto,
attributes = enum 0,
genericParams = ilContractGenericParams,
customAttrs = mkILCustomAttrs [mkCompilationMappingAttr g (int SourceConstructFlags.Closure) ],
fields = emptyILFields,
events= emptyILEvents,
properties = emptyILProperties,
methods= mkILMethods ilContractMeths,
methodImpls= emptyILMethodImpls,
nestedTypes=emptyILTypeDefs,
implements = [],
extends= Some g.ilg.typ_Object,
securityDecls= emptyILSecurityDecls)
// the contract type is an abstract type and not sealed
let ilContractTypeDef =
ilContractTypeDef
.WithAbstract(true)
.WithAccess(ComputeTypeAccess ilContractTypeRef true)
.WithSerializable(true)
.WithSpecialName(true)
.WithLayout(ILTypeDefLayout.Auto)
.WithInitSemantics(ILTypeInit.BeforeField)
.WithEncoding(ILDefaultPInvokeEncoding.Auto)
cgbuf.mgbuf.AddTypeDef(ilContractTypeRef, ilContractTypeDef, false, false, None)
let ilCtorBody = mkILMethodBody (true, [], 8, nonBranchingInstrsToCode (mkCallBaseConstructor(ilContractTy, [])), None )
let cloMethods = [ mkILGenericVirtualMethod("DirectInvoke", ILMemberAccess.Assembly, cloinfo.localTypeFuncDirectILGenericParams, [], mkILReturn (cloinfo.cloILFormalRetTy), MethodBody.IL ilCloBody) ]
let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, cloinfo.cloILGenericParams, [], cloinfo.cloILFreeVars, cloinfo.ilCloLambdas, ilCtorBody, cloMethods, [], ilContractTy, [])
cloTypeDefs
else
GenClosureTypeDefs cenv (ilCloTypeRef, cloinfo.cloILGenericParams, [], cloinfo.cloILFreeVars, cloinfo.ilCloLambdas, ilCloBody, [], [], g.ilg.typ_Object, [])
CountClosure()
for cloTypeDef in cloTypeDefs do
cgbuf.mgbuf.AddTypeDef(ilCloTypeRef, cloTypeDef, false, false, None)
DelayGenMethodForLambda cenv cgbuf.mgbuf eenv (entryPointInfo, cloinfo, eenvinner, body, isLocalTypeFunc, m)
cloinfo, m
| _ -> failwith "GenLambda: not a lambda"
......
......@@ -278,6 +278,8 @@ let [<Literal>] localOptDefault = true
let [<Literal>] crossModuleOptDefault = true
let [<Literal>] LambdaInlineThresholdDefault = 6
type OptimizationSettings =
{ abstractBigTargets : bool
......@@ -315,7 +317,7 @@ type OptimizationSettings =
bigTargetSize = 100
veryBigExprSize = 3000
crossModuleOptUser = None
lambdaInlineThreshold = 6
lambdaInlineThreshold = LambdaInlineThresholdDefault
reportingPhase = false
reportNoNeedToTailcall = false
reportFunctionSizes = false
......@@ -419,6 +421,14 @@ type IncrementalOptimizationEnv =
override x.ToString() = "<IncrementalOptimizationEnv>"
let SetAbstractBigTargetsOn cenv =
{ cenv with
settings =
{ cenv.settings with
abstractBigTargets = true
}
}
//-------------------------------------------------------------------------
// IsPartialExprVal - is the expr fully known?
//-------------------------------------------------------------------------
......@@ -2911,6 +2921,15 @@ and OptimizeLambdas (vspec: Val option) cenv env topValInfo e ety =
let env = Option.foldBack (BindInternalValToUnknown cenv) baseValOpt env
let env = BindTypeVarsToUnknown tps env
let env = List.foldBack (BindInternalValsToUnknown cenv) vsl env
let cenv =
match env.functionVal with
// If the lambda is compiler generated and we are in the reporing phase, allow lambda to be split.
// As an example, allows generated GetHashCode/Equals/CompareTo/etc methods to be split even if optimizations were off.
// This helps prevent stack overflows in IlxGen.fs.
| Some (v, _) when v.IsCompilerGenerated && cenv.settings.reportingPhase -> SetAbstractBigTargetsOn cenv
| _ -> cenv
let env = BindInternalValsToUnknown cenv (Option.toList baseValOpt) env
let bodyR, bodyinfo = OptimizeExpr cenv env body
let exprR = mkMemberLambdas m tps ctorThisValOpt baseValOpt vsl (bodyR, bodyty)
......
......@@ -62,3 +62,7 @@ val UnionOptimizationInfos: seq<ImplFileOptimizationInfo> -> CcuOptimizationInfo
val ExprHasEffect: TcGlobals -> Expr -> bool
val internal u_CcuOptimizationInfo : TastPickle.ReaderState -> CcuOptimizationInfo
// REVIEW: We need to put the literal at the end of a file due to a bug that causes a compiler error when a literal is put in the middle other signature constructs.
[<Literal>]
val LambdaInlineThresholdDefault : int = 6
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册