Skip to content

Commit bd3ed35

Browse files
committed
integrate visualfsharp master
2 parents a771a5f + 432784c commit bd3ed35

File tree

2 files changed

+50
-51
lines changed

2 files changed

+50
-51
lines changed

fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,6 @@
278278
<Compile Include="$(FSharpSourcesRoot)/ilx/EraseUnions.fs">
279279
<Link>ILXErase/EraseUnions.fs</Link>
280280
</Compile>
281-
<FsLex Include="$(FSharpSourcesRoot)\absil\illex.fsl">
282-
<OtherFlags>--unicode --lexlib Internal.Utilities.Text.Lexing</OtherFlags>
283-
<Link>AbsIL/illex.fsl</Link>
284-
</FsLex>
285281
<FsLex Include="$(FSharpSourcesRoot)\fsharp\lex.fsl">
286282
<OtherFlags>--unicode --lexlib Internal.Utilities.Text.Lexing</OtherFlags>
287283
<Link>ParserAndUntypedAST/lex.fsl</Link>

src/absil/ilread.fs

Lines changed: 50 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,11 @@ open System.Reflection
3333

3434
let checking = false
3535
let logging = false
36-
let _ = if checking then dprintn "warning : Ilread.checking is on"
36+
let _ = if checking then dprintn "warning : ILBinaryReader.checking is on"
3737
let noStableFileHeuristic = try (System.Environment.GetEnvironmentVariable("FSharp_NoStableFileHeuristic") <> null) with _ -> false
3838
let alwaysMemoryMapFSC = try (System.Environment.GetEnvironmentVariable("FSharp_AlwaysMemoryMapCommandLineCompiler") <> null) with _ -> false
39+
let stronglyHeldReaderCacheSizeDefault = 30
40+
let stronglyHeldReaderCacheSize = try (match System.Environment.GetEnvironmentVariable("FSharp_StronglyHeldBinaryReaderCacheSize") with null -> stronglyHeldReaderCacheSizeDefault | s -> int32 s) with _ -> stronglyHeldReaderCacheSizeDefault
3941

4042
let singleOfBits (x:int32) = System.BitConverter.ToSingle(System.BitConverter.GetBytes(x), 0)
4143
let doubleOfBits (x:int64) = System.BitConverter.Int64BitsToDouble(x)
@@ -346,7 +348,7 @@ type ByteFile(fileName: string, bytes:byte[]) =
346348
/// This is the default implementation used by F# Compiler Services when accessing "stable" binaries. It is not used
347349
/// by Visual Studio, where tryGetMetadataSnapshot provides a RawMemoryFile backed by Roslyn data.
348350
[<DebuggerDisplay("{FileName}")>]
349-
type WeakByteFile(fileName: string) =
351+
type WeakByteFile(fileName: string, chunk: (int * int) option) =
350352

351353
do stats.weakByteFileCount <- stats.weakByteFileCount + 1
352354

@@ -357,30 +359,29 @@ type WeakByteFile(fileName: string) =
357359
let weakBytes = new WeakReference<byte[]> (null)
358360

359361
member __.FileName = fileName
360-
/// Get the bytes for the file
361-
member this.Get() =
362-
let mutable tg = null
363-
if not (weakBytes.TryGetTarget(&tg)) then
364-
if FileSystem.GetLastWriteTimeShim(fileName) <> fileStamp then
365-
errorR (Error (FSComp.SR.ilreadFileChanged fileName, range0))
366-
367-
tg <- FileSystem.ReadAllBytesShim fileName
368-
weakBytes.SetTarget tg
369-
tg
370362

363+
/// Get the bytes for the file
371364
interface BinaryFile with
372-
override __.GetView() =
373-
let mutable tg = null
365+
366+
override this.GetView() =
374367
let strongBytes =
368+
let mutable tg = null
375369
if not (weakBytes.TryGetTarget(&tg)) then
376370
if FileSystem.GetLastWriteTimeShim(fileName) <> fileStamp then
377-
errorR (Error (FSComp.SR.ilreadFileChanged fileName, range0))
371+
error (Error (FSComp.SR.ilreadFileChanged fileName, range0))
372+
373+
let bytes =
374+
match chunk with
375+
| None -> FileSystem.ReadAllBytesShim fileName
376+
| Some(start, length) -> File.ReadBinaryChunk (fileName, start, length)
377+
378+
tg <- bytes
379+
380+
weakBytes.SetTarget bytes
378381

379-
tg <- FileSystem.ReadAllBytesShim fileName
380-
weakBytes.SetTarget tg
381382
tg
382-
(ByteView(strongBytes) :> BinaryView)
383383

384+
(ByteView(strongBytes) :> BinaryView)
384385

385386

386387
let seekReadByte (mdv:BinaryView) addr = mdv.ReadByte addr
@@ -3927,27 +3928,31 @@ type ILModuleReader(ilModule: ILModuleDef, ilAssemblyRefs: Lazy<ILAssemblyRef li
39273928

39283929
// ++GLOBAL MUTABLE STATE (concurrency safe via locking)
39293930
type ILModuleReaderCacheLockToken() = interface LockToken
3930-
let ilModuleReaderCache = new AgedLookup<ILModuleReaderCacheLockToken, (string * System.DateTime * ILScopeRef * bool * ReduceMemoryFlag * MetadataOnlyFlag), ILModuleReader>(0, areSimilar=(fun (x, y) -> x = y))
3931+
type ILModuleReaderCacheKey = ILModuleReaderCacheKey of string * DateTime * ILScopeRef * bool * ReduceMemoryFlag * MetadataOnlyFlag
3932+
let ilModuleReaderCache = new AgedLookup<ILModuleReaderCacheLockToken, ILModuleReaderCacheKey, ILModuleReader>(stronglyHeldReaderCacheSize, areSimilar=(fun (x, y) -> x = y))
39313933
let ilModuleReaderCacheLock = Lock()
39323934

39333935
let stableFileHeuristicApplies fileName =
39343936
not noStableFileHeuristic && try FileSystem.IsStableFileHeuristic fileName with _ -> false
39353937

3936-
let createByteFile opts fileName =
3938+
let createByteFileChunk opts fileName chunk =
39373939
// If we're trying to reduce memory usage then we are willing to go back and re-read the binary, so we can use
39383940
// a weakly-held handle to an array of bytes.
39393941
if opts.reduceMemoryUsage = ReduceMemoryFlag.Yes && stableFileHeuristicApplies fileName then
3940-
WeakByteFile(fileName) :> BinaryFile
3942+
WeakByteFile(fileName, chunk) :> BinaryFile
39413943
else
3942-
let bytes = FileSystem.ReadAllBytesShim(fileName)
3944+
let bytes =
3945+
match chunk with
3946+
| None -> FileSystem.ReadAllBytesShim fileName
3947+
| Some (start, length) -> File.ReadBinaryChunk(fileName, start, length)
39433948
ByteFile(fileName, bytes) :> BinaryFile
39443949

3945-
let tryMemoryMap opts fileName =
3950+
let tryMemoryMapWholeFile opts fileName =
39463951
let file =
39473952
try
39483953
MemoryMapFile.Create fileName :> BinaryFile
39493954
with _ ->
3950-
createByteFile opts fileName
3955+
createByteFileChunk opts fileName None
39513956
let disposer =
39523957
{ new IDisposable with
39533958
member __.Dispose() =
@@ -3963,17 +3968,16 @@ let OpenILModuleReaderFromBytes fileName bytes opts =
39633968

39643969
let OpenILModuleReader fileName opts =
39653970
// Pseudo-normalize the paths.
3966-
let ((_,writeStamp,_,_,_,_) as key), keyOk =
3971+
let (ILModuleReaderCacheKey (fullPath,writeStamp,_,_,_,_) as key), keyOk =
39673972
try
3968-
(FileSystem.GetFullPathShim(fileName),
3969-
FileSystem.GetLastWriteTimeShim(fileName),
3970-
opts.ilGlobals.primaryAssemblyScopeRef,
3971-
opts.pdbPath.IsSome,
3972-
opts.reduceMemoryUsage,
3973-
opts.metadataOnly), true
3974-
with e ->
3975-
System.Diagnostics.Debug.Assert(false, sprintf "Failed to compute key in OpenILModuleReader cache for '%s'. Falling back to uncached." fileName)
3976-
("", System.DateTime.UtcNow, ILScopeRef.Local, false, ReduceMemoryFlag.Yes, MetadataOnlyFlag.Yes), false
3973+
let fullPath = FileSystem.GetFullPathShim(fileName)
3974+
let writeTime = FileSystem.GetLastWriteTimeShim(fileName)
3975+
let key = ILModuleReaderCacheKey (fullPath, writeTime, opts.ilGlobals.primaryAssemblyScopeRef, opts.pdbPath.IsSome, opts.reduceMemoryUsage, opts.metadataOnly)
3976+
key, true
3977+
with exn ->
3978+
System.Diagnostics.Debug.Assert(false, sprintf "Failed to compute key in OpenILModuleReader cache for '%s'. Falling back to uncached. Error = %s" fileName (exn.ToString()))
3979+
let fakeKey = ILModuleReaderCacheKey(fileName, System.DateTime.UtcNow, ILScopeRef.Local, false, ReduceMemoryFlag.Yes, MetadataOnlyFlag.Yes)
3980+
fakeKey, false
39773981

39783982
let cacheResult =
39793983
if keyOk then
@@ -3999,30 +4003,29 @@ let OpenILModuleReader fileName opts =
39994003

40004004
// See if tryGetMetadata gives us a BinaryFile for the metadata section alone.
40014005
let mdfileOpt =
4002-
match opts.tryGetMetadataSnapshot (fileName, writeStamp) with
4003-
| Some (obj, start, len) -> Some (RawMemoryFile(fileName, obj, start, len) :> BinaryFile)
4006+
match opts.tryGetMetadataSnapshot (fullPath, writeStamp) with
4007+
| Some (obj, start, len) -> Some (RawMemoryFile(fullPath, obj, start, len) :> BinaryFile)
40044008
| None -> None
40054009

40064010
// For metadata-only, always use a temporary, short-lived PE file reader, preferably over a memory mapped file.
40074011
// Then use the metadata blob as the long-lived memory resource.
4008-
let disposer, pefileEager = tryMemoryMap opts fileName
4012+
let disposer, pefileEager = tryMemoryMapWholeFile opts fullPath
40094013
use _disposer = disposer
4010-
let (metadataPhysLoc, metadataSize, peinfo, pectxtEager, pevEager, _pdb) = openPEFileReader (fileName, pefileEager, None)
4014+
let (metadataPhysLoc, metadataSize, peinfo, pectxtEager, pevEager, _pdb) = openPEFileReader (fullPath, pefileEager, None)
40114015
let mdfile =
40124016
match mdfileOpt with
40134017
| Some mdfile -> mdfile
40144018
| None ->
40154019
// If tryGetMetadata doesn't give anything, then just read the metadata chunk out of the binary
4016-
let bytes = File.ReadBinaryChunk (fileName, metadataPhysLoc, metadataSize)
4017-
ByteFile(fileName, bytes) :> BinaryFile
4020+
createByteFileChunk opts fullPath (Some (metadataPhysLoc, metadataSize))
40184021

4019-
let ilModule, ilAssemblyRefs = openPEMetadataOnly (fileName, peinfo, pectxtEager, pevEager, mdfile, reduceMemoryUsage, opts.ilGlobals)
4022+
let ilModule, ilAssemblyRefs = openPEMetadataOnly (fullPath, peinfo, pectxtEager, pevEager, mdfile, reduceMemoryUsage, opts.ilGlobals)
40204023
new ILModuleReader(ilModule, ilAssemblyRefs, ignore)
40214024
else
40224025
// If we are not doing metadata-only, then just go ahead and read all the bytes and hold them either strongly or weakly
40234026
// depending on the heuristic
4024-
let pefile = createByteFile opts fileName
4025-
let ilModule, ilAssemblyRefs, _pdb = openPE (fileName, pefile, None, reduceMemoryUsage, opts.ilGlobals)
4027+
let pefile = createByteFileChunk opts fullPath None
4028+
let ilModule, ilAssemblyRefs, _pdb = openPE (fullPath, pefile, None, reduceMemoryUsage, opts.ilGlobals)
40264029
new ILModuleReader(ilModule, ilAssemblyRefs, ignore)
40274030

40284031
if keyOk then
@@ -4042,14 +4045,14 @@ let OpenILModuleReader fileName opts =
40424045
// multi-proc build. So use memory mapping, but only for stable files. Other files
40434046
// fill use an in-memory ByteFile
40444047
let _disposer, pefile =
4045-
if alwaysMemoryMapFSC || stableFileHeuristicApplies fileName then
4046-
tryMemoryMap opts fileName
4048+
if alwaysMemoryMapFSC || stableFileHeuristicApplies fullPath then
4049+
tryMemoryMapWholeFile opts fullPath
40474050
else
4048-
let pefile = createByteFile opts fileName
4051+
let pefile = createByteFileChunk opts fullPath None
40494052
let disposer = { new IDisposable with member __.Dispose() = () }
40504053
disposer, pefile
40514054

4052-
let ilModule, ilAssemblyRefs, pdb = openPE (fileName, pefile, opts.pdbPath, reduceMemoryUsage, opts.ilGlobals)
4055+
let ilModule, ilAssemblyRefs, pdb = openPE (fullPath, pefile, opts.pdbPath, reduceMemoryUsage, opts.ilGlobals)
40534056
let ilModuleReader = new ILModuleReader(ilModule, ilAssemblyRefs, (fun () -> ClosePdbReader pdb))
40544057

40554058
// Readers with PDB reader disposal logic don't go in the cache. Note the PDB reader is only used in static linking.

0 commit comments

Comments
 (0)