@@ -8,6 +8,7 @@ namespace Microsoft.FSharp.Core
8
8
9
9
open System
10
10
open System.Reflection
11
+ open System.Threading
11
12
open Microsoft.FSharp .Core .LanguagePrimitives .IntrinsicOperators
12
13
open Microsoft.FSharp .Collections
13
14
@@ -390,44 +391,52 @@ module internal Impl =
390
391
// Which field holds the nested tuple?
391
392
let tupleEncField = maxTuple-1
392
393
393
- let rec mkTupleType isStruct ( asm : Assembly ) ( tys : Type []) =
394
- let tupleFullName n =
395
- if isStruct then
396
- match n with
397
- | 1 -> " System.ValueTuple`1"
398
- | 2 -> " System.ValueTuple`2"
399
- | 3 -> " System.ValueTuple`3"
400
- | 4 -> " System.ValueTuple`4"
401
- | 5 -> " System.ValueTuple`5"
402
- | 6 -> " System.ValueTuple`6"
403
- | 7 -> " System.ValueTuple`7"
404
- | 8 -> " System.ValueTuple`8"
405
- | _ -> " System.ValueTuple"
406
- else
394
+ let dictionaryLock = obj()
395
+ let refTupleTypes = System.Collections.Generic.Dictionary< Assembly, Type[]>()
396
+ let valueTupleTypes = System.Collections.Generic.Dictionary< Assembly, Type[]>()
397
+
398
+ let rec mkTupleType isStruct ( asm : Assembly ) ( tys : Type []) =
399
+ let table =
400
+ let makeIt n =
401
+ let tupleFullName n =
402
+ let structOffset = if isStruct then 9 else 0
403
+ let index = n - 1 + structOffset
404
+ tupleNames.[ index]
405
+
407
406
match n with
408
- | 1 -> " System.Tuple`1"
409
- | 2 -> " System.Tuple`2"
410
- | 3 -> " System.Tuple`3"
411
- | 4 -> " System.Tuple`4"
412
- | 5 -> " System.Tuple`5"
413
- | 6 -> " System.Tuple`6"
414
- | 7 -> " System.Tuple`7"
415
- | 8 -> " System.Tuple`8"
416
- | _ -> " System.Tuple"
417
-
418
- match tys.Length with
419
- | 1 -> asm.GetType( tupleFullName 1 ) .MakeGenericType( tys)
420
- | 2 -> asm.GetType( tupleFullName 2 ) .MakeGenericType( tys)
421
- | 3 -> asm.GetType( tupleFullName 3 ) .MakeGenericType( tys)
422
- | 4 -> asm.GetType( tupleFullName 4 ) .MakeGenericType( tys)
423
- | 5 -> asm.GetType( tupleFullName 5 ) .MakeGenericType( tys)
424
- | 6 -> asm.GetType( tupleFullName 6 ) .MakeGenericType( tys)
425
- | 7 -> asm.GetType( tupleFullName 7 ) .MakeGenericType( tys)
426
- | n when n >= maxTuple ->
407
+ | 1 -> asm.GetType( tupleFullName 1 )
408
+ | 2 -> asm.GetType( tupleFullName 2 )
409
+ | 3 -> asm.GetType( tupleFullName 3 )
410
+ | 4 -> asm.GetType( tupleFullName 4 )
411
+ | 5 -> asm.GetType( tupleFullName 5 )
412
+ | 6 -> asm.GetType( tupleFullName 6 )
413
+ | 7 -> asm.GetType( tupleFullName 7 )
414
+ | 8 -> asm.GetType( tupleFullName 8 )
415
+ | _ -> invalidArg " tys" ( SR.GetString( SR.invalidTupleTypes))
416
+
417
+ let tables = if isStruct then valueTupleTypes else refTupleTypes
418
+ match tables.TryGetValue( asm) with
419
+ | false , _ ->
420
+ let a = ref ( Array.init< Type> 8 ( fun i -> makeIt ( i + 1 )))
421
+ lock dictionaryLock ( fun () -> match tables.TryGetValue( asm) with
422
+ | true , t -> a := t
423
+ | false , _ -> tables.Add( asm, ! a))
424
+ ! a
425
+ | true , t -> t
426
+
427
+ match tys.Length with
428
+ | 1 -> table.[ 0 ]. MakeGenericType( tys)
429
+ | 2 -> table.[ 1 ]. MakeGenericType( tys)
430
+ | 3 -> table.[ 2 ]. MakeGenericType( tys)
431
+ | 4 -> table.[ 3 ]. MakeGenericType( tys)
432
+ | 5 -> table.[ 4 ]. MakeGenericType( tys)
433
+ | 6 -> table.[ 5 ]. MakeGenericType( tys)
434
+ | 7 -> table.[ 6 ]. MakeGenericType( tys)
435
+ | n when n >= maxTuple ->
427
436
let tysA = tys.[ 0 .. tupleEncField-1 ]
428
437
let tysB = tys.[ maxTuple-1 ..]
429
438
let tyB = mkTupleType isStruct asm tysB
430
- asm.GetType ( tupleFullName 8 ) .MakeGenericType( Array.append tysA [| tyB |])
439
+ table .[ 7 ] . MakeGenericType( Array.append tysA [| tyB |])
431
440
| _ -> invalidArg " tys" ( SR.GetString( SR.invalidTupleTypes))
432
441
433
442
let rec getTupleTypeInfo ( typ : Type ) =
@@ -774,13 +783,13 @@ type FSharpType =
774
783
invalidArg " types" ( SR.GetString( SR.nullsNotAllowedInArray))
775
784
Impl.mkTupleType false asm types
776
785
777
- static member MakeTupleTypeWithAssembly ( asm : Assembly ) ( types : Type []) =
786
+ static member MakeTupleType ( asm : Assembly , types : Type []) =
778
787
Impl.checkNonNull " types" types
779
788
if types |> Array.exists ( function null -> true | _ -> false ) then
780
789
invalidArg " types" ( SR.GetString( SR.nullsNotAllowedInArray))
781
790
Impl.mkTupleType false asm types
782
791
783
- static member MakeStructTupleTypeWithAssembly ( asm : Assembly ) ( types : Type []) =
792
+ static member MakeValueTupleType ( asm : Assembly , types : Type []) =
784
793
Impl.checkNonNull " types" types
785
794
if types |> Array.exists ( function null -> true | _ -> false ) then
786
795
invalidArg " types" ( SR.GetString( SR.nullsNotAllowedInArray))
@@ -875,7 +884,7 @@ type FSharpValue =
875
884
let ( f : ( obj -> obj ) -> obj ) = downcast o
876
885
f implementation
877
886
878
- static member MakeTuple ( tupleElements : obj [], tupleType : Type ) =
887
+ static member MakeTuple ( tupleElements : obj [], tupleType : Type ) =
879
888
Impl.checkNonNull " tupleElements" tupleElements
880
889
Impl.checkTupleType( " tupleType" , tupleType)
881
890
Impl.getTupleConstructor tupleType tupleElements
0 commit comments