forked from dotnet/fsharp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCompilerGlobalState.fs
More file actions
121 lines (93 loc) · 5.75 KB
/
Copy pathCompilerGlobalState.fs
File metadata and controls
121 lines (93 loc) · 5.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
/// Defines the global environment for all type checking.
module FSharp.Compiler.CompilerGlobalState
open System
open System.Collections.Concurrent
open System.Threading
open Internal.Utilities.Library
open FSharp.Compiler.Syntax.PrettyNaming
open FSharp.Compiler.Text
/// Generates compiler-generated names. Each name generated also includes the StartLine number of the range passed in
/// at the point of first generation.
///
/// This type may be accessed concurrently, though in practice it is only used from the compilation thread.
/// It is made concurrency-safe since a global instance of the type is allocated in tast.fs, and it is good
/// policy to make all globally-allocated objects concurrency safe in case future versions of the compiler
/// are used to host multiple concurrent instances of compilation.
type NiceNameGenerator() =
let basicNameCounts = ConcurrentDictionary<struct (string * int), int ref>(max Environment.ProcessorCount 1, 127)
// Cache this as a delegate.
let basicNameCountsAddDelegate = Func<struct (string * int), int ref>(fun _ -> ref 0)
let incrementBucket basicName (fileIndex: int) =
let key = struct (basicName, fileIndex)
let countCell = basicNameCounts.GetOrAdd(key, basicNameCountsAddDelegate)
Interlocked.Increment(countCell)
let increment basicName (m: range) = incrementBucket basicName m.FileIndex
let mkName basicName (m: range) count =
CompilerGeneratedNameSuffix basicName (string m.StartLine + (match (count - 1) with 0 -> "" | n -> "-" + string n))
member _.FreshCompilerGeneratedNameOfBasicName (basicName, m: range) =
let count = increment basicName m
mkName basicName m count
member this.FreshCompilerGeneratedName (name, m: range) =
this.FreshCompilerGeneratedNameOfBasicName (GetBasicNameOfPossibleCompilerGeneratedName name, m)
member _.FreshCompilerGeneratedNameInScope (scopeFileIndex: int, name: string, m: range) =
let basicName = GetBasicNameOfPossibleCompilerGeneratedName name
let count = incrementBucket basicName scopeFileIndex
mkName basicName m count
/// Reset the per-(basicName, file) occurrence counters so a subsequent codegen run assigns the
/// same compiler-generated occurrence names a fresh process would. Callers must ensure no
/// concurrent codegen is using this generator when resetting.
member _.ResetCompilerGeneratedNameState() = basicNameCounts.Clear()
/// Generates compiler-generated names marked up with a source code location, but if given the same unique value then
/// return precisely the same name. Each name generated also includes the StartLine number of the range passed in
/// at the point of first generation.
///
/// This type may be accessed concurrently, though in practice it is only used from the compilation thread.
/// It is made concurrency-safe since a global instance of the type is allocated in tast.fs.
type StableNiceNameGenerator() =
let niceNames = ConcurrentDictionary<string * int64, Lazy<string>>(max Environment.ProcessorCount 1, 127)
let innerGenerator = NiceNameGenerator()
member x.GetUniqueCompilerGeneratedName (name, m: range, uniq) =
let basicName = GetBasicNameOfPossibleCompilerGeneratedName name
let key = basicName, uniq
niceNames.GetOrAddLazy(key, fun (basicName, _) -> innerGenerator.FreshCompilerGeneratedNameOfBasicName(basicName, m))
/// Reset the stable-name cache and inner occurrence counters, so both the cached stable names and
/// the underlying occurrence counters are cleared. See NiceNameGenerator.ResetCompilerGeneratedNameState.
member _.ResetCompilerGeneratedNameState() =
niceNames.Clear()
innerGenerator.ResetCompilerGeneratedNameState()
[<Sealed>]
type PerFileNamingScope internal (nng: NiceNameGenerator, fileIndex: int) =
member _.Fresh (name: string, m: range) =
nng.FreshCompilerGeneratedNameInScope(fileIndex, name, m)
type internal CompilerGlobalState () =
/// A global generator of compiler generated names
let globalNng = NiceNameGenerator()
/// A global generator of stable compiler generated names
let globalStableNameGenerator = StableNiceNameGenerator ()
/// A name generator used by IlxGen for static fields, some generated arguments and other things.
let ilxgenGlobalNng = NiceNameGenerator ()
member _.NiceNameGenerator = globalNng
member _.StableNameGenerator = globalStableNameGenerator
member _.IlxGenNiceNameGenerator = ilxgenGlobalNng
member _.NewFileScope (fileRange: range) =
PerFileNamingScope(globalNng, fileRange.FileIndex)
/// Reset all compiler-generated-name occurrence counters on this state, so successive in-process
/// codegen runs over the same source produce identical generated names (a fresh-process layout).
/// Callers must ensure no compilation is concurrently generating names (quiescence). Needed by
/// Edit-and-Continue style scenarios that re-emit from a warm checker.
member _.ResetCompilerGeneratedNameState() =
globalNng.ResetCompilerGeneratedNameState()
globalStableNameGenerator.ResetCompilerGeneratedNameState()
ilxgenGlobalNng.ResetCompilerGeneratedNameState()
/// Unique name generator for stamps attached to lambdas and object expressions
type Unique = int64
//++GLOBAL MUTABLE STATE (concurrency-safe)
let mutable private uniqueCount = 0L
let newUnique() = Interlocked.Increment &uniqueCount
/// Unique name generator for stamps attached to to val_specs, tycon_specs etc.
//++GLOBAL MUTABLE STATE (concurrency-safe)
let mutable private stampCount = 0L
let newStamp() =
let stamp = Interlocked.Increment &stampCount
stamp