Skip to content

Commit f564cc9

Browse files
DedSec256psfinakivzarytovskiiT-Gro
authored
Make ILTypeDef interface calculation lazy (#17392)
* wip * wip * wip * wip * formatting * release notes --------- Co-authored-by: Petr <[email protected]> Co-authored-by: Vlad Zarytovskii <[email protected]> Co-authored-by: Tomas Grosup <[email protected]>
1 parent 52133d0 commit f564cc9

File tree

16 files changed

+164
-114
lines changed

16 files changed

+164
-114
lines changed

docs/release-notes/.FSharp.Compiler.Service/9.0.100.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
* Better CE error reporting when using `use!` with `and!` ([PR #17671](https://github.com/dotnet/fsharp/pull/17671))
5353
* Better error reporting for let bindings. ([PR #17601](https://github.com/dotnet/fsharp/pull/17601))
5454
* Optimize ILTypeDef interface impls reading from metadata. ([PR #17382](https://github.com/dotnet/fsharp/pull/17382))
55+
* Make ILTypeDef interface impls calculation lazy. ([PR #17392](https://github.com/dotnet/fsharp/pull/17392))
5556
* Better error reporting for active patterns. ([PR #17666](https://github.com/dotnet/fsharp/pull/17666))
5657

57-
5858
### Breaking Changes

src/Compiler/AbstractIL/il.fs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1909,6 +1909,23 @@ let inline conditionalAdd condition flagToAdd source =
19091909

19101910
let NoMetadataIdx = -1
19111911

1912+
type InterfaceImpl =
1913+
{ Idx: int; Type: ILType; mutable CustomAttrsStored: ILAttributesStored }
1914+
1915+
member x.CustomAttrs =
1916+
match x.CustomAttrsStored with
1917+
| ILAttributesStored.Reader f ->
1918+
let res = ILAttributes(f x.Idx)
1919+
x.CustomAttrsStored <- ILAttributesStored.Given res
1920+
res
1921+
| ILAttributesStored.Given attrs -> attrs
1922+
1923+
static member Create(ilType: ILType, customAttrsStored: ILAttributesStored) =
1924+
{ Idx = NoMetadataIdx; Type = ilType; CustomAttrsStored = customAttrsStored }
1925+
1926+
static member Create(ilType: ILType) = InterfaceImpl.Create(ilType, emptyILCustomAttrsStored)
1927+
1928+
19121929
[<NoComparison; NoEquality; StructuredFormatDisplay("{DebugText}")>]
19131930
type ILMethodDef
19141931
(
@@ -2635,8 +2652,7 @@ type ILTypeDef
26352652
name: string,
26362653
attributes: TypeAttributes,
26372654
layout: ILTypeDefLayout,
2638-
implements: ILTypes,
2639-
implementsCustomAttrs: (ILAttributesStored * int) list option,
2655+
implements: InterruptibleLazy<InterfaceImpl list>,
26402656
genericParams: ILGenericParameterDefs,
26412657
extends: ILType option,
26422658
methods: ILMethodDefs,
@@ -2659,7 +2675,6 @@ type ILTypeDef
26592675
attributes,
26602676
layout,
26612677
implements,
2662-
implementsCustomAttrs,
26632678
genericParams,
26642679
extends,
26652680
methods,
@@ -2676,7 +2691,6 @@ type ILTypeDef
26762691
attributes,
26772692
layout,
26782693
implements,
2679-
implementsCustomAttrs,
26802694
genericParams,
26812695
extends,
26822696
methods,
@@ -2703,8 +2717,6 @@ type ILTypeDef
27032717

27042718
member _.Implements = implements
27052719

2706-
member _.ImplementsCustomAttrs = implementsCustomAttrs
2707-
27082720
member _.Extends = extends
27092721

27102722
member _.Methods = methods
@@ -2744,8 +2756,7 @@ type ILTypeDef
27442756
?properties,
27452757
?newAdditionalFlags,
27462758
?customAttrs,
2747-
?securityDecls,
2748-
?implementsCustomAttrs
2759+
?securityDecls
27492760
) =
27502761
ILTypeDef(
27512762
name = defaultArg name x.Name,
@@ -2754,7 +2765,6 @@ type ILTypeDef
27542765
genericParams = defaultArg genericParams x.GenericParams,
27552766
nestedTypes = defaultArg nestedTypes x.NestedTypes,
27562767
implements = defaultArg implements x.Implements,
2757-
implementsCustomAttrs = defaultArg implementsCustomAttrs x.ImplementsCustomAttrs,
27582768
extends = defaultArg extends x.Extends,
27592769
methods = defaultArg methods x.Methods,
27602770
securityDecls = defaultArg securityDecls x.SecurityDecls,
@@ -3333,6 +3343,8 @@ let mkILTypeDefs l = mkILTypeDefsFromArray (Array.ofList l)
33333343
let mkILTypeDefsComputed f = ILTypeDefs f
33343344
let emptyILTypeDefs = mkILTypeDefsFromArray [||]
33353345

3346+
let emptyILInterfaceImpls = InterruptibleLazy<InterfaceImpl list>.FromValue([])
3347+
33363348
// --------------------------------------------------------------------
33373349
// Operations on method tables.
33383350
// --------------------------------------------------------------------
@@ -4240,7 +4252,7 @@ let mkILSimpleStorageCtor (baseTySpec, ty, extraParams, flds, access, tag, impor
42404252
let mkILStorageCtor (preblock, ty, flds, access, tag, imports) =
42414253
mkILStorageCtorWithParamNames (preblock, ty, [], addParamNames flds, access, tag, imports)
42424254

4243-
let mkILGenericClass (nm, access, genparams, extends, impl, methods, fields, nestedTypes, props, events, attrs, init) =
4255+
let mkILGenericClass (nm, access, genparams, extends, impls, methods, fields, nestedTypes, props, events, attrs, init) =
42444256
let attributes =
42454257
convertTypeAccessFlags access
42464258
||| TypeAttributes.AutoLayout
@@ -4254,8 +4266,7 @@ let mkILGenericClass (nm, access, genparams, extends, impl, methods, fields, nes
42544266
name = nm,
42554267
attributes = attributes,
42564268
genericParams = genparams,
4257-
implements = impl,
4258-
implementsCustomAttrs = None,
4269+
implements = InterruptibleLazy.FromValue(impls),
42594270
layout = ILTypeDefLayout.Auto,
42604271
extends = Some extends,
42614272
methods = methods,
@@ -4279,8 +4290,7 @@ let mkRawDataValueTypeDef (iltyp_ValueType: ILType) (nm, size, pack) =
42794290
||| TypeAttributes.ExplicitLayout
42804291
||| TypeAttributes.BeforeFieldInit
42814292
||| TypeAttributes.AnsiClass),
4282-
implements = [],
4283-
implementsCustomAttrs = None,
4293+
implements = emptyILInterfaceImpls,
42844294
extends = Some iltyp_ValueType,
42854295
layout = ILTypeDefLayout.Explicit { Size = Some size; Pack = Some pack },
42864296
methods = emptyILMethods,
@@ -5586,7 +5596,7 @@ and refsOfILMethodImpl s m =
55865596
and refsOfILTypeDef s (td: ILTypeDef) =
55875597
refsOfILTypeDefs s td.NestedTypes
55885598
refsOfILGenericParams s td.GenericParams
5589-
refsOfILTypes s td.Implements
5599+
refsOfILTypes s (td.Implements.Value |> List.map _.Type)
55905600
Option.iter (refsOfILType s) td.Extends
55915601
refsOfILMethodDefs s td.Methods
55925602
refsOfILFieldDefs s (td.Fields.AsList())

src/Compiler/AbstractIL/il.fsi

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,15 @@ type ILCallingSignature =
327327
ArgTypes: ILTypes
328328
ReturnType: ILType }
329329

330+
type InterfaceImpl =
331+
{ Idx: int
332+
Type: ILType
333+
mutable CustomAttrsStored: ILAttributesStored }
334+
335+
member CustomAttrs: ILAttributes
336+
static member Create: ilType: ILType * customAttrsStored: ILAttributesStored -> InterfaceImpl
337+
static member Create: ilType: ILType -> InterfaceImpl
338+
330339
/// Actual generic parameters are always types.
331340
type ILGenericArgs = ILType list
332341

@@ -1518,8 +1527,7 @@ type ILTypeDef =
15181527
name: string *
15191528
attributes: TypeAttributes *
15201529
layout: ILTypeDefLayout *
1521-
implements: ILTypes *
1522-
implementsCustomAttrs: (ILAttributesStored * int) list option *
1530+
implements: InterruptibleLazy<InterfaceImpl list> *
15231531
genericParams: ILGenericParameterDefs *
15241532
extends: ILType option *
15251533
methods: ILMethodDefs *
@@ -1539,8 +1547,7 @@ type ILTypeDef =
15391547
name: string *
15401548
attributes: TypeAttributes *
15411549
layout: ILTypeDefLayout *
1542-
implements: ILTypes *
1543-
implementsCustomAttrs: (ILAttributesStored * int) list option *
1550+
implements: InterruptibleLazy<InterfaceImpl list> *
15441551
genericParams: ILGenericParameterDefs *
15451552
extends: ILType option *
15461553
methods: ILMethodDefs *
@@ -1559,8 +1566,7 @@ type ILTypeDef =
15591566
member GenericParams: ILGenericParameterDefs
15601567
member Layout: ILTypeDefLayout
15611568
member NestedTypes: ILTypeDefs
1562-
member Implements: ILTypes
1563-
member ImplementsCustomAttrs: (ILAttributesStored * int) list option
1569+
member Implements: InterruptibleLazy<InterfaceImpl list>
15641570
member Extends: ILType option
15651571
member Methods: ILMethodDefs
15661572
member SecurityDecls: ILSecurityDecls
@@ -1609,7 +1615,7 @@ type ILTypeDef =
16091615
?name: string *
16101616
?attributes: TypeAttributes *
16111617
?layout: ILTypeDefLayout *
1612-
?implements: ILTypes *
1618+
?implements: InterruptibleLazy<InterfaceImpl list> *
16131619
?genericParams: ILGenericParameterDefs *
16141620
?extends: ILType option *
16151621
?methods: ILMethodDefs *
@@ -1620,8 +1626,7 @@ type ILTypeDef =
16201626
?properties: ILPropertyDefs *
16211627
?newAdditionalFlags: ILTypeDefAdditionalFlags *
16221628
?customAttrs: ILAttributesStored *
1623-
?securityDecls: ILSecurityDecls *
1624-
?implementsCustomAttrs: (ILAttributesStored * int) list option ->
1629+
?securityDecls: ILSecurityDecls ->
16251630
ILTypeDef
16261631

16271632
/// Represents a prefix of information for ILTypeDef.
@@ -2161,7 +2166,7 @@ val internal mkILGenericClass:
21612166
ILTypeDefAccess *
21622167
ILGenericParameterDefs *
21632168
ILType *
2164-
ILType list *
2169+
InterfaceImpl list *
21652170
ILMethodDefs *
21662171
ILFieldDefs *
21672172
ILTypeDefs *
@@ -2245,6 +2250,8 @@ val internal mkCtorMethSpecForDelegate: ILGlobals -> ILType * bool -> ILMethodSp
22452250
/// The toplevel "class" for a module or assembly.
22462251
val internal mkILTypeForGlobalFunctions: ILScopeRef -> ILType
22472252

2253+
val emptyILInterfaceImpls: InterruptibleLazy<InterfaceImpl list>
2254+
22482255
/// Making tables of custom attributes, etc.
22492256
val mkILCustomAttrs: ILAttribute list -> ILAttributes
22502257
val mkILCustomAttrsFromArray: ILAttribute[] -> ILAttributes

src/Compiler/AbstractIL/ilmorph.fs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,8 +368,13 @@ let rec tdef_ty2ty_ilmbody2ilmbody_mdefs2mdefs isInKnownSet enc fs (tdef: ILType
368368
let mdefsR = fMethodDefs (enc, tdef) tdef.Methods
369369
let fdefsR = fdefs_ty2ty fTyInCtxtR tdef.Fields
370370

371+
let implements =
372+
tdef.Implements.Value
373+
|> List.map (fun x -> { x with Type = fTyInCtxtR x.Type })
374+
|> InterruptibleLazy.FromValue
375+
371376
tdef.With(
372-
implements = List.map fTyInCtxtR tdef.Implements,
377+
implements = implements,
373378
genericParams = gparams_ty2ty fTyInCtxtR tdef.GenericParams,
374379
extends = Option.map fTyInCtxtR tdef.Extends,
375380
methods = mdefsR,

src/Compiler/AbstractIL/ilprint.fs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -752,8 +752,9 @@ let goutput_superclass env os =
752752
output_string os "extends "
753753
(goutput_typ_with_shortened_class_syntax env) os typ
754754

755-
let goutput_implements env os (imp: ILTypes) =
755+
let goutput_implements env os (imp: InterfaceImpl list) =
756756
if not (List.isEmpty imp) then
757+
let imp = imp |> Seq.map _.Type
757758
output_string os "implements "
758759
output_seq ", " (goutput_typ_with_shortened_class_syntax env) os imp
759760

@@ -836,7 +837,7 @@ let rec goutput_tdef enc env contents os (cd: ILTypeDef) =
836837
output_string os "\n\t"
837838
goutput_superclass env os cd.Extends
838839
output_string os "\n\t"
839-
goutput_implements env os cd.Implements
840+
goutput_implements env os cd.Implements.Value
840841
output_string os "\n{\n "
841842

842843
if contents then

src/Compiler/AbstractIL/ilread.fs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,8 +2192,7 @@ and typeDefReader ctxtH : ILTypeDefStored =
21922192
let fdefs = seekReadFields ctxt (numTypars, hasLayout) fieldsIdx endFieldsIdx
21932193
let nested = seekReadNestedTypeDefs ctxt idx
21942194

2195-
let impls, intImplsAttrs =
2196-
seekReadInterfaceImpls ctxt mdv numTypars idx |> List.unzip
2195+
let impls = seekReadInterfaceImpls ctxt mdv numTypars idx
21972196

21982197
let mimpls = seekReadMethodImpls ctxt numTypars idx
21992198
let props = seekReadProperties ctxt numTypars idx
@@ -2206,7 +2205,6 @@ and typeDefReader ctxtH : ILTypeDefStored =
22062205
layout = layout,
22072206
nestedTypes = nested,
22082207
implements = impls,
2209-
implementsCustomAttrs = Some intImplsAttrs,
22102208
extends = super,
22112209
methods = mdefs,
22122210
securityDeclsStored = ctxt.securityDeclsReader_TypeDef,
@@ -2240,19 +2238,26 @@ and seekReadNestedTypeDefs (ctxt: ILMetadataReader) tidx =
22402238
|])
22412239

22422240
and seekReadInterfaceImpls (ctxt: ILMetadataReader) mdv numTypars tidx =
2243-
seekReadIndexedRows (
2244-
ctxt.getNumRows TableNames.InterfaceImpl,
2245-
id,
2246-
id,
2247-
(fun idx ->
2248-
let mutable addr = ctxt.rowAddr TableNames.InterfaceImpl idx
2249-
let _tidx = seekReadUntaggedIdx TableNames.TypeDef ctxt mdv &addr
2250-
simpleIndexCompare tidx _tidx),
2251-
isSorted ctxt TableNames.InterfaceImpl,
2252-
(fun idx ->
2253-
let intfIdx = seekReadInterfaceIdx ctxt mdv idx
2254-
seekReadTypeDefOrRef ctxt numTypars AsObject [] intfIdx, (ctxt.customAttrsReader_InterfaceImpl, idx))
2255-
)
2241+
InterruptibleLazy(fun () ->
2242+
seekReadIndexedRows (
2243+
ctxt.getNumRows TableNames.InterfaceImpl,
2244+
id,
2245+
id,
2246+
(fun idx ->
2247+
let mutable addr = ctxt.rowAddr TableNames.InterfaceImpl idx
2248+
let _tidx = seekReadUntaggedIdx TableNames.TypeDef ctxt mdv &addr
2249+
simpleIndexCompare tidx _tidx),
2250+
isSorted ctxt TableNames.InterfaceImpl,
2251+
(fun idx ->
2252+
let intfIdx = seekReadInterfaceIdx ctxt mdv idx
2253+
let ilType = seekReadTypeDefOrRef ctxt numTypars AsObject [] intfIdx
2254+
2255+
{
2256+
Idx = idx
2257+
Type = ilType
2258+
CustomAttrsStored = ctxt.customAttrsReader_InterfaceImpl
2259+
})
2260+
))
22562261

22572262
and seekReadGenericParams ctxt numTypars (a, b) : ILGenericParameterDefs =
22582263
ctxt.seekReadGenericParams (GenericParamsIdx(numTypars, a, b))

src/Compiler/AbstractIL/ilreflect.fs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2178,7 +2178,8 @@ let rec buildTypeDefPass2 cenv nesting emEnv (tdef: ILTypeDef) =
21782178
let typB = envGetTypB emEnv tref
21792179
let emEnv = envPushTyvars emEnv (getGenericArgumentsOfType typB)
21802180
// add interface impls
2181-
tdef.Implements
2181+
tdef.Implements.Value
2182+
|> List.map _.Type
21822183
|> convTypes cenv emEnv
21832184
|> List.iter (fun implT -> typB.AddInterfaceImplementationAndLog implT)
21842185
// add methods, properties
@@ -2339,7 +2340,8 @@ let createTypeRef (visited: Dictionary<_, _>, created: Dictionary<_, _>) emEnv t
23392340
if verbose2 then
23402341
dprintf "buildTypeDefPass4: Creating Interface Chain of %s\n" tdef.Name
23412342

2342-
tdef.Implements |> List.iter (traverseType CollectTypes.All)
2343+
tdef.Implements.Value
2344+
|> List.iter (fun x -> traverseType CollectTypes.All x.Type)
23432345

23442346
if verbose2 then
23452347
dprintf "buildTypeDefPass4: Do value types in fields of %s\n" tdef.Name

src/Compiler/AbstractIL/ilwrite.fs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1323,7 +1323,7 @@ and GenTypeDefPass2 pidx enc cenv (tdef: ILTypeDef) =
13231323
// Now generate or assign index numbers for tables referenced by the maps.
13241324
// Don't yet generate contents of these tables - leave that to pass3, as
13251325
// code may need to embed these entries.
1326-
cenv.implementsIdxs[tidx] <- tdef.Implements |> List.map (GenImplementsPass2 cenv env tidx)
1326+
cenv.implementsIdxs[tidx] <- tdef.Implements.Value |> List.map (fun x -> GenImplementsPass2 cenv env tidx x.Type)
13271327

13281328
tdef.Fields.AsList() |> List.iter (GenFieldDefPass2 tdef cenv tidx)
13291329
tdef.Methods |> Seq.iter (GenMethodDefPass2 tdef cenv tidx)
@@ -2875,12 +2875,9 @@ let rec GenTypeDefPass3 enc cenv (tdef: ILTypeDef) =
28752875
let env = envForTypeDef tdef
28762876
let tidx = GetIdxForTypeDef cenv (TdKey(enc, tdef.Name))
28772877

2878-
match tdef.ImplementsCustomAttrs with
2879-
| None -> ()
2880-
| Some attrList ->
2881-
attrList
2882-
|> List.zip cenv.implementsIdxs[tidx]
2883-
|> List.iter (fun (impIdx,(attrs,metadataIdx)) -> GenCustomAttrsPass3Or4 cenv (hca_InterfaceImpl,impIdx) (attrs.GetCustomAttrs metadataIdx))
2878+
tdef.Implements.Value
2879+
|> List.zip cenv.implementsIdxs[tidx]
2880+
|> List.iter (fun (impIdx, impl) -> GenCustomAttrsPass3Or4 cenv (hca_InterfaceImpl,impIdx) impl.CustomAttrs)
28842881

28852882
tdef.Properties.AsList() |> List.iter (GenPropertyPass3 cenv env)
28862883
tdef.Events.AsList() |> List.iter (GenEventPass3 cenv env)

src/Compiler/Checking/TypeHierarchy.fs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,17 +117,16 @@ let GetImmediateInterfacesOfMetadataType g amap m skipUnref ty (tcref: TyconRef)
117117
// succeeded with more reported. There are pathological corner cases where this
118118
// doesn't apply: e.g. for mscorlib interfaces like IComparable, but we can always
119119
// assume those are present.
120-
match tdef.ImplementsCustomAttrs with
121-
| Some attrsList when g.langFeatureNullness && g.checkNullness ->
122-
for (attrs,attrsIdx),intfTy in tdef.Implements |> List.zip attrsList do
123-
if skipUnref = SkipUnrefInterfaces.No || CanRescopeAndImportILType scoref amap m intfTy then
120+
let checkNullness = g.langFeatureNullness && g.checkNullness
121+
for {Idx = attrsIdx; Type = intfTy; CustomAttrsStored = attrs} in tdef.Implements.Value do
122+
if skipUnref = SkipUnrefInterfaces.No || CanRescopeAndImportILType scoref amap m intfTy then
123+
if checkNullness then
124124
let typeAttrs = AttributesFromIL(attrsIdx,attrs)
125125
let nullness = {DirectAttributes = typeAttrs; Fallback = FromClass typeAttrs}
126126
RescopeAndImportILType scoref amap m tinst nullness intfTy
127-
| _ ->
128-
for intfTy in tdef.Implements do
129-
if skipUnref = SkipUnrefInterfaces.No || CanRescopeAndImportILType scoref amap m intfTy then
127+
else
130128
RescopeAndImportILTypeSkipNullness scoref amap m tinst intfTy
129+
131130
| FSharpOrArrayOrByrefOrTupleOrExnTypeMetadata ->
132131
for intfTy in tcref.ImmediateInterfaceTypesOfFSharpTycon do
133132
instType (mkInstForAppTy g ty) intfTy ]

src/Compiler/CodeGen/EraseClosures.fs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -572,8 +572,7 @@ let rec convIlxClosureDef cenv encl (td: ILTypeDef) clo =
572572
name = td.Name,
573573
genericParams = td.GenericParams,
574574
attributes = td.Attributes,
575-
implements = [],
576-
implementsCustomAttrs = None,
575+
implements = emptyILInterfaceImpls,
577576
nestedTypes = emptyILTypeDefs,
578577
layout = ILTypeDefLayout.Auto,
579578
extends = Some cenv.mkILTyFuncTy,
@@ -707,8 +706,7 @@ let rec convIlxClosureDef cenv encl (td: ILTypeDef) clo =
707706
name = td.Name,
708707
genericParams = td.GenericParams,
709708
attributes = td.Attributes,
710-
implements = [],
711-
implementsCustomAttrs = None,
709+
implements = emptyILInterfaceImpls,
712710
layout = ILTypeDefLayout.Auto,
713711
nestedTypes = emptyILTypeDefs,
714712
extends = Some nowEnvParentClass,

0 commit comments

Comments
 (0)