Реализация деструкторов в сгенерированном C-коде - PullRequest
0 голосов
/ 16 июня 2011

Предположим, что я когда-нибудь хотел бы написать компилятор, который генерирует код на языке C для языка, который:

  • имеет чисто подсчет ссылок GC,
  • позволяет вам возвращаться к точке в нескольких кадрахвверх по стеку (крадет форму (return-from) Common Lisp),
  • и позволяет вам определить деструктор для каждого типа данных (который вызывается непосредственно перед освобождением памяти для структуры данных).

Как бы вы это реализовали?Не могли бы вы сделать это (хорошо) с помощью C setjmp() и longjmp() и глобального списка точек, к которым нужно вернуться для очистки при разматывании стека?

Другая возможность - просто сгенерировать код C ++.

1 Ответ

1 голос
/ 29 июня 2011

Есть несколько способов, которые я бы рассмотрел в первую очередь.

Один похож на фреймы исключений.Создайте для каждого потока связанный список структур.Перед вызовом функции создайте структуру в стеке и добавьте ее в конец списка.Структура содержит jmp_buf.Вызовите setjmp, и если он вернет 0, продолжайте работу с этой функцией, в противном случае (каким-то образом) проверьте, не является ли вы целью return-from - если это так, затем продолжите работу с этой функцией, в противном случае очистите ваших местных жителей и longjmpпредыдущий кадр.Я думаю, что это может быть излишним, это зависит от того, насколько гибким должен быть этот return-from.Нужно ли только возвращаться из функции, которая находится в окружающей лексической области, или мы на самом деле ищем в стеке вызовов именованную функцию, которая может или не может даже присутствовать?Если первое, я сомневаюсь, что нам это нужно.

Другая возможность состоит в том, чтобы заставить все подсчитанные ссылками типы реализовывать общий интерфейс (внутренне для языковой реализации, это - это не должно быть видимым для пользователей),Затем вы можете просто создать стек (указателей) объектов, которые требуют очистки, вместе с возможностью создавать индексные точки в этом стеке, соответствующие уровням стека вызовов.При выходе из функции вы очищаете все переменные ниже уровня стека, к которому вы возвращаетесь, просто просматривая список с разыменованием каждого из них, вместо того, чтобы переходить к очистке сегментов кода в подпрограммах над нами в стеке вызовов.Тогда вы могли бы longjmp прямиком к цели или придумать «соглашение о вызовах», в котором возвращаемое значение, если говорить о вашем языке, фактически хранится в местоположении, определяемом параметром указателя (out-param), в то время как возвращаемое значение для C указывает, где в стеке вы возвращаетесь.Поэтому вызывающие программы проверяют, соответствует ли возвращаемое значение их собственному уровню, а если нет, немедленно возвращаются, и нет необходимости в longjmp.Это может быть или не быть более эффективным для longjmp, в зависимости от того, сколько уровней стека вы пропускаете, и, следовательно, сколько повторений проверки и возврата.

Эта схема немного похожа на стек очисткив Symbian / C ++.Фактически, это идет немного дальше - это не очищаемый ресурс, который должен реализовывать общий интерфейс, а то, что идет в стеке, это TCleanupItem, состоящий из функции, которая знает, как освободить ресурс, и некоторых данных для подачи вэта функция.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...