提交 3ff08d45 编写于 作者: S Steffen Forkmann 提交者: Don Syme

Implement `MethodImplOptions.AggressiveInlining` flag - fixes #1637 (#3154)

* Implement `MethodImplOptions.AggressiveInlining` flag - fixes #1637

* More inlining

* remove change to TAST

* fix build

* add test
上级 a29abe34
......@@ -1075,6 +1075,7 @@ type ILMethodBody =
{ IsZeroInit: bool;
MaxStack: int32;
NoInlining: bool;
AggressiveInlining: bool;
Locals: ILLocals;
Code: ILCode;
SourceMarker: ILSourceMarker option }
......@@ -1374,6 +1375,7 @@ type ILMethodDef =
IsPreserveSig: bool;
IsMustRun: bool;
IsNoInline: bool;
IsAggressiveInline : bool
GenericParams: ILGenericParameterDefs;
CustomAttrs: ILAttributes; }
member x.ParameterTypes = typesOfILParams x.Parameters
......@@ -2279,6 +2281,7 @@ let mkILMethodBody (zeroinit,locals,maxstack,code,tag) : ILMethodBody =
{ IsZeroInit=zeroinit
MaxStack=maxstack
NoInlining=false
AggressiveInlining=false
Locals= locals
Code= code
SourceMarker=tag }
......@@ -2314,6 +2317,7 @@ let mkILCtor (access,args,impl) =
IsUnmanagedExport=false;
IsSynchronized=false;
IsNoInline=false;
IsAggressiveInline=false
IsMustRun=false;
IsPreserveSig=false;
CustomAttrs = emptyILCustomAttrs; }
......@@ -2367,6 +2371,7 @@ let mkILStaticMethod (genparams,nm,access,args,ret,impl) =
IsUnmanagedExport=false;
IsSynchronized=false;
IsNoInline=false;
IsAggressiveInline=false;
IsMustRun=false;
IsPreserveSig=false; }
......@@ -2396,6 +2401,7 @@ let mkILClassCtor impl =
IsUnmanagedExport=false;
IsSynchronized=false;
IsNoInline=false;
IsAggressiveInline=false
IsMustRun=false;
IsPreserveSig=false; }
......@@ -2436,6 +2442,7 @@ let mkILGenericVirtualMethod (nm,access,genparams,actual_args,actual_ret,impl) =
IsUnmanagedExport=false;
IsSynchronized=false;
IsNoInline=false;
IsAggressiveInline=false
IsMustRun=false;
IsPreserveSig=false; }
......@@ -2465,6 +2472,7 @@ let mkILGenericNonVirtualMethod (nm,access,genparams, actual_args,actual_ret, im
IsUnmanagedExport=false;
IsSynchronized=false;
IsNoInline=false;
IsAggressiveInline=false
IsMustRun=false;
IsPreserveSig=false; }
......
......@@ -804,9 +804,10 @@ type ILLocals = list<ILLocal>
[<RequireQualifiedAccess; NoComparison; NoEquality>]
type ILMethodBody =
{ IsZeroInit: bool;
/// strictly speakin should be a uint16
/// strictly speaking should be a uint16
MaxStack: int32;
NoInlining: bool;
AggressiveInlining: bool;
Locals: ILLocals;
Code: ILCode;
SourceMarker: ILSourceMarker option }
......@@ -1054,6 +1055,7 @@ type ILMethodDef =
/// .NET 2.0 feature: SafeHandle finalizer must be run.
IsMustRun: bool;
IsNoInline: bool;
IsAggressiveInline: bool;
GenericParams: ILGenericParameterDefs;
CustomAttrs: ILAttributes; }
......
......@@ -846,10 +846,11 @@ let goutput_mdef env os md =
output_string os " ";
(goutput_params menv) os md.Parameters;
output_string os " ";
if md.IsSynchronized then output_string os "synchronized ";
if md.IsMustRun then output_string os "/* mustrun */ ";
if md.IsPreserveSig then output_string os "preservesig ";
if md.IsNoInline then output_string os "noinlining ";
if md.IsSynchronized then output_string os "synchronized "
if md.IsMustRun then output_string os "/* mustrun */ "
if md.IsPreserveSig then output_string os "preservesig "
if md.IsNoInline then output_string os "noinlining "
if md.IsAggressiveInline then output_string os "aggressiveinlining "
(goutput_mbody is_entrypoint menv) os md;
output_string os "\n"
......
......@@ -2301,6 +2301,7 @@ and seekReadMethod ctxt numtypars (idx:int) =
let internalcall = (implflags &&& 0x1000) <> 0x0
let synchronized = (implflags &&& 0x0020) <> 0x0
let noinline = (implflags &&& 0x0008) <> 0x0
let aggressiveinline = (implflags &&& 0x0100) <> 0x0
let mustrun = (implflags &&& 0x0040) <> 0x0
let cctor = (nm = ".cctor")
let ctor = (nm = ".ctor")
......@@ -2338,6 +2339,7 @@ and seekReadMethod ctxt numtypars (idx:int) =
IsUnmanagedExport=export
IsSynchronized=synchronized
IsNoInline=noinline
IsAggressiveInline=aggressiveinline
IsMustRun=mustrun
IsPreserveSig=preservesig
IsManaged = not unmanaged
......@@ -2358,7 +2360,7 @@ and seekReadMethod ctxt numtypars (idx:int) =
//if codeRVA <> 0x0 then dprintn "non-IL or abstract method with non-zero RVA"
mkMethBodyLazyAux (notlazy MethodBody.Abstract)
else
seekReadMethodRVA ctxt (idx,nm,internalcall,noinline,numtypars) codeRVA
seekReadMethodRVA ctxt (idx,nm,internalcall,noinline,aggressiveinline,numtypars) codeRVA
}
......@@ -2877,9 +2879,9 @@ and seekReadTopCode ctxt numtypars (sz:int) start seqpoints =
instrs,rawToLabel, lab2pc, raw2nextLab
#if FX_NO_PDB_READER
and seekReadMethodRVA ctxt (_idx,nm,_internalcall,noinline,numtypars) rva =
and seekReadMethodRVA ctxt (_idx,nm,_internalcall,noinline,aggressiveinline,numtypars) rva =
#else
and seekReadMethodRVA ctxt (idx,nm,_internalcall,noinline,numtypars) rva =
and seekReadMethodRVA ctxt (idx,nm,_internalcall,noinline,aggressiveinline,numtypars) rva =
#endif
mkMethBodyLazyAux
(lazy
......@@ -2965,6 +2967,7 @@ and seekReadMethodRVA ctxt (idx,nm,_internalcall,noinline,numtypars) rva =
{ IsZeroInit=false
MaxStack= 8
NoInlining=noinline
AggressiveInlining=aggressiveinline
Locals=List.empty
SourceMarker=methRangePdbInfo
Code=code }
......@@ -3090,6 +3093,7 @@ and seekReadMethodRVA ctxt (idx,nm,_internalcall,noinline,numtypars) rva =
{ IsZeroInit=initlocals
MaxStack= maxstack
NoInlining=noinline
AggressiveInlining=aggressiveinline
Locals = locals
Code=code
SourceMarker=methRangePdbInfo}
......
......@@ -1466,6 +1466,7 @@ let convMethodImplFlags mdef =
||| flagsIf mdef.IsPreserveSig MethodImplAttributes.PreserveSig
||| flagsIf mdef.IsSynchronized MethodImplAttributes.Synchronized
||| flagsIf (match mdef.mdBody.Contents with MethodBody.IL b -> b.NoInlining | _ -> false) MethodImplAttributes.NoInlining
||| flagsIf (match mdef.mdBody.Contents with MethodBody.IL b -> b.AggressiveInlining | _ -> false) MethodImplAttributes.AggressiveInlining
//----------------------------------------------------------------------------
// buildMethodPass2
......
......@@ -2539,6 +2539,7 @@ let GenMethodDefAsRow cenv env midx (md: ILMethodDef) =
| _ -> false) then 0x1000 else 0x0) ||| // RTSpecialName
(if md.IsReqSecObj then 0x8000 else 0x0) |||
(if md.HasSecurity || not md.SecurityDecls.AsList.IsEmpty then 0x4000 else 0x0)
let implflags =
(match md.mdCodeKind with
| MethodCodeKind.Native -> 0x0001
......@@ -2550,7 +2551,8 @@ let GenMethodDefAsRow cenv env midx (md: ILMethodDef) =
(if md.IsPreserveSig then 0x0080 else 0x0000) |||
(if md.IsSynchronized then 0x0020 else 0x0000) |||
(if md.IsMustRun then 0x0040 else 0x0000) |||
(if (md.IsNoInline || (match md.mdBody.Contents with MethodBody.IL il -> il.NoInlining | _ -> false)) then 0x0008 else 0x0000)
(if (md.IsNoInline || (match md.mdBody.Contents with MethodBody.IL il -> il.NoInlining | _ -> false)) then 0x0008 else 0x0000) |||
(if (md.IsAggressiveInline || (match md.mdBody.Contents with MethodBody.IL il -> il.AggressiveInlining | _ -> false)) then 0x0100 else 0x0000)
if md.IsEntryPoint then
if cenv.entrypoint <> None then failwith "duplicate entrypoint"
......
......@@ -5061,13 +5061,16 @@ and ComputeMethodImplAttribs cenv (_v:Val) attrs =
// 0x80 - hasPreserveSigImplFlag
// 0x20 - synchronize
// (See ECMA 335, Partition II, section 23.1.11 - Flags for methods [MethodImplAttributes])
let attrs = attrs
|> List.filter (IsMatchingFSharpAttribute cenv.g cenv.g.attrib_MethodImplAttribute >> not)
|> List.filter (IsMatchingFSharpAttributeOpt cenv.g cenv.g.attrib_PreserveSigAttribute >> not)
let attrs =
attrs
|> List.filter (IsMatchingFSharpAttribute cenv.g cenv.g.attrib_MethodImplAttribute >> not)
|> List.filter (IsMatchingFSharpAttributeOpt cenv.g cenv.g.attrib_PreserveSigAttribute >> not)
let hasPreserveSigImplFlag = ((implflags &&& 0x80) <> 0x0) || hasPreserveSigAttr
let hasSynchronizedImplFlag = (implflags &&& 0x20) <> 0x0
let hasNoInliningImplFlag = (implflags &&& 0x08) <> 0x0
hasPreserveSigImplFlag, hasSynchronizedImplFlag, hasNoInliningImplFlag, attrs
let hasAggressiveInliningImplFlag = (implflags &&& 0x0100) <> 0x0
hasPreserveSigImplFlag, hasSynchronizedImplFlag, hasNoInliningImplFlag, hasAggressiveInliningImplFlag, attrs
and GenMethodForBinding
cenv cgbuf eenv
......@@ -5152,7 +5155,7 @@ and GenMethodForBinding
| _ -> [],None
// check if the hasPreserveSigNamedArg and hasSynchronizedImplFlag implementation flags have been specified
let hasPreserveSigImplFlag, hasSynchronizedImplFlag, hasNoInliningFlag, attrs = ComputeMethodImplAttribs cenv v attrs
let hasPreserveSigImplFlag, hasSynchronizedImplFlag, hasNoInliningFlag, hasAggressiveInliningImplFlag, attrs = ComputeMethodImplAttribs cenv v attrs
let securityAttributes,attrs = attrs |> List.partition (fun a -> IsSecurityAttribute cenv.g cenv.amap cenv.casApplied a m)
......@@ -5183,6 +5186,7 @@ and GenMethodForBinding
IsSynchronized = hasSynchronizedImplFlag
IsEntryPoint = isExplicitEntryPoint
IsNoInline = hasNoInliningFlag
IsAggressiveInline = hasAggressiveInliningImplFlag
HasSecurity = mdef.HasSecurity || (securityAttributes.Length > 0)
SecurityDecls = secDecls }
......@@ -6012,7 +6016,7 @@ and GenAbstractBinding cenv eenv tref (vref:ValRef) =
let m = vref.Range
let memberInfo = Option.get vref.MemberInfo
let attribs = vref.Attribs
let hasPreserveSigImplFlag,hasSynchronizedImplFlag,hasNoInliningFlag,attribs = ComputeMethodImplAttribs cenv vref.Deref attribs
let hasPreserveSigImplFlag,hasSynchronizedImplFlag,hasNoInliningFlag,hasAggressiveInliningImplFlag,attribs = ComputeMethodImplAttribs cenv vref.Deref attribs
if memberInfo.MemberFlags.IsDispatchSlot && not memberInfo.IsImplemented then
let ilAttrs =
[ yield! GenAttrs cenv eenv attribs
......@@ -6033,6 +6037,7 @@ and GenAbstractBinding cenv eenv tref (vref:ValRef) =
IsPreserveSig=hasPreserveSigImplFlag
IsSynchronized=hasSynchronizedImplFlag
IsNoInline=hasNoInliningFlag
IsAggressiveInline=hasAggressiveInliningImplFlag
mdKind=match mdef.mdKind with
| MethodKind.Virtual vinfo ->
MethodKind.Virtual {vinfo with IsFinal=memberInfo.MemberFlags.IsFinal
......
......@@ -1159,6 +1159,7 @@ and FSharpInlineAnnotation =
| AlwaysInline
| OptionalInline
| NeverInline
| AggressiveInline
and FSharpMemberOrValData =
| E of EventInfo
......
......@@ -694,14 +694,16 @@ and [<RequireQualifiedAccess>] FSharpInlineAnnotation =
#else
and [<RequireQualifiedAccess>] internal FSharpInlineAnnotation =
#endif
/// Indictes the value is inlined and compiled code for the function does not exist
/// Indicates the value is inlined and compiled code for the function does not exist
| PseudoValue
/// Indictes the value is inlined but compiled code for the function still exists, e.g. to satisfy interfaces on objects, but that it is also always inlined
/// Indicates the value is inlined but compiled code for the function still exists, e.g. to satisfy interfaces on objects, but that it is also always inlined
| AlwaysInline
/// Indictes the value is optionally inlined
/// Indicates the value is optionally inlined
| OptionalInline
/// Indictes the value is never inlined
| NeverInline
/// Indicates the value is never inlined
| NeverInline
/// Indicates the value is aggressively inlined by the .NET runtime
| AggressiveInline
/// A subtype of F# symbol that represents an F# method, property, event, function or value, including extension members.
#if COMPILER_PUBLIC_API
......
// Regression test for DevDiv:212424
// "NoInlining attribute not emitted into IL"
module M
[<System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)>]
let getUnit (f : unit -> unit) = f()
\ No newline at end of file
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.17295
// Copyright (c) Microsoft Corporation. All rights reserved.
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly extern FSharp.Core
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 4:3:0:0
}
.assembly MethodImplAttribute.AggressiveInlining
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.FSharpInterfaceDataVersionAttribute::.ctor(int32,
int32,
int32) = ( 01 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 )
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = ( 01 00 01 01 00 00 00 00 )
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.mresource public FSharpSignatureData.MethodImplAttribute.AggressiveInlining
{
// Offset: 0x00000000 Length: 0x0000035A
}
.mresource public FSharpOptimizationData.MethodImplAttribute.AggressiveInlining
{
// Offset: 0x00000360 Length: 0x0000007D
}
.module MethodImplAttribute.AggressiveInlining.dll
// MVID: {4E66F6A9-F47B-58B3-A745-0383A9F6664E}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x0000000000180000
// =============== CLASS MEMBERS DECLARATION ===================
.class public abstract auto ansi sealed M
extends [mscorlib]System.Object
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 07 00 00 00 00 00 )
.method public static void getUnit(class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit> f) cil managed aggressiveinlining
{
// Code size 10 (0xa)
.maxstack 8
.language '{AB4F38C9-B6E6-43BA-BE3B-58080B2CCCE3}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
.line 5,5 : 34,37
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldnull
IL_0003: callvirt instance !1 class [FSharp.Core]Microsoft.FSharp.Core.FSharpFunc`2<class [FSharp.Core]Microsoft.FSharp.Core.Unit,class [FSharp.Core]Microsoft.FSharp.Core.Unit>::Invoke(!0)
IL_0008: pop
IL_0009: ret
} // end of method M::getUnit
} // end of class M
.class private abstract auto ansi sealed '<StartupCode$MethodImplAttribute-AggressiveInlining>'.$M
extends [mscorlib]System.Object
{
} // end of class '<StartupCode$MethodImplAttribute-AggressiveInlining>'.$M
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************
......@@ -2,6 +2,7 @@
SOURCE=MethodImplAttribute.ForwardRef.fs SCFLAGS="-a -g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd MethodImplAttribute.ForwardRef.dll" # MethodImplAttribute.ForwardRef.fs
SOURCE=MethodImplAttribute.InternalCall.fs SCFLAGS="-a -g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd MethodImplAttribute.InternalCall.dll" # MethodImplAttribute.InternalCall.fs
SOURCE=MethodImplAttribute.NoInlining.fs SCFLAGS="-a -g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd MethodImplAttribute.NoInlining.dll" # MethodImplAttribute.NoInlining.fs
SOURCE=MethodImplAttribute.AggressiveInlining.fs SCFLAGS="-a -g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd MethodImplAttribute.AggressiveInlining.dll" # MethodImplAttribute.AggressiveInlining.fs
SOURCE=MethodImplAttribute.NoOptimization.fs SCFLAGS="-a -g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd MethodImplAttribute.NoOptimization.dll" # MethodImplAttribute.NoOptimization.fs
SOURCE=MethodImplAttribute.PreserveSig.fs SCFLAGS="-a -g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd MethodImplAttribute.PreserveSig.dll" # MethodImplAttribute.PreserveSig.fs
SOURCE=MethodImplAttribute.Synchronized.fs SCFLAGS="-a -g --optimize-" COMPILE_ONLY=1 POSTCMD="..\\CompareIL.cmd MethodImplAttribute.Synchronized.dll" # MethodImplAttribute.Synchronized.fs
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册