Информация об изменениях

Сообщение Re[11]: секунда WTF (lock) от 28.01.2017 16:47

Изменено 28.01.2017 16:48 Mystic Artifact

Re[11]: секунда WTF (lock)
Здравствуйте, Sinix, Вы писали:

F>> PS: А Dictionary — зачем там?

S>http://stackoverflow.com/questions/3366376/are-net-switch-statements-hashed-or-indexed
Понял. То ли не знал, то ли забыл... Но рослин так не делает. Вместо этого он считает хэш строки, и генерирует код который сравнивает хэши. Начинает так делать он только если есть как минимум 7 кейсов.

Ну т.е. для:
        public static int Main(string[] args)
        {
            switch (args[0])
            {
                case "s1": return 1;
                case "s2": return 2;
                case "s3": return 3;
                case "s4": return 4;
                case "s5": return 5;
                case "s6": return 6;
                case "s7": return 7;
            }
            return 0;
        }


Он генерирует:

public static int Main(string[] args)
{
    string text = args[0];
    uint num = <PrivateImplementationDetails>.ComputeStringHash(text);
    if (num <= 139573449u)
    {
        if (num != 89240592u)
        {
            if (num != 106018211u)
            {
                if (num == 139573449u)
                {
                    if (text == "s1")
                    {
                        return 1;
                    }
                }
            }
            else if (text == "s3")
            {
                return 3;
            }
        }
        else if (text == "s2")
        {
            return 2;
        }
    }
    else if (num <= 173128687u)
    {
        if (num != 156351068u)
        {
            if (num == 173128687u)
            {
                if (text == "s7")
                {
                    return 7;
                }
            }
        }
        else if (text == "s6")
        {
            return 6;
        }
    }
    else if (num != 189906306u)
    {
        if (num == 206683925u)
        {
            if (text == "s5")
            {
                return 5;
            }
        }
    }
    else if (text == "s4")
    {
        return 4;
    }
    return 0;
}


Где ComputeStringHash:

.method assembly hidebysig static 
    uint32 ComputeStringHash (
        string s
    ) cil managed 
{
    // Method begins at RVA 0x21a8
    // Code size 44 (0x2c)
    .maxstack 2
    .locals init (
        [0] uint32,
        [1] int32
    )

    IL_0000: ldarg.0
    IL_0001: brfalse.s IL_002a

    IL_0003: ldc.i4 -2128831035
    IL_0008: stloc.0
    IL_0009: ldc.i4.0
    IL_000a: stloc.1
    IL_000b: br.s IL_0021
    // loop start (head: IL_0021)
        IL_000d: ldarg.0
        IL_000e: ldloc.1
        IL_000f: callvirt instance char [mscorlib]System.String::get_Chars(int32)
        IL_0014: ldloc.0
        IL_0015: xor
        IL_0016: ldc.i4 16777619
        IL_001b: mul
        IL_001c: stloc.0
        IL_001d: ldloc.1
        IL_001e: ldc.i4.1
        IL_001f: add
        IL_0020: stloc.1

        IL_0021: ldloc.1
        IL_0022: ldarg.0
        IL_0023: callvirt instance int32 [mscorlib]System.String::get_Length()
        IL_0028: blt.s IL_000d
    // end loop

    IL_002a: ldloc.0
    IL_002b: ret
} // end of method '<PrivateImplementationDetails>'::ComputeStringHash


К сожалению ilspy не хочет видеть PrivateImplementationDetails.
Re[11]: секунда WTF (lock)
Здравствуйте, Sinix, Вы писали:

F>> PS: А Dictionary — зачем там?

S>http://stackoverflow.com/questions/3366376/are-net-switch-statements-hashed-or-indexed
Понял. То ли не знал, то ли забыл... Но рослин так не делает. Вместо этого он считает хэш строки, и генерирует код который сравнивает хэши. Начинает так делать он только если есть как минимум 7 кейсов.

Ну т.е. для:
        public static int Main(string[] args)
        {
            switch (args[0])
            {
                case "s1": return 1;
                case "s2": return 2;
                case "s3": return 3;
                case "s4": return 4;
                case "s5": return 5;
                case "s6": return 6;
                case "s7": return 7;
            }
            return 0;
        }


Он генерирует:

public static int Main(string[] args)
{
    string text = args[0];
    uint num = <PrivateImplementationDetails>.ComputeStringHash(text);
    if (num <= 139573449u)
    {
        if (num != 89240592u)
        {
            if (num != 106018211u)
            {
                if (num == 139573449u)
                {
                    if (text == "s1")
                    {
                        return 1;
                    }
                }
            }
            else if (text == "s3")
            {
                return 3;
            }
        }
        else if (text == "s2")
        {
            return 2;
        }
    }
    else if (num <= 173128687u)
    {
        if (num != 156351068u)
        {
            if (num == 173128687u)
            {
                if (text == "s7")
                {
                    return 7;
                }
            }
        }
        else if (text == "s6")
        {
            return 6;
        }
    }
    else if (num != 189906306u)
    {
        if (num == 206683925u)
        {
            if (text == "s5")
            {
                return 5;
            }
        }
    }
    else if (text == "s4")
    {
        return 4;
    }
    return 0;
}


Где ComputeStringHash:

.method assembly hidebysig static 
    uint32 ComputeStringHash (
        string s
    ) cil managed 
{
    // Method begins at RVA 0x21a8
    // Code size 44 (0x2c)
    .maxstack 2
    .locals init (
        [0] uint32,
        [1] int32
    )

    IL_0000: ldarg.0
    IL_0001: brfalse.s IL_002a

    IL_0003: ldc.i4 -2128831035
    IL_0008: stloc.0
    IL_0009: ldc.i4.0
    IL_000a: stloc.1
    IL_000b: br.s IL_0021
    // loop start (head: IL_0021)
        IL_000d: ldarg.0
        IL_000e: ldloc.1
        IL_000f: callvirt instance char [mscorlib]System.String::get_Chars(int32)
        IL_0014: ldloc.0
        IL_0015: xor
        IL_0016: ldc.i4 16777619
        IL_001b: mul
        IL_001c: stloc.0
        IL_001d: ldloc.1
        IL_001e: ldc.i4.1
        IL_001f: add
        IL_0020: stloc.1

        IL_0021: ldloc.1
        IL_0022: ldarg.0
        IL_0023: callvirt instance int32 [mscorlib]System.String::get_Length()
        IL_0028: blt.s IL_000d
    // end loop

    IL_002a: ldloc.0
    IL_002b: ret
} // end of method '<PrivateImplementationDetails>'::ComputeStringHash


К сожалению ilspy не хочет видеть PrivateImplementationDetails (при декомпиляции в C#).