@@ -3,7 +3,9 @@ namespace CodecMapper
33open System.Text
44open System.Collections .Generic
55open System.Globalization
6+ #if ! FABLE_ COMPILER
67open System.Collections .Concurrent
8+ #endif
79open Microsoft.FSharp .Reflection
810
911/// JSON codec compilation and runtime helpers.
@@ -62,7 +64,11 @@ module Json =
6264 sprintf " JSON decode error at %s : %s " ( renderPath path) detail
6365
6466 module internal Runtime =
67+ #if ! FABLE_ COMPILER
6568 let private objectArrayPools = ConcurrentDictionary< int, ConcurrentBag< obj array>>()
69+ #else
70+ let private objectArrayPools = Dictionary< int, ResizeArray< obj array>>()
71+ #endif
6672
6773 let private asDecodeException detail path inner =
6874 JsonDecodeException( path, detail, inner) :> exn
@@ -279,10 +285,10 @@ module Json =
279285 let mutable finished = false
280286 let mutable hadEscapes = false
281287
282- ///
283- /// Unknown-field skipping should stay linear even for escaped text,
284- /// so scan forward once instead of recounting backslashes at every
285- /// candidate quote.
288+ //
289+ // Unknown-field skipping should stay linear even for escaped text,
290+ // so scan forward once instead of recounting backslashes at every
291+ // candidate quote.
286292 while i < data.Length && not finished do
287293 match data[ i] with
288294 | 34 uy -> finished <- true
@@ -576,13 +582,17 @@ module Json =
576582
577583 equal
578584
585+ #if ! FABLE_ COMPILER
579586 let private listBuilders = ConcurrentDictionary< System.Type, obj array -> obj>()
587+ #else
588+ let private listBuilders = Dictionary< System.Type, obj array -> obj>()
589+ #endif
580590
581591 let makeListBuilder ( elementType : System.Type ) =
592+ #if ! FABLE_ COMPILER
582593 listBuilders.GetOrAdd(
583594 elementType,
584595 System.Func<_, _>( fun elementType ->
585- #if ! FABLE_ COMPILER
586596 let listType = typedefof<_ list>. MakeGenericType([| elementType |])
587597 let emptyList = listType.GetProperty( " Empty" ) .GetValue( null )
588598 let cons = listType.GetMethod( " Cons" )
@@ -593,12 +603,16 @@ module Json =
593603 for i in elements.Length - 1 .. - 1 .. 0 do
594604 result <- cons.Invoke( null , [| elements[ i]; result |])
595605
596- result
606+ result)
607+ )
597608#else
598- fun ( elements : obj array ) -> List.ofArray elements |> box
609+ match listBuilders.TryGetValue( elementType) with
610+ | true , builder -> builder
611+ | false , _ ->
612+ let builder = fun ( elements : obj array ) -> List.ofArray elements |> box
613+ listBuilders[ elementType] <- builder
614+ builder
599615#endif
600- )
601- )
602616
603617 ///
604618 /// XML shares the same erased list-construction helper, so keep the
@@ -616,20 +630,44 @@ module Json =
616630 /// pooling the ` obj[] ` buffers removes one of the largest remaining
617631 /// allocation sources on nested decode workloads.
618632 let rentObjectArray length =
633+ #if ! FABLE_ COMPILER
619634 let pool = objectArrayPools.GetOrAdd( length, fun _ -> ConcurrentBag< obj array>())
620635 let mutable rented = Unchecked.defaultof< obj array>
621636
622637 if pool.TryTake(& rented) then
623638 rented
624639 else
625640 Array.zeroCreate length
641+ #else
642+ match objectArrayPools.TryGetValue( length) with
643+ | true , pool when pool.Count > 0 ->
644+ let lastIndex = pool.Count - 1
645+ let rented = pool[ lastIndex]
646+ pool.RemoveAt( lastIndex)
647+ rented
648+ | _ -> Array.zeroCreate length
649+ #endif
626650
627651 ///
628652 /// Record field buffers may hold arbitrary user objects, so return
629653 /// them cleared to avoid keeping payload graphs alive across runs.
630654 let returnObjectArray ( buffer : obj array ) ( usedLength : int ) =
631- System.Array.Clear( buffer, 0 , usedLength)
655+ for i in 0 .. usedLength - 1 do
656+ buffer[ i] <- null
657+
658+ #if ! FABLE_ COMPILER
632659 objectArrayPools.GetOrAdd( usedLength, fun _ -> ConcurrentBag< obj array>()) .Add( buffer)
660+ #else
661+ let pool =
662+ match objectArrayPools.TryGetValue( usedLength) with
663+ | true , existing -> existing
664+ | false , _ ->
665+ let created = ResizeArray< obj array>()
666+ objectArrayPools[ usedLength] <- created
667+ created
668+
669+ pool.Add( buffer)
670+ #endif
633671
634672 type CompiledCodec = {
635673 Encode: IByteWriter -> obj -> unit
0 commit comments