@@ -389,147 +389,190 @@ module StructuralUtilities =
389389
390390[<Struct; NoComparison; RequireQualifiedAccess>]
391391type TypeToken =
392- | Stampof stamp : Stamp
393- | UCaseof name : string
394- | Nullnessof nullness : NullnessInfo
392+ | Stampof int
393+ | UCaseof int
394+ | Nullnessof int
395395| NullnessUnsolved
396- | TupInfoof b : bool
396+ | TupInfoof int
397397| Forallof int
398398| MeasureOne
399- | MeasureRationalof int * int
399+ | MeasureDenominatorof int
400+ | MeasureNumeratorof int
400401| Solvedof int
401402| Unsolvedof int
402403| Rigidof int
403404
404405type TypeStructure =
405406| Stableof TypeToken []
407+ // Unstable means that the type structure of a given TType may change because of constraint solving or Trace.Undo.
406408| Unstableof TypeToken []
407409| PossiblyInfinite
408410
409- type private EmitContext =
410- {
411- typarMap: System .Collections .Generic .Dictionary < Stamp , int >
412- emitNullness: bool
413- mutable stable: bool
414- }
411+ type private GenerationContext () =
412+ member val TyparMap = System.Collections.Generic.Dictionary< Stamp, int>( 4 )
413+ member val Tokens = ResizeArray< TypeToken>( 256 )
414+ member val EmitNullness = false with get, set
415+ member val Stable = true with get, set
415416
416- let private emitNullness env ( n : Nullness ) =
417- seq {
418- if env.emitNullnessthen
419- env.stable<- false //
417+ member this.Reset () =
418+ this.TyparMap.Clear()
419+ this.Tokens.Clear()
420+ this.EmitNullness<- false
421+ this.Stable<- true
420422
423+ let private context =
424+ new System.Threading.ThreadLocal< GenerationContext>( fun () -> GenerationContext())
425+
426+ let private getContext () =
427+ let ctx = context.Value
428+ ctx.Reset()
429+ ctx
430+
431+ let inline private encodeNullness ( n : NullnessInfo ) =
432+ match nwith
433+ | NullnessInfo.AmbivalentToNull-> 0
434+ | NullnessInfo.WithNull-> 1
435+ | NullnessInfo.WithoutNull-> 2
436+
437+ let private emitNullness ( ctx : GenerationContext ) ( n : Nullness ) =
438+ if ctx.EmitNullnessthen
439+ ctx.Stable<- false
440+
441+ let out = ctx.Tokens
442+
443+ if out.Count< 256 then
421444match n.TryEvaluate() with
422- | ValueSome k-> TypeToken.Nullness k
423- | ValueNone-> TypeToken.NullnessUnsolved
424- }
445+ | ValueSome k-> out.Add( TypeToken.Nullness( encodeNullness k))
446+ | ValueNone-> out.Add( TypeToken.NullnessUnsolved)
447+
448+ let inline private emitStamp ( ctx : GenerationContext ) ( stamp : Stamp ) =
449+ let out = ctx.Tokens
450+
451+ if out.Count< 256 then
452+ // Emit low 32 bits first
453+ let lo = int( stamp&&& 0xFFFFFFFF L)
454+ out.Add( TypeToken.Stamp lo)
455+ // If high 32 bits are non-zero, emit them as another token
456+ let hi64 = stamp>>> 32
457+
458+ if hi64<> 0 L&& out.Count< 256 then
459+ out.Add( TypeToken.Stamp( int hi64))
425460
426- let rec private emitMeasure ( m : Measure ) =
427- seq {
461+ let rec private emitMeasure ( ctx : GenerationContext ) ( m : Measure ) =
462+ let out = ctx.Tokens
463+
464+ if out.Count>= 256 then
465+ ()
466+ else
428467match mwith
429- | Measure.Var mv-> TypeToken.Stamp mv.Stamp
430- | Measure.Const( tcref, _) -> TypeToken.Stamp tcref.Stamp
468+ | Measure.Var mv-> emitStamp ctx mv.Stamp
469+ | Measure.Const( tcref, _) -> emitStamp ctx tcref.Stamp
431470| Measure.Prod( m1, m2, _) ->
432- yield ! emitMeasure m1
433- yield ! emitMeasure m2
434- | Measure.Inv m1-> yield ! emitMeasure m1
435- | Measure.One_ -> TypeToken.MeasureOne
471+ emitMeasure ctx m1
472+ emitMeasure ctx m2
473+ | Measure.Inv m1-> emitMeasure ctx m1
474+ | Measure.One_ -> out.Add ( TypeToken.MeasureOne)
436475| Measure.RationalPower( m1, r) ->
437- yield ! emitMeasure m1
438- TypeToken.MeasureRational( GetNumerator r, GetDenominator r)
439- }
476+ emitMeasure ctx m1
477+
478+ if out.Count< 256 then
479+ out.Add( TypeToken.MeasureNumerator( GetNumerator r))
480+ out.Add( TypeToken.MeasureDenominator( GetDenominator r))
481+
482+ let rec private emitTType ( ctx : GenerationContext ) ( ty : TType ) =
483+ let out = ctx.Tokens
440484
441- and private emitTType ( env : EmitContext ) ( ty : TType ) =
442- seq {
485+ if out.Count>= 256 then
486+ ()
487+ else
443488match tywith
444489| TType_ ucase( u, tinst) ->
445- TypeToken.Stamp u.TyconRef.Stamp
446- TypeToken.UCase u.CaseName
490+ emitStamp ctx u.TyconRef.Stamp
491+
492+ if out.Count< 256 then
493+ out.Add( TypeToken.UCase( hashText u.CaseName))
447494
448495for argin tinstdo
449- yield ! emitTTypeenv arg
496+ emitTTypectx arg
450497
451498| TType_ app( tcref, tinst, n) ->
452- TypeToken.Stamp tcref.Stamp
453- yield ! emitNullnessenv n
499+ emitStamp ctx tcref.Stamp
500+ emitNullnessctx n
454501
455502for argin tinstdo
456- yield ! emitTTypeenv arg
503+ emitTTypectx arg
457504
458505| TType_ anon( info, tys) ->
459- TypeToken.Stamp info.Stamp
506+ emitStamp ctx info.Stamp
460507
461508for argin tysdo
462- yield ! emitTTypeenv arg
509+ emitTTypectx arg
463510
464511| TType_ tuple( tupInfo, tys) ->
465- TypeToken.TupInfo( evalTupInfoIsStruct tupInfo)
512+ out.Add ( TypeToken.TupInfo( if evalTupInfoIsStruct tupInfothen 1 else 0 ) )
466513
467514for argin tysdo
468- yield ! emitTTypeenv arg
515+ emitTTypectx arg
469516
470517| TType_ forall( tps, tau) ->
471518for tpin tpsdo
472- env.typarMap .[ tp.Stamp] <- env.typarMap .Count
519+ ctx.TyparMap .[ tp.Stamp] <- ctx.TyparMap .Count
473520
474- TypeToken.Forall tps.Length
521+ out.Add ( TypeToken.Forall tps.Length)
475522
476- yield ! emitTTypeenv tau
523+ emitTTypectx tau
477524
478525| TType_ fun( d, r, n) ->
479- yield ! emitTTypeenv d
480- yield ! emitTTypeenv r
481- yield ! emitNullnessenv n
526+ emitTTypectx d
527+ emitTTypectx r
528+ emitNullnessctx n
482529
483530| TType_ var( r, n) ->
484- yield ! emitNullnessenv n
531+ emitNullnessctx n
485532
486533let typarId =
487- match env.typarMap .TryGetValue r.Stampwith
534+ match ctx.TyparMap .TryGetValue r.Stampwith
488535| true , idx-> idx
489536| _ ->
490- let idx = env.typarMap .Count
491- env.typarMap .[ r.Stamp] <- idx
537+ let idx = ctx.TyparMap .Count
538+ ctx.TyparMap .[ r.Stamp] <- idx
492539 idx
493540
494541// Solved may become unsolved, in case of Trace.Undo.
495- env.stable<- false
542+ if not r.IsFromErrorthen
543+ ctx.Stable<- false
496544
497545match r.Solutionwith
498- | Some ty-> yield ! emitTTypeenv ty
546+ | Some ty-> emitTTypectx ty
499547| None->
500- if r.Rigidity= TyparRigidity.Rigidthen
501- TypeToken.Rigid typarId
502- else
503- TypeToken.Unsolved typarId
504-
505- | TType_ measure m-> yield ! emitMeasure m
506- }
548+ if out.Count< 256 then
549+ if r.Rigidity= TyparRigidity.Rigidthen
550+ out.Add( TypeToken.Rigid typarId)
551+ else
552+ out.Add( TypeToken.Unsolved typarId)
507553
508- let private getTypeStructureOfStrippedType ( ty : TType ) =
554+ | TType _ measure m -> emitMeasure ctx m
509555
510- let env =
511- {
512- typarMap= System.Collections.Generic.Dictionary< Stamp, int>()
513- emitNullness= false
514- stable= true
515- }
556+ let private getTypeStructureOfStrippedTypeUncached ( ty : TType ) =
557+ let ctx = getContext()
558+ emitTType ctx ty
516559
517- let tokens = emitTType env ty |> Seq.truncate 256 |> Seq.toArray
560+ let out = ctx.Tokens
518561
519562// If the sequence got too long, just drop it, we could be dealing with an infinite type.
520- if tokens.Length = 256 then PossiblyInfinite
521- elif not env.stable then Unstable tokens
522- else Stable tokens
563+ if out.Count > =256 then PossiblyInfinite
564+ elif not ctx.Stable then Unstable( out.ToArray ())
565+ else Stable( out.ToArray ())
523566
524567// Speed up repeated calls by memoizing results for types that yield a stable structure.
525- let private memoize =
568+ let private getTypeStructureOfStrippedType =
526569 WeakMap.cacheConditionally
527570( function
528571| Stable_ -> true
529572| _ -> false )
530- getTypeStructureOfStrippedType
573+ getTypeStructureOfStrippedTypeUncached
531574
532575let tryGetTypeStructureOfStrippedType ty =
533- match memoize tywith
576+ match getTypeStructureOfStrippedType tywith
534577| PossiblyInfinite-> ValueNone
535578| ts-> ValueSome ts