@@ -389,147 +389,190 @@ module StructuralUtilities =
389389
390390 [<Struct; NoComparison; RequireQualifiedAccess>]
391391 type TypeToken =
392- | Stamp of stamp : Stamp
393- | UCase of name : string
394- | Nullness of nullness : NullnessInfo
392+ | Stamp of int
393+ | UCase of int
394+ | Nullness of int
395395 | NullnessUnsolved
396- | TupInfo of b : bool
396+ | TupInfo of int
397397 | Forall of int
398398 | MeasureOne
399- | MeasureRational of int * int
399+ | MeasureDenominator of int
400+ | MeasureNumerator of int
400401 | Solved of int
401402 | Unsolved of int
402403 | Rigid of int
403404
404405 type TypeStructure =
405406 | Stable of TypeToken []
407+ // Unstable means that the type structure of a given TType may change because of constraint solving or Trace.Undo.
406408 | Unstable of 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.emitNullness then
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 n with
433+ | NullnessInfo.AmbivalentToNull -> 0
434+ | NullnessInfo.WithNull -> 1
435+ | NullnessInfo.WithoutNull -> 2
436+
437+ let private emitNullness ( ctx : GenerationContext ) ( n : Nullness ) =
438+ if ctx.EmitNullness then
439+ ctx.Stable <- false
440+
441+ let out = ctx.Tokens
442+
443+ if out.Count < 256 then
421444 match 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
428467 match m with
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
443488 match ty with
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
448495 for arg in tinst do
449- yield ! emitTType env arg
496+ emitTType ctx arg
450497
451498 | TType_ app( tcref, tinst, n) ->
452- TypeToken.Stamp tcref.Stamp
453- yield ! emitNullness env n
499+ emitStamp ctx tcref.Stamp
500+ emitNullness ctx n
454501
455502 for arg in tinst do
456- yield ! emitTType env arg
503+ emitTType ctx arg
457504
458505 | TType_ anon( info, tys) ->
459- TypeToken.Stamp info.Stamp
506+ emitStamp ctx info.Stamp
460507
461508 for arg in tys do
462- yield ! emitTType env arg
509+ emitTType ctx arg
463510
464511 | TType_ tuple( tupInfo, tys) ->
465- TypeToken.TupInfo( evalTupInfoIsStruct tupInfo)
512+ out.Add ( TypeToken.TupInfo( if evalTupInfoIsStruct tupInfo then 1 else 0 ) )
466513
467514 for arg in tys do
468- yield ! emitTType env arg
515+ emitTType ctx arg
469516
470517 | TType_ forall( tps, tau) ->
471518 for tp in tps do
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 ! emitTType env tau
523+ emitTType ctx tau
477524
478525 | TType_ fun( d, r, n) ->
479- yield ! emitTType env d
480- yield ! emitTType env r
481- yield ! emitNullness env n
526+ emitTType ctx d
527+ emitTType ctx r
528+ emitNullness ctx n
482529
483530 | TType_ var( r, n) ->
484- yield ! emitNullness env n
531+ emitNullness ctx n
485532
486533 let typarId =
487- match env.typarMap .TryGetValue r.Stamp with
534+ match ctx.TyparMap .TryGetValue r.Stamp with
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.IsFromError then
543+ ctx.Stable <- false
496544
497545 match r.Solution with
498- | Some ty -> yield ! emitTType env ty
546+ | Some ty -> emitTType ctx ty
499547 | None ->
500- if r.Rigidity = TyparRigidity.Rigid then
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.Rigid then
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
532575 let tryGetTypeStructureOfStrippedType ty =
533- match memoize ty with
576+ match getTypeStructureOfStrippedType ty with
534577 | PossiblyInfinite -> ValueNone
535578 | ts -> ValueSome ts
0 commit comments