Skip to content

Commit be8ec25

Browse files
authored
Merge pull request #9262 from dotnet/merges/master-to-release/dev16.7
Merge master to release/dev16.7
2 parents 6f4968d + 596f3d7 commit be8ec25

18 files changed

Lines changed: 632 additions & 320 deletions

src/fsharp/IlxGen.fs

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4396,7 +4396,15 @@ and GenClosureTypeDefs cenv (tref: ILTypeRef, ilGenParams, attrs, ilCloAllFreeVa
43964396

43974397
let tdefs = EraseClosures.convIlxClosureDef g.ilxPubCloEnv tref.Enclosing tdef cloInfo
43984398
tdefs
4399-
4399+
4400+
and GenStaticClosureTypeDefs cenv (tref: ILTypeRef, ilGenParams, attrs, ilCloAllFreeVars, ilCloLambdas, ilCtorBody, mdefs, mimpls, ext, ilIntfTys) =
4401+
let tdefs = GenClosureTypeDefs cenv (tref, ilGenParams, attrs, ilCloAllFreeVars, ilCloLambdas, ilCtorBody, mdefs, mimpls, ext, ilIntfTys)
4402+
4403+
// Apply the abstract attribute, turning the sealed class into abstract sealed (i.e. static class).
4404+
// Remove the redundant constructor.
4405+
tdefs |> List.map (fun td -> td.WithAbstract(true)
4406+
.With(methods= mkILMethodsFromArray (td.Methods.AsArray |> Array.filter (fun m -> not m.IsConstructor))))
4407+
44004408
and GenGenericParams cenv eenv tps =
44014409
tps |> DropErasedTypars |> List.map (GenGenericParam cenv eenv)
44024410

@@ -4781,54 +4789,72 @@ and GenDelegateExpr cenv cgbuf eenvouter expr (TObjExprMethod((TSlotSig(_, deleg
47814789
false
47824790
with _ ->
47834791
false
4784-
4792+
47854793
// Work out the free type variables for the morphing thunk
47864794
let takenNames = List.map nameOfVal tmvs
47874795
let (cloAttribs, _, _, cloFreeTyvars, cloFreeVars, ilDelegeeTypeRef, ilCloFreeVars, eenvinner) =
47884796
GetIlxClosureFreeVars cenv m [] eenvouter takenNames expr
47894797
let ilDelegeeGenericParams = GenGenericParams cenv eenvinner cloFreeTyvars
47904798
let ilDelegeeGenericActualsInner = mkILFormalGenericArgs 0 ilDelegeeGenericParams
47914799

4800+
// When creating a delegate that does not capture any variables, we can instead create a static closure and directly reference the method.
4801+
let useStaticClosure = cloFreeVars.IsEmpty
4802+
47924803
// Create a new closure class with a single "delegee" method that implements the delegate.
47934804
let delegeeMethName = "Invoke"
47944805
let ilDelegeeTyInner = mkILBoxedTy ilDelegeeTypeRef ilDelegeeGenericActualsInner
4795-
4806+
47964807
let envForDelegeeUnderTypars = AddTyparsToEnv methTyparsOfOverridingMethod eenvinner
4797-
4798-
let numthis = 1
4808+
4809+
let numthis = if useStaticClosure then 0 else 1
47994810
let tmvs, body = BindUnitVars g (tmvs, List.replicate (List.concat slotsig.FormalParams).Length ValReprInfo.unnamedTopArg1, body)
4800-
4811+
48014812
// The slot sig contains a formal instantiation. When creating delegates we're only
48024813
// interested in the actual instantiation since we don't have to emit a method impl.
48034814
let ilDelegeeParams, ilDelegeeRet = GenActualSlotsig m cenv envForDelegeeUnderTypars slotsig methTyparsOfOverridingMethod tmvs
4804-
4815+
48054816
let envForDelegeeMeth = AddStorageForLocalVals g (List.mapi (fun i v -> (v, Arg (i+numthis))) tmvs) envForDelegeeUnderTypars
48064817
let ilMethodBody = CodeGenMethodForExpr cenv cgbuf.mgbuf (SPAlways, [], delegeeMethName, envForDelegeeMeth, 1, body, (if slotSigHasVoidReturnTy slotsig then discardAndReturnVoid else Return))
48074818
let delegeeInvokeMeth =
4808-
mkILNonGenericInstanceMethod
4809-
(delegeeMethName, ILMemberAccess.Assembly,
4819+
(if useStaticClosure then mkILNonGenericStaticMethod else mkILNonGenericInstanceMethod)
4820+
(delegeeMethName,
4821+
ILMemberAccess.Assembly,
48104822
ilDelegeeParams,
48114823
ilDelegeeRet,
48124824
MethodBody.IL ilMethodBody)
48134825
let delegeeCtorMeth = mkILSimpleStorageCtor(None, Some g.ilg.typ_Object.TypeSpec, ilDelegeeTyInner, [], [], ILMemberAccess.Assembly)
48144826
let ilCtorBody = delegeeCtorMeth.MethodBody
4815-
4827+
48164828
let ilCloLambdas = Lambdas_return ilCtxtDelTy
48174829
let ilAttribs = GenAttrs cenv eenvinner cloAttribs
4818-
let cloTypeDefs = GenClosureTypeDefs cenv (ilDelegeeTypeRef, ilDelegeeGenericParams, ilAttribs, ilCloFreeVars, ilCloLambdas, ilCtorBody, [delegeeInvokeMeth], [], g.ilg.typ_Object, [])
4830+
let cloTypeDefs =
4831+
(if useStaticClosure then GenStaticClosureTypeDefs else GenClosureTypeDefs)
4832+
cenv (ilDelegeeTypeRef, ilDelegeeGenericParams, ilAttribs, ilCloFreeVars, ilCloLambdas, ilCtorBody, [delegeeInvokeMeth], [], g.ilg.typ_Object, [])
48194833
for cloTypeDef in cloTypeDefs do
48204834
cgbuf.mgbuf.AddTypeDef(ilDelegeeTypeRef, cloTypeDef, false, false, None)
48214835
CountClosure()
48224836

4837+
// Push the constructor for the delegee
48234838
let ctxtGenericArgsForDelegee = GenGenericArgs m eenvouter.tyenv cloFreeTyvars
4824-
let ilxCloSpec = IlxClosureSpec.Create(IlxClosureRef(ilDelegeeTypeRef, ilCloLambdas, ilCloFreeVars), ctxtGenericArgsForDelegee)
4825-
GenGetLocalVals cenv cgbuf eenvouter m cloFreeVars
4826-
CG.EmitInstr cgbuf (pop ilCloFreeVars.Length) (Push [EraseClosures.mkTyOfLambdas g.ilxPubCloEnv ilCloLambdas]) (I_newobj (ilxCloSpec.Constructor, None))
4827-
4839+
if useStaticClosure then
4840+
GenUnit cenv eenvouter m cgbuf
4841+
else
4842+
let ilxCloSpec = IlxClosureSpec.Create(IlxClosureRef(ilDelegeeTypeRef, ilCloLambdas, ilCloFreeVars), ctxtGenericArgsForDelegee)
4843+
GenGetLocalVals cenv cgbuf eenvouter m cloFreeVars
4844+
CG.EmitInstr cgbuf (pop ilCloFreeVars.Length) (Push [EraseClosures.mkTyOfLambdas g.ilxPubCloEnv ilCloLambdas]) (I_newobj (ilxCloSpec.Constructor, None))
4845+
4846+
// Push the function pointer to the Invoke method of the delegee
48284847
let ilDelegeeTyOuter = mkILBoxedTy ilDelegeeTypeRef ctxtGenericArgsForDelegee
4829-
let ilDelegeeInvokeMethOuter = mkILNonGenericInstanceMethSpecInTy (ilDelegeeTyOuter, "Invoke", typesOfILParams ilDelegeeParams, ilDelegeeRet.Type)
4830-
let ilDelegeeCtorMethOuter = mkCtorMethSpecForDelegate g.ilg (ilCtxtDelTy, useUIntPtrForDelegateCtor)
4848+
let ilDelegeeInvokeMethOuter =
4849+
(if useStaticClosure then mkILNonGenericStaticMethSpecInTy else mkILNonGenericInstanceMethSpecInTy)
4850+
(ilDelegeeTyOuter,
4851+
"Invoke",
4852+
typesOfILParams ilDelegeeParams,
4853+
ilDelegeeRet.Type)
48314854
CG.EmitInstr cgbuf (pop 0) (Push [g.ilg.typ_IntPtr]) (I_ldftn ilDelegeeInvokeMethOuter)
4855+
4856+
// Instantiate the delegate
4857+
let ilDelegeeCtorMethOuter = mkCtorMethSpecForDelegate g.ilg (ilCtxtDelTy, useUIntPtrForDelegateCtor)
48324858
CG.EmitInstr cgbuf (pop 2) (Push [ilCtxtDelTy]) (I_newobj(ilDelegeeCtorMethOuter, None))
48334859
GenSequel cenv eenvouter.cloc cgbuf sequel
48344860

src/fsharp/fsi/fsi.fs

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,51 @@ type internal FsiDynamicCompiler
12851285

12861286
{ istate with boundValues = boundValues }, Completed itValue
12871287

1288+
let addCcusToIncrementalEnv istate ccuinfos =
1289+
let optEnv = List.fold (AddExternalCcuToOptimizationEnv tcGlobals) istate.optEnv ccuinfos
1290+
istate.ilxGenerator.AddExternalCcus (ccuinfos |> List.map (fun ccuinfo -> ccuinfo.FSharpViewOfMetadata))
1291+
{ istate with optEnv = optEnv }
1292+
1293+
let importReflectionType istate reflectionTy =
1294+
let tcImports = istate.tcImports
1295+
let tcGlobals = istate.tcGlobals
1296+
let amap = tcImports.GetImportMap()
1297+
1298+
let prevCcuinfos = tcImports.GetImportedAssemblies()
1299+
1300+
let rec import ccuinfos (ilTy: ILType) =
1301+
let ccuinfos, tinst =
1302+
(ilTy.GenericArgs, (ccuinfos, []))
1303+
||> List.foldBack (fun ilGenericArgTy (ccuInfos, tinst) ->
1304+
let ccuinfos2, ty = import ccuInfos ilGenericArgTy
1305+
(ccuinfos2 @ ccuinfos, ty :: tinst))
1306+
1307+
let ty = Import.ImportILType amap range0 tinst ilTy
1308+
let ccuinfos =
1309+
match tryTcrefOfAppTy tcGlobals ty with
1310+
| ValueSome tcref ->
1311+
match tcref.CompilationPath.ILScopeRef with
1312+
| ILScopeRef.Assembly aref ->
1313+
(tcImports.GetImportedAssemblies() |> List.find (fun x -> x.FSharpViewOfMetadata.AssemblyName = aref.Name)) :: ccuinfos
1314+
| _ ->
1315+
ccuinfos
1316+
| _ ->
1317+
ccuinfos
1318+
ccuinfos, ty
1319+
1320+
let ilTy = convertReflectionTypeToILType reflectionTy
1321+
1322+
if not (Import.CanImportILType amap range0 ilTy) then
1323+
invalidOp (sprintf "Unable to import type, %A." reflectionTy)
1324+
1325+
let ccuinfos, ty = import [] ilTy
1326+
let ccuinfos =
1327+
ccuinfos
1328+
|> List.distinctBy (fun x -> x.FSharpViewOfMetadata.AssemblyName)
1329+
|> List.filter (fun asm1 -> not (prevCcuinfos |> List.exists (fun asm2 -> asm2.FSharpViewOfMetadata.AssemblyName = asm1.FSharpViewOfMetadata.AssemblyName)))
1330+
// After we have successfully imported the type, then we can add newly resolved ccus to the env.
1331+
addCcusToIncrementalEnv istate ccuinfos, ty
1332+
12881333
member __.DynamicAssemblyName = assemblyName
12891334

12901335
member __.DynamicAssembly = (assemblyBuilder :> Assembly)
@@ -1381,10 +1426,8 @@ type internal FsiDynamicCompiler
13811426
with e ->
13821427
tcConfigB.RemoveReferencedAssemblyByPath(m,path)
13831428
reraise()
1384-
let optEnv = List.fold (AddExternalCcuToOptimizationEnv tcGlobals) istate.optEnv ccuinfos
1385-
istate.ilxGenerator.AddExternalCcus (ccuinfos |> List.map (fun ccuinfo -> ccuinfo.FSharpViewOfMetadata))
13861429
resolutions,
1387-
{ istate with tcState = tcState.NextStateAfterIncrementalFragment(tcEnv); optEnv = optEnv }
1430+
{ addCcusToIncrementalEnv istate ccuinfos with tcState = tcState.NextStateAfterIncrementalFragment(tcEnv) }
13881431

13891432

13901433
member __.EvalDependencyManagerTextFragment (packageManager:IDependencyManagerProvider,m,path: string) =
@@ -1522,37 +1565,6 @@ type internal FsiDynamicCompiler
15221565
| _ ->
15231566
None
15241567

1525-
member private this.ImportReflectionType (ctok, istate, reflectionTy) =
1526-
let amap = istate.tcImports.GetImportMap()
1527-
1528-
let resolveAssemblyRefOfILType istate (ilTy: ILType) =
1529-
let tcImports = istate.tcImports
1530-
1531-
if ilTy.IsNominal then
1532-
match ilTy.TypeRef.Scope with
1533-
| ILScopeRef.Assembly aref ->
1534-
// Simple name unification. If it fails, then try to resolve the assembly.
1535-
if tcImports.TryFindDllInfo(ctok, range0, aref.Name, lookupOnly = true).IsNone then
1536-
this.EvalRequireReference(ctok, istate, range0, aref.Name)
1537-
|> snd
1538-
else
1539-
istate
1540-
| _ ->
1541-
istate
1542-
else
1543-
istate
1544-
1545-
let rec import istate (ilTy: ILType) =
1546-
let istate = resolveAssemblyRefOfILType istate ilTy
1547-
let istate, tinst =
1548-
(ilTy.GenericArgs, (istate, []))
1549-
||> List.foldBack (fun ilGenericArgTy (istate, tinst) ->
1550-
let istate, ty = import istate ilGenericArgTy
1551-
(istate, ty :: tinst))
1552-
istate, Import.ImportILType amap range0 tinst ilTy
1553-
1554-
import istate (convertReflectionTypeToILType reflectionTy)
1555-
15561568
member this.AddBoundValue (ctok, errorLogger: ErrorLogger, istate, name: string, value: obj) =
15571569
try
15581570
match value with
@@ -1573,7 +1585,7 @@ type internal FsiDynamicCompiler
15731585
if PrettyNaming.IsCompilerGeneratedName name then
15741586
invalidArg "name" (FSComp.SR.lexhlpIdentifiersContainingAtSymbolReserved() |> snd)
15751587

1576-
let istate, ty = this.ImportReflectionType(ctok, istate, value.GetType())
1588+
let istate, ty = importReflectionType istate (value.GetType())
15771589
let amap = istate.tcImports.GetImportMap()
15781590

15791591
let i = nextFragmentId()

src/fsharp/import.fs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -287,16 +287,19 @@ let rec ImportProvidedType (env: ImportMap) (m: range) (* (tinst: TypeInst) *) (
287287
tcref, []
288288

289289
/// Adjust for the known primitive numeric types that accept units of measure.
290-
let tcref =
291-
if tyconRefEq g tcref g.system_Double_tcref && genericArgs.Length = 1 then g.pfloat_tcr
292-
elif tyconRefEq g tcref g.system_Single_tcref && genericArgs.Length = 1 then g.pfloat32_tcr
293-
elif tyconRefEq g tcref g.system_Decimal_tcref && genericArgs.Length = 1 then g.pdecimal_tcr
294-
elif tyconRefEq g tcref g.system_Int16_tcref && genericArgs.Length = 1 then g.pint16_tcr
295-
elif tyconRefEq g tcref g.system_Int32_tcref && genericArgs.Length = 1 then g.pint_tcr
296-
elif tyconRefEq g tcref g.system_Int64_tcref && genericArgs.Length = 1 then g.pint64_tcr
297-
elif tyconRefEq g tcref g.system_SByte_tcref && genericArgs.Length = 1 then g.pint8_tcr
298-
else tcref
299-
290+
let tcref =
291+
match genericArgs with
292+
| [_] ->
293+
if tyconRefEq g tcref g.system_Double_tcref then g.pfloat_tcr
294+
elif tyconRefEq g tcref g.system_Single_tcref then g.pfloat32_tcr
295+
elif tyconRefEq g tcref g.system_Decimal_tcref then g.pdecimal_tcr
296+
elif tyconRefEq g tcref g.system_Int16_tcref then g.pint16_tcr
297+
elif tyconRefEq g tcref g.system_Int32_tcref then g.pint_tcr
298+
elif tyconRefEq g tcref g.system_Int64_tcref then g.pint64_tcr
299+
elif tyconRefEq g tcref g.system_SByte_tcref then g.pint8_tcr
300+
else tcref
301+
| _ -> tcref
302+
300303
let tps = tcref.Typars m
301304
if tps.Length <> genericArgs.Length then
302305
error(Error(FSComp.SR.impInvalidNumberOfGenericArguments(tcref.CompiledName, tps.Length, genericArgs.Length), m))

0 commit comments

Comments
 (0)