Найбільш захоплюючою особливістю Carbon є його умовність викликів

Минулого тижня Чендлер Керрут анонсував Carbon, потенційну заміну C++, над якою він працював протягом двох років. Він має звичайні круті функції, яких ви очікуєте від сучасної мови: корисні генерики, інтерфейси компілятора/риси/концепції, модулі тощо. .

Це те, про що я сам думав у минулому, і, наскільки мені відомо, ніколи раніше не робилося мовою низького рівня, але ця концепція має великий потенціал. Дозвольте мені пояснити, про що я говорю.

Передача вуглецевих параметрів

За замовчуванням, тобто якщо ви більше нічого не пишете, параметри Carbon передаються через еквівалент const T& у C++.

бал класу { змінна x: i64; змінна y:i64; змінна z:i64; } fn Print(p: Dot); точка попадання { std::uint64_t x, y, z; }; void Print(const Point&p);

Проте - і це частина імпорту - компілятору дозволено перетворити це на T згідно з правилом "як ніби".

fn Print(x: i32); void Print(std::int32_tx);

... і що? Чому я так радію цьому?

Перевага №1: Продуктивність

Пропускати речі через const T& завжди добре, чи не так? Зрештою, ви уникаєте копії!

Хоча це правда, посилання по суті є покажчиками на рівні збірки. Це означає, що передача аргументу через const T& встановлює регістр на його адресу, що означає

у викликаючому аргументі потрібна адреса, і він повинен зберігатися десь у пам’яті, і у callee, параметр повинен завантажити значення з пам'яті під час його читання.

Це єдині варіанти для типів, які не вміщуються в реєстр, або невеликих типів із нетривіальними конструкторами копіювання, але вони менш ідеальні для тривіально скопійованих типів, які підходять.

Порівняйте збірку між функцією add, яка отримує свої аргументи через const T&

[[gnu::noinline]] int add(const int& a, const int& b) { повернути a + b; } int foo() { повертає add(11, 42); }

і той, хто цього не робить

[[gnu::noinline]] int add(int a, int b) { повернути a + b; } int foo() { повертає add(11, 42); }

Усі сховища та завантаження пам’яті зникають; ви не хочете переходити за посиланням!

Тож дуже добре, що в Carbon вам не потрібно думати про це – компілятор просто зробить правильні речі за вас. Крім того, ви не завжди можете зробити це вручну.

Перевага №2: Оптимальна домовленість про виклики в загальному коді

Припустімо, ми хочемо написати загальну функцію друку на C++. Тип може бути як завгодно великим із як завгодно дорогим конструктором копіювання, тому вам слід використовувати const T& у загальному коді.

модель void Print(const T&obj);

Однак це погіршує ситуацію для малих і дешевих типів, що є прикро. Це також не те, що компілятор може виправити за допомогою оптимізації, тому що сигнатура функції та умова виклику є частиною - ось наша улюблена абревіатура з трьох літер - ABI. У найкращому випадку компілятор може включити його та виключити весь виклик.

Є способи обійти це, бо, звичайно, вони є, але це працює™ у Carbon, і це добре.

Але справжня причина, чому я в захваті від цієї функції, не пов’язана з усуненням завантажень/зберігань пам’яті.

Перевага №3: ​​копії, які не є копіями

Зауважте, що перетворення, яке може виконати компілятор, не зовсім те саме, що const T& -> T у C++. Останній створює копію аргументу: якщо необхідно, він викличе конструктор і деструктор копіювання.

У Carbon це не так: значення просто встановлюється на регістр. Оскільки викликана функція не викликає деструктор параметра, викликаю не потрібно викликати конструктор копіювання. Це означає, що оптимізація буде проведена навіть для вуглецевого еквівалента std::unique_ptr. там ...

Найбільш захоплюючою особливістю Carbon є його умовність викликів

Минулого тижня Чендлер Керрут анонсував Carbon, потенційну заміну C++, над якою він працював протягом двох років. Він має звичайні круті функції, яких ви очікуєте від сучасної мови: корисні генерики, інтерфейси компілятора/риси/концепції, модулі тощо. .

Це те, про що я сам думав у минулому, і, наскільки мені відомо, ніколи раніше не робилося мовою низького рівня, але ця концепція має великий потенціал. Дозвольте мені пояснити, про що я говорю.

Передача вуглецевих параметрів

За замовчуванням, тобто якщо ви більше нічого не пишете, параметри Carbon передаються через еквівалент const T& у C++.

бал класу { змінна x: i64; змінна y:i64; змінна z:i64; } fn Print(p: Dot); точка попадання { std::uint64_t x, y, z; }; void Print(const Point&p);

Проте - і це частина імпорту - компілятору дозволено перетворити це на T згідно з правилом "як ніби".

fn Print(x: i32); void Print(std::int32_tx);

... і що? Чому я так радію цьому?

Перевага №1: Продуктивність

Пропускати речі через const T& завжди добре, чи не так? Зрештою, ви уникаєте копії!

Хоча це правда, посилання по суті є покажчиками на рівні збірки. Це означає, що передача аргументу через const T& встановлює регістр на його адресу, що означає

у викликаючому аргументі потрібна адреса, і він повинен зберігатися десь у пам’яті, і у callee, параметр повинен завантажити значення з пам'яті під час його читання.

Це єдині варіанти для типів, які не вміщуються в реєстр, або невеликих типів із нетривіальними конструкторами копіювання, але вони менш ідеальні для тривіально скопійованих типів, які підходять.

Порівняйте збірку між функцією add, яка отримує свої аргументи через const T&

[[gnu::noinline]] int add(const int& a, const int& b) { повернути a + b; } int foo() { повертає add(11, 42); }

і той, хто цього не робить

[[gnu::noinline]] int add(int a, int b) { повернути a + b; } int foo() { повертає add(11, 42); }

Усі сховища та завантаження пам’яті зникають; ви не хочете переходити за посиланням!

Тож дуже добре, що в Carbon вам не потрібно думати про це – компілятор просто зробить правильні речі за вас. Крім того, ви не завжди можете зробити це вручну.

Перевага №2: Оптимальна домовленість про виклики в загальному коді

Припустімо, ми хочемо написати загальну функцію друку на C++. Тип може бути як завгодно великим із як завгодно дорогим конструктором копіювання, тому вам слід використовувати const T& у загальному коді.

модель void Print(const T&obj);

Однак це погіршує ситуацію для малих і дешевих типів, що є прикро. Це також не те, що компілятор може виправити за допомогою оптимізації, тому що сигнатура функції та умова виклику є частиною - ось наша улюблена абревіатура з трьох літер - ABI. У найкращому випадку компілятор може включити його та виключити весь виклик.

Є способи обійти це, бо, звичайно, вони є, але це працює™ у Carbon, і це добре.

Але справжня причина, чому я в захваті від цієї функції, не пов’язана з усуненням завантажень/зберігань пам’яті.

Перевага №3: ​​копії, які не є копіями

Зауважте, що перетворення, яке може виконати компілятор, не зовсім те саме, що const T& -> T у C++. Останній створює копію аргументу: якщо необхідно, він викличе конструктор і деструктор копіювання.

У Carbon це не так: значення просто встановлюється на регістр. Оскільки викликана функція не викликає деструктор параметра, викликаю не потрібно викликати конструктор копіювання. Це означає, що оптимізація буде проведена навіть для вуглецевого еквівалента std::unique_ptr. там ...

What's Your Reaction?

like

dislike

love

funny

angry

sad

wow