Затворы ДИП

Сделайте укупорку великолепной хоть раз».

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

Второй — цепочка контекстов со следующим указателем, хранящимся в конце объекта контекста (если есть родитель, статически мы его знаем)

Третье — все доступы к переменным при выполнении codegen в этих областях видимости проходят через контекстный указатель (но мы можем сохранять ссылки на глубоко вложенные контексты).

Последний — иметь квалификаторы для делегата, чтобы указать, должен ли его контекст быть общим или постоянным. Если да — убедитесь, что в этом замыкании нет доступа к изменяемым данным. Мы можем начать с черепах до самого верха — если самый глубокий уровень неизменяем, вся цепочка должна быть такой же, как и с общим.

Примеры кода:

1-й — 2 отдельных прицела с общим родительским прицелом, передать их в «черную дыру». Blackhole вызывает их N раз. взяв из массива в качестве кольцевого буфера. Изображение, обсудите, как код генерируется этим DIP.

2-й — найти код, который сегодня не компилируется (2 указателя контекста!!!) и показать новый путь.

3-й — &instance.foo и его codegen теперь, сравните с 1-м.

4-й — более длинные цепочки с телами циклов, контекст выделяется несколько раз.

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

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

  1. no vtbl struct — смещение к полям, вычисляемым как обычно
  2. vtbl struct — нужно было пропустить vtbl еще до этого слова DIP +1 во всех полях
  3. context — подобно структуре, но имеет «следующий» в конце_ структуры, он также может не существовать(!), если используется только первый уровень контекста (анализ ststic). Для обобщения и оптимизации (см. ниже) он может иметь смещение +K слов для доступа к полям.
  4. делегат — это контекст, в котором next не существует, а codegen имеет K=0 или K=+1.

Таким образом, на самом деле число 3 достаточно общее, чтобы охватить все 4 способа выполнения «T-делегата (ARGS)». Поэтому у нас может быть один ABI с кодом, скомпилированным в предположении определенного смещения от this (структуры или класса!) или просто области видимости.

Оптимизация может быть сделана для объединения областей видимости, если они никогда не используются в циклах и т. д. В этом DIP об этом не говорится, но в некоторых распространенных (!) случаях мы можем просто выделить кадр стека в куче GC или лучше выделить с помощью RC.

RC для замыканий также выходит за рамки этого DIP, но мы показываем, как мы можем легко подсчитывать каждый из контекстных объектов  — после next или в любом другом месте, пока функции у нас есть. один и тот же код для. обычный this.foo(a,b,c) и auto dg = this.foo; дг(а,б,в);

Это в основном говорит о том, что ABI делегата должен быть таким же, как «этот вызов», и мы должны сделать это уже (!).