From 58c0c818a6fbb3f48417fb34b3fd22401e5037b5 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 13 Jan 2021 10:15:57 -0800 Subject: [PATCH 1/6] Backing out stackoverflow fix by delayed gen methods --- src/fsharp/IlxGen.fs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index f404443813a..06006ebcfe1 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -5616,8 +5616,7 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) star CommitStartScope cgbuf startScopeMarkOpt - // if we have any expression recursion depth, we should delay the generation of a method to prevent stack overflows - let generator = if cenv.exprRecursionDepth > 0 then DelayGenMethodForBinding else GenMethodForBinding + let generator = GenMethodForBinding let hasWitnessEntry = cenv.g.generateWitnesses && not witnessInfos.IsEmpty generator cenv cgbuf.mgbuf eenv (vspec, mspec, hasWitnessEntry, false, access, ctps, mtps, [], curriedArgInfos, paramInfos, argTys, retInfo, topValInfo, methLambdaCtorThisValOpt, methLambdaBaseValOpt, methLambdaTypars, methLambdaVars, methLambdaBody, methLambdaBodyTy) From 9cc657062dbbc842671fef3090e0090428ff55ca Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 13 Jan 2021 14:18:36 -0800 Subject: [PATCH 2/6] Trying to lazily gen IL --- src/fsharp/IlxGen.fs | 4 ++-- src/fsharp/absil/il.fs | 1 + src/fsharp/absil/il.fsi | 1 + src/fsharp/absil/ilreflect.fs | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 06006ebcfe1..04d7e89c92b 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -6187,10 +6187,10 @@ and GenMethodForBinding else body - let ilCode = CodeGenMethodForExpr cenv mgbuf (SPAlways, tailCallInfo, mspec.Name, eenvForMeth, 0, bodyExpr, sequel) + let ilCode = lazy CodeGenMethodForExpr cenv mgbuf (SPAlways, tailCallInfo, mspec.Name, eenvForMeth, 0, bodyExpr, sequel) // This is the main code generation for most methods - false, MethodBody.IL ilCode, false + false, MethodBody.LazyIL(ilCode), false // Do not generate DllImport attributes into the code - they are implicit from the P/Invoke let attrs = diff --git a/src/fsharp/absil/il.fs b/src/fsharp/absil/il.fs index ae3e2cd9c5d..c237019839c 100644 --- a/src/fsharp/absil/il.fs +++ b/src/fsharp/absil/il.fs @@ -1548,6 +1548,7 @@ type ILMethodVirtualInfo = [] type MethodBody = | IL of ILMethodBody + | LazyIL of Lazy | PInvoke of PInvokeMethod (* platform invoke to native *) | Abstract | Native diff --git a/src/fsharp/absil/il.fsi b/src/fsharp/absil/il.fsi index 5071ea5670b..5e817ce2e47 100644 --- a/src/fsharp/absil/il.fsi +++ b/src/fsharp/absil/il.fsi @@ -936,6 +936,7 @@ type internal ILOverridesSpec = [] type internal MethodBody = | IL of ILMethodBody + | LazyIL of Lazy | PInvoke of PInvokeMethod | Abstract | Native diff --git a/src/fsharp/absil/ilreflect.fs b/src/fsharp/absil/ilreflect.fs index 6d235ccf4f0..068fd4363a1 100644 --- a/src/fsharp/absil/ilreflect.fs +++ b/src/fsharp/absil/ilreflect.fs @@ -1380,6 +1380,7 @@ let emitILMethodBody cenv modB emEnv (ilG: ILGenerator) (ilmbody: ILMethodBody) let emitMethodBody cenv modB emEnv ilG _name (mbody: ILLazyMethodBody) = match mbody.Contents with | MethodBody.IL ilmbody -> emitILMethodBody cenv modB emEnv (ilG()) ilmbody + | MethodBody.LazyIL ilmbody -> emitILMethodBody cenv modB emEnv (ilG()) ilmbody.Value | MethodBody.PInvoke _pinvoke -> () | MethodBody.Abstract -> () | MethodBody.Native -> failwith "emitMethodBody: native" From c142091f2d5f91c7260fca78685da518a95942c0 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 13 Jan 2021 14:46:37 -0800 Subject: [PATCH 3/6] Making ILMethodBody.IL be lazy --- src/fsharp/IlxGen.fs | 41 +++++++++++++++++++++------------ src/fsharp/absil/il.fs | 18 ++++++++------- src/fsharp/absil/il.fsi | 3 +-- src/fsharp/absil/ilmorph.fs | 4 +++- src/fsharp/absil/ilread.fs | 34 ++++++++++++++------------- src/fsharp/absil/ilreflect.fs | 3 +-- src/fsharp/absil/ilwrite.fs | 3 ++- src/fsharp/ilx/EraseClosures.fs | 10 +++++--- 8 files changed, 68 insertions(+), 48 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index 04d7e89c92b..de1e3e8534b 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -4371,7 +4371,7 @@ and GenObjectMethod cenv eenvinner (cgbuf: CodeGenBuffer) useMethodImpl tmethod GenGenericParams cenv eenvUnderTypars methTyparsOfOverridingMethod, ilParamsOfOverridingMethod, ilReturnOfOverridingMethod, - MethodBody.IL ilMethodBody) + MethodBody.IL (lazy ilMethodBody)) // fixup attributes to generate a method impl let mdef = if useMethodImpl then fixupMethodImplFlags mdef else mdef let mdef = fixupVirtualSlotFlags mdef @@ -4473,20 +4473,20 @@ and GenSequenceExpr CG.EmitInstr cgbuf (pop ilCloAllFreeVars.Length) (Push [ilCloRetTyInner]) (I_newobj (formalClospec.Constructor, None)) GenSequel cenv eenv.cloc cgbuf Return), m) - mkILNonGenericVirtualMethod("GetFreshEnumerator", ILMemberAccess.Public, [], mkILReturn ilCloEnumeratorTy, MethodBody.IL mbody) + mkILNonGenericVirtualMethod("GetFreshEnumerator", ILMemberAccess.Public, [], mkILReturn ilCloEnumeratorTy, MethodBody.IL (lazy mbody)) |> AddNonUserCompilerGeneratedAttribs g let closeMethod = // Note: We suppress the first sequence point in the body of this method since it is the initial state machine jump let spReq = SPSuppress let ilCode = CodeGenMethodForExpr cenv cgbuf.mgbuf (spReq, [], "Close", eenvinner, 1, closeExpr, discardAndReturnVoid) - mkILNonGenericVirtualMethod("Close", ILMemberAccess.Public, [], mkILReturn ILType.Void, MethodBody.IL ilCode) + mkILNonGenericVirtualMethod("Close", ILMemberAccess.Public, [], mkILReturn ILType.Void, MethodBody.IL (lazy ilCode)) let checkCloseMethod = // Note: We suppress the first sequence point in the body of this method since it is the initial state machine jump let spReq = SPSuppress let ilCode = CodeGenMethodForExpr cenv cgbuf.mgbuf (spReq, [], "get_CheckClose", eenvinner, 1, checkCloseExpr, Return) - mkILNonGenericVirtualMethod("get_CheckClose", ILMemberAccess.Public, [], mkILReturn g.ilg.typ_Bool, MethodBody.IL ilCode) + mkILNonGenericVirtualMethod("get_CheckClose", ILMemberAccess.Public, [], mkILReturn g.ilg.typ_Bool, MethodBody.IL (lazy ilCode)) let generateNextMethod = // Note: We suppress the first sequence point in the body of this method since it is the initial state machine jump @@ -4495,12 +4495,12 @@ and GenSequenceExpr let eenvinner = eenvinner |> AddStorageForLocalVals g [ (nextEnumeratorValRef.Deref, Arg 1) ] let ilParams = [mkILParamNamed("next", ILType.Byref ilCloEnumerableTy)] let ilReturn = mkILReturn g.ilg.typ_Int32 - let ilCode = MethodBody.IL (CodeGenMethodForExpr cenv cgbuf.mgbuf (spReq, [], "GenerateNext", eenvinner, 2, generateNextExpr, Return)) + let ilCode = MethodBody.IL (lazy (CodeGenMethodForExpr cenv cgbuf.mgbuf (spReq, [], "GenerateNext", eenvinner, 2, generateNextExpr, Return))) mkILNonGenericVirtualMethod("GenerateNext", ILMemberAccess.Public, ilParams, ilReturn, ilCode) let lastGeneratedMethod = let ilCode = CodeGenMethodForExpr cenv cgbuf.mgbuf (SPSuppress, [], "get_LastGenerated", eenvinner, 1, exprForValRef m currvref, Return) - mkILNonGenericVirtualMethod("get_LastGenerated", ILMemberAccess.Public, [], mkILReturn ilCloSeqElemTy, MethodBody.IL ilCode) + mkILNonGenericVirtualMethod("get_LastGenerated", ILMemberAccess.Public, [], mkILReturn ilCloSeqElemTy, MethodBody.IL (lazy ilCode)) |> AddNonUserCompilerGeneratedAttribs g let ilCtorBody = @@ -4543,7 +4543,7 @@ and GenClosureTypeDefs cenv (tref: ILTypeRef, ilGenParams, attrs, ilCloAllFreeVa let fspec = mkILFieldSpec (cloSpec.GetStaticFieldSpec().FieldRef, cloTy) let ctorSpec = mkILMethSpecForMethRefInTy (cloSpec.Constructor.MethodRef, cloTy, []) let ilCode = mkILMethodBody (true, [], 8, nonBranchingInstrsToCode ([ I_newobj (ctorSpec, None); mkNormalStsfld fspec ]), None) - let cctor = mkILClassCtor (MethodBody.IL ilCode) + let cctor = mkILClassCtor (MethodBody.IL (lazy ilCode)) let ilFieldDef = mkILStaticField(fspec.Name, fspec.FormalType, None, None, ILMemberAccess.Assembly).WithInitOnly(true) (cctor :: mdefs), [ ilFieldDef ] else @@ -4642,7 +4642,7 @@ and GenLambdaClosure cenv (cgbuf: CodeGenBuffer) eenv isLocalTypeFunc thisVars e 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.ilCloFormalReturnTy), MethodBody.IL ilCloBody) ] + let cloMethods = [ mkILGenericVirtualMethod("DirectInvoke", ILMemberAccess.Assembly, cloinfo.localTypeFuncDirectILGenericParams, [], mkILReturn (cloinfo.ilCloFormalReturnTy), MethodBody.IL(lazy ilCloBody)) ] let cloTypeDefs = GenClosureTypeDefs cenv (ilCloTypeRef, cloinfo.cloILGenericParams, [], cloinfo.ilCloAllFreeVars, cloinfo.ilCloLambdas, ilCtorBody, cloMethods, [], ilContractTy, [], Some cloinfo.cloSpec) cloTypeDefs @@ -5039,7 +5039,7 @@ and GenDelegateExpr cenv cgbuf eenvouter expr (TObjExprMethod((TSlotSig(_, deleg ILMemberAccess.Assembly, ilDelegeeParams, ilDelegeeRet, - MethodBody.IL ilMethodBody) + MethodBody.IL(lazy ilMethodBody)) let delegeeCtorMeth = mkILSimpleStorageCtor(None, Some g.ilg.typ_Object.TypeSpec, ilDelegeeTyInner, [], [], ILMemberAccess.Assembly) let ilCtorBody = delegeeCtorMeth.MethodBody @@ -5644,7 +5644,8 @@ and GenBindingAfterDebugPoint cenv cgbuf eenv sp (TBind(vspec, rhsExpr, _)) star cgbuf.mgbuf.AddOrMergePropertyDef(ilGetterMethSpec.MethodRef.DeclaringTypeRef, ilPropDef, m) let ilMethodDef = - let ilMethodBody = MethodBody.IL(CodeGenMethodForExpr cenv cgbuf.mgbuf (SPSuppress, [], ilGetterMethSpec.Name, eenv, 0, rhsExpr, Return)) + let ilCode = CodeGenMethodForExpr cenv cgbuf.mgbuf (SPSuppress, [], ilGetterMethSpec.Name, eenv, 0, rhsExpr, Return) + let ilMethodBody = MethodBody.IL(lazy ilCode) (mkILStaticMethod ([], ilGetterMethSpec.Name, access, [], mkILReturn ilTy, ilMethodBody)).WithSpecialName |> AddNonUserCompilerGeneratedAttribs g @@ -6187,10 +6188,20 @@ and GenMethodForBinding else body - let ilCode = lazy CodeGenMethodForExpr cenv mgbuf (SPAlways, tailCallInfo, mspec.Name, eenvForMeth, 0, bodyExpr, sequel) + let ilCodeLazy = lazy CodeGenMethodForExpr cenv mgbuf (SPAlways, tailCallInfo, mspec.Name, eenvForMeth, 0, bodyExpr, sequel) // This is the main code generation for most methods - false, MethodBody.LazyIL(ilCode), false + false, MethodBody.IL(ilCodeLazy), false + + match ilMethodBody with + | MethodBody.IL(ilCodeLazy) -> + if cenv.exprRecursionDepth > 0 then + cenv.delayedGenMethods.Enqueue(fun _ -> ilCodeLazy.Force() |> ignore) + else + // Eagerly codegen if we are not in an expression depth. + ilCodeLazy.Force() |> ignore + | _ -> + () // Do not generate DllImport attributes into the code - they are implicit from the P/Invoke let attrs = @@ -7032,7 +7043,7 @@ and GenImplFile cenv (mgbuf: AssemblyBuilder) mainInfoOpt eenv (implFile: TypedI // This adds the explicit init of the .cctor to the explicit entry point main method mgbuf.AddExplicitInitToSpecificMethodDef((fun md -> md.IsEntryPoint), tref, fspec, GenPossibleILSourceMarker cenv m, feefee, seqpt)) - let cctorMethDef = mkILClassCtor (MethodBody.IL topCode) + let cctorMethDef = mkILClassCtor (MethodBody.IL (lazy topCode)) mgbuf.AddMethodDef(initClassTy.TypeRef, cctorMethDef) // Final file, implicit entry point. We generate no .cctor. @@ -7047,7 +7058,7 @@ and GenImplFile cenv (mgbuf: AssemblyBuilder) mainInfoOpt eenv (implFile: TypedI // generate main@ let ilMainMethodDef = - let mdef = mkILNonGenericStaticMethod(mainMethName, ILMemberAccess.Public, [], mkILReturn ILType.Void, MethodBody.IL topCode) + let mdef = mkILNonGenericStaticMethod(mainMethName, ILMemberAccess.Public, [], mkILReturn ILType.Void, MethodBody.IL (lazy topCode)) mdef.With(isEntryPoint= true, customAttrs = ilAttrs) mgbuf.AddMethodDef(initClassTy.TypeRef, ilMainMethodDef) @@ -7057,7 +7068,7 @@ and GenImplFile cenv (mgbuf: AssemblyBuilder) mainInfoOpt eenv (implFile: TypedI | None -> if doesSomething then // Add the cctor - let cctorMethDef = mkILClassCtor (MethodBody.IL topCode) + let cctorMethDef = mkILClassCtor (MethodBody.IL (lazy topCode)) mgbuf.AddMethodDef(initClassTy.TypeRef, cctorMethDef) // Commit the directed initializations diff --git a/src/fsharp/absil/il.fs b/src/fsharp/absil/il.fs index c237019839c..ea93694123f 100644 --- a/src/fsharp/absil/il.fs +++ b/src/fsharp/absil/il.fs @@ -1547,8 +1547,7 @@ type ILMethodVirtualInfo = [] type MethodBody = - | IL of ILMethodBody - | LazyIL of Lazy + | IL of Lazy | PInvoke of PInvokeMethod (* platform invoke to native *) | Abstract | Native @@ -1682,14 +1681,14 @@ type ILMethodDef (name: string, attributes: MethodAttributes, implAttributes: Me member md.Code = match md.Body.Contents with - | MethodBody.IL il-> Some il.Code + | MethodBody.IL il-> Some il.Value.Code | _ -> None member x.IsIL = match x.Body.Contents with | MethodBody.IL _ -> true | _ -> false - member x.Locals = match x.Body.Contents with | MethodBody.IL il -> il.Locals | _ -> [] + member x.Locals = match x.Body.Contents with | MethodBody.IL il -> il.Value.Locals | _ -> [] - member x.MethodBody = match x.Body.Contents with MethodBody.IL il -> il | _ -> failwith "not IL" + member x.MethodBody = match x.Body.Contents with MethodBody.IL il -> il.Value | _ -> failwith "not IL" member x.SourceMarker = x.MethodBody.SourceMarker @@ -2939,7 +2938,9 @@ let mkILMethodBody (initlocals, locals, maxstack, code, tag) : ILMethodBody = Code= code SourceMarker=tag } -let mkMethodBody (zeroinit, locals, maxstack, code, tag) = MethodBody.IL (mkILMethodBody (zeroinit, locals, maxstack, code, tag)) +let mkMethodBody (zeroinit, locals, maxstack, code, tag) = + let ilCode = mkILMethodBody (zeroinit, locals, maxstack, code, tag) + MethodBody.IL (lazy ilCode) // -------------------------------------------------------------------- // Make a constructor @@ -3084,7 +3085,8 @@ let mdef_code2code f (md: ILMethodDef) = match md.Body.Contents with | MethodBody.IL il-> il | _ -> failwith "mdef_code2code - method not IL" - let b = MethodBody.IL (ilmbody_code2code f il) + let ilCode = ilmbody_code2code f il.Value + let b = MethodBody.IL (lazy ilCode) md.With(body = mkMethBodyAux b) let prependInstrsToCode (instrs: ILInstr list) (c2: ILCode) = @@ -4171,7 +4173,7 @@ and refs_of_local s loc = refs_of_typ s loc.Type and refs_of_mbody s x = match x with - | MethodBody.IL il -> refs_of_ilmbody s il + | MethodBody.IL il -> refs_of_ilmbody s il.Value | MethodBody.PInvoke (attr) -> refs_of_modref s attr.Where | _ -> () diff --git a/src/fsharp/absil/il.fsi b/src/fsharp/absil/il.fsi index 5e817ce2e47..d0e5996ddab 100644 --- a/src/fsharp/absil/il.fsi +++ b/src/fsharp/absil/il.fsi @@ -935,8 +935,7 @@ type internal ILOverridesSpec = [] type internal MethodBody = - | IL of ILMethodBody - | LazyIL of Lazy + | IL of Lazy | PInvoke of PInvokeMethod | Abstract | Native diff --git a/src/fsharp/absil/ilmorph.fs b/src/fsharp/absil/ilmorph.fs index b6fb7ce69b6..b653fe0dc6c 100644 --- a/src/fsharp/absil/ilmorph.fs +++ b/src/fsharp/absil/ilmorph.fs @@ -216,7 +216,9 @@ let ilmbody_instr2instr_ty2ty fs (il: ILMethodBody) = let morphILMethodBody (filmbody) (x: ILLazyMethodBody) = let c = match x.Contents with - | MethodBody.IL il -> MethodBody.IL (filmbody il) + | MethodBody.IL il -> + let ilCode = filmbody il.Value // Eager + MethodBody.IL (lazy ilCode) | x -> x mkMethBodyAux c diff --git a/src/fsharp/absil/ilread.fs b/src/fsharp/absil/ilread.fs index 0139adbddff..7e9ac807893 100644 --- a/src/fsharp/absil/ilread.fs +++ b/src/fsharp/absil/ilread.fs @@ -2878,14 +2878,15 @@ and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (idx, nm, _int (* Convert the linear code format to the nested code format *) let localPdbInfos2 = List.map (fun f -> f raw2nextLab) localPdbInfos let code = buildILCode nm lab2pc instrs [] localPdbInfos2 - MethodBody.IL - { IsZeroInit=false - MaxStack= 8 - NoInlining=noinline - AggressiveInlining=aggressiveinline - Locals=List.empty - SourceMarker=methRangePdbInfo - Code=code } + MethodBody.IL( + lazy + { IsZeroInit=false + MaxStack= 8 + NoInlining=noinline + AggressiveInlining=aggressiveinline + Locals=List.empty + SourceMarker=methRangePdbInfo + Code=code }) elif (b &&& e_CorILMethod_FormatMask) = e_CorILMethod_FatFormat then let hasMoreSections = (b &&& e_CorILMethod_MoreSects) <> 0x0uy @@ -3002,14 +3003,15 @@ and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (idx, nm, _int if logging then dprintn ("done localPdbInfos2, checking code...") let code = buildILCode nm lab2pc instrs !seh localPdbInfos2 if logging then dprintn ("done checking code.") - MethodBody.IL - { IsZeroInit=initlocals - MaxStack= maxstack - NoInlining=noinline - AggressiveInlining=aggressiveinline - Locals = locals - Code=code - SourceMarker=methRangePdbInfo} + MethodBody.IL( + lazy + { IsZeroInit=initlocals + MaxStack= maxstack + NoInlining=noinline + AggressiveInlining=aggressiveinline + Locals = locals + Code=code + SourceMarker=methRangePdbInfo}) else if logging then failwith "unknown format" MethodBody.Abstract) diff --git a/src/fsharp/absil/ilreflect.fs b/src/fsharp/absil/ilreflect.fs index 068fd4363a1..41295d221cf 100644 --- a/src/fsharp/absil/ilreflect.fs +++ b/src/fsharp/absil/ilreflect.fs @@ -1379,8 +1379,7 @@ let emitILMethodBody cenv modB emEnv (ilG: ILGenerator) (ilmbody: ILMethodBody) let emitMethodBody cenv modB emEnv ilG _name (mbody: ILLazyMethodBody) = match mbody.Contents with - | MethodBody.IL ilmbody -> emitILMethodBody cenv modB emEnv (ilG()) ilmbody - | MethodBody.LazyIL ilmbody -> emitILMethodBody cenv modB emEnv (ilG()) ilmbody.Value + | MethodBody.IL ilmbody -> emitILMethodBody cenv modB emEnv (ilG()) ilmbody.Value | MethodBody.PInvoke _pinvoke -> () | MethodBody.Abstract -> () | MethodBody.Native -> failwith "emitMethodBody: native" diff --git a/src/fsharp/absil/ilwrite.fs b/src/fsharp/absil/ilwrite.fs index a184d0bf420..25106c99815 100644 --- a/src/fsharp/absil/ilwrite.fs +++ b/src/fsharp/absil/ilwrite.fs @@ -2447,7 +2447,8 @@ let GenMethodDefAsRow cenv env midx (md: ILMethodDef) = else cenv.entrypoint <- Some (true, midx) let codeAddr = (match md.Body.Contents with - | MethodBody.IL ilmbody -> + | MethodBody.IL ilmbodyLazy -> + let ilmbody = ilmbodyLazy.Value let addr = cenv.nextCodeAddr let (localToken, code, seqpoints, rootScope) = GenILMethodBody md.Name cenv env ilmbody diff --git a/src/fsharp/ilx/EraseClosures.fs b/src/fsharp/ilx/EraseClosures.fs index 7c960a99306..9fb0e3ad1a4 100644 --- a/src/fsharp/ilx/EraseClosures.fs +++ b/src/fsharp/ilx/EraseClosures.fs @@ -315,7 +315,9 @@ let convILMethodBody (thisClo, boxReturnTy) (il: ILMethodBody) = {il with MaxStack=newMax; IsZeroInit=true; Code= code } let convMethodBody thisClo = function - | MethodBody.IL il -> MethodBody.IL (convILMethodBody (thisClo, None) il) + | MethodBody.IL il -> + let convil = convILMethodBody (thisClo, None) il.Value + MethodBody.IL (lazy convil) | x -> x let convMethodDef thisClo (md: ILMethodDef) = @@ -466,6 +468,7 @@ let rec convIlxClosureDef cenv encl (td: ILTypeDef) clo = else // CASE 1b. Build a type application. let boxReturnTy = Some nowReturnTy (* box prior to all I_ret *) + let convil = convILMethodBody (Some nowCloSpec, boxReturnTy) (Lazy.force clo.cloCode) let nowApplyMethDef = mkILGenericVirtualMethod ("Specialize", @@ -473,7 +476,7 @@ let rec convIlxClosureDef cenv encl (td: ILTypeDef) clo = addedGenParams, (* method is generic over added ILGenericParameterDefs *) [], mkILReturn(cenv.ilg.typ_Object), - MethodBody.IL (convILMethodBody (Some nowCloSpec, boxReturnTy) (Lazy.force clo.cloCode))) + MethodBody.IL (lazy convil)) let ctorMethodDef = mkILStorageCtor (None, @@ -565,12 +568,13 @@ let rec convIlxClosureDef cenv encl (td: ILTypeDef) clo = let nowEnvParentClass = typ_Func cenv (typesOfILParams nowParams) nowReturnTy let cloTypeDef = + let convil = convILMethodBody (Some nowCloSpec, None) (Lazy.force clo.cloCode) let nowApplyMethDef = mkILNonGenericVirtualMethod ("Invoke", ILMemberAccess.Public, nowParams, mkILReturn nowReturnTy, - MethodBody.IL (convILMethodBody (Some nowCloSpec, None) (Lazy.force clo.cloCode))) + MethodBody.IL (lazy convil)) let ctorMethodDef = mkILStorageCtor From 0d7599c6cb4954e33a9618ff1bfca2bd963d0412 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Wed, 13 Jan 2021 16:32:20 -0800 Subject: [PATCH 4/6] Consolidating lazy methodbodies by removing ILLazyMethodBody --- src/fsharp/IlxGen.fs | 5 +- src/fsharp/absil/il.fs | 48 ++++++++----------- src/fsharp/absil/il.fsi | 25 ++++------ src/fsharp/absil/ilmorph.fs | 14 +++--- src/fsharp/absil/ilread.fs | 84 +++++++++++++++++---------------- src/fsharp/absil/ilreflect.fs | 11 +++-- src/fsharp/absil/ilwrite.fs | 7 +-- src/fsharp/ilx/EraseClosures.fs | 4 +- 8 files changed, 91 insertions(+), 107 deletions(-) diff --git a/src/fsharp/IlxGen.fs b/src/fsharp/IlxGen.fs index de1e3e8534b..b6f0e72771b 100644 --- a/src/fsharp/IlxGen.fs +++ b/src/fsharp/IlxGen.fs @@ -6406,7 +6406,7 @@ and GenPInvokeMethod (nm, dll, namedArgs) = let hasPreserveSigNamedArg = decoder.FindBool "PreserveSig" true hasPreserveSigNamedArg, - MethodBody.PInvoke + let pinvoke = { Where=mkSimpleModRef dll Name=decoder.FindString "EntryPoint" nm CallingConv= @@ -6427,7 +6427,8 @@ and GenPInvokeMethod (nm, dll, namedArgs) = NoMangle= decoder.FindBool "ExactSpelling" false LastError= decoder.FindBool "SetLastError" false ThrowOnUnmappableChar= if (decoder.FindBool "ThrowOnUnmappableChar" false) then PInvokeThrowOnUnmappableChar.Enabled else PInvokeThrowOnUnmappableChar.UseAssembly - CharBestFit=if (decoder.FindBool "BestFitMapping" false) then PInvokeCharBestFit.Enabled else PInvokeCharBestFit.UseAssembly } + CharBestFit=if (decoder.FindBool "BestFitMapping" false) then PInvokeCharBestFit.Enabled else PInvokeCharBestFit.UseAssembly } : PInvokeMethod + MethodBody.PInvoke(lazy pinvoke) and GenBindings cenv cgbuf eenv binds = List.iter (GenBinding cenv cgbuf eenv) binds diff --git a/src/fsharp/absil/il.fs b/src/fsharp/absil/il.fs index ea93694123f..4e3121de9bb 100644 --- a/src/fsharp/absil/il.fs +++ b/src/fsharp/absil/il.fs @@ -1548,27 +1548,17 @@ type ILMethodVirtualInfo = [] type MethodBody = | IL of Lazy - | PInvoke of PInvokeMethod (* platform invoke to native *) + | PInvoke of Lazy (* platform invoke to native *) | Abstract | Native | NotAvailable -type ILLazyMethodBody = - | ILLazyMethodBody of Lazy - - member x.Contents = let (ILLazyMethodBody mb) = x in mb.Force() - static member NotAvailable = ILLazyMethodBody (notlazy MethodBody.NotAvailable) - [] type MethodCodeKind = | IL | Native | Runtime -let mkMethBodyAux mb = ILLazyMethodBody (notlazy mb) - -let mkMethBodyLazyAux mb = ILLazyMethodBody mb - let typesOfILParams (ps: ILParameters) : ILTypes = ps |> List.map (fun p -> p.Type) [] @@ -1624,7 +1614,7 @@ let NoMetadataIdx = -1 [] type ILMethodDef (name: string, attributes: MethodAttributes, implAttributes: MethodImplAttributes, callingConv: ILCallingConv, - parameters: ILParameters, ret: ILReturn, body: ILLazyMethodBody, isEntryPoint: bool, genericParams: ILGenericParameterDefs, + parameters: ILParameters, ret: ILReturn, body: MethodBody, isEntryPoint: bool, genericParams: ILGenericParameterDefs, securityDeclsStored: ILSecurityDeclsStored, customAttrsStored: ILAttributesStored, metadataIndex: int32) = new (name, attributes, implAttributes, callingConv, parameters, ret, body, isEntryPoint, genericParams, securityDecls, customAttrs) = @@ -1658,7 +1648,7 @@ type ILMethodDef (name: string, attributes: MethodAttributes, implAttributes: Me member x.With (?name: string, ?attributes: MethodAttributes, ?implAttributes: MethodImplAttributes, ?callingConv: ILCallingConv, ?parameters: ILParameters, ?ret: ILReturn, - ?body: ILLazyMethodBody, ?securityDecls: ILSecurityDecls, ?isEntryPoint: bool, + ?body: MethodBody, ?securityDecls: ILSecurityDecls, ?isEntryPoint: bool, ?genericParams: ILGenericParameterDefs, ?customAttrs: ILAttributes) = ILMethodDef (name = defaultArg name x.Name, @@ -1680,15 +1670,15 @@ type ILMethodDef (name: string, attributes: MethodAttributes, implAttributes: Me member x.ParameterTypes = typesOfILParams x.Parameters member md.Code = - match md.Body.Contents with + match md.Body with | MethodBody.IL il-> Some il.Value.Code | _ -> None - member x.IsIL = match x.Body.Contents with | MethodBody.IL _ -> true | _ -> false + member x.IsIL = match x.Body with | MethodBody.IL _ -> true | _ -> false - member x.Locals = match x.Body.Contents with | MethodBody.IL il -> il.Value.Locals | _ -> [] + member x.Locals = match x.Body with | MethodBody.IL il -> il.Value.Locals | _ -> [] - member x.MethodBody = match x.Body.Contents with MethodBody.IL il -> il.Value | _ -> failwith "not IL" + member x.MethodBody = match x.Body with MethodBody.IL il -> il.Value | _ -> failwith "not IL" member x.SourceMarker = x.MethodBody.SourceMarker @@ -2948,11 +2938,11 @@ let mkMethodBody (zeroinit, locals, maxstack, code, tag) = let mkILVoidReturn = mkILReturn ILType.Void -let methBodyNotAvailable = mkMethBodyAux MethodBody.NotAvailable +let methBodyNotAvailable = MethodBody.NotAvailable -let methBodyAbstract = mkMethBodyAux MethodBody.Abstract +let methBodyAbstract = MethodBody.Abstract -let methBodyNative = mkMethBodyAux MethodBody.Native +let methBodyNative = MethodBody.Native let mkILCtor (access, args, impl) = ILMethodDef(name=".ctor", @@ -2961,7 +2951,7 @@ let mkILCtor (access, args, impl) = callingConv=ILCallingConv.Instance, parameters = args, ret= mkILVoidReturn, - body= mkMethBodyAux impl, + body= impl, securityDecls=emptyILSecurityDecls, isEntryPoint=false, genericParams=mkILEmptyGenericParams, @@ -3010,7 +3000,7 @@ let mkILStaticMethod (genparams, nm, access, args, ret, impl) = securityDecls=emptyILSecurityDecls, isEntryPoint=false, customAttrs = emptyILCustomAttrs, - body= mkMethBodyAux impl) + body= impl) let mkILNonGenericStaticMethod (nm, access, args, ret, impl) = mkILStaticMethod (mkILEmptyGenericParams, nm, access, args, ret, impl) @@ -3026,7 +3016,7 @@ let mkILClassCtor impl = isEntryPoint=false, securityDecls=emptyILSecurityDecls, customAttrs=emptyILCustomAttrs, - body= mkMethBodyAux impl) + body= impl) // -------------------------------------------------------------------- // Make a virtual method, where the overriding is simply the default @@ -3050,7 +3040,7 @@ let mkILGenericVirtualMethod (nm, access, genparams, actual_args, actual_ret, im isEntryPoint=false, securityDecls=emptyILSecurityDecls, customAttrs = emptyILCustomAttrs, - body= mkMethBodyAux impl) + body= impl) let mkILNonGenericVirtualMethod (nm, access, args, ret, impl) = mkILGenericVirtualMethod (nm, access, mkILEmptyGenericParams, args, ret, impl) @@ -3066,7 +3056,7 @@ let mkILGenericNonVirtualMethod (nm, access, genparams, actual_args, actual_ret, isEntryPoint=false, securityDecls=emptyILSecurityDecls, customAttrs = emptyILCustomAttrs, - body= mkMethBodyAux impl) + body= impl) let mkILNonGenericInstanceMethod (nm, access, args, ret, impl) = mkILGenericNonVirtualMethod (nm, access, mkILEmptyGenericParams, args, ret, impl) @@ -3082,12 +3072,12 @@ let ilmbody_code2code f (il: ILMethodBody) = let mdef_code2code f (md: ILMethodDef) = let il = - match md.Body.Contents with + match md.Body with | MethodBody.IL il-> il | _ -> failwith "mdef_code2code - method not IL" let ilCode = ilmbody_code2code f il.Value let b = MethodBody.IL (lazy ilCode) - md.With(body = mkMethBodyAux b) + md.With(body = b) let prependInstrsToCode (instrs: ILInstr list) (c2: ILCode) = let instrs = Array.ofList instrs @@ -4174,13 +4164,13 @@ and refs_of_local s loc = refs_of_typ s loc.Type and refs_of_mbody s x = match x with | MethodBody.IL il -> refs_of_ilmbody s il.Value - | MethodBody.PInvoke (attr) -> refs_of_modref s attr.Where + | MethodBody.PInvoke (attr) -> refs_of_modref s attr.Value.Where | _ -> () and refs_of_mdef s (md: ILMethodDef) = List.iter (refs_of_param s) md.Parameters refs_of_return s md.Return - refs_of_mbody s md.Body.Contents + refs_of_mbody s md.Body refs_of_custom_attrs s md.CustomAttrs refs_of_genparams s md.GenericParams diff --git a/src/fsharp/absil/il.fsi b/src/fsharp/absil/il.fsi index d0e5996ddab..f64cb22b029 100644 --- a/src/fsharp/absil/il.fsi +++ b/src/fsharp/absil/il.fsi @@ -936,7 +936,7 @@ type internal ILOverridesSpec = [] type internal MethodBody = | IL of Lazy - | PInvoke of PInvokeMethod + | PInvoke of Lazy | Abstract | Native | NotAvailable @@ -970,12 +970,6 @@ type ILGenericParameterDef = type ILGenericParameterDefs = ILGenericParameterDef list -[] -type internal ILLazyMethodBody = - member internal Contents: MethodBody - - static member NotAvailable: ILLazyMethodBody - /// IL Method definitions. [] type ILMethodDef = @@ -983,12 +977,12 @@ type ILMethodDef = /// Functional creation of a value, with delayed reading of some elements via a metadata index internal new: name: string * attributes: MethodAttributes * implAttributes: MethodImplAttributes * callingConv: ILCallingConv * - parameters: ILParameters * ret: ILReturn * body: ILLazyMethodBody * isEntryPoint:bool * genericParams: ILGenericParameterDefs * + parameters: ILParameters * ret: ILReturn * body: MethodBody * isEntryPoint:bool * genericParams: ILGenericParameterDefs * securityDeclsStored: ILSecurityDeclsStored * customAttrsStored: ILAttributesStored * metadataIndex: int32 -> ILMethodDef /// Functional creation of a value, immediate new: name: string * attributes: MethodAttributes * implAttributes: MethodImplAttributes * callingConv: ILCallingConv * - parameters: ILParameters * ret: ILReturn * body: ILLazyMethodBody * isEntryPoint:bool * genericParams: ILGenericParameterDefs * + parameters: ILParameters * ret: ILReturn * body: MethodBody * isEntryPoint:bool * genericParams: ILGenericParameterDefs * securityDecls: ILSecurityDecls * customAttrs: ILAttributes -> ILMethodDef member Name: string @@ -997,7 +991,7 @@ type ILMethodDef = member CallingConv: ILCallingConv member Parameters: ILParameters member Return: ILReturn - member Body: ILLazyMethodBody + member Body: MethodBody member SecurityDecls: ILSecurityDecls member IsEntryPoint:bool member GenericParams: ILGenericParameterDefs @@ -1054,7 +1048,7 @@ type ILMethodDef = /// Functional update of the value member internal With: ?name: string * ?attributes: MethodAttributes * ?implAttributes: MethodImplAttributes * ?callingConv: ILCallingConv * - ?parameters: ILParameters * ?ret: ILReturn * ?body: ILLazyMethodBody * ?securityDecls: ILSecurityDecls * ?isEntryPoint:bool * + ?parameters: ILParameters * ?ret: ILReturn * ?body: MethodBody * ?securityDecls: ILSecurityDecls * ?isEntryPoint:bool * ?genericParams: ILGenericParameterDefs * ?customAttrs: ILAttributes -> ILMethodDef member internal WithSpecialName: ILMethodDef member internal WithHideBySig: unit -> ILMethodDef @@ -1819,9 +1813,9 @@ val internal mkILEmptyGenericParams: ILGenericParameterDefs /// Make method definitions. val internal mkILMethodBody: initlocals:bool * ILLocals * int * ILCode * ILSourceMarker option -> ILMethodBody val internal mkMethodBody: bool * ILLocals * int * ILCode * ILSourceMarker option -> MethodBody -val internal methBodyNotAvailable: ILLazyMethodBody -val internal methBodyAbstract: ILLazyMethodBody -val internal methBodyNative: ILLazyMethodBody +val internal methBodyNotAvailable: MethodBody +val internal methBodyAbstract: MethodBody +val internal methBodyNative: MethodBody val internal mkILCtor: ILMemberAccess * ILParameter list * MethodBody -> ILMethodDef val internal mkILClassCtor: MethodBody -> ILMethodDef @@ -1890,9 +1884,6 @@ val emptyILSecurityDecls: ILSecurityDecls val internal storeILSecurityDecls: ILSecurityDecls -> ILSecurityDeclsStored val internal mkILSecurityDeclsReader: (int32 -> ILSecurityDecl[]) -> ILSecurityDeclsStored -val internal mkMethBodyAux: MethodBody -> ILLazyMethodBody -val internal mkMethBodyLazyAux: Lazy -> ILLazyMethodBody - val internal mkILEvents: ILEventDef list -> ILEventDefs val internal mkILEventsLazy: Lazy -> ILEventDefs val internal emptyILEvents: ILEventDefs diff --git a/src/fsharp/absil/ilmorph.fs b/src/fsharp/absil/ilmorph.fs index b653fe0dc6c..7e43c1c16b4 100644 --- a/src/fsharp/absil/ilmorph.fs +++ b/src/fsharp/absil/ilmorph.fs @@ -213,14 +213,12 @@ let ilmbody_instr2instr_ty2ty fs (il: ILMethodBody) = {il with Code=code_instr2instr_ty2ty (finstr,ftye) il.Code Locals = locals_ty2ty ftye il.Locals } -let morphILMethodBody (filmbody) (x: ILLazyMethodBody) = - let c = - match x.Contents with - | MethodBody.IL il -> - let ilCode = filmbody il.Value // Eager - MethodBody.IL (lazy ilCode) - | x -> x - mkMethBodyAux c +let morphILMethodBody (filmbody) (x: MethodBody) = + match x with + | MethodBody.IL il -> + let ilCode = filmbody il.Value // Eager + MethodBody.IL (lazy ilCode) + | x -> x let ospec_ty2ty f (OverridesSpec(mref,ty)) = OverridesSpec(mref_ty2ty f mref, f ty) diff --git a/src/fsharp/absil/ilread.fs b/src/fsharp/absil/ilread.fs index 7e9ac807893..274c5b409d9 100644 --- a/src/fsharp/absil/ilread.fs +++ b/src/fsharp/absil/ilread.fs @@ -2494,7 +2494,7 @@ and seekReadConstant (ctxt: ILMetadataReader) idx = | _ -> ILFieldInit.Null and seekReadImplMap (ctxt: ILMetadataReader) nm midx = - mkMethBodyLazyAux + MethodBody.PInvoke (lazy let mdv = ctxt.mdfile.GetView() let (flags, nameIdx, scopeIdx) = seekReadIndexedRow (ctxt.getNumRows TableNames.ImplMap, @@ -2535,17 +2535,17 @@ and seekReadImplMap (ctxt: ILMetadataReader) nm midx = elif masked = 0x2000 then PInvokeThrowOnUnmappableChar.Disabled else (dprintn "strange ThrowOnUnmappableChar"; PInvokeThrowOnUnmappableChar.UseAssembly) - MethodBody.PInvoke { CallingConv = cc - CharEncoding = enc - CharBestFit=bestfit - ThrowOnUnmappableChar=unmap - NoMangle = (flags &&& 0x0001) <> 0x0 - LastError = (flags &&& 0x0040) <> 0x0 - Name = - (match readStringHeapOption ctxt nameIdx with - | None -> nm - | Some nm2 -> nm2) - Where = seekReadModuleRef ctxt mdv scopeIdx }) + { CallingConv = cc + CharEncoding = enc + CharBestFit=bestfit + ThrowOnUnmappableChar=unmap + NoMangle = (flags &&& 0x0001) <> 0x0 + LastError = (flags &&& 0x0040) <> 0x0 + Name = + (match readStringHeapOption ctxt nameIdx with + | None -> nm + | Some nm2 -> nm2) + Where = seekReadModuleRef ctxt mdv scopeIdx }) and seekReadTopCode (ctxt: ILMetadataReader) pev mdv numtypars (sz: int) start seqpoints = let labelsOfRawOffsets = new Dictionary<_, _>(sz/2) @@ -2797,9 +2797,21 @@ and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (_idx, nm, _in #else and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (idx, nm, _internalcall, noinline, aggressiveinline, numtypars) rva = #endif - mkMethBodyLazyAux + let pev = pectxt.pefile.GetView() + let baseRVA = pectxt.anyV2P("method rva", rva) + // ": reading body of method "+nm+" at rva "+string rva+", phys "+string baseRVA + let b = seekReadByte pev baseRVA + + let isTinyFormat = (b &&& e_CorILMethod_FormatMask) = e_CorILMethod_TinyFormat + let isFatFormat = (b &&& e_CorILMethod_FormatMask) = e_CorILMethod_FatFormat + + if not isTinyFormat && not isFatFormat then + if logging then failwith "unknown format" + MethodBody.Abstract + else + + MethodBody.IL (lazy - let pev = pectxt.pefile.GetView() let mdv = ctxt.mdfile.GetView() // Read any debug information for this method into temporary data structures @@ -2867,10 +2879,7 @@ and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (idx, nm, _int [], None, [] #endif - let baseRVA = pectxt.anyV2P("method rva", rva) - // ": reading body of method "+nm+" at rva "+string rva+", phys "+string baseRVA - let b = seekReadByte pev baseRVA - if (b &&& e_CorILMethod_FormatMask) = e_CorILMethod_TinyFormat then + if isTinyFormat then let codeBase = baseRVA + 1 let codeSize = (int32 b >>>& 2) // tiny format for "+nm+", code size = " + string codeSize) @@ -2878,17 +2887,15 @@ and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (idx, nm, _int (* Convert the linear code format to the nested code format *) let localPdbInfos2 = List.map (fun f -> f raw2nextLab) localPdbInfos let code = buildILCode nm lab2pc instrs [] localPdbInfos2 - MethodBody.IL( - lazy - { IsZeroInit=false - MaxStack= 8 - NoInlining=noinline - AggressiveInlining=aggressiveinline - Locals=List.empty - SourceMarker=methRangePdbInfo - Code=code }) - - elif (b &&& e_CorILMethod_FormatMask) = e_CorILMethod_FatFormat then + { IsZeroInit=false + MaxStack= 8 + NoInlining=noinline + AggressiveInlining=aggressiveinline + Locals=List.empty + SourceMarker=methRangePdbInfo + Code=code } + + else let hasMoreSections = (b &&& e_CorILMethod_MoreSects) <> 0x0uy let initlocals = (b &&& e_CorILMethod_InitLocals) <> 0x0uy let maxstack = seekReadUInt16AsInt32 pev (baseRVA + 2) @@ -3003,18 +3010,13 @@ and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (idx, nm, _int if logging then dprintn ("done localPdbInfos2, checking code...") let code = buildILCode nm lab2pc instrs !seh localPdbInfos2 if logging then dprintn ("done checking code.") - MethodBody.IL( - lazy - { IsZeroInit=initlocals - MaxStack= maxstack - NoInlining=noinline - AggressiveInlining=aggressiveinline - Locals = locals - Code=code - SourceMarker=methRangePdbInfo}) - else - if logging then failwith "unknown format" - MethodBody.Abstract) + { IsZeroInit=initlocals + MaxStack= maxstack + NoInlining=noinline + AggressiveInlining=aggressiveinline + Locals = locals + Code=code + SourceMarker=methRangePdbInfo}) and int32AsILVariantType (ctxt: ILMetadataReader) (n: int32) = if List.memAssoc n (Lazy.force ILVariantTypeRevMap) then diff --git a/src/fsharp/absil/ilreflect.fs b/src/fsharp/absil/ilreflect.fs index 41295d221cf..5999c8099cf 100644 --- a/src/fsharp/absil/ilreflect.fs +++ b/src/fsharp/absil/ilreflect.fs @@ -1377,8 +1377,8 @@ let emitILMethodBody cenv modB emEnv (ilG: ILGenerator) (ilmbody: ILMethodBody) emitCode cenv modB emEnv ilG ilmbody.Code -let emitMethodBody cenv modB emEnv ilG _name (mbody: ILLazyMethodBody) = - match mbody.Contents with +let emitMethodBody cenv modB emEnv ilG _name (mbody: MethodBody) = + match mbody with | MethodBody.IL ilmbody -> emitILMethodBody cenv modB emEnv (ilG()) ilmbody.Value | MethodBody.PInvoke _pinvoke -> () | MethodBody.Abstract -> () @@ -1497,8 +1497,9 @@ let rec buildMethodPass2 cenv tref (typB: TypeBuilder) emEnv (mdef: ILMethodDef) envAddEntryPt emEnv (typB, mdef.Name) else emEnv - match mdef.Body.Contents with - | MethodBody.PInvoke p when enablePInvoke -> + match mdef.Body with + | MethodBody.PInvoke pLazy when enablePInvoke -> + let p = pLazy.Value let argtys = convTypesToArray cenv emEnv mdef.ParameterTypes let rty = convType cenv emEnv mdef.Return.Type @@ -1575,7 +1576,7 @@ let rec buildMethodPass2 cenv tref (typB: TypeBuilder) emEnv (mdef: ILMethodDef) let rec buildMethodPass3 cenv tref modB (typB: TypeBuilder) emEnv (mdef: ILMethodDef) = let mref = mkRefToILMethod (tref, mdef) let isPInvoke = - match mdef.Body.Contents with + match mdef.Body with | MethodBody.PInvoke _p -> true | _ -> false match mdef.Name with diff --git a/src/fsharp/absil/ilwrite.fs b/src/fsharp/absil/ilwrite.fs index 25106c99815..421cfed830d 100644 --- a/src/fsharp/absil/ilwrite.fs +++ b/src/fsharp/absil/ilwrite.fs @@ -2446,7 +2446,7 @@ let GenMethodDefAsRow cenv env midx (md: ILMethodDef) = if cenv.entrypoint <> None then failwith "duplicate entrypoint" else cenv.entrypoint <- Some (true, midx) let codeAddr = - (match md.Body.Contents with + (match md.Body with | MethodBody.IL ilmbodyLazy -> let ilmbody = ilmbodyLazy.Value let addr = cenv.nextCodeAddr @@ -2519,8 +2519,9 @@ let GenMethodDefPass3 cenv env (md: ILMethodDef) = md.CustomAttrs |> GenCustomAttrsPass3Or4 cenv (hca_MethodDef, midx) md.SecurityDecls.AsList |> GenSecurityDeclsPass3 cenv (hds_MethodDef, midx) md.GenericParams |> List.iteri (fun n gp -> GenGenericParamPass3 cenv env n (tomd_MethodDef, midx) gp) - match md.Body.Contents with - | MethodBody.PInvoke attr -> + match md.Body with + | MethodBody.PInvoke attrLazy -> + let attr = attrLazy.Value let flags = begin match attr.CallingConv with | PInvokeCallingConvention.None -> 0x0000 diff --git a/src/fsharp/ilx/EraseClosures.fs b/src/fsharp/ilx/EraseClosures.fs index 9fb0e3ad1a4..4195a81230e 100644 --- a/src/fsharp/ilx/EraseClosures.fs +++ b/src/fsharp/ilx/EraseClosures.fs @@ -321,8 +321,8 @@ let convMethodBody thisClo = function | x -> x let convMethodDef thisClo (md: ILMethodDef) = - let b' = convMethodBody thisClo (md.Body.Contents) - md.With(body=mkMethBodyAux b') + let b' = convMethodBody thisClo (md.Body) + md.With(body=b') // -------------------------------------------------------------------- // Make fields for free variables of a type abstraction. From 9063ca55710859ed438fa8880303df4c914da8d5 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 14 Jan 2021 18:29:27 -0800 Subject: [PATCH 5/6] Updating baseline and fixing build --- src/fsharp/absil/ilprint.fs | 9 +++++---- src/fsharp/absil/ilread.fs | 1 + .../SurfaceArea.netstandard.fs | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/fsharp/absil/ilprint.fs b/src/fsharp/absil/ilprint.fs index 42c0dcddd6a..f5a446c3f62 100644 --- a/src/fsharp/absil/ilprint.fs +++ b/src/fsharp/absil/ilprint.fs @@ -807,8 +807,8 @@ let goutput_mbody is_entrypoint env os (md: ILMethodDef) = output_string os " \n{ \n" goutput_security_decls env os md.SecurityDecls goutput_custom_attrs env os md.CustomAttrs - match md.Body.Contents with - | MethodBody.IL il -> goutput_ilmbody env os il + match md.Body with + | MethodBody.IL il -> goutput_ilmbody env os il.Value | _ -> () if is_entrypoint then output_string os " .entrypoint" output_string os "\n" @@ -827,8 +827,9 @@ let goutput_mdef env os (md:ILMethodDef) = elif md.IsConstructor then "rtspecialname" elif md.IsStatic then "static " + - (match md.Body.Contents with - MethodBody.PInvoke (attr) -> + (match md.Body with + MethodBody.PInvoke (attrLazy) -> + let attr = attrLazy.Value "pinvokeimpl(\"" + attr.Where.Name + "\" as \"" + attr.Name + "\"" + (match attr.CallingConv with | PInvokeCallingConvention.None -> "" diff --git a/src/fsharp/absil/ilread.fs b/src/fsharp/absil/ilread.fs index 274c5b409d9..b6111cc0028 100644 --- a/src/fsharp/absil/ilread.fs +++ b/src/fsharp/absil/ilread.fs @@ -2812,6 +2812,7 @@ and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (idx, nm, _int MethodBody.IL (lazy + let pev = pectxt.pefile.GetView() let mdv = ctxt.mdfile.GetView() // Read any debug information for this method into temporary data structures diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index 20a1eab5459..e7069242919 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -588,8 +588,6 @@ FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILCallingConv CallingConv FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILCallingConv get_CallingConv() FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILCallingSignature CallingSignature FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILCallingSignature get_CallingSignature() -FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILLazyMethodBody Body -FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILLazyMethodBody get_Body() FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILMemberAccess Access FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILMemberAccess get_Access() FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILMethodBody MethodBody @@ -600,6 +598,8 @@ FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILSecurityDecls SecurityDecls FSharp.Compiler.AbstractIL.IL+ILMethodDef: ILSecurityDecls get_SecurityDecls() FSharp.Compiler.AbstractIL.IL+ILMethodDef: Int32 MaxStack FSharp.Compiler.AbstractIL.IL+ILMethodDef: Int32 get_MaxStack() +FSharp.Compiler.AbstractIL.IL+ILMethodDef: MethodBody Body +FSharp.Compiler.AbstractIL.IL+ILMethodDef: MethodBody get_Body() FSharp.Compiler.AbstractIL.IL+ILMethodDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef] GenericParams FSharp.Compiler.AbstractIL.IL+ILMethodDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef] get_GenericParams() FSharp.Compiler.AbstractIL.IL+ILMethodDef: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILLocal] Locals @@ -616,7 +616,7 @@ FSharp.Compiler.AbstractIL.IL+ILMethodDef: System.Reflection.MethodImplAttribute FSharp.Compiler.AbstractIL.IL+ILMethodDef: System.Reflection.MethodImplAttributes get_ImplAttributes() FSharp.Compiler.AbstractIL.IL+ILMethodDef: System.String Name FSharp.Compiler.AbstractIL.IL+ILMethodDef: System.String get_Name() -FSharp.Compiler.AbstractIL.IL+ILMethodDef: Void .ctor(System.String, System.Reflection.MethodAttributes, System.Reflection.MethodImplAttributes, ILCallingConv, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILParameter], ILReturn, ILLazyMethodBody, Boolean, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef], ILSecurityDecls, ILAttributes) +FSharp.Compiler.AbstractIL.IL+ILMethodDef: Void .ctor(System.String, System.Reflection.MethodAttributes, System.Reflection.MethodImplAttributes, ILCallingConv, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILParameter], ILReturn, MethodBody, Boolean, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef], ILSecurityDecls, ILAttributes) FSharp.Compiler.AbstractIL.IL+ILMethodDefs: ILMethodDef[] AsArray FSharp.Compiler.AbstractIL.IL+ILMethodDefs: ILMethodDef[] get_AsArray() FSharp.Compiler.AbstractIL.IL+ILMethodDefs: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILMethodDef] AsList From c96a3800018cd5e1eb219c13cef288b24e8ecd29 Mon Sep 17 00:00:00 2001 From: Will Smith Date: Thu, 14 Jan 2021 19:05:46 -0800 Subject: [PATCH 6/6] Minor change --- src/fsharp/absil/il.fs | 30 ++++++++++--------- src/fsharp/absil/il.fsi | 12 ++++---- src/fsharp/absil/ilmorph.fs | 2 +- src/fsharp/absil/ilread.fs | 2 ++ src/fsharp/ilx/EraseClosures.fs | 2 +- .../SurfaceArea.netstandard.fs | 2 +- 6 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/fsharp/absil/il.fs b/src/fsharp/absil/il.fs index 4e3121de9bb..d65340701aa 100644 --- a/src/fsharp/absil/il.fs +++ b/src/fsharp/absil/il.fs @@ -1614,13 +1614,15 @@ let NoMetadataIdx = -1 [] type ILMethodDef (name: string, attributes: MethodAttributes, implAttributes: MethodImplAttributes, callingConv: ILCallingConv, - parameters: ILParameters, ret: ILReturn, body: MethodBody, isEntryPoint: bool, genericParams: ILGenericParameterDefs, + parameters: ILParameters, ret: ILReturn, body: Lazy, isEntryPoint: bool, genericParams: ILGenericParameterDefs, securityDeclsStored: ILSecurityDeclsStored, customAttrsStored: ILAttributesStored, metadataIndex: int32) = new (name, attributes, implAttributes, callingConv, parameters, ret, body, isEntryPoint, genericParams, securityDecls, customAttrs) = ILMethodDef (name, attributes, implAttributes, callingConv, parameters, ret, body, isEntryPoint, genericParams, storeILSecurityDecls securityDecls, storeILCustomAttrs customAttrs, NoMetadataIdx) + member private _.LazyBody = body + // The captured data - remember the object will be as large as the data captured by these members member _.Name = name @@ -1634,7 +1636,7 @@ type ILMethodDef (name: string, attributes: MethodAttributes, implAttributes: Me member _.Return = ret - member _.Body = body + member _.Body = body.Value member _.SecurityDeclsStored = securityDeclsStored @@ -1648,7 +1650,7 @@ type ILMethodDef (name: string, attributes: MethodAttributes, implAttributes: Me member x.With (?name: string, ?attributes: MethodAttributes, ?implAttributes: MethodImplAttributes, ?callingConv: ILCallingConv, ?parameters: ILParameters, ?ret: ILReturn, - ?body: MethodBody, ?securityDecls: ILSecurityDecls, ?isEntryPoint: bool, + ?body: Lazy, ?securityDecls: ILSecurityDecls, ?isEntryPoint: bool, ?genericParams: ILGenericParameterDefs, ?customAttrs: ILAttributes) = ILMethodDef (name = defaultArg name x.Name, @@ -1657,7 +1659,7 @@ type ILMethodDef (name: string, attributes: MethodAttributes, implAttributes: Me callingConv = defaultArg callingConv x.CallingConv, parameters = defaultArg parameters x.Parameters, ret = defaultArg ret x.Return, - body = defaultArg body x.Body, + body = defaultArg body x.LazyBody, securityDecls = (match securityDecls with None -> x.SecurityDecls | Some attrs -> attrs), isEntryPoint = defaultArg isEntryPoint x.IsEntryPoint, genericParams = defaultArg genericParams x.GenericParams, @@ -2938,11 +2940,11 @@ let mkMethodBody (zeroinit, locals, maxstack, code, tag) = let mkILVoidReturn = mkILReturn ILType.Void -let methBodyNotAvailable = MethodBody.NotAvailable +let methBodyNotAvailable = notlazy MethodBody.NotAvailable -let methBodyAbstract = MethodBody.Abstract +let methBodyAbstract = notlazy MethodBody.Abstract -let methBodyNative = MethodBody.Native +let methBodyNative = notlazy MethodBody.Native let mkILCtor (access, args, impl) = ILMethodDef(name=".ctor", @@ -2951,7 +2953,7 @@ let mkILCtor (access, args, impl) = callingConv=ILCallingConv.Instance, parameters = args, ret= mkILVoidReturn, - body= impl, + body= notlazy impl, securityDecls=emptyILSecurityDecls, isEntryPoint=false, genericParams=mkILEmptyGenericParams, @@ -3000,7 +3002,7 @@ let mkILStaticMethod (genparams, nm, access, args, ret, impl) = securityDecls=emptyILSecurityDecls, isEntryPoint=false, customAttrs = emptyILCustomAttrs, - body= impl) + body= notlazy impl) let mkILNonGenericStaticMethod (nm, access, args, ret, impl) = mkILStaticMethod (mkILEmptyGenericParams, nm, access, args, ret, impl) @@ -3016,7 +3018,7 @@ let mkILClassCtor impl = isEntryPoint=false, securityDecls=emptyILSecurityDecls, customAttrs=emptyILCustomAttrs, - body= impl) + body= notlazy impl) // -------------------------------------------------------------------- // Make a virtual method, where the overriding is simply the default @@ -3040,7 +3042,7 @@ let mkILGenericVirtualMethod (nm, access, genparams, actual_args, actual_ret, im isEntryPoint=false, securityDecls=emptyILSecurityDecls, customAttrs = emptyILCustomAttrs, - body= impl) + body= notlazy impl) let mkILNonGenericVirtualMethod (nm, access, args, ret, impl) = mkILGenericVirtualMethod (nm, access, mkILEmptyGenericParams, args, ret, impl) @@ -3056,7 +3058,7 @@ let mkILGenericNonVirtualMethod (nm, access, genparams, actual_args, actual_ret, isEntryPoint=false, securityDecls=emptyILSecurityDecls, customAttrs = emptyILCustomAttrs, - body= impl) + body= notlazy impl) let mkILNonGenericInstanceMethod (nm, access, args, ret, impl) = mkILGenericNonVirtualMethod (nm, access, mkILEmptyGenericParams, args, ret, impl) @@ -3076,8 +3078,8 @@ let mdef_code2code f (md: ILMethodDef) = | MethodBody.IL il-> il | _ -> failwith "mdef_code2code - method not IL" let ilCode = ilmbody_code2code f il.Value - let b = MethodBody.IL (lazy ilCode) - md.With(body = b) + let b = MethodBody.IL (notlazy ilCode) + md.With(body = notlazy b) let prependInstrsToCode (instrs: ILInstr list) (c2: ILCode) = let instrs = Array.ofList instrs diff --git a/src/fsharp/absil/il.fsi b/src/fsharp/absil/il.fsi index f64cb22b029..2d964a2aded 100644 --- a/src/fsharp/absil/il.fsi +++ b/src/fsharp/absil/il.fsi @@ -977,12 +977,12 @@ type ILMethodDef = /// Functional creation of a value, with delayed reading of some elements via a metadata index internal new: name: string * attributes: MethodAttributes * implAttributes: MethodImplAttributes * callingConv: ILCallingConv * - parameters: ILParameters * ret: ILReturn * body: MethodBody * isEntryPoint:bool * genericParams: ILGenericParameterDefs * + parameters: ILParameters * ret: ILReturn * body: Lazy * isEntryPoint:bool * genericParams: ILGenericParameterDefs * securityDeclsStored: ILSecurityDeclsStored * customAttrsStored: ILAttributesStored * metadataIndex: int32 -> ILMethodDef /// Functional creation of a value, immediate new: name: string * attributes: MethodAttributes * implAttributes: MethodImplAttributes * callingConv: ILCallingConv * - parameters: ILParameters * ret: ILReturn * body: MethodBody * isEntryPoint:bool * genericParams: ILGenericParameterDefs * + parameters: ILParameters * ret: ILReturn * body: Lazy * isEntryPoint:bool * genericParams: ILGenericParameterDefs * securityDecls: ILSecurityDecls * customAttrs: ILAttributes -> ILMethodDef member Name: string @@ -1048,7 +1048,7 @@ type ILMethodDef = /// Functional update of the value member internal With: ?name: string * ?attributes: MethodAttributes * ?implAttributes: MethodImplAttributes * ?callingConv: ILCallingConv * - ?parameters: ILParameters * ?ret: ILReturn * ?body: MethodBody * ?securityDecls: ILSecurityDecls * ?isEntryPoint:bool * + ?parameters: ILParameters * ?ret: ILReturn * ?body: Lazy * ?securityDecls: ILSecurityDecls * ?isEntryPoint:bool * ?genericParams: ILGenericParameterDefs * ?customAttrs: ILAttributes -> ILMethodDef member internal WithSpecialName: ILMethodDef member internal WithHideBySig: unit -> ILMethodDef @@ -1813,9 +1813,9 @@ val internal mkILEmptyGenericParams: ILGenericParameterDefs /// Make method definitions. val internal mkILMethodBody: initlocals:bool * ILLocals * int * ILCode * ILSourceMarker option -> ILMethodBody val internal mkMethodBody: bool * ILLocals * int * ILCode * ILSourceMarker option -> MethodBody -val internal methBodyNotAvailable: MethodBody -val internal methBodyAbstract: MethodBody -val internal methBodyNative: MethodBody +val internal methBodyNotAvailable: Lazy +val internal methBodyAbstract: Lazy +val internal methBodyNative: Lazy val internal mkILCtor: ILMemberAccess * ILParameter list * MethodBody -> ILMethodDef val internal mkILClassCtor: MethodBody -> ILMethodDef diff --git a/src/fsharp/absil/ilmorph.fs b/src/fsharp/absil/ilmorph.fs index 7e43c1c16b4..5db44948f36 100644 --- a/src/fsharp/absil/ilmorph.fs +++ b/src/fsharp/absil/ilmorph.fs @@ -227,7 +227,7 @@ let mdef_ty2ty_ilmbody2ilmbody ilg fs (md: ILMethodDef) = let ftye' = ftye (Some md) let body' = morphILMethodBody (filmbody (Some md)) md.Body md.With(genericParams=gparams_ty2ty ftye' md.GenericParams, - body= body', + body= notlazy body', parameters = List.map (param_ty2ty ilg ftye') md.Parameters, ret = return_ty2ty ilg ftye' md.Return, customAttrs=cattrs_ty2ty ilg ftye' md.CustomAttrs) diff --git a/src/fsharp/absil/ilread.fs b/src/fsharp/absil/ilread.fs index b6111cc0028..be0fc741542 100644 --- a/src/fsharp/absil/ilread.fs +++ b/src/fsharp/absil/ilread.fs @@ -2494,6 +2494,7 @@ and seekReadConstant (ctxt: ILMetadataReader) idx = | _ -> ILFieldInit.Null and seekReadImplMap (ctxt: ILMetadataReader) nm midx = + lazy MethodBody.PInvoke (lazy let mdv = ctxt.mdfile.GetView() @@ -2797,6 +2798,7 @@ and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (_idx, nm, _in #else and seekReadMethodRVA (pectxt: PEReader) (ctxt: ILMetadataReader) (idx, nm, _internalcall, noinline, aggressiveinline, numtypars) rva = #endif + lazy let pev = pectxt.pefile.GetView() let baseRVA = pectxt.anyV2P("method rva", rva) // ": reading body of method "+nm+" at rva "+string rva+", phys "+string baseRVA diff --git a/src/fsharp/ilx/EraseClosures.fs b/src/fsharp/ilx/EraseClosures.fs index 4195a81230e..cfb541244d9 100644 --- a/src/fsharp/ilx/EraseClosures.fs +++ b/src/fsharp/ilx/EraseClosures.fs @@ -322,7 +322,7 @@ let convMethodBody thisClo = function let convMethodDef thisClo (md: ILMethodDef) = let b' = convMethodBody thisClo (md.Body) - md.With(body=b') + md.With(body=notlazy b') // -------------------------------------------------------------------- // Make fields for free variables of a type abstraction. diff --git a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs index e7069242919..17753856dca 100644 --- a/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs +++ b/tests/FSharp.Compiler.Service.Tests/SurfaceArea.netstandard.fs @@ -616,7 +616,7 @@ FSharp.Compiler.AbstractIL.IL+ILMethodDef: System.Reflection.MethodImplAttribute FSharp.Compiler.AbstractIL.IL+ILMethodDef: System.Reflection.MethodImplAttributes get_ImplAttributes() FSharp.Compiler.AbstractIL.IL+ILMethodDef: System.String Name FSharp.Compiler.AbstractIL.IL+ILMethodDef: System.String get_Name() -FSharp.Compiler.AbstractIL.IL+ILMethodDef: Void .ctor(System.String, System.Reflection.MethodAttributes, System.Reflection.MethodImplAttributes, ILCallingConv, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILParameter], ILReturn, MethodBody, Boolean, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef], ILSecurityDecls, ILAttributes) +FSharp.Compiler.AbstractIL.IL+ILMethodDef: Void .ctor(System.String, System.Reflection.MethodAttributes, System.Reflection.MethodImplAttributes, ILCallingConv, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILParameter], ILReturn, System.Lazy`1[FSharp.Compiler.AbstractIL.IL+MethodBody], Boolean, Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILGenericParameterDef], ILSecurityDecls, ILAttributes) FSharp.Compiler.AbstractIL.IL+ILMethodDefs: ILMethodDef[] AsArray FSharp.Compiler.AbstractIL.IL+ILMethodDefs: ILMethodDef[] get_AsArray() FSharp.Compiler.AbstractIL.IL+ILMethodDefs: Microsoft.FSharp.Collections.FSharpList`1[FSharp.Compiler.AbstractIL.IL+ILMethodDef] AsList