@@ -19,6 +19,31 @@ open Microsoft.FSharp.Compiler.AbstractIL.Internal.Library
1919open Microsoft.FSharp .Compiler .ErrorLogger
2020open Microsoft.FSharp .Compiler .Range
2121
22+
23+ type BlobBuildingStream () =
24+ inherit Stream()
25+
26+ static let chunkSize = 32 * 1024
27+ let builder = new BlobBuilder( chunkSize)
28+
29+ override this.CanWrite = true
30+ override this.CanRead = false
31+ override this.CanSeek = false
32+ override this.Length = int64( builder.Count)
33+
34+ override this.Write ( buffer : byte array , offset : int , count : int ) = builder.WriteBytes( buffer, offset, count)
35+ override this.WriteByte ( value : byte ) = builder.WriteByte( value)
36+ member this.WriteInt32 ( value : int ) = builder.WriteInt32( value)
37+ member this.ToImmutableArray () = builder.ToImmutableArray()
38+ member this.TryWriteBytes ( stream : Stream , length : int ) = builder.TryWriteBytes( stream, length)
39+
40+ override this.Flush () = ()
41+ override this.Dispose ( _disposing : bool ) = ()
42+ override this.Seek ( _offset : int64 , _origin : SeekOrigin ) = raise ( new NotSupportedException())
43+ override this.Read ( _buffer : byte array , _offset : int , _count : int ) = raise ( new NotSupportedException())
44+ override this.SetLength ( _value : int64 ) = raise ( new NotSupportedException())
45+ override val Position = 0 L with get, set
46+
2247// --------------------------------------------------------------------
2348// PDB types
2449// --------------------------------------------------------------------
@@ -227,7 +252,7 @@ let fixupOverlappingSequencePoints fixupSPs showTimes methods =
227252 Array.sortInPlaceBy fst allSps
228253 spCounts, allSps
229254
230- let generatePortablePdb fixupSPs showTimes ( info : PdbData ) =
255+ let generatePortablePdb fixupSPs ( embedAllSource : bool ) ( embedSourceList : string list ) showTimes ( info : PdbData ) =
231256 sortMethods showTimes info
232257 let _spCounts , _allSps = fixupOverlappingSequencePoints fixupSPs showTimes info.Methods
233258 let externalRowCounts = getRowCounts info.TableRowCounts
@@ -253,23 +278,69 @@ let generatePortablePdb fixupSPs showTimes (info:PdbData) =
253278 metadata.GetOrAddBlob( writer)
254279
255280 let corSymLanguageTypeFSharp = System.Guid( 0xAB4F38C9 u, 0xB6E6 us, 0x43ba us, 0xBE uy, 0x3B uy, 0x58 uy, 0x08 uy, 0x0B uy, 0x2C uy, 0xCC uy, 0xE3 uy)
281+ let embeddedSource = System.Guid( 0x0e8a571b u, 0x6926 us, 0x466e us, 0xb4 uy, 0xad uy, 0x8a uy, 0xb0 uy, 0x46 uy, 0x11 uy, 0xf5 uy, 0xfe uy)
282+
283+ /// <summary>
284+ /// The maximum number of bytes in to write out uncompressed.
285+ ///
286+ /// This prevents wasting resources on compressing tiny files with little to negative gain
287+ /// in PDB file size.
288+ ///
289+ /// Chosen as the point at which we start to see > 10% blob size reduction using all
290+ /// current source files in corefx and roslyn as sample data.
291+ /// </summary>
292+ let sourceCompressionThreshold = 200
293+
256294 let documentIndex =
295+ let includeSource file =
296+ let isInList =
297+ if embedSourceList.Length = 0 then false
298+ else
299+ embedSourceList |> List.tryFind( fun f -> String.Compare( file, f, StringComparison.OrdinalIgnoreCase ) = 0 ) |> Option.isSome
300+
301+ if not embedAllSource && not isInList || not ( File.Exists( file)) then
302+ None
303+ else
304+ let stream = File.OpenRead( file)
305+ let length64 = stream.Length
306+ if length64 > int64( Int32.MaxValue) then raise ( new IOException( " File is too long" ))
307+
308+ let builder = new BlobBuildingStream()
309+ let length = int( length64)
310+ if length < sourceCompressionThreshold then
311+ builder.WriteInt32( 0 )
312+ builder.TryWriteBytes( stream, length) |> ignore
313+ else
314+ builder.WriteInt32( length) |> ignore
315+ use deflater = new DeflateStream( builder, CompressionMode.Compress, true )
316+ stream.CopyTo( deflater) |> ignore
317+ Some ( builder.ToImmutableArray())
318+
257319 let mutable index = new Dictionary< string, DocumentHandle>( docs.Length)
258320 metadata.SetCapacity( TableIndex.Document, docs.Length)
259321 for doc in docs do
260322 let handle =
261323 match checkSum doc.File with
262324 | Some ( hashAlg, checkSum) ->
263- serializeDocumentName doc.File,
264- metadata.GetOrAddGuid( hashAlg),
265- metadata.GetOrAddBlob( checkSum.ToImmutableArray()),
266- metadata.GetOrAddGuid( corSymLanguageTypeFSharp)
325+ let dbgInfo =
326+ ( serializeDocumentName doc.File,
327+ metadata.GetOrAddGuid( hashAlg),
328+ metadata.GetOrAddBlob( checkSum.ToImmutableArray()),
329+ metadata.GetOrAddGuid( corSymLanguageTypeFSharp)) |> metadata.AddDocument
330+ match includeSource doc.File with
331+ | None -> ()
332+ | Some blob ->
333+ metadata.AddCustomDebugInformation( DocumentHandle.op_ Implicit( dbgInfo),
334+ metadata.GetOrAddGuid( embeddedSource),
335+ metadata.GetOrAddBlob( blob)) |> ignore
336+ dbgInfo
267337 | None ->
268- serializeDocumentName doc.File,
269- metadata.GetOrAddGuid( System.Guid.Empty),
270- metadata.GetOrAddBlob( ImmutableArray< byte>. Empty),
271- metadata.GetOrAddGuid( corSymLanguageTypeFSharp)
272- |> metadata.AddDocument
338+ let dbgInfo =
339+ ( serializeDocumentName doc.File,
340+ metadata.GetOrAddGuid( System.Guid.Empty),
341+ metadata.GetOrAddBlob( ImmutableArray< byte>. Empty),
342+ metadata.GetOrAddGuid( corSymLanguageTypeFSharp)) |> metadata.AddDocument
343+ dbgInfo
273344 index.Add( doc.File, handle)
274345 index
275346
@@ -291,7 +362,7 @@ let generatePortablePdb fixupSPs showTimes (info:PdbData) =
291362 else
292363 match documentIndex.TryGetValue( docs.[ d]. File) with
293364 | false , _ -> Unchecked.defaultof< DocumentHandle>
294- | true , f -> f
365+ | true , h -> h
295366
296367 if sps.Length = 0 then
297368 Unchecked.defaultof< DocumentHandle>, Unchecked.defaultof< BlobHandle>
@@ -306,7 +377,6 @@ let generatePortablePdb fixupSPs showTimes (info:PdbData) =
306377 singleDocumentIndex
307378
308379 let builder = new BlobBuilder()
309-
310380 builder.WriteCompressedInteger( minfo.LocalSignatureToken)
311381
312382 // Initial document: When sp's spread over more than one document we put the initial document here.
0 commit comments