Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Start the wire up
  • Loading branch information
KevinRansom committed May 9, 2019
commit ca080c403a2d7088b225f0221e24d55c1b5de151
3 changes: 3 additions & 0 deletions fcs/FSharp.Compiler.Service/FSharp.Compiler.Service.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,9 @@
<Compile Include="$(FSharpSourcesRoot)/fsharp/QuotationPickler.fs">
<Link>TypedAST/QuotationPickler.fs</Link>
</Compile>
<Compile Include="$(FSharpSourcesRoot)/fsharp/CompilerGlobalState.fs">
<Link>TypedAST/CompilerGlobalState.fs</Link>
</Compile>
<Compile Include="$(FSharpSourcesRoot)/fsharp/tast.fs">
<Link>TypedAST/tast.fs</Link>
</Compile>
Expand Down
12 changes: 6 additions & 6 deletions src/fsharp/CompileOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4639,13 +4639,13 @@ type TcImports(tcConfigP: TcConfigProvider, initialResolutions: TcAssemblyResolu
match scoref with
| ILScopeRef.Assembly aref -> Some aref
| ILScopeRef.Local | ILScopeRef.Module _ -> error(InternalError("not ILScopeRef.Assembly", rangeStartup)))
fslibCcuInfo.FSharpViewOfMetadata
fslibCcuInfo.FSharpViewOfMetadata

// OK, now we have both mscorlib.dll and FSharp.Core.dll we can create TcGlobals
let tcGlobals = TcGlobals(tcConfig.compilingFslib, ilGlobals, fslibCcu,
tcConfig.implicitIncludeDir, tcConfig.mlCompatibility,
tcConfig.isInteractive, tryFindSysTypeCcu, tcConfig.emitDebugInfoInQuotations,
tcConfig.noDebugData, tcConfig.pathMap)
let tcGlobals = TcGlobals(tcConfig.compilingFslib, ilGlobals, fslibCcu,
tcConfig.implicitIncludeDir, tcConfig.mlCompatibility,
tcConfig.isInteractive, tryFindSysTypeCcu, tcConfig.emitDebugInfoInQuotations,
tcConfig.noDebugData, tcConfig.pathMap)

#if DEBUG
// the global_g reference cell is used only for debug printing
Expand Down
4 changes: 2 additions & 2 deletions src/fsharp/CompileOps.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ val GetInitialTcEnv: assemblyName: string * range * TcConfig * TcImports * TcGlo
[<Sealed>]
/// Represents the incremental type checking state for a set of inputs
type TcState =
member NiceNameGenerator: Ast.NiceNameGenerator
member NiceNameGenerator: NiceNameGenerator

/// The CcuThunk for the current assembly being checked
member Ccu: CcuThunk
Expand All @@ -729,7 +729,7 @@ type TcState =

/// Get the initial type checking state for a set of inputs
val GetInitialTcState:
range * string * TcConfig * TcGlobals * TcImports * Ast.NiceNameGenerator * TcEnv -> TcState
range * string * TcConfig * TcGlobals * TcImports * NiceNameGenerator * TcEnv -> TcState

/// Check one input, returned as an Eventually computation
val TypeCheckOneInputEventually :
Expand Down
96 changes: 96 additions & 0 deletions src/fsharp/CompilerGlobalState.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// 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.

namespace FSharp.Compiler

open System.Collections.Generic
open FSharp.Compiler.AbstractIL
open FSharp.Compiler.Range
open FSharp.Compiler.PrettyNaming


/// 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 lockObj = obj()
let basicNameCounts = new Dictionary<string, int>(100)

member x.FreshCompilerGeneratedName (name, m: range) =
lock lockObj (fun () ->
let basicName = GetBasicNameOfPossibleCompilerGeneratedName name
let n =
match basicNameCounts.TryGetValue basicName with
| true, count -> count
| _ -> 0
let nm = CompilerGeneratedNameSuffix basicName (string m.StartLine + (match n with 0 -> "" | n -> "-" + string n))
basicNameCounts.[basicName] <- n + 1
nm)

member x.Reset () =
lock lockObj (fun () ->
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 lockObj = obj()

let names = new Dictionary<(string * int64), string>(100)
let basicNameCounts = new Dictionary<string, int>(100)

member x.GetUniqueCompilerGeneratedName (name, m: range, uniq) =
lock lockObj (fun () ->
let basicName = GetBasicNameOfPossibleCompilerGeneratedName name
let key = basicName, uniq
match names.TryGetValue key with
| true, nm -> nm
| _ ->
let n =
match basicNameCounts.TryGetValue basicName with
| true, c -> c
| _ -> 0
let nm = CompilerGeneratedNameSuffix basicName (string m.StartLine + (match n with 0 -> "" | n -> "-" + string n))
names.[key] <- nm
basicNameCounts.[basicName] <- n + 1
nm
)

member x.Reset () =
lock lockObj (fun () ->
basicNameCounts.Clear()
names.Clear()
)

type internal CompilerGlobalState () =
/// A global generator of compiler generated names
// ++GLOBAL MUTABLE STATE (concurrency safe by locking inside NiceNameGenerator)
let globalNng = NiceNameGenerator()


/// A global generator of stable compiler generated names
// MUTABLE STATE (concurrency safe by locking inside StableNiceNameGenerator)
let globalStableNameGenerator = StableNiceNameGenerator ()

/// A name generator used by IlxGen for static fields, some generated arguments and other things.
/// REVIEW: this will mean the hosted compiler service is not deterministic. We should at least create a new one
/// of these for each compilation.
let ilxgenGlobalNng = NiceNameGenerator ()

member __.NiceNameGenerator = globalNng

member __.StableNameGenerator = globalStableNameGenerator

member __.IlxGenNiceNameGenerator = ilxgenGlobalNng
2 changes: 1 addition & 1 deletion src/fsharp/DetupleArgs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ let mkTransform g (f: Val) m tps x1Ntys rty (callPattern, tyfringes: (TType list
let tysrN = List.drop tyfringes.Length x1Ntys (* types for remaining args *)
let argtys = tys1r @ tysrN
let fCty = mkLambdaTy tps argtys rty
let transformedVal = mkLocalVal f.Range (globalNng.FreshCompilerGeneratedName (f.LogicalName, f.Range)) fCty topValInfo
let transformedVal = mkLocalVal f.Range (g.CompilerGlobalState.NiceNameGenerator.FreshCompilerGeneratedName (f.LogicalName, f.Range)) fCty topValInfo
{ transformCallPattern = callPattern
transformedFormals = transformedFormals
transformedVal = transformedVal }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,9 @@
<Compile Include="..\QuotationPickler.fs">
<Link>TypedAST\QuotationPickler.fs</Link>
</Compile>
<Compile Include="..\CompilerGlobalState.fs">
<Link>TypedAST\CompilerGlobalState.fs</Link>
</Compile>
<Compile Include="..\tast.fs">
<Link>TypedAST\tast.fs</Link>
</Compile>
Expand Down
26 changes: 10 additions & 16 deletions src/fsharp/IlxGen.fs
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,6 @@ let ChooseFreeVarNames takenNames ts =
let ts, _names = List.mapFold chooseName names tns
ts

/// +++GLOBAL STATE: a name generator used by IlxGen for static fields, some generated arguments and other things.
/// REVIEW: this will mean the hosted compiler service is not deterministic. We should at least create a new one
/// of these for each compilation.
let ilxgenGlobalNng = NiceNameGenerator ()

/// We can't tailcall to methods taking byrefs. This helper helps search for them
let IsILTypeByref = function ILType.Byref _ -> true | _ -> false

Expand Down Expand Up @@ -653,7 +648,7 @@ let GenFieldSpecForStaticField (isInteractive, g, ilContainerTy, vspec: Val, nm,
let fieldName = if isInteractive then CompilerGeneratedName fieldName else fieldName
mkILFieldSpecInTy (ilContainerTy, fieldName, ilTy)
else
let fieldName = ilxgenGlobalNng.FreshCompilerGeneratedName (nm, m)
let fieldName = g.CompilerGlobalState.IlxGenNiceNameGenerator.FreshCompilerGeneratedName (nm, m)
let ilFieldContainerTy = mkILTyForCompLoc (CompLocForInitClass cloc)
mkILFieldSpecInTy (ilFieldContainerTy, fieldName, ilTy)

Expand Down Expand Up @@ -3059,7 +3054,7 @@ and GenApp cenv cgbuf eenv (f, fty, tyargs, args, m) sequel =
// Only save arguments that have effects
if Optimizer.ExprHasEffect g laterArg then
let ilTy = laterArg |> tyOfExpr g |> GenType cenv.amap m eenv.tyenv
let locName = ilxgenGlobalNng.FreshCompilerGeneratedName ("arg", m), ilTy, false
let locName = cenv.g.CompilerGlobalState.IlxGenNiceNameGenerator.FreshCompilerGeneratedName ("arg", m), ilTy, false
let loc, _realloc, eenv = AllocLocal cenv cgbuf eenv true locName scopeMarks
GenExpr cenv cgbuf eenv SPSuppress laterArg Continue
EmitSetLocal cgbuf loc
Expand Down Expand Up @@ -3222,7 +3217,7 @@ and GenTry cenv cgbuf eenv scopeMarks (e1, m, resty, spTry) =
let ilResultTy = GenType cenv.amap m eenvinner.tyenv resty

let whereToSave, _realloc, eenvinner =
AllocLocal cenv cgbuf eenvinner true (ilxgenGlobalNng.FreshCompilerGeneratedName ("tryres", m), ilResultTy, false) (startTryMark, endTryMark)
AllocLocal cenv cgbuf eenvinner true (cenv.g.CompilerGlobalState.IlxGenNiceNameGenerator.FreshCompilerGeneratedName ("tryres", m), ilResultTy, false) (startTryMark, endTryMark)

// Generate the body of the try. In the normal case (SequencePointAtTry) we generate a sequence point
// both on the 'try' keyword and on the start of the expression in the 'try'. For inlined code and
Expand Down Expand Up @@ -3386,7 +3381,7 @@ and GenForLoop cenv cgbuf eenv (spFor, v, e1, dir, e2, loopBody, m) sequel =

let finishIdx, eenvinner =
if isFSharpStyle then
let v, _realloc, eenvinner = AllocLocal cenv cgbuf eenvinner true (ilxgenGlobalNng.FreshCompilerGeneratedName ("endLoop", m), g.ilg.typ_Int32, false) (start, finish)
let v, _realloc, eenvinner = AllocLocal cenv cgbuf eenvinner true (cenv.g.CompilerGlobalState.IlxGenNiceNameGenerator.FreshCompilerGeneratedName ("endLoop", m), g.ilg.typ_Int32, false) (start, finish)
v, eenvinner
else
-1, eenvinner
Expand Down Expand Up @@ -3842,7 +3837,7 @@ and GenDefaultValue cenv cgbuf eenv (ty, m) =
| _ ->
let ilTy = GenType cenv.amap m eenv.tyenv ty
LocalScope "ilzero" cgbuf (fun scopeMarks ->
let locIdx, realloc, _ = AllocLocal cenv cgbuf eenv true (ilxgenGlobalNng.FreshCompilerGeneratedName ("default", m), ilTy, false) scopeMarks
let locIdx, realloc, _ = AllocLocal cenv cgbuf eenv true (cenv.g.CompilerGlobalState.IlxGenNiceNameGenerator.FreshCompilerGeneratedName ("default", m), ilTy, false) scopeMarks
// "initobj" (Generated by EmitInitLocal) doesn't work on byref types
// But ilzero(&ty) only gets generated in the built-in get-address function so
// we can just rely on zeroinit of all IL locals.
Expand Down Expand Up @@ -4348,7 +4343,7 @@ and GetIlxClosureFreeVars cenv m selfv eenvouter takenNames expr =
// FSharp 1.0 bug 3404: System.Reflection doesn't like '.' and '`' in type names
let basenameSafeForUseAsTypename = CleanUpGeneratedTypeName basename
let suffixmark = expr.Range
let cloName = globalStableNameGenerator.GetUniqueCompilerGeneratedName(basenameSafeForUseAsTypename, suffixmark, uniq)
let cloName = g.CompilerGlobalState.StableNameGenerator.GetUniqueCompilerGeneratedName(basenameSafeForUseAsTypename, suffixmark, uniq)
NestedTypeRefForCompLoc eenvouter.cloc cloName

// Collect the free variables of the closure
Expand Down Expand Up @@ -5492,7 +5487,7 @@ and GenParams cenv eenv (mspec: ILMethodSpec) (attribs: ArgReprInfo list) method
(Set.empty, List.zip methodArgTys argInfosAndTypes)
||> List.mapFold (fun takenNames (methodArgTy, ((ilArgTy, topArgInfo), implValOpt)) ->
let inFlag, outFlag, optionalFlag, defaultParamValue, Marshal, attribs = GenParamAttribs cenv methodArgTy topArgInfo.Attribs

let idOpt = (match topArgInfo.Name with
| Some v -> Some v
| None -> match implValOpt with
Expand All @@ -5502,14 +5497,13 @@ and GenParams cenv eenv (mspec: ILMethodSpec) (attribs: ArgReprInfo list) method
let nmOpt, takenNames =
match idOpt with
| Some id ->
let nm = if takenNames.Contains(id.idText) then globalNng.FreshCompilerGeneratedName (id.idText, id.idRange) else id.idText
let nm = if takenNames.Contains(id.idText) then cenv.g.CompilerGlobalState.NiceNameGenerator.FreshCompilerGeneratedName (id.idText, id.idRange) else id.idText
Some nm, takenNames.Add nm
| None ->
None, takenNames


let ilAttribs = GenAttrs cenv eenv attribs

let ilAttribs =
match GenReadOnlyAttributeIfNecessary g methodArgTy with
| Some attr -> ilAttribs @ [attr]
Expand Down Expand Up @@ -6161,7 +6155,7 @@ and EmitSaveStack cenv cgbuf eenv m scopeMarks =
let savedStack = (cgbuf.GetCurrentStack())
let savedStackLocals, eenvinner =
(eenv, savedStack) ||> List.mapFold (fun eenv ty ->
let idx, _realloc, eenv = AllocLocal cenv cgbuf eenv true (ilxgenGlobalNng.FreshCompilerGeneratedName ("spill", m), ty, false) scopeMarks
let idx, _realloc, eenv = AllocLocal cenv cgbuf eenv true (cenv.g.CompilerGlobalState.IlxGenNiceNameGenerator.FreshCompilerGeneratedName ("spill", m), ty, false) scopeMarks
idx, eenv)
List.iter (EmitSetLocal cgbuf) savedStackLocals
cgbuf.AssertEmptyStack()
Expand Down
7 changes: 2 additions & 5 deletions src/fsharp/TastOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -8823,8 +8823,8 @@ let DetectAndOptimizeForExpression g option expr =
// let elem = str.[idx]
// body elem

let strVar, strExpr = mkCompGenLocal mEnumExpr "str" enumerableTy
let idxVar, idxExpr = mkCompGenLocal elemVar.Range "idx" g.int32_ty
let strVar, strExpr = mkCompGenLocal g mEnumExpr "str" enumerableTy
let idxVar, idxExpr = mkCompGenLocal g elemVar.Range "idx" g.int32_ty

let lengthExpr = mkGetStringLength g mForLoop strExpr
let charExpr = mkGetStringChar g mForLoop strExpr idxExpr
Expand Down Expand Up @@ -8897,13 +8897,10 @@ let BindUnitVars g (mvs: Val list, paramInfos: ArgReprInfo list, body) =
[], mkLet NoSequencePointAtInvisibleBinding v.Range v (mkUnit g v.Range) body
| _ -> mvs, body


let isThreadOrContextStatic g attrs =
HasFSharpAttributeOpt g g.attrib_ThreadStaticAttribute attrs ||
HasFSharpAttributeOpt g g.attrib_ContextStaticAttribute attrs

let mkUnitDelayLambda (g: TcGlobals) m e =
let uv, _ = mkCompGenLocal m "unitVar" g.unit_ty
mkLambda m uv (e, tyOfExpr g e)


2 changes: 1 addition & 1 deletion src/fsharp/TastOps.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ val mkCompGenLet : range -> Val -> Expr -> Expr -> Expr

/// Make a let-expression that locally binds a compiler-generated value to an expression, where the expression
/// is returned by the given continuation. Compiler-generated bindings do not give rise to a sequence point in debugging.
val mkCompGenLetIn: range -> string -> TType -> Expr -> (Val * Expr -> Expr) -> Expr
val mkCompGenLetIn: TcGlobals -> range -> string -> TType -> Expr -> (Val * Expr -> Expr) -> Expr

/// Make a let-expression that locally binds a value to an expression in an "invisible" way.
/// Invisible bindings are not given a sequence point and should not have side effects.
Expand Down
2 changes: 1 addition & 1 deletion src/fsharp/TastPickle.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ val internal u_ty : unpickler<TType>
val internal unpickleCcuInfo : ReaderState -> PickledCcuInfo

/// Deserialize an arbitrary object which may have holes referring to other compilation units
val internal unpickleObjWithDanglingCcus : file:string -> viewedScope:ILScopeRef -> ilModule:ILModuleDef option -> ('T unpickler) -> byte[] -> PickledDataWithReferences<'T>
val internal unpickleObjWithDanglingCcus : file:string -> viewedScope:ILScopeRef -> ilModule:ILModuleDef option -> ('T unpickler) -> byte[] -> PickledDataWithReferences<'T>



Loading