diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 38dd2d65b0a..313e6a340e6 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -163,6 +163,7 @@ * Expand `` at tooling time. In IDE tooltips, completion, and signature help, documentation is inherited from base classes, interfaces, overridden members, and constructors (matched by parameter signature). The FCS Symbols API (`FSharpSymbol.XmlDoc`) additionally resolves explicit `cref` targets, but does not expand constructor inheritance. The compiler emits the tag verbatim into generated XML documentation files, matching C#; `` is not implemented. ([Issue #19175](https://github.com/dotnet/fsharp/issues/19175), [PR #19188](https://github.com/dotnet/fsharp/pull/19188)) * Add symbol and type highlighting to F# diagnostics ([PR #20097](https://github.com/dotnet/fsharp/pull/20097)) * IL: add `ILPreNamespace`, make `ILPreTypeDef` creation lazy ([PR #20092](https://github.com/dotnet/fsharp/pull/20092)) +* IL: use empty tables for members when possible ([PR #20249](https://github.com/dotnet/fsharp/pull/20249)) ### Improved diff --git a/src/Compiler/AbstractIL/ilread.fs b/src/Compiler/AbstractIL/ilread.fs index 0ccdd9cf35c..e764d51a691 100644 --- a/src/Compiler/AbstractIL/ilread.fs +++ b/src/Compiler/AbstractIL/ilread.fs @@ -1542,6 +1542,26 @@ let seekReadMethodImplRow (ctxt: ILMetadataReader) mdv idx = let mdeclIdx = seekReadMethodDefOrRefIdx ctxt mdv &addr (tidx, mbodyIdx, mdeclIdx) +/// Rows of a table keyed by type def in its first column: at most one per type in EventMap and +/// PropertyMap, pointing at its member range, and the overrides themselves in MethodImpl. Called per +/// type def rather than when the table it feeds is forced, so the types with no rows - most of them - +/// can share the empty table. +let seekReadRowRangeForTypeDef (ctxt: ILMetadataReader) mdv (table: TableName) tidx = + let searcher = + { new ISeekReadIndexedRowReader with + member _.GetRow(i, rowIndex) = rowIndex <- i + member _.GetKey(rowIndex) = rowIndex + + member _.CompareKey(rowIndex) = + let mutable addr = ctxt.rowAddr table rowIndex + let rowTidx = seekReadUntaggedIdx TableNames.TypeDef ctxt mdv &addr + simpleIndexCompare tidx rowTidx + + member _.ConvertRow(rowIndex) = rowIndex + } + + seekReadIndexedRowsRange (ctxt.getNumRows table) true searcher + /// Read Table ILModuleRef. let seekReadModuleRefRow (ctxt: ILMetadataReader) mdv idx = let mutable addr = ctxt.rowAddr TableNames.ModuleRef idx @@ -2192,9 +2212,9 @@ and typeDefReader ctxtH : ILTypeDefStored = let impls = seekReadInterfaceImpls ctxt mdv numTypars idx - let mimpls = seekReadMethodImpls ctxt numTypars idx - let props = seekReadProperties ctxt numTypars idx - let events = seekReadEvents ctxt numTypars idx + let mimpls = seekReadMethodImpls ctxt mdv numTypars idx + let props = seekReadProperties ctxt mdv numTypars idx + let events = seekReadEvents ctxt mdv numTypars idx ILTypeDef( name = nm, @@ -2544,26 +2564,30 @@ and seekReadField ctxt mdv (numTypars, hasLayout) (idx: int) = ) and seekReadFields (ctxt: ILMetadataReader) (numTypars, hasLayout) fidx1 fidx2 = - mkILFieldsLazy ( - InterruptibleLazy(fun _ -> - let mdv = ctxt.mdfile.GetView() + if fidx1 <= 0 || fidx2 <= fidx1 then + emptyILFields + else + mkILFieldsLazy ( + InterruptibleLazy(fun _ -> + let mdv = ctxt.mdfile.GetView() - [ - if fidx1 > 0 then + [ for i = fidx1 to fidx2 - 1 do yield seekReadField ctxt mdv (numTypars, hasLayout) i - ]) - ) + ]) + ) and seekReadMethods (ctxt: ILMetadataReader) numTypars midx1 midx2 = - mkILMethodsComputed (fun () -> - let mdv = ctxt.mdfile.GetView() + if midx1 <= 0 || midx2 <= midx1 then + emptyILMethods + else + mkILMethodsComputed (fun () -> + let mdv = ctxt.mdfile.GetView() - [| - if midx1 > 0 then + [| for i = midx1 to midx2 - 1 do yield seekReadMethod ctxt mdv numTypars i - |]) + |]) and sigptrGetTypeDefOrRefOrSpecIdx bytes sigptr = let struct (n, sigptr) = sigptrGetZInt32 bytes sigptr @@ -3110,40 +3134,37 @@ and seekReadParamExtras (ctxt: ILMetadataReader) mdv (retRes: byref, p MetadataIndex = idx } -and seekReadMethodImpls (ctxt: ILMetadataReader) numTypars tidx = - mkILMethodImplsLazy ( - lazy - let mdv = ctxt.mdfile.GetView() +and seekReadMethodImpls (ctxt: ILMetadataReader) mdv numTypars tidx = + let startIdx, endIdx = + seekReadRowRangeForTypeDef ctxt mdv TableNames.MethodImpl tidx - let mimpls = - seekReadIndexedRows ( - ctxt.getNumRows TableNames.MethodImpl, - id, - id, - (fun i -> - let mutable addr = ctxt.rowAddr TableNames.MethodImpl i - let _tidx = seekReadUntaggedIdx TableNames.TypeDef ctxt mdv &addr - simpleIndexCompare tidx _tidx), - isSorted ctxt TableNames.MethodImpl, - seekReadMethodImplRow ctxt mdv - ) + if startIdx <= 0 || endIdx < startIdx then + emptyILMethodImpls + else + mkILMethodImplsLazy ( + lazy + let mdv = ctxt.mdfile.GetView() - mimpls - |> List.map (fun (_, b, c) -> - { - OverrideBy = - let (MethodData(enclTy, cc, nm, argTys, retTy, methInst)) = - seekReadMethodDefOrRefNoVarargs ctxt numTypars b + [ + for i in startIdx..endIdx do + let _, b, c = seekReadMethodImplRow ctxt mdv i + + yield + { + OverrideBy = + let (MethodData(enclTy, cc, nm, argTys, retTy, methInst)) = + seekReadMethodDefOrRefNoVarargs ctxt numTypars b - mkILMethSpecInTy (enclTy, cc, nm, argTys, retTy, methInst) - Overrides = - let (MethodData(enclTy, cc, nm, argTys, retTy, methInst)) = - seekReadMethodDefOrRefNoVarargs ctxt numTypars c + mkILMethSpecInTy (enclTy, cc, nm, argTys, retTy, methInst) + Overrides = + let (MethodData(enclTy, cc, nm, argTys, retTy, methInst)) = + seekReadMethodDefOrRefNoVarargs ctxt numTypars c - let mspec = mkILMethSpecInTy (enclTy, cc, nm, argTys, retTy, methInst) - OverridesSpec(mspec.MethodRef, mspec.DeclaringType) - }) - ) + let mspec = mkILMethSpecInTy (enclTy, cc, nm, argTys, retTy, methInst) + OverridesSpec(mspec.MethodRef, mspec.DeclaringType) + } + ] + ) and seekReadMultipleMethodSemantics (ctxt: ILMetadataReader) (flags, id) = seekReadIndexedRows ( @@ -3189,27 +3210,17 @@ and seekReadEvent ctxt mdv numTypars idx = metadataIndex = idx ) -(* REVIEW: can substantially reduce numbers of EventMap and PropertyMap reads by first checking if the whole table mdv sorted according to ILTypeDef tokens and then doing a binary chop *) -and seekReadEvents (ctxt: ILMetadataReader) numTypars tidx = - mkILEventsLazy ( - InterruptibleLazy(fun _ -> - let mdv = ctxt.mdfile.GetView() +and seekReadEvents (ctxt: ILMetadataReader) mdv numTypars tidx = + let rowNum, _ = seekReadRowRangeForTypeDef ctxt mdv TableNames.EventMap tidx + + if rowNum <= 0 then + emptyILEvents + else + mkILEventsLazy ( + InterruptibleLazy(fun _ -> + let mdv = ctxt.mdfile.GetView() + let _, beginEventIdx = seekReadEventMapRow ctxt mdv rowNum - match - seekReadOptionalIndexedRow ( - ctxt.getNumRows TableNames.EventMap, - id, - id, - (fun i -> - let mutable addr = ctxt.rowAddr TableNames.EventMap i - let _tidx = seekReadUntaggedIdx TableNames.TypeDef ctxt mdv &addr - simpleIndexCompare tidx _tidx), - false, - (fun i -> i, seekReadEventMapRow ctxt mdv i |> snd) - ) - with - | None -> [] - | Some(rowNum, beginEventIdx) -> let endEventIdx = if rowNum >= ctxt.getNumRows TableNames.EventMap then ctxt.getNumRows TableNames.Event + 1 @@ -3222,7 +3233,7 @@ and seekReadEvents (ctxt: ILMetadataReader) numTypars tidx = for i in beginEventIdx .. endEventIdx - 1 do yield seekReadEvent ctxt mdv numTypars i ]) - ) + ) and seekReadProperty ctxt mdv numTypars idx = let flags, nameIdx, typIdx = seekReadPropertyRow ctxt mdv idx @@ -3260,26 +3271,17 @@ and seekReadProperty ctxt mdv numTypars idx = metadataIndex = idx ) -and seekReadProperties (ctxt: ILMetadataReader) numTypars tidx = - mkILPropertiesLazy ( - InterruptibleLazy(fun _ -> - let mdv = ctxt.mdfile.GetView() +and seekReadProperties (ctxt: ILMetadataReader) mdv numTypars tidx = + let rowNum, _ = seekReadRowRangeForTypeDef ctxt mdv TableNames.PropertyMap tidx + + if rowNum <= 0 then + emptyILProperties + else + mkILPropertiesLazy ( + InterruptibleLazy(fun _ -> + let mdv = ctxt.mdfile.GetView() + let _, beginPropIdx = seekReadPropertyMapRow ctxt mdv rowNum - match - seekReadOptionalIndexedRow ( - ctxt.getNumRows TableNames.PropertyMap, - id, - id, - (fun i -> - let mutable addr = ctxt.rowAddr TableNames.PropertyMap i - let _tidx = seekReadUntaggedIdx TableNames.TypeDef ctxt mdv &addr - simpleIndexCompare tidx _tidx), - false, - (fun i -> i, seekReadPropertyMapRow ctxt mdv i |> snd) - ) - with - | None -> [] - | Some(rowNum, beginPropIdx) -> let endPropIdx = if rowNum >= ctxt.getNumRows TableNames.PropertyMap then ctxt.getNumRows TableNames.Property + 1 @@ -3292,7 +3294,7 @@ and seekReadProperties (ctxt: ILMetadataReader) numTypars tidx = for i in beginPropIdx .. endPropIdx - 1 do yield seekReadProperty ctxt mdv numTypars i ]) - ) + ) and customAttrsReaderFn ctxtH tag : int32 -> ILAttribute[] = fun idx ->