Пример #1
0
        static void _CustomWriteIntUnrolledSigned_ThunkWriter(ref ThunkWriter writer, int num, char[] buffer)
        {
            // Why signed integers?
            // Earlier versions of this code used unsigned integers, 
            //   but it turns out that's not ideal and here's why.
            // 
            // The signed version of the relevant code gets JIT'd down to:
            // instr       operands                    latency/throughput (approx. worst case; Haswell)
            // ========================================================================================
            // mov         ecx,###                      2 /  0.5 
            // cdq                                      1 /  -
            // idiv        eax,ecx                     29 / 11
            // mov         ecx,###                      2 /  0.5
            // cdq                                      1 /  -
            // idiv        eax,ecx                     29 / 11
            // movsx       edx,dl                       - /  0.5
            //
            // The unsigned version gets JIT'd down to:
            // instr       operands                    latency/throughput (approx. worst case; Haswell)
            // ========================================================================================
            // mov         ecx,###                       2 /  0.5
            // xor         edx,edx                       1 /  0.25
            // div         eax,ecx                      29 / 11
            // mov         ecx,###                       2 /  0.5
            // xor         edx,edx                       1 /  0.25
            // div         eax,ecx                      29 / 11
            // and         edx,###                       1 /  0.25
            //
            // In theory div (usigned division) is faster than idiv, and it probably is *but* cdq + cdq + movsx is
            //   faster than xor + xor + and; in practice it's fast *enough* to make up the difference.
            // have to special case this, we can't negate it
            if (num == int.MinValue)
            {
                writer.WriteMinConstant(ConstantString_Min.Int_MinValue);
                return;
            }

            int numLen;
            int number;

            if (num < 0)
            {
                writer.Write('-');
                number = -num;
            }
            else
            {
                number = num;
            }

            if (number < 1000)
            {
                if (number >= 100)
                {
                    writer.Write(DigitTriplets, number * 3, 3);
                }
                else
                {
                    if (number >= 10)
                    {
                        writer.Write(DigitTriplets, number * 3 + 1, 2);
                    }
                    else
                    {
                        writer.Write(DigitTriplets, number * 3 + 2, 1);
                    }
                }
                return;
            }
            var d012 = number % 1000 * 3;

            int d543;
            if (number < 1000000)
            {
                d543 = (number / 1000) * 3;
                if (number >= 100000)
                {
                    numLen = 6;
                    goto digit5;
                }
                else
                {
                    if (number >= 10000)
                    {
                        numLen = 5;
                        goto digit4;
                    }
                    else
                    {
                        numLen = 4;
                        goto digit3;
                    }
                }
            }
            d543 = (number / 1000) % 1000 * 3;

            int d876;
            if (number < 1000000000)
            {
                d876 = (number / 1000000) * 3;
                if (number >= 100000000)
                {
                    numLen = 9;
                    goto digit8;
                }
                else
                {
                    if (number >= 10000000)
                    {
                        numLen = 8;
                        goto digit7;
                    }
                    else
                    {
                        numLen = 7;
                        goto digit6;
                    }
                }
            }
            d876 = (number / 1000000) % 1000 * 3;

            numLen = 10;

            // uint is between 0 & 4,294,967,295 (in practice we only get to int.MaxValue, but that's the same # of digits)
            // so 1 to 10 digits

            // [01,]000,000-[99,]000,000
            var d9 = number / 1000000000;
            buffer[0] = (char)('0' + d9);

            digit8:
            buffer[1] = DigitTriplets[d876];
            digit7:
            buffer[2] = DigitTriplets[d876 + 1];
            digit6:
            buffer[3] = DigitTriplets[d876 + 2];

            digit5:
            buffer[4] = DigitTriplets[d543];
            digit4:
            buffer[5] = DigitTriplets[d543 + 1];
            digit3:
            buffer[6] = DigitTriplets[d543 + 2];

            buffer[7] = DigitTriplets[d012];
            buffer[8] = DigitTriplets[d012 + 1];
            buffer[9] = DigitTriplets[d012 + 2];

            writer.Write(buffer, 10 - numLen, numLen);
        }
Пример #2
0
        static void _CustomWriteInt_ThunkWriter(ref ThunkWriter writer, int number, char[] buffer)
        {
            // Gotta special case this, we can't negate it
            if (number == int.MinValue)
            {
                writer.WriteMinConstant(ConstantString_Min.Int_MinValue);
                return;
            }

            var ptr = InlineSerializer<object>.CharBufferSize - 1;

            uint copy;
            if (number < 0)
            {
                writer.Write('-');
                copy = (uint)(-number);
            }
            else
            {
                copy = (uint)number;
            }

            do
            {
                byte ix = (byte)(copy % 100);
                copy /= 100;

                var chars = DigitPairs[ix];
                buffer[ptr--] = chars.Second;
                buffer[ptr--] = chars.First;
            } while (copy != 0);

            if (buffer[ptr + 1] == '0')
            {
                ptr++;
            }

            writer.Write(buffer, ptr + 1, InlineSerializer<object>.CharBufferSize - 1 - ptr);
        }