LINUX.ORG.RU

Разрешено использование C++ в GCC

 , , , , ,


0

1

Вчера в списке рассылки GCC появилось важное сообщение по поводу использования языка программирования C++ при разработке GCC (GNU Compiler Collection, а не сам компилятор языка C).

Марк Митчелл (Mark Mitchell), один из основных разработчиков GCC:

Я рад сообщить, что руководящий комитет GCC и FSF одобрили использование C++ в самом GCC. Конечно, нет никаких причин использовать возможности С++ только потому, что мы умеем это делать. Главная цель - предоставить пользователям более качественные компиляторы, а не кодовую базу на C++ для самих себя.

Перед тем, как мы действительно начнём использовать C++, мы должны определиться с набором правил, которыми нужно будет руководствоваться при использовании C++ для разработки GCC. Я считаю, что для начала мы должны минимизировать список разрешённых возможностей С++, чтобы не подвергать разработчиков GCC, не знакомых с C++, таким резким переменам в основном языке разработки компиляторов. Мы всегда сможем расширить использование С++ позднее, если появится такая необходимость.

На данный момент разработчики ограничиваются стандартом C++98 и использованием типа long long для 64-битных целых чисел. Использование множественного наследования, шаблонов (тех, которые не входят в стандартную библиотеку C++) и исключений, скорее всего, будет запрещено. Это мотивировано тем, что это будет сложно для программистов на C, а также тем, что сами программисты C++ могут с лёгкостью допустить ошибки в таких вещах.

Так как язык C++ достаточно обширен, то Марк Митчелл предложил составить список того, что разрешается использовать, а не того, что использовать нельзя. На данный момент необходимо составить некоторые информационные нормативы, а не очередной стандарт ISO.

Все желающие поучаствовать в разработке нормативов могут связаться с разработчиками GCC. На данный момент предполагается сделать это в виде странички в Wiki.

>>> Официальный анонс

★★★★

Проверено: JB ()
Последнее исправление: MuZHiK-2 (всего исправлений: 1)
Ответ на: комментарий от anonymous

> я помню, что была статья, где исключения в плюсах как оптимизацию юзали (когда их вероятность мала). и страуссруп тоже писал, что без броска они почти ничего не стоят. какой-то ты хуевый плюсатник.

без броска - это стоит один jmp, проверка стоит mov+cmp+jmp, но каждый catch + throw - это лишний код и не маленький( который Manhunt «умело» скрыл в своем «примере» ), а чем раздутей код - тем больше вероятность, что он не влезет в кэш

lester ★★★★
()
Ответ на: комментарий от lester

> и да - на вложенных try/throw появляется неилюзорный лишний код, который всегда дороже проверки

я тестировал исключения, и при их достаточно малом проценте плюсовый код работает как сишный или быстрее; вот мои тестовые проги

http://www.linux.org.ru/forum/development/3856841

www_linux_org_ru ★★★★★
()
Ответ на: комментарий от lester

>, а чем раздутей код - тем больше вероятность, что он не влезет в кэш

чисто гадание на кофейной гуще. и медленный код, который отработает менее чем в 1% случаев, в кеше не нужен.

anonymous
()
Ответ на: комментарий от lester

> чем раздутей код - тем больше вероятность, что он не влезет в кэш

Вот ты и не потянул на троечку по своей же шкале. В кэш попадает лишь тот код, который фактически выполняется процессором. Если throw и catch секции управление не получают, то и кэша они почти не занимают. Подучи на досуге, имеют ввиду под словом «ассоцативный», когда говорят о кэшах.

> каждый catch + throw - это лишний код и не маленький( который Manhunt «умело» скрыл в своем «примере» )

Идиотушка, запомни: catch - сами по себе (и ты видел, что они ничего не стоят, пока не нужно передавать им управение), throw - сами по себе. Давай посмотрим, чего стоят throw.

$ cat d.cc
int g(int);                             

class MyException
{                
};               

int f_ex(int arg)
{                
        if(arg==0)
                throw MyException();
        int t = g(arg);             
        if(t==0)                    
                throw MyException();
        return t;                   
}

int f_no_ex(int arg)
{
        if(arg==0)
                return -1;
        int t = g(arg);
        if(t==0)
                return -1;
        return t;
}

$ g++ -c -O2 d.cc

$ objdump -d -C d.o

d.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <f_no_ex(int)>:
   0:   48 83 ec 08             sub    $0x8,%rsp
   4:   85 ff                   test   %edi,%edi
   6:   75 10                   jne    18 <f_no_ex(int)+0x18>
   8:   b8 ff ff ff ff          mov    $0xffffffff,%eax
   d:   48 83 c4 08             add    $0x8,%rsp
  11:   c3                      retq
  12:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)
  18:   e8 00 00 00 00          callq  1d <f_no_ex(int)+0x1d>
  1d:   ba ff ff ff ff          mov    $0xffffffff,%edx
  22:   85 c0                   test   %eax,%eax
  24:   0f 44 c2                cmove  %edx,%eax
  27:   eb e4                   jmp    d <f_no_ex(int)+0xd>
  29:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)

0000000000000030 <f_ex(int)>:
  30:   48 83 ec 08             sub    $0x8,%rsp
  34:   85 ff                   test   %edi,%edi
  36:   74 0e                   je     46 <f_ex(int)+0x16>
  38:   e8 00 00 00 00          callq  3d <f_ex(int)+0xd>
  3d:   85 c0                   test   %eax,%eax
  3f:   74 05                   je     46 <f_ex(int)+0x16>
  41:   48 83 c4 08             add    $0x8,%rsp
  45:   c3                      retq
  46:   bf 01 00 00 00          mov    $0x1,%edi
  4b:   0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)
  50:   e8 00 00 00 00          callq  55 <f_ex(int)+0x25>
  55:   31 d2                   xor    %edx,%edx
  57:   be 00 00 00 00          mov    $0x0,%esi
  5c:   48 89 c7                mov    %rax,%rdi
  5f:   e8 00 00 00 00          callq  64 <f_ex(int)+0x34>

В случае с исключениями компилятор знает, что они возникают редко, и поэтому переместил код их бросания куда подальше, а «горячий» код расположил «вподряд», инструкцию за инструкцией.

В случае с if-ами компилятор не знает, какой случай чаще. Поэтому «горячий» код выполняет jne и перемежается (с редко выполняемым) кодом обработки возварщения -1. C точки зрения кэша такой код как раз является распухшим.

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

> Вот ты и не потянул на троечку по своей же шкале. В кэш попадает лишь тот код, который фактически выполняется процессором. Если throw и catch секции управление не получают, то и кэша они почти не занимают. Подучи на досуге, имеют ввиду под словом «ассоцативный», когда говорят о кэшах.

ололо, какой ты фантазер :) процессор не вырезает блоки памяти, а потом склеивает, а копирует целиком

запомни: catch - сами по себе (и ты видел, что они ничего не стоят, пока не нужно передавать им управение), throw - сами по себе


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

lester ★★★★
()
Ответ на: комментарий от Manhunt

> В случае с исключениями компилятор знает, что они возникают редко, и поэтому переместил код их бросания куда подальше, а «горячий» код расположил «вподряд», инструкцию за инструкцией.

ты сначала примеры разнозначные напиши - а потом что-то сравнивай

lester ★★★★
()
Ответ на: комментарий от lester

> процессор не вырезает блоки памяти, а потом склеивает, а копирует целиком

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

запомни: catch - сами по себе, throw - сами по себе

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


Это лишь характеризует автора примера как порядочного чудака :)

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

> В кэше хранятся именно что небольшие блоки. Поэтому блоки, содержащие объемный, но не выполняемый код, в кэше места не занимают. Их там тупо не оказывается.

Я конечно не особо силен в теме, но где-то слышал про фичу look-ahead, которая позволяет предугадать что загружать в кеш кроме того, что непосредственно потребовалось для выполнения для собственно усорения последующей работы. Это так или я ошибаюсь?

EvilBlueBeaver
()
Ответ на: комментарий от Manhunt

> В кэше хранятся именно что небольшие блоки. Поэтому блоки, содержащие объемный, но не выполняемый код, в кэше места не занимают. Их там тупо не оказывается.

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

Это лишь характеризует автора примера как порядочного чудака :)


если исключениями не пользоваться, то они ничего не стоят - да

lester ★★★★
()
Ответ на: комментарий от EvilBlueBeaver

to EvilBlueBeaver - я сторонник плюсов, и CMake мне тоже нравится

AVATAR
()
Ответ на: комментарий от lester

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

Ты тупишь. Компилятор старается разместить код throw в конце функции. Поэтому часто выполняемый код не разбавлен кодом обработки редких ситуаций, и следовательно лучше кэшируется. Чтобы добиться аналогичного эффекта с обычной проверкой ошибок, придется использовать прагмы или profile-guided оптимизацию (то есть тратить усилия на то, что при использовании исключений получается автоматически и без дополнительных трудозатрат).

если исключениями не пользоваться, то они ничего не стоят - да


Если пользоваться ими по прямому назначению: для обработки редких ситуаций.

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

> Ты тупишь

давай уже без оскорблений

Компилятор старается разместить код throw в конце функции. Поэтому часто выполняемый код не разбавлен кодом обработки редких ситуаций, и следовательно лучше кэшируется.


если в функции не используются try/catch, а они нужны везде - если кидаешь исключения, то и должен их отлавливать

Если пользоваться ими по прямому назначению: для обработки редких ситуаций.


если б ими только так и пользовались

lester ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.