Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce fixed overhead of some Utf8Parser.TryParse methods #33507

Merged
merged 3 commits into from
Mar 13, 2020

Conversation

GrabYourPitchforks
Copy link
Member

This builds atop the work that Andy did as part of #33004. There are no behavioral changes here - only slight refactorings that produce better codegen at the entry points to some of the Utf8Parser.TryParse methods. In particular, this does not include many of the optimizations discussed at #32843.

Integral types

For the TryParse methods that work with integral types, reflowing the logic in this fashion moves the "default" behavior into a fast-path and reduces the total amount of logic in the switch statement. We're now able to tail-call into the workhorse methods without performing any register shuffling or stack spilling

Method Toolchain Mean Error StdDev Ratio
TryParseInt32 master 976.3 ns 5.34 ns 4.73 ns 1.00
TryParseInt32 tryparse 913.9 ns 8.03 ns 6.71 ns 0.94
;;; OLD CODEGEN ;;;
00007fff`4803cb40 56           push    rsi
00007fff`4803cb41 4883ec20     sub     rsp, 20h
00007fff`4803cb45 410fb7f1     movzx   esi, r9w
00007fff`4803cb49 83fe4e       cmp     esi, 4Eh
00007fff`4803cb4c 772c         ja      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e299ba (00007fff`4803cb7a)
00007fff`4803cb4e 83fe44       cmp     esi, 44h
00007fff`4803cb51 7713         ja      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e299a6 (00007fff`4803cb66)
00007fff`4803cb53 85f6         test    esi, esi
00007fff`4803cb55 7405         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e2999c (00007fff`4803cb5c)
00007fff`4803cb57 83fe44       cmp     esi, 44h
00007fff`4803cb5a 754c         jne     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e299e8 (00007fff`4803cba8)
00007fff`4803cb5c 4883c420     add     rsp, 20h
00007fff`4803cb60 5e           pop     rsi
00007fff`4803cb61 e97acaffff   jmp     CLRStub[MethodDescPrestub]@7fff480395e0 (00007fff`480395e0)
00007fff`4803cb66 83fe47       cmp     esi, 47h
00007fff`4803cb69 74f1         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e2999c (00007fff`4803cb5c)
00007fff`4803cb6b 83fe4e       cmp     esi, 4Eh
00007fff`4803cb6e 7538         jne     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e299e8 (00007fff`4803cba8)
00007fff`4803cb70 4883c420     add     rsp, 20h
00007fff`4803cb74 5e           pop     rsi
00007fff`4803cb75 e986caffff   jmp     CLRStub[MethodDescPrestub]@7fff48039600 (00007fff`48039600)
00007fff`4803cb7a 83fe64       cmp     esi, 64h
00007fff`4803cb7d 770c         ja      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e299cb (00007fff`4803cb8b)
00007fff`4803cb7f 83fe58       cmp     esi, 58h
00007fff`4803cb82 7416         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e299da (00007fff`4803cb9a)
00007fff`4803cb84 83fe64       cmp     esi, 64h
00007fff`4803cb87 751f         jne     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e299e8 (00007fff`4803cba8)
00007fff`4803cb89 ebd1         jmp     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e2999c (00007fff`4803cb5c)
00007fff`4803cb8b 83fe67       cmp     esi, 67h
00007fff`4803cb8e 74cc         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e2999c (00007fff`4803cb5c)
00007fff`4803cb90 83fe6e       cmp     esi, 6Eh
00007fff`4803cb93 74db         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e299b0 (00007fff`4803cb70)
00007fff`4803cb95 83fe78       cmp     esi, 78h
00007fff`4803cb98 750e         jne     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e299e8 (00007fff`4803cba8)
00007fff`4803cb9a 33c0         xor     eax, eax
00007fff`4803cb9c 8902         mov     dword ptr [rdx], eax
00007fff`4803cb9e 4883c420     add     rsp, 20h
00007fff`4803cba2 5e           pop     rsi
00007fff`4803cba3 e9d8caffff   jmp     CLRStub[MethodDescPrestub]@7fff48039680 (00007fff`48039680)
00007fff`4803cba8 33c0         xor     eax, eax
00007fff`4803cbaa 8902         mov     dword ptr [rdx], eax
00007fff`4803cbac 418900       mov     dword ptr [r8], eax
00007fff`4803cbaf e8dcd8d8ff   call    CLRStub[MethodDescPrestub]@7fff47dca490 (00007fff`47dca490)
00007fff`4803cbb4 cc           int     3

;;; NEW CODEGEN ;;;
00007fff`4802cc60 410fb7c1     movzx   eax, r9w
00007fff`4802cc64 85c0         test    eax, eax
00007fff`4802cc66 7505         jne     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e199bd (00007fff`4802cc6d)
00007fff`4802cc68 e97bc9ffff   jmp     CLRStub[MethodDescPrestub]@7fff480295e8 (00007fff`480295e8)
00007fff`4802cc6d 410fb7c1     movzx   eax, r9w
00007fff`4802cc71 83c820       or      eax, 20h
00007fff`4802cc74 83f867       cmp     eax, 67h
00007fff`4802cc77 7f0c         jg      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e199d5 (00007fff`4802cc85)
00007fff`4802cc79 83f864       cmp     eax, 64h
00007fff`4802cc7c 74ea         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e199b8 (00007fff`4802cc68)
00007fff`4802cc7e 83f867       cmp     eax, 67h
00007fff`4802cc81 74e5         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e199b8 (00007fff`4802cc68)
00007fff`4802cc83 eb16         jmp     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e199eb (00007fff`4802cc9b)
00007fff`4802cc85 83f86e       cmp     eax, 6Eh
00007fff`4802cc88 7407         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e199e1 (00007fff`4802cc91)
00007fff`4802cc8a 83f878       cmp     eax, 78h
00007fff`4802cc8d 7407         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e199e6 (00007fff`4802cc96)
00007fff`4802cc8f eb0a         jmp     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  Int32 ByRef,  Int32 ByRef,  Char)+0xffffffff`a9e199eb (00007fff`4802cc9b)
00007fff`4802cc91 e972c9ffff   jmp     CLRStub[MethodDescPrestub]@7fff48029608 (00007fff`48029608)
00007fff`4802cc96 e9edc9ffff   jmp     CLRStub[MethodDescPrestub]@7fff48029688 (00007fff`48029688)
00007fff`4802cc9b e9a0fdffff   jmp     CLRStub[MethodDescPrestub]@7fff4802ca40 (00007fff`4802ca40)

TryParse(..., out bool, ...)

Minor improvement here to avoid the range check when dereferencing source[4]. There's also less register shuffling in the error path. Avoiding this shuffling doesn't impact the success case, but I saw it as low-hanging fruit since it reduces the overall method codegen size by a little bit.

TryParse(..., out Guid, ...)

Similar to the integral types, the switch statement has been restructured to have the common case go through a fast path. Additionally, by changing the signature of the TryParseGuidCore method, we can avoid the stack spillage that would normally result on Win64 from passing so many parameters to the workhorse routine.

Method Toolchain Mean Error StdDev Median Ratio RatioSD
ParseGuid_Default master 5,881.1 ns 58.94 ns 55.14 ns 5,876.8 ns 1.00 0.00
ParseGuid_Default tryparse 5,545.2 ns 88.36 ns 82.65 ns 5,517.9 ns 0.94 0.02
ParseGuid_Braces master 6,154.5 ns 119.47 ns 132.79 ns 6,137.5 ns 1.00 0.00
ParseGuid_Braces tryparse 5,821.1 ns 67.85 ns 63.47 ns 5,803.3 ns 0.95 0.02
;;; OLD CODEGEN ;;;
00007fff`3ccccdd0 56           push    rsi
00007fff`3ccccdd1 4883ec40     sub     rsp, 40h
00007fff`3ccccdd5 c5f877       vzeroupper 
00007fff`3ccccdd8 33c0         xor     eax, eax
00007fff`3ccccdda 4889442430   mov     qword ptr [rsp+30h], rax
00007fff`3ccccddf 410fb7f1     movzx   esi, r9w
00007fff`3ccccde3 83fe42       cmp     esi, 42h
00007fff`3ccccde6 7745         ja      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a5ad (00007fff`3cccce2d)
00007fff`3ccccde8 85f6         test    esi, esi
00007fff`3ccccdea 0f8481000000 je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a5f1 (00007fff`3cccce71)
00007fff`3ccccdf0 83fe42       cmp     esi, 42h
00007fff`3ccccdf3 0f85c3000000 jne     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a63c (00007fff`3ccccebc)
00007fff`3ccccdf9 c5fa6f01     vmovdqu xmm0, xmmword ptr [rcx]
00007fff`3ccccdfd c5fa7f442430 vmovdqu xmmword ptr [rsp+30h], xmm0
00007fff`3cccce03 4889542420   mov     qword ptr [rsp+20h], rdx
00007fff`3cccce08 4c89442428   mov     qword ptr [rsp+28h], r8
00007fff`3cccce0d 488d4c2430   lea     rcx, [rsp+30h]
00007fff`3cccce12 ba01000000   mov     edx, 1
00007fff`3cccce17 41b87b000000 mov     r8d, 7Bh
00007fff`3cccce1d 41b97d000000 mov     r9d, 7Dh
00007fff`3cccce23 e888c7ffff   call    CLRStub[MethodDescPrestub]@7fff3ccc95b0 (00007fff`3ccc95b0)
00007fff`3cccce28 e986000000   jmp     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a633 (00007fff`3cccceb3)
00007fff`3cccce2d 83fe44       cmp     esi, 44h
00007fff`3cccce30 743f         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a5f1 (00007fff`3cccce71)
00007fff`3cccce32 83fe4e       cmp     esi, 4Eh
00007fff`3cccce35 7468         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a61f (00007fff`3cccce9f)
00007fff`3cccce37 83fe50       cmp     esi, 50h
00007fff`3cccce3a 0f857c000000 jne     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a63c (00007fff`3ccccebc)
00007fff`3cccce40 c5fa6f01     vmovdqu xmm0, xmmword ptr [rcx]
00007fff`3cccce44 c5fa7f442430 vmovdqu xmmword ptr [rsp+30h], xmm0
00007fff`3cccce4a 4889542420   mov     qword ptr [rsp+20h], rdx
00007fff`3cccce4f 4c89442428   mov     qword ptr [rsp+28h], r8
00007fff`3cccce54 488d4c2430   lea     rcx, [rsp+30h]
00007fff`3cccce59 ba01000000   mov     edx, 1
00007fff`3cccce5e 41b828000000 mov     r8d, 28h
00007fff`3cccce64 41b929000000 mov     r9d, 29h
00007fff`3cccce6a e841c7ffff   call    CLRStub[MethodDescPrestub]@7fff3ccc95b0 (00007fff`3ccc95b0)
00007fff`3cccce6f eb42         jmp     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a633 (00007fff`3cccceb3)
00007fff`3cccce71 c5fa6f01     vmovdqu xmm0, xmmword ptr [rcx]
00007fff`3cccce75 c5fa7f442430 vmovdqu xmmword ptr [rsp+30h], xmm0
00007fff`3cccce7b 4889542420   mov     qword ptr [rsp+20h], rdx
00007fff`3cccce80 4c89442428   mov     qword ptr [rsp+28h], r8
00007fff`3cccce85 488d4c2430   lea     rcx, [rsp+30h]
00007fff`3cccce8a 33d2         xor     edx, edx
00007fff`3cccce8c 41b820000000 mov     r8d, 20h
00007fff`3cccce92 41b920000000 mov     r9d, 20h
00007fff`3cccce98 e813c7ffff   call    CLRStub[MethodDescPrestub]@7fff3ccc95b0 (00007fff`3ccc95b0)
00007fff`3cccce9d eb14         jmp     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a633 (00007fff`3cccceb3)
00007fff`3cccce9f c5fa6f01     vmovdqu xmm0, xmmword ptr [rcx]
00007fff`3ccccea3 c5fa7f442430 vmovdqu xmmword ptr [rsp+30h], xmm0
00007fff`3ccccea9 488d4c2430   lea     rcx, [rsp+30h]
00007fff`3cccceae e8f5c6ffff   call    CLRStub[MethodDescPrestub]@7fff3ccc95a8 (00007fff`3ccc95a8)
00007fff`3cccceb3 0fb6c0       movzx   eax, al
00007fff`3cccceb6 4883c440     add     rsp, 40h
00007fff`3cccceba 5e           pop     rsi
00007fff`3ccccebb c3           ret     
00007fff`3ccccebc c5f857c0     vxorps  xmm0, xmm0, xmm0
00007fff`3ccccec0 c5fa7f02     vmovdqu xmmword ptr [rdx], xmm0
00007fff`3ccccec4 33c0         xor     eax, eax
00007fff`3ccccec6 418900       mov     dword ptr [r8], eax
00007fff`3ccccec9 e8c2d5d8ff   call    CLRStub[MethodDescPrestub]@7fff3ca5a490 (00007fff`3ca5a490)
00007fff`3ccccece cc           int     3

;;; NEW CODEGEN ;;;
00007fff`3cccccc0 410fb7c1     movzx   eax, r9w
00007fff`3cccccc4 85c0         test    eax, eax
00007fff`3cccccc6 7508         jne     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a370 (00007fff`3cccccd0)
00007fff`3cccccc8 4533c9       xor     r9d, r9d
00007fff`3ccccccb e9a8d1ffff   jmp     CLRStub[MethodDescPrestub]@7fff3ccc9e78 (00007fff`3ccc9e78)
00007fff`3cccccd0 450fb7c9     movzx   r9d, r9w
00007fff`3cccccd4 4183f944     cmp     r9d, 44h
00007fff`3cccccd8 770e         ja      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a388 (00007fff`3ccccce8)
00007fff`3cccccda 4183f942     cmp     r9d, 42h
00007fff`3cccccde 7416         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a396 (00007fff`3cccccf6)
00007fff`3ccccce0 4183f944     cmp     r9d, 44h
00007fff`3ccccce4 74e2         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a368 (00007fff`3cccccc8)
00007fff`3ccccce6 eb29         jmp     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a3b1 (00007fff`3ccccd11)
00007fff`3ccccce8 4183f94e     cmp     r9d, 4Eh
00007fff`3cccccec 741e         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a3ac (00007fff`3ccccd0c)
00007fff`3cccccee 4183f950     cmp     r9d, 50h
00007fff`3cccccf2 740d         je      System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a3a1 (00007fff`3ccccd01)
00007fff`3cccccf4 eb1b         jmp     System_Private_CoreLib!System.Buffers.Text.Utf8Parser.TryParse(System.ReadOnlySpan`1<Byte>,  System.Guid ByRef,  Int32 ByRef,  Char)+0xffffffff`a0c9a3b1 (00007fff`3ccccd11)
00007fff`3cccccf6 41b97b7d0000 mov     r9d, 7D7Bh
00007fff`3cccccfc e977d1ffff   jmp     CLRStub[MethodDescPrestub]@7fff3ccc9e78 (00007fff`3ccc9e78)
00007fff`3ccccd01 41b928290000 mov     r9d, 2928h
00007fff`3ccccd07 e96cd1ffff   jmp     CLRStub[MethodDescPrestub]@7fff3ccc9e78 (00007fff`3ccc9e78)
00007fff`3ccccd0c e95fd1ffff   jmp     CLRStub[MethodDescPrestub]@7fff3ccc9e70 (00007fff`3ccc9e70)
00007fff`3ccccd11 e91afdffff   jmp     CLRStub[MethodDescPrestub]@7fff3cccca30 (00007fff`3cccca30)

{
if (source[0] != begin)
if (source[0] != (byte)ends)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JIT could produce better codegen for this pattern. See #33504.

@GrabYourPitchforks GrabYourPitchforks added the tenet-performance Performance related issue label Mar 12, 2020
@stephentoub
Copy link
Member

How does this relate to #32843?

Can similar tweaks be made to the corresponding char-based APIs (e.g. int.Parse)?

Copy link
Member

@adamsitnik adamsitnik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

another really nice improvement @GrabYourPitchforks !

LGTM, thanks for adding the comment that explains the bit shifting logic

@GrabYourPitchforks
Copy link
Member Author

@stephentoub That PR was primarily concerned with improving the workhorse routine. From that investigation came the idea of improving the entry point. This PR focuses just on the fixed overhead of the entry points while leaving the workhorse routines largely unchanged.

I haven't tried applying these optimizations to the char overloads yet because their entry points generally look different than these entry points. But I imagine once we get back to the PR that optimizes the workhorse routines the optimizations there will be generally applicable to both char and byte.

Copy link
Member

@tannergooding tannergooding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes LGTM. Had a couple questions about the codegen

@GrabYourPitchforks
Copy link
Member Author

CI failures seem to be unrelated infrastructure failures.

@GrabYourPitchforks GrabYourPitchforks merged commit 099bc4b into dotnet:master Mar 13, 2020
@GrabYourPitchforks GrabYourPitchforks deleted the tryparse_upd branch March 13, 2020 00:57
@ghost ghost locked as resolved and limited conversation to collaborators Dec 10, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants