anchor.diff:          mkClonerCached<'T> ctx
   
       and cloneUntyped s c (o:obj) : obj =
  -        if obj.ReferenceEquals(o,null) then null else
  -        let shape = o.GetType() |> TypeShape.Create
  -        shape.Accept { new ITypeVisitor<obj> with
  -            member _.Visit<'T>() = mkCloner () s c (o :?> 'T) :> obj }
  +        let t = o.GetType()
  +        let mutable res = Unchecked.defaultof<obj>
  +        let cloner =
  +            if cache.TryGetValue(t, &res) then res :?> Cloner
  +            else
  +                let shape = TypeShape.Create t
  +                shape.Accept { new ITypeVisitor<Cloner> with
  +                    member _.Visit<'T>() = mkCloner<'T>() :> Cloner }
  +
  +        cloner.CloneUntyped s c o
   
       and mkRefEqCloner<'T> (cloner : Cloner<'T>) : Cloner<'T> =
           match shapeof<'T> with
  
positive.code:         | Shape.BigInt
          | Shape.Unit
          | Shape.Decimal
          | Shape.Enum _ -> fun _ _ x -> x
          | Shape.String -> fun _ _ x -> x
          | Shape.Array s when s.Rank = 1 ->
              s.Element.Accept {
                  new ITypeVisitor<Cloner<'T>> with
                      member _.Visit<'t> () =
                          if typeof<'t>.IsPrimitive then
                              EQ(fun _ _ (ts:'t[]) -> ts.Clone() :?> 't[])
                          else
                              let ec = mkClonerCached<'t> ctx
                              EQ(fun s c (ts:'t[]) ->
                                  // pre-register the uninitialized array
                                  // to account for cylic arrays
                                  let ts' = Array.zeroCreate<'t> ts.Length
                                  let _ = c.AddValue(s.ObjectId, ts')
                                  for i = 0 to ts.Length - 1 do ts'.[i] <- ec s c ts.[i]
                                  ts') }
  
          | Shape.Nullable s ->
              s.Accept { new INullableVisitor<Cloner<'T>> with
  
negative.code: 
  module private Impl =
  
      [<AbstractClass>]
      type Cloner () =
          abstract CloneUntyped : ObjectStack -> ObjectCache -> obj -> obj
  
      [<AbstractClass>]
      type Cloner<'T> () =
          inherit Cloner()
          abstract Clone : ObjectStack -> ObjectCache -> 'T -> 'T
          override this.CloneUntyped s c o = this.Clone s c (o :?> 'T) :> obj
  
      type FieldCloner<'T> = delegate of ObjectStack * ObjectCache * source:inref<'T> * target:byref<'T> -> unit
  
      let rec mkCloner<'T> () : Cloner<'T> =
          let mutable f = Unchecked.defaultof<Cloner<'T>>
  