Skip to content

Commit 1788c19

Browse files
committed
Serialization and deserialization of the typechecking data
1 parent cae1069 commit 1788c19

21 files changed

+1921
-212
lines changed

src/Compiler/AbstractIL/il.fs

+2
Original file line numberDiff line numberDiff line change
@@ -2781,6 +2781,8 @@ type ILTypeDef
27812781

27822782
member _.MetadataIndex = metadataIndex
27832783

2784+
member _.Flags = additionalFlags
2785+
27842786
member x.With
27852787
(
27862788
?name,

src/Compiler/AbstractIL/il.fsi

+6
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,8 @@ type internal ILSecurityDecl = ILSecurityDecl of ILSecurityAction * byte[]
949949
/// below to construct/destruct these.
950950
[<NoComparison; NoEquality; Struct>]
951951
type internal ILSecurityDecls =
952+
new: array: ILSecurityDecl[] -> ILSecurityDecls
953+
952954
member AsList: unit -> ILSecurityDecl list
953955

954956
/// Represents the efficiency-oriented storage of ILSecurityDecls in another item.
@@ -1207,6 +1209,8 @@ type ILMethodDef =
12071209
/// name and arity.
12081210
[<NoEquality; NoComparison; Class; Sealed>]
12091211
type ILMethodDefs =
1212+
new: f: (unit -> ILMethodDef array) -> ILMethodDefs
1213+
12101214
inherit DelayInitArrayMap<ILMethodDef, string, ILMethodDef list>
12111215

12121216
interface IEnumerable<ILMethodDef>
@@ -1311,6 +1315,7 @@ type ILFieldDef =
13111315
/// a form to allow efficient looking up fields by name.
13121316
[<NoEquality; NoComparison; Sealed>]
13131317
type ILFieldDefs =
1318+
13141319
member internal AsList: unit -> ILFieldDef list
13151320

13161321
member internal LookupByName: string -> ILFieldDef list
@@ -1613,6 +1618,7 @@ type ILTypeDef =
16131618
member Encoding: ILDefaultPInvokeEncoding
16141619
member IsKnownToBeAttribute: bool
16151620
member CanContainExtensionMethods: bool
1621+
member Flags: ILTypeDefAdditionalFlags
16161622

16171623
member internal WithAccess: ILTypeDefAccess -> ILTypeDef
16181624
member internal WithNestedAccess: ILMemberAccess -> ILTypeDef

src/Compiler/Driver/CompilerImports.fs

+48
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,54 @@ let EncodeOptimizationData (tcGlobals, tcConfig: TcConfig, outfile, exportRemapp
337337
else
338338
[]
339339

340+
let GetTypecheckingData (file, ilScopeRef, ilModule, byteReaderA, byteReaderB) =
341+
342+
let memA = byteReaderA ()
343+
344+
let memB =
345+
match byteReaderB with
346+
| None -> ByteMemory.Empty.AsReadOnly()
347+
| Some br -> br ()
348+
349+
unpickleObjWithDanglingCcus file ilScopeRef ilModule unpickleTcInfo memA memB
350+
351+
let WriteTypecheckingData (tcConfig: TcConfig, tcGlobals, fileName, inMem, ccu, tcInfo) =
352+
353+
// need to understand the naming and if we even want two resources here...
354+
let rName = "FSharpTypecheckingData"
355+
let rNameB = "FSharpTypecheckingDataB"
356+
357+
PickleToResource
358+
inMem
359+
fileName
360+
tcGlobals
361+
tcConfig.compressMetadata
362+
ccu
363+
(rName + ccu.AssemblyName)
364+
(rNameB + ccu.AssemblyName)
365+
pickleTcInfo
366+
tcInfo
367+
368+
let EncodeTypecheckingData (tcConfig: TcConfig, tcGlobals, generatedCcu, outfile, isIncrementalBuild, tcInfo) =
369+
let r1, r2 =
370+
WriteTypecheckingData(
371+
tcConfig,
372+
tcGlobals,
373+
outfile,
374+
isIncrementalBuild,
375+
generatedCcu,
376+
tcInfo)
377+
378+
let resources =
379+
[
380+
r1
381+
match r2 with
382+
| None -> ()
383+
| Some r -> r
384+
]
385+
386+
resources
387+
340388
exception AssemblyNotResolved of originalName: string * range: range
341389

342390
exception MSBuildReferenceResolutionWarning of message: string * warningCode: string * range: range

src/Compiler/Driver/CompilerImports.fsi

+18
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ open FSharp.Compiler.TcGlobals
1919
open FSharp.Compiler.BuildGraph
2020
open FSharp.Compiler.IO
2121
open FSharp.Compiler.Text
22+
open FSharp.Compiler.TypedTreePickle
2223
open FSharp.Core.CompilerServices
2324

2425
#if !NO_TYPEPROVIDERS
@@ -71,6 +72,23 @@ val EncodeOptimizationData:
7172
isIncrementalBuild: bool ->
7273
ILResource list
7374

75+
val GetTypecheckingData:
76+
file: string *
77+
ilScopeRef: ILScopeRef *
78+
ilModule: ILModuleDef option *
79+
byteReaderA: (unit -> ReadOnlyByteMemory) *
80+
byteReaderB: (unit -> ReadOnlyByteMemory) option ->
81+
PickledDataWithReferences<PickledTcInfo>
82+
83+
val EncodeTypecheckingData:
84+
tcConfig: TcConfig *
85+
tcGlobals: TcGlobals *
86+
generatedCcu: CcuThunk *
87+
outfile: string *
88+
isIncrementalBuild: bool *
89+
tcInfo: PickledTcInfo ->
90+
ILResource list
91+
7492
[<RequireQualifiedAccess>]
7593
type ResolveAssemblyReferenceMode =
7694
| Speculative

src/Compiler/Driver/ReuseTcResults/CachingDriver.fs

+62
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@ module internal FSharp.Compiler.ReuseTcResults
33
open System.Collections.Generic
44
open System.IO
55

6+
open FSharp.Compiler.CheckDeclarations
67
open FSharp.Compiler.CompilerConfig
78
open FSharp.Compiler.Diagnostics
89
open FSharp.Compiler.GraphChecking
910
open FSharp.Compiler.IO
11+
open FSharp.Compiler.ParseAndCheckInputs
1012
open FSharp.Compiler.Syntax
1113
open FSharp.Compiler.Syntax.PrettyNaming
14+
open FSharp.Compiler.TypedTree
15+
open CompilerImports
16+
open FSharp.Compiler.AbstractIL.IL
1217

1318
type TcData =
1419
{
@@ -139,3 +144,60 @@ type CachingDriver(tcConfig: TcConfig) =
139144
use _ = Activity.start Activity.Events.reuseTcResultsCacheAbsent []
140145
writeThisTcData thisTcData
141146
false
147+
148+
member _.ReuseTcResults inputs (tcInitialState: TcState) =
149+
150+
let bytes = File.ReadAllBytes("tc")
151+
let memory = ByteMemory.FromArray(bytes)
152+
let byteReaderA () = ReadOnlyByteMemory(memory)
153+
154+
let byteReaderB = None
155+
156+
let tcInfo =
157+
GetTypecheckingData(
158+
"", // assembly.FileName,
159+
ILScopeRef.Local, // assembly.ILScopeRef,
160+
None, //assembly.RawMetadata.TryGetILModuleDef(),
161+
byteReaderA,
162+
byteReaderB
163+
)
164+
165+
let rawData = tcInfo.RawData
166+
167+
let topAttrs: TopAttribs =
168+
{
169+
mainMethodAttrs = rawData.MainMethodAttrs
170+
netModuleAttrs = rawData.NetModuleAttrs
171+
assemblyAttrs = rawData.AssemblyAttrs
172+
}
173+
174+
// need to understand if anything can be used here, pickling state is hard
175+
tcInitialState,
176+
topAttrs,
177+
rawData.DeclaredImpls,
178+
// this is quite definitely wrong, need to figure out what to do with the environment
179+
tcInitialState.TcEnvFromImpls
180+
181+
member _.CacheTcResults(tcState: TcState, topAttrs: TopAttribs, declaredImpls, tcEnvAtEndOfLastFile, inputs, tcGlobals, outfile) =
182+
let thisTcData =
183+
{
184+
CmdLine = getThisCompilationCmdLine tcConfig.cmdLineArgs
185+
Graph = getThisCompilationGraph inputs
186+
References = getThisCompilationReferences tcConfig.referencedDLLs
187+
}
188+
189+
writeThisTcData thisTcData
190+
191+
let tcInfo =
192+
{
193+
MainMethodAttrs = topAttrs.mainMethodAttrs
194+
NetModuleAttrs = topAttrs.netModuleAttrs
195+
AssemblyAttrs = topAttrs.assemblyAttrs
196+
DeclaredImpls = declaredImpls
197+
}
198+
199+
let encodedData =
200+
EncodeTypecheckingData(tcConfig, tcGlobals, tcState.Ccu, outfile, false, tcInfo)
201+
202+
let resource = encodedData[0].GetBytes().ToArray()
203+
File.WriteAllBytes("tc", resource)

src/Compiler/Driver/fsc.fs

+33-15
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ let TypeCheck
150150
tcEnv0,
151151
openDecls0,
152152
inputs,
153-
exiter: Exiter
153+
exiter: Exiter,
154+
outfile
154155
) =
155156
try
156157
if isNil inputs then
@@ -167,20 +168,35 @@ let TypeCheck
167168
let cachingDriver = CachingDriver(tcConfig)
168169

169170
if cachingDriver.CanReuseTcResults(inputs) then
170-
// do nothing, yet
171-
()
171+
cachingDriver.ReuseTcResults inputs tcInitialState
172+
else
173+
let tcState, topAttrs, declaredImpls, tcEnvAtEndOfLastFile =
174+
CheckClosedInputSet(
175+
ctok,
176+
diagnosticsLogger.CheckForErrors,
177+
tcConfig,
178+
tcImports,
179+
tcGlobals,
180+
None,
181+
tcInitialState,
182+
eagerFormat,
183+
inputs
184+
)
172185

173-
CheckClosedInputSet(
174-
ctok,
175-
(fun () -> diagnosticsLogger.CheckForRealErrorsIgnoringWarnings),
176-
tcConfig,
177-
tcImports,
178-
tcGlobals,
179-
None,
180-
tcInitialState,
181-
eagerFormat,
182-
inputs
183-
)
186+
cachingDriver.CacheTcResults(tcState, topAttrs, declaredImpls, tcEnvAtEndOfLastFile, inputs, tcGlobals, outfile)
187+
tcState, topAttrs, declaredImpls, tcEnvAtEndOfLastFile
188+
else
189+
CheckClosedInputSet(
190+
ctok,
191+
(fun () -> diagnosticsLogger.CheckForRealErrorsIgnoringWarnings),
192+
tcConfig,
193+
tcImports,
194+
tcGlobals,
195+
None,
196+
tcInitialState,
197+
eagerFormat,
198+
inputs
199+
)
184200
with exn ->
185201
errorRecovery exn rangeStartup
186202
exiter.Exit 1
@@ -481,6 +497,8 @@ let main1
481497
disposables: DisposablesTracker
482498
) =
483499

500+
CompilerGlobalState.stampCount <- 0L
501+
484502
// See Bug 735819
485503
let lcidFromCodePage =
486504
let thread = Thread.CurrentThread
@@ -701,7 +719,7 @@ let main1
701719
let inputs = inputs |> List.map fst
702720

703721
let tcState, topAttrs, typedAssembly, _tcEnvAtEnd =
704-
TypeCheck(ctok, tcConfig, tcImports, tcGlobals, diagnosticsLogger, assemblyName, tcEnv0, openDecls0, inputs, exiter)
722+
TypeCheck(ctok, tcConfig, tcImports, tcGlobals, diagnosticsLogger, assemblyName, tcEnv0, openDecls0, inputs, exiter, outfile)
705723

706724
AbortOnError(diagnosticsLogger, exiter)
707725
ReportTime tcConfig "Typechecked"

src/Compiler/TypedTree/CompilerGlobalState.fs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ let newUnique() = System.Threading.Interlocked.Increment &uniqueCount
7272

7373
/// Unique name generator for stamps attached to to val_specs, tycon_specs etc.
7474
//++GLOBAL MUTABLE STATE (concurrency-safe)
75-
let mutable private stampCount = 0L
75+
let mutable stampCount = 0L
7676
let newStamp() =
7777
let stamp = System.Threading.Interlocked.Increment &stampCount
7878
stamp

src/Compiler/TypedTree/CompilerGlobalState.fsi

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ type Unique = int64
4747
/// Concurrency-safe
4848
val newUnique: (unit -> int64)
4949

50+
val mutable stampCount: int64
51+
5052
/// Unique name generator for stamps attached to to val_specs, tycon_specs etc.
5153
/// Concurrency-safe
5254
val newStamp: (unit -> int64)

src/Compiler/TypedTree/TypedTree.fs

+9
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ type ValFlags(flags: int64) =
252252
// Clear the IsGeneratedEventVal, since there's no use in propagating specialname information for generated add/remove event vals
253253
(flags &&& ~~~0b010011001100000000000L)
254254

255+
member x.Flags = flags
256+
255257
/// Represents the kind of a type parameter
256258
[<RequireQualifiedAccess (* ; StructuredFormatDisplay("{DebugText}") *) >]
257259
type TyparKind =
@@ -490,6 +492,7 @@ type EntityFlags(flags: int64) =
490492
/// Get the flags as included in the F# binary metadata
491493
member x.PickledBits = (flags &&& ~~~0b000111111000100L)
492494

495+
member x.Flags = flags
493496

494497

495498
exception UndefinedName of
@@ -5918,6 +5921,12 @@ type PickledCcuInfo =
59185921

59195922
override _.ToString() = "PickledCcuInfo(...)"
59205923

5924+
type PickledTcInfo = {
5925+
MainMethodAttrs: Attribs
5926+
NetModuleAttrs: Attribs
5927+
AssemblyAttrs: Attribs
5928+
DeclaredImpls: CheckedImplFile list
5929+
}
59215930

59225931
/// Represents a set of free local values. Computed and cached by later phases
59235932
/// (never cached type checking). Cached in expressions. Not pickled.

src/Compiler/TypedTree/TypedTree.fsi

+10
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,8 @@ type ValFlags =
162162

163163
member WithMakesNoCriticalTailcalls: ValFlags
164164

165+
member Flags: int64
166+
165167
/// Represents the kind of a type parameter
166168
[<RequireQualifiedAccess>]
167169
type TyparKind =
@@ -292,6 +294,8 @@ type EntityFlags =
292294
/// Get the flags as included in the F# binary metadata
293295
member PickledBits: int64
294296

297+
member Flags: int64
298+
295299
member PreEstablishedHasDefaultConstructor: bool
296300

297301
/// These two bits represents the on-demand analysis about whether the entity is assumed to be a readonly struct
@@ -4297,6 +4301,12 @@ type PickledCcuInfo =
42974301
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
42984302
member DebugText: string
42994303
4304+
type PickledTcInfo =
4305+
{ MainMethodAttrs: Attribs
4306+
NetModuleAttrs: Attribs
4307+
AssemblyAttrs: Attribs
4308+
DeclaredImpls: CheckedImplFile list }
4309+
43004310
/// Represents a set of free local values. Computed type cached by later phases
43014311
/// (never cached type checking). Cached in expressions. Not pickled.
43024312
type FreeLocals = Zset<Val>

0 commit comments

Comments
 (0)