@@ -4396,7 +4396,15 @@ and GenClosureTypeDefs cenv (tref: ILTypeRef, ilGenParams, attrs, ilCloAllFreeVa
43964396
43974397 let tdefs = EraseClosures.convIlxClosureDef g.ilxPubCloEnv tref.Enclosing tdef cloInfo
43984398 tdefs
4399-
4399+
4400+ and GenStaticClosureTypeDefs cenv ( tref : ILTypeRef , ilGenParams , attrs , ilCloAllFreeVars , ilCloLambdas , ilCtorBody , mdefs , mimpls , ext , ilIntfTys ) =
4401+ let tdefs = GenClosureTypeDefs cenv ( tref, ilGenParams, attrs, ilCloAllFreeVars, ilCloLambdas, ilCtorBody, mdefs, mimpls, ext, ilIntfTys)
4402+
4403+ // Apply the abstract attribute, turning the sealed class into abstract sealed (i.e. static class).
4404+ // Remove the redundant constructor.
4405+ tdefs |> List.map ( fun td -> td.WithAbstract( true )
4406+ .With( methods= mkILMethodsFromArray ( td.Methods.AsArray |> Array.filter ( fun m -> not m.IsConstructor))))
4407+
44004408and GenGenericParams cenv eenv tps =
44014409 tps |> DropErasedTypars |> List.map ( GenGenericParam cenv eenv)
44024410
@@ -4781,54 +4789,72 @@ and GenDelegateExpr cenv cgbuf eenvouter expr (TObjExprMethod((TSlotSig(_, deleg
47814789 false
47824790 with _ ->
47834791 false
4784-
4792+
47854793 // Work out the free type variables for the morphing thunk
47864794 let takenNames = List.map nameOfVal tmvs
47874795 let ( cloAttribs , _ , _ , cloFreeTyvars , cloFreeVars , ilDelegeeTypeRef , ilCloFreeVars , eenvinner ) =
47884796 GetIlxClosureFreeVars cenv m [] eenvouter takenNames expr
47894797 let ilDelegeeGenericParams = GenGenericParams cenv eenvinner cloFreeTyvars
47904798 let ilDelegeeGenericActualsInner = mkILFormalGenericArgs 0 ilDelegeeGenericParams
47914799
4800+ // When creating a delegate that does not capture any variables, we can instead create a static closure and directly reference the method.
4801+ let useStaticClosure = cloFreeVars.IsEmpty
4802+
47924803 // Create a new closure class with a single "delegee" method that implements the delegate.
47934804 let delegeeMethName = " Invoke"
47944805 let ilDelegeeTyInner = mkILBoxedTy ilDelegeeTypeRef ilDelegeeGenericActualsInner
4795-
4806+
47964807 let envForDelegeeUnderTypars = AddTyparsToEnv methTyparsOfOverridingMethod eenvinner
4797-
4798- let numthis = 1
4808+
4809+ let numthis = if useStaticClosure then 0 else 1
47994810 let tmvs , body = BindUnitVars g ( tmvs, List.replicate ( List.concat slotsig.FormalParams) .Length ValReprInfo.unnamedTopArg1, body)
4800-
4811+
48014812 // The slot sig contains a formal instantiation. When creating delegates we're only
48024813 // interested in the actual instantiation since we don't have to emit a method impl.
48034814 let ilDelegeeParams , ilDelegeeRet = GenActualSlotsig m cenv envForDelegeeUnderTypars slotsig methTyparsOfOverridingMethod tmvs
4804-
4815+
48054816 let envForDelegeeMeth = AddStorageForLocalVals g ( List.mapi ( fun i v -> ( v, Arg ( i+ numthis))) tmvs) envForDelegeeUnderTypars
48064817 let ilMethodBody = CodeGenMethodForExpr cenv cgbuf.mgbuf ( SPAlways, [], delegeeMethName, envForDelegeeMeth, 1 , body, ( if slotSigHasVoidReturnTy slotsig then discardAndReturnVoid else Return))
48074818 let delegeeInvokeMeth =
4808- mkILNonGenericInstanceMethod
4809- ( delegeeMethName, ILMemberAccess.Assembly,
4819+ ( if useStaticClosure then mkILNonGenericStaticMethod else mkILNonGenericInstanceMethod)
4820+ ( delegeeMethName,
4821+ ILMemberAccess.Assembly,
48104822 ilDelegeeParams,
48114823 ilDelegeeRet,
48124824 MethodBody.IL ilMethodBody)
48134825 let delegeeCtorMeth = mkILSimpleStorageCtor( None, Some g.ilg.typ_ Object.TypeSpec, ilDelegeeTyInner, [], [], ILMemberAccess.Assembly)
48144826 let ilCtorBody = delegeeCtorMeth.MethodBody
4815-
4827+
48164828 let ilCloLambdas = Lambdas_ return ilCtxtDelTy
48174829 let ilAttribs = GenAttrs cenv eenvinner cloAttribs
4818- let cloTypeDefs = GenClosureTypeDefs cenv ( ilDelegeeTypeRef, ilDelegeeGenericParams, ilAttribs, ilCloFreeVars, ilCloLambdas, ilCtorBody, [ delegeeInvokeMeth], [], g.ilg.typ_ Object, [])
4830+ let cloTypeDefs =
4831+ ( if useStaticClosure then GenStaticClosureTypeDefs else GenClosureTypeDefs)
4832+ cenv ( ilDelegeeTypeRef, ilDelegeeGenericParams, ilAttribs, ilCloFreeVars, ilCloLambdas, ilCtorBody, [ delegeeInvokeMeth], [], g.ilg.typ_ Object, [])
48194833 for cloTypeDef in cloTypeDefs do
48204834 cgbuf.mgbuf.AddTypeDef( ilDelegeeTypeRef, cloTypeDef, false , false , None)
48214835 CountClosure()
48224836
4837+ // Push the constructor for the delegee
48234838 let ctxtGenericArgsForDelegee = GenGenericArgs m eenvouter.tyenv cloFreeTyvars
4824- let ilxCloSpec = IlxClosureSpec.Create( IlxClosureRef( ilDelegeeTypeRef, ilCloLambdas, ilCloFreeVars), ctxtGenericArgsForDelegee)
4825- GenGetLocalVals cenv cgbuf eenvouter m cloFreeVars
4826- CG.EmitInstr cgbuf ( pop ilCloFreeVars.Length) ( Push [ EraseClosures.mkTyOfLambdas g.ilxPubCloEnv ilCloLambdas]) ( I_ newobj ( ilxCloSpec.Constructor, None))
4827-
4839+ if useStaticClosure then
4840+ GenUnit cenv eenvouter m cgbuf
4841+ else
4842+ let ilxCloSpec = IlxClosureSpec.Create( IlxClosureRef( ilDelegeeTypeRef, ilCloLambdas, ilCloFreeVars), ctxtGenericArgsForDelegee)
4843+ GenGetLocalVals cenv cgbuf eenvouter m cloFreeVars
4844+ CG.EmitInstr cgbuf ( pop ilCloFreeVars.Length) ( Push [ EraseClosures.mkTyOfLambdas g.ilxPubCloEnv ilCloLambdas]) ( I_ newobj ( ilxCloSpec.Constructor, None))
4845+
4846+ // Push the function pointer to the Invoke method of the delegee
48284847 let ilDelegeeTyOuter = mkILBoxedTy ilDelegeeTypeRef ctxtGenericArgsForDelegee
4829- let ilDelegeeInvokeMethOuter = mkILNonGenericInstanceMethSpecInTy ( ilDelegeeTyOuter, " Invoke" , typesOfILParams ilDelegeeParams, ilDelegeeRet.Type)
4830- let ilDelegeeCtorMethOuter = mkCtorMethSpecForDelegate g.ilg ( ilCtxtDelTy, useUIntPtrForDelegateCtor)
4848+ let ilDelegeeInvokeMethOuter =
4849+ ( if useStaticClosure then mkILNonGenericStaticMethSpecInTy else mkILNonGenericInstanceMethSpecInTy)
4850+ ( ilDelegeeTyOuter,
4851+ " Invoke" ,
4852+ typesOfILParams ilDelegeeParams,
4853+ ilDelegeeRet.Type)
48314854 CG.EmitInstr cgbuf ( pop 0 ) ( Push [ g.ilg.typ_ IntPtr]) ( I_ ldftn ilDelegeeInvokeMethOuter)
4855+
4856+ // Instantiate the delegate
4857+ let ilDelegeeCtorMethOuter = mkCtorMethSpecForDelegate g.ilg ( ilCtxtDelTy, useUIntPtrForDelegateCtor)
48324858 CG.EmitInstr cgbuf ( pop 2 ) ( Push [ ilCtxtDelTy]) ( I_ newobj( ilDelegeeCtorMethOuter, None))
48334859 GenSequel cenv eenvouter.cloc cgbuf sequel
48344860
0 commit comments