Re[2]: ThrowHelper
От: rameel https://github.com/rsdn/CodeJam
Дата: 03.11.16 13:47
Оценка:
Здравствуйте, Sinix, Вы писали:

  Скрытый текст
S>В смысле, у нас весь код выполнен в стиле
S>
S>void Check(...)
S>{
S>  if (somethingBadHappened)
S>  {
S>    throw CreateException(...);
S>  }
S>}
S>

S>всё, что поменяется с DOES_NOT_RETURN — это не будет инлайниться CreateException(), который по определению находится в cold path. Сам Check инлайнится по-прежнему.

Предлагается сделать так:
void Check(...)
{
  if (somethingBadHappened)
  {
    ThrowHelper.ThrowSomeException();
  }
}

class ThrowHelper
{
    public static void ThrowSomeException()
    {
        throw CodeExceptions.SomeException();
    }
}


В данном случае инлайнится Check и CodeExceptions. С DOES_NOT_RETURN не инлайнится ThrowHelper.ThrowSomeException(), который переедет в cold path.

Для вот такого кода
  Пример кода на C#
public static int Add(int value)
{
    Assert(value, nameof(value));
    return value + 10;
}

public static void Assert(int value, string paramName)
{
    if (value < 0)
        throw CreateException(paramName);
}

private static ArgumentOutOfRangeException CreateException(string paramName)
{
    return new ArgumentOutOfRangeException(paramName);
}

c DOES_NOT_RETURN и без него джит генерирует такой код
00007FF7BA0D04C0  push        rsi  
00007FF7BA0D04C1  sub         rsp,20h  

            Assert(value, nameof(value));
00007FF7BA0D04C5  test        ecx,ecx  
00007FF7BA0D04C7  jl          00007FF7BA0D04D2

            return value + 10;
00007FF7BA0D04C9  lea         eax,[rcx+0Ah]  
00007FF7BA0D04CC  add         rsp,20h  
00007FF7BA0D04D0  pop         rsi  
00007FF7BA0D04D1  ret  

            Assert(value, nameof(value));
00007FF7BA0D04D2  mov         rcx,7FF818831FC0h  
00007FF7BA0D04DC  call        00007FF8196C2510  
00007FF7BA0D04E1  mov         rsi,rax  
00007FF7BA0D04E4  mov         ecx,1  
00007FF7BA0D04E9  mov         rdx,7FF7B9FC40E0h  
00007FF7BA0D04F3  call        00007FF8198737E0  
00007FF7BA0D04F8  mov         rdx,rax  
00007FF7BA0D04FB  mov         rcx,rsi  
00007FF7BA0D04FE  call        00007FF818ED4890  
00007FF7BA0D0503  mov         rcx,rsi  
00007FF7BA0D0506  call        00007FF8198604E0  
00007FF7BA0D050B  int         3


Вот для такого
  Пример кода на C#
public static int Add(int value)
{
    Assert(value, nameof(value));
    return value + 10;
}

public static void Assert(int value, string paramName)
{
    if (value < 0)
    {
        // Вынесли код, бросающий исключение в отдельный метод
        ThrowException(paramName);
    }
}

private static void ThrowException(string paramName)
{
    throw CreateException(paramName);
}

private static ArgumentOutOfRangeException CreateException(string paramName)
{
    return new ArgumentOutOfRangeException(paramName);
}

c DOES_NOT_RETURN джит генерирует вот такое
00007FF7BA0D04C0  push        rsi  
00007FF7BA0D04C1  sub         rsp,20h  

            Assert(value, nameof(value));
00007FF7BA0D04C5  test        ecx,ecx  
00007FF7BA0D04C7  jl          00007FF7BA0C04CB

            return value + 10;
00007FF7BA0D04C9  lea         eax,[rcx+0Ah]  
00007FF7BA0D04CC  add         rsp,20h  
00007FF7BA0D04D0  pop         rsi  
00007FF7BA0D04D1  ret  

            Assert(value, nameof(value));
00007FF7BA0C04CB  mov         rcx,1D39B833578h  
00007FF7BA0C04D5  mov         rcx,qword ptr [rcx]  
00007FF7BA0C04D8  call        00007FF7BA0C0090

В общем, с новым джитом и вынесением методов, бросающих исключение, код становится более кеш-френдли. Без этого генерируемый код исключений плодится по всем методам, где его используют

S>Короч, нужен тест чтоб было видно что текущее положение дел не ухудшилось.


Для текущего джита можно навесить на методы ThrowHelper.Throw... MethodImplOptions.AggressiveInlining, тогда асм. код будет один в один как сейчас.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Отредактировано 03.11.2016 13:52 rameel . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.