Обновить
52.83

Компиляторы *

Из исходного кода в машинный

Сначала показывать
Порог рейтинга
Уровень сложности

Знакомьтесь, loop fracking

Время на прочтение15 мин
Количество просмотров14K
image

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

Автор назвал эту технику “loops fracking” по аналогии с, например, “loops unrolling” или “loops nesting”. Тем более, что термин отражает смысл и не занят.
Читать дальше →

Легковесный конструктор парсеров с интерактивным режимом

Время на прочтение9 мин
Количество просмотров9K
Периодически сталкиваясь с мелкими задачками по разработке простеньких анализаторов текста, решил данную задачу автоматизировать, да и академический интерес не давал покоя. Первоначально смотрел в сторону Racc (одна из интерпретаций Yacc), но он мне показался достаточно не простым решением для моих мелких задач и тогда я решил разработать свой простенький анализатор. Хотя, конечно, если вы разрабатываете компилятор или что-то подобное да и еще в промышленных масштабах, то определенно вам стоит посмотреть в сторону Racc.

Но если вы хотите сами разобраться, что же такое парсер и как быстренько его написать самому, при этом не читая кучу статей про лексические анализаторы типа книги дракона, тогда вперед под кат (хотя книга очень хорошая).
Читать дальше →

Конец эпохи динамических языков

Время на прочтение8 мин
Количество просмотров45K
Несколько последних месяцев я программирую преимущественно на Scala (по работе) и на Haskell (для души). На этой неделе я, правда, ещё немного пописал на Ruby (по работе) и Clojure (для души).

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

Но вот что касается моего новенького, с иголочки, проекта-любимца на Clojure… О, Clojure! Глоток свежего воздуха! Благодатная земля хорошо скомпонованных функций, иммутабельных структур данных и всего такого. Как прекрасен твой синтаксис и как мудра твоя чувствительность! Вся твоя суть в функциях, принимающих мэпы и возвращающих мэпы. И твой SQL-генератор, и слой доступа к БД, и HTML-парсер, и URL-роутер являют собой одну и ту же завораживающую картину мэпов, гоняемых туда-сюда тактами процессора, прекрасную с своём ритме хорошо собранных швейцарских часов.

Вернуться к Clojure после долгого времени это всё равно, что почувствовать себя дома. Это просто окрыляет программиста. Но почему-то в этот раз я ощутил и ещё одно, неожиданное для себя чувство: неопределённость.
Читать дальше →

Полвека «универсальным машинным языкам» (1966—2016): прошлое, настоящее, будущее

Время на прочтение27 мин
Количество просмотров19K
КДПВ

Прошлое


Повествование можно начать с 1962 г., когда в Кембриджском университете началась работа над CPL («Cambridge Programming Language») — «усовершенствованным вариантом» ALGOL-60. К работе над языком подключился аспирант Мартин Ричардс; главной сложностью в реализации нового ЯП ему показалась необходимость ручного портирования компилятора для разных компьютерных платформ. В частности, когда кембриджский EDSAC-2 заменили на Atlas-2, разработчики CPL потратили много времени на портирование своего компилятора для новой платформы.

Диссертация Мартина была посвящена «само-компилирующемуся» CPL: разработанный Мартином компилятор был написан на сильно упрощённом варианте CPL, компилятор которого несложно было написать на тогдашнем макроассемблере. Перенос CPL на новую платформу теперь можно было выполнить в два шага:
  1. Вручную пишем компилятор «упрощённого CPL»;
  2. Компилируем им компилятор «полного CPL».

На этом Мартин не остановился, и разработал BCPL — систему для разработки переносимых компиляторов. Компилятор BCPL генерировал псевдокод, названный Мартином «OCODE».
OCODE выглядел примерно так:
OCODE «расшифровка» («procode»)
94 5 L1 83 73 69 86 69
95 4
42 0
42 0 40 2 14
83
42 0 42 1 40 2 14 83
42 2
40 3 42 1 15
92
85 L5
90 L6
42 1 40 4 40 2 14 83
40 4 42 1 14 80 4 
90 5 40 4 40 5 88 L6
91 4
42 2 40 3 42 1 15 92
85 L7
90 L8 40 4 40 2 14
8 87 L9
40 4 42 2 11 92
85 L11
90 L10
42 0 40 6 40 2 14 83
40 4 40 6 14 80 6
90 L11
40 6 40 3 22 86 L10
91 6 90 L9
40 4 42 1 14 80 4
90 L7 40 4 40 5 88 L8
91 4 97 103 0
ENTRY 5 L1  'S' 'I' 'E' 'V' 'E'
SAVE 4
LN 0
LN 0 LP 2 PLUS
STIND
LN 0 LN 1 LP 2 PLUS STIND
LN 2
LP 3 LN 1 MINUS
STORE
JUMP L5
LAB L6
LN 1 LP 4 LP 2 PLUS STIND
LP 4 LN 1 PLUS SP 4
LAB L5 LP 4 LP 5 ENDFOR L6
STACK 4
LN 2 LP 3 LN 1 MINUS STORE
JUMP L7
LAB L8 LP 4 LP 2 PLUS
RV JF L9
LP 4 LN 2 MULT STORE
JUMP L11
LAB L10
LN 0 LP 6 LP 2 PLUS STIND
LP 4 LP 6 PLUS SP 6
LAB L11
LP 6 LP 3 LS JT L10
STACK 6 LAB L9
LP 4 LN 1 PLUS SP 4
LAB L7 LP 4 LP 5 ENDFOR L8
STACK 4 RTRN ENDPROC 0
; заголовок процедуры
; стековый кадр (два параметра и две локальные переменные)
; поместить на стек число 0
; поместить ещё один 0, прибавить к нему 2-ой элемент стека
; записать в массив на вершине стека значение под ним
; всё то же самое для 1-ого элемента массива
; поместить на стек число 2
; вычесть единицу из значения 3-его элемента стека
; записать результат в локальную переменную
; перейти к метке L5
; объявление метки L6
; взять 4-ый элемент стека, записать в массив по этому индексу 1
; прибавить к 4-ому элементу стека 1, записать результат обратно
; L5: перейти к метке L6, если 4-ый элемент стека <= 5-ому
; объявление, что на стеке сейчас четыре элемента
; вычесть единицу из значения 3-его элемента стека
; перейти к метке L7
; L8: сложить 4-ый и 2-ой элементы стека
; прочитать значение по этому адресу; если это 0, перейти к L9
; умножить 4-ый элемент на два
; перейти к метке L11
; объявление метки L10
; взять 6-ой элемент стека, записать в массив по этому индексу 0
; прибавить к 6-ому элементу стека 4-ый, записать рез-т обратно
; объявление метки L11
; перейти к метке L10, если 7-ой элемент стека меньше 4-ого
; на стеке сейчас шесть элементов; объявление метки L9
; прибавить к 4-ому элементу стека 1, записать результат обратно
; L10: перейти к L8, если 4-ый элемент стека <= 5-ому
; на стеке четыре элемента; окончание процедуры
(Для экономии места, последовательности команд записаны в одну строчку. Мартин в своём руководстве по BCPL поступает точно так же.)

Исходный код на BCPL:
LET sieve(workvec, vecsize) BE
{
  workvec!0 := 0
  workvec!1 := 0
  FOR i = 2 TO vecsize-1 DO workvec!i := 1
  FOR i = 2 TO vecsize-1 DO
    IF workvec!i DO
    { LET j = 2 * i
      WHILE j < vecsize DO
      { workvec!j := 0
        j := j + i
      }
    }
}
В более новых версиях OCODE добавилась поддержка чисел с плавающей точкой (соответственно, набор поддерживаемых опкодов почти удвоился), а также удалили опкод ENDFOR — вместо него генерируется пара LE JT.

Среди «универсальных машинных языков» OCODE уникален тем, что метки в нём определяются специальными инструкциями — т.е. для интерпретации программы её нужно сначала всю загрузить в память, и найти в ней метки.
— а отдельная программа, кодогенератор, превращала файл с таким псевдокодом в исполнимую программу для конечного процессора. OCODE сохранялся в виде текстового файла из десятичных чисел, разделённых пробелами и переводами строк: в то время, когда OCODE разрабатывался, привязка формата файла к конкретному размеру байта ограничивала бы переносимость такого файла.

Компилятор BCPL(1) поставлялся в виде OCODE, и чтобы перенести его на новую платформу, нужно было:
  1. Вручную написать интерпретатор псевдокода(2) (на любом языке, хоть на Бейсике);
  2. Адаптировать кодогенератор,(3) написанный на BCPL, для своей платформы;
  3. Запустить под интерпретатором (2) компилятор BCPL (1), скормить ему кодогенератор (3), и получить на выходе исполнимый файл кодогенератора(4);
    • Интерпретатор (2) нам с этого момента больше не нужен.
  4. Прогнать через кодогенератор (4) псевдокод компилятора (1), и получить на выходе исполнимый файл компилятора.


Такой подход означал, что для переноса компилятора на новую платформу требуется лишь самый минимум низкоуровневого программирования; и действительно, реализация BCPL была завершена к 1967 г. — раньше, чем была завершена реализация CPL, начатая на несколько лет раньше!

Достоинства BCPL применительно к системному программированию вдохновили Кена Томпсона на создание языка Би, а тот — коллегу Кена, Денниса Ритчи, на создание Си. Именно из BCPL пошла традиция обозначать {фигурными скобками} блоки программы, и именно на BCPL была написана первая программа «Hello, World!».
GET "libhdr"

LET start() = VALOF
{ writef("Hello*n")
  RESULTIS 0
}
Более важная нам причина, по которой BCPL вошёл в историю: OCODE — первая универсальная «архитектура набора команд» (ISA), т.е. «виртуальная машина», не привязанная ни к какой конкретной аппаратной платформе с её особенностями. BCPL, таким образом — первый язык программирования, соответствующий парадигме «Write once, run anywhere» (WORA): программу на BCPL можно распространять в скомпилированном виде, и её можно будет запустить на любой платформе, для которой существует OCODE-кодогенератор.
Читать дальше →

Введение в разработку предметно-ориентированных языков (DSL) с помощью EMFText

Время на прочтение18 мин
Количество просмотров14K

Это 5-я статья цикла по разработке, управляемой моделями. В предыдущих статьях мы уже разобрались с метамоделями, валидацией моделей, некоторыми нотациями для моделей (диаграммы и таблицы). Всё это было в рамках пространства моделирования MOF. Сегодня мы построим мост в пространство моделирования EBNF – познакомимся с текстовой нотацией для MOF-моделей.
Читать дальше →

Где и как купить USDT в Москве: топ 3 способа

Время на прочтение9 мин
Количество просмотров36K
Что такое USDT и зачем он нужен
USDT, или Tether, — это стейблкоин. Это значит, что в отличие от обычных криптовалют, цена на него не скачет вверх-вниз. Один токен USDT всегда равен примерно одному доллару США. Почему это удобно? Представь, что у тебя есть биткоины — сегодня они стоят много, а завтра — на 20% меньше. Не очень приятно, да? А USDT стабилен. Это как цифровой доллар, только без банков.

Tether придумали для того, чтобы можно было хранить деньги в криптовалюте, не переживая о резких изменениях курса. Его используют трейдеры, бизнесмены и просто люди, которым нужен надёжный и быстрый способ перевода денег по всему миру.

Почему именно USDT популярен среди москвичей


Представь себе: ты в Москве, и хочешь перевести деньги родственнику за границу. Через банк — долго, куча проверок и комиссий. А с USDT всё просто: за пару минут токены улетят хоть в Индию, хоть в Аргентину. Без лишних вопросов.
Читать дальше →

Дизайн и эволюция языка С++: выдержки

Время на прочтение8 мин
Количество просмотров26K
В комментариях к переводу «30 лет С++» было заметно, что далеко не все этапы эволюции языка одинаково хорошо известны, иногда вообще нету представления о происхождении и процессе развития того или иного элемента синтаксиса или соответствующей семантики. Возможно, этой заметкой удастся заинтересовать читателей обратится к уже давно не новой книге автора языка с целью формирования более полной картины о C++. Книга рассказывает как происходило его развитие, что оказывало влияние на этот процесс и почему было отдано предпочтение одним подходам вместо других.
Читать дальше →

Статический анализ printf-like функций в Си при помощи libclang

Время на прочтение11 мин
Количество просмотров8.6K
По сравнению со многими современными языками язык Си зачастую кажется крайне примитивным и небезопасным. И одной из частых претензий к языку является невозможность доступа из кода в его же внутреннее представление. В других языках это традиционно осуществляется механизмами, вроде reflections, и довольно удобно в применении.

Тем не менее, с появлением libclang, можно писать собственные анализаторы и генераторы кода прямо в compile time, устраняя достаточно большое множество проблем на ранних этапах работы. Сочетание инструментов статического анализа общего плана (coverity, clang-scan), инструментов анализа для конкретного проекта, а также дисциплины написания кода позволяет намного улучшить качество и безопасность кода, написанного на Си. Конечно, это не даст гарантий, каких дает haskell или даже rust, но позволяет существенно оптимизировать процесс разработки, особенно в случае, когда переписывать огромный проект на другом языке является нереальной задачей.

В данной статье я хотел бы поделиться опытом создания плагина статического анализа format argument для функций, похожих на printf. В ходе написания плагина, мне пришлось очень много рыться в исходниках и doxygen документации libclang, поэтому я счел полезным сделать некоторый обзор для тех, кто хочет ступить на этот тернистый путь, но пока еще не уверен в целесообразности траты времени на сбор информации. В статье не будет картинок, и даже картинок блюющих единорогов, простите.
Читать дальше →

К тридцатилетию первого C++ компилятора: ищем ошибки в Cfront

Время на прочтение5 мин
Количество просмотров19K
Бьёрн Страуструп
Авторы: Андрей Карпов, Бьёрн Страуструп.

Cfront это компилятор для С++, существующий примерно с 1983 года и разработанный Бьёрном Страуструпом. В то время он был известен как «C с классами». Cfront имел полноценный парсер, таблицы символов, строил дерево для каждого класса, функции и т.д. Cfront был основан на CPre. Cfront определял развитие языка приблизительно до 1990г. Многие неясные моменты, имеющие место в С++, связаны с ограничениями реализации Cfront. Причина в том, что Cfront осуществлял трансляцию с C++ в C. Одним словом, Cfront — это священный артефакт для любого C++ программиста. И я просто не мог пройти мимо, не проверив этот проект.
Читать дальше →

Анализ AST c помощью паттернов

Время на прочтение12 мин
Количество просмотров12K

Сейчас я работаю над senjin/gglsl — библиотекой для программирования шейдеров с помощью Groovy, о которой недавно писал.

Здесь я опишу три подхода к анализу AST (abstract syntax tree), все на примерах под-задач, вытекающих одна из другой и связанных общим контекстом: рекурсивные функции, паттерн Visitor, и паттерн-матчинг.
Паттерн-матчинг реализован на Java и доступен на GitHub.
Читать дальше →

30 лет С++

Время на прочтение7 мин
Количество просмотров34K
14 октября этого года состоялась одна из важнейших годовщин мира программирования – 30-летие языка C++. За это время он завоевал огромную популярность и до сих пор остаётся одним из самых востребованных и широко используемых языков программирования в мире.

В связи с этим юбилеем мы предлагаем вашему вниманию перевод интервью с основателем языка Бьёрном Страуструпом.


Читать дальше →

Автоматическая генерация программного кода микроконтроллера на основе событийно-ориентированной модели

Время на прочтение4 мин
Количество просмотров16K
Постановка задачи:
Создание сложной автоматизированной системы на основе контроллера для управления различной периферией (электронные замки, двигатели, светодиодные ленты и прочая электроника).

Создание данной системы потребовалась для квест комнаты, подобной этой, но в городе Хабаровск.
Наш квест в ином сеттинге, но в целом имеет примерно тот же набор исполнительных механизмов: реле, замки, ленты, герконы и т.д.

Основные требования к системе:
  • Надежность — при разработке сложных систем высока вероятность допустить трудно уловимые ошибки, чем больше код тем больше шанс пропустить ошибку и тем больше времени нужно на отладку, необходимо свести к минимуму вероятность некорректной работы.
  • Гибкость — возможность с минимальными временными затратами изменить логику работы
  • Функциональность — управление любым оборудованием и подключение любых сенсоров

image
Читать дальше →

Интервью с Одри Тан, часть 1

Время на прочтение9 мин
Количество просмотров6K


Одри Тан в первую очередь известна как создатель и разработчик Pugs, Perl 6 User’s Golfing System, реализации Perl 6 на Haskell, которая появилась 1 февраля 2005 года и была наиболее активно разрабатываемой и наиболее полной реализацией на то время.
Читать интервью

Ближайшие события

Microsoft добавит поддержку компилятора Clang в ноябрьском обновлении Visual Studio 2015

Время на прочтение2 мин
Количество просмотров22K


Microsoft добавит поддержку компилятора Clang в ноябрськом обновлении Visual Studio 2015 — об этом было заявлено на конференции CPPCon 2015, проходящей сейчас в городе Белвью, США.

Clang это компилятор кода на С, С++ и Objective-C, который в связке с LLVM позволяет собирать программы под различные платформы. Visual Studio 2015 уже поддерживает Clang для разработки Android и iOS-приложений. При разработке под Android можно выбирать между GCC и Clang, а для iOS приходится использовать внешний Mac в качестве билд-сервера.

Планируемое обновление принесёт поддержку Clang на качественно новом уровне — теперь им можно будет собирать обычные Windows-приложения.
Читать дальше →

JCoro — асинхронность на сопрограммах в Java

Время на прочтение13 мин
Количество просмотров15K
К исследованиям в этой сфере меня вдохновила статья Асинхронность: назад в будущее. В ней автор описывает идею о том, как, используя сопрограммы, можно упростить асинхронный код так, чтобы выглядел он так же, как обычный синхронный, но сохранял плюшки, которые нам даёт применение асинхронных операций. Вкратце, суть подхода такова: если у нас есть механизм, позволяющий сохранять и восстанавливать контекст выполнения (поддержка сопрограмм), то код на цепочках callback'ов

startReadSocket((data) -> {
   startWriteFile(data, (result) -> {
      if (result == ok) ...
   });
});

мы можем переписать так:

data = readSocket();
result = writeFile(data);
if (result == ok) ...

Здесь readSocket() и writeFile() — сопрограммы, в которых асинхронные операции вызываются следующим образом:

byte[] readSocket() {
    byte[] result = null;
    startReadSocket((data) -> {
	    result = data;
	    resume();
    });
    yield();
    return result;
}

Методы yield() и resume() сохраняют и восстанавливают контекст выполнения, со всеми фреймами и локальными переменными. Происходит следующее: при вызове readSocket() мы планируем асинхронную операцию вызовом startReadSocket() и выполняем yield(). Yield() сохраняет контекст выполнения и поток завершается (возвращается в пул). Когда асинхронная операция будет выполнена, мы вызовем resume() перед выходом из callback'a, и тем самым возобновим выполнение кода. Управление снова получит основная функция, которая вызовет writeFile(). writeFile() устроен аналогично, и всё повторится.

Сделав единожды такое преобразование для всех используемых асинхронных операций и поместив полученные функции в библиотеку, мы получаем инструмент, позволяющий нам писать асинхронный код так, как будто это обычный синхронный код. Мы получаем возможность сочетать плюсы синхронного кода (читабельность, удобная обработка ошибок) и асинхронного (производительность). Плата за это удобство — необходимость как-то сохранять и восстанавливать контекст выполнения. В статье автор описывает реализацию на С++, мне же захотелось заиметь что-то такое в Java. Об этом и пойдёт речь.
Читать дальше →

Async/await и механизм реализации в C# 5.0

Время на прочтение20 мин
Количество просмотров81K

Подробно о преобразовании асинхронного кода, осуществляемого компилятором


Механизм async реализован в компиляторе C# при поддержке со стороны библиотек базовых классов .NET. В саму исполняющую среду не пришлось вносить никаких изменений. Это означает, что ключевое слово await реализовано путем преобразования к виду, который мы могли бы написать и сами в предыдущих версиях C#. Для изучения генерируемого кода можно воспользоваться декомпилятором .NET Reflector или ILSpy. Это не только интересно, но и полезно для отладки, анализа производительности и других видов диагностики асинхронного кода.
Подробности

А ваш язык программирования необоснованный? (или почему предсказуемость важна)

Время на прочтение15 мин
Количество просмотров35K
Как должно быть очевидно, одна из целей этого сайта — убедить принимать F# всерьёз в роли универсального языка разработки.

Но в то время как функциональный стиль всё больше проникает в массы, и C# уже получил такие функциональные средства как лямбды и LINQ, кажется, что C# всё больше и больше наступает на пятки F#. Так что, как это ни странно, но я стал всё чаще слышать как высказывают такие мысли:

  • «C# уже обладает большей частью инструментария F#, и зачем мне напрягаться с переходом?»
  • «Нет никакой необходимости что-то менять. Всё, что нам нужно сделать, так это пару лет подождать, и C# получит достаточно от F#, что обеспечит практически все плюшки.»
  • «F# только чуть лучше, чем C#, но не настолько, чтобы в самом деле тратить время с переходом на него.»
  • «F# кажется действительно неплох, хоть и пугает местами. Но я не могу найти ему практического применения, чтобы использовать вместо C#.»

Не сомневаюсь, что теперь, когда и в Java тоже добавлены лямбды, подобные комментарии зазвучали в экосистеме JVM при обсуждении «Scala и Closure против Java».

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

По следам C++ Siberia: дракон в мешке

Время на прочтение7 мин
Количество просмотров24K
Конференции бывают разные. Некоторые собирают огромные толпы зрителей, другие могут быть интересны лишь полутора специалистам.

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

На самом деле, пост не о том.

Так уж вышло, что мне довелось выступать на означенной конференции, где я на пальцах и с приплясываниями рассказывал, что такое LLVM, чем интересна нотация SSA, что такое IR код и, наконец, как так получается, что детерменированные на первый взгляд C++ программы, оказывается, провоцируют неопределенное поведение.

Кстати, этот доклад можно поставить пятым номером в серии статей про виртуальную машину Smalltalk. Многие просили подробнее рассказать о LLVM. В общем, убиваем всех зайцев сразу. Заинтересовавшимся, предлагаю «откинуться на спинку кресла», опционально налить чего-нибудь интересного и послушать. Обещаю, что больше часа времени я не отниму.

Ах да, под катом можно найти пояснения тех моментов, которым не было уделено должное внимание на конференции. Я постарался ответить на часто задаваемые вопросы и детально разобрать листинги LLVM IR. В принципе, текстовую часть статьи можно читать как самостоятельное произведение, тем не мене я рассчитывал на то, что читатель обратится к нему уже после просмотра видео.


Читать дальше →

Приемы использования масочных регистров в AVX512 коде

Время на прочтение14 мин
Количество просмотров12K
В процессорах компании Intel на смену AVX2 приходит новый набор инструкций AVX512, в котором появилась концепция масочных регистров. Автор этой статьи уже несколько лет занимается разработкой версии библиотеки Intel Integrated Performance Primitives, оптимизированной для AVX512, и накопил довольно большой опыт использования AVX512 инструкций с масками, который было решено объединить в одну отдельную статью, поскольку само использование таких инструкций с масками позволяет упростить и ускорить код в дополнение к ускорению от двукратного увеличения ширины регистров.
далее несколько примеров использования AVX512 инструкций с масками

Нет ничего проще, чем вызвать функцию, я сам это делал неоднократно

Время на прочтение12 мин
Количество просмотров36K

Предшествующая статья про исключения в С++ оставила кучу тёмных мест,
главное, что осталось непонятным — так как же всё-таки осуществляется
передача управления при возбуждении исключения?
С SJLJ всё понятно, но, утверждается, что эта технология практически
вытеснена некоторым без-затратным (при отсутствии исключений) табличным механизмом.
А вот что это за механизм такой и как он устроен, будем разбираться под катом.
Читать дальше →

Вклад авторов