Когда Delphi чтит "inline", а когда нет? - PullRequest
5 голосов
/ 19 июня 2011

Я пытался оптимизировать фрагмент кода, имеющий такую ​​конструкцию:

while (i > 0) do begin
  Dec(i);

Это выглядит неэффективно, поэтому я попытался сделать это:

while (Dec(i) >= 0) do begin

Это не работает, потому что Dec - это процедура, а не функция.

Поэтому я переписываю это:

procedure Withloop;
var
  ....
  function Decr(var a: integer): integer; inline;
  begin
    Dec(a);
    Result:= a;
  end;

...
  while (Decr(i) >= 0) do begin

Но это компилируется в:

SDIMAIN.pas.448: while (Decr(i) >= 0) do begin
00468EE5 8BC4             mov eax,esp
00468EE7 E8D0FEFFFF       call Decr          <<--- A call??
00468EEC 85C0             test eax,eax
00468EEE 0F8D12FFFFFF     jnl $00468e06
00468EF4 EB01             jmp $00468ef7

Тем не менее, в другой части программы, она прекрасно вписывает функцию.
Какое практическое правило (или жесткое правило) я могу использовать, чтобы знать, что Delphi будет соблюдать директиву inline?

Ответы [ 2 ]

22 голосов
/ 19 июня 2011

Delphi Documentation перечисляет условия, при которых встраивание происходит или не происходит:

  • Встраивание не будет происходить ни при какой форме метода с поздним связыванием. Это включает виртуальные, динамические и методы сообщений.
  • Подпрограммы, содержащие ассемблерный код, не будут встроены.
  • Конструкторы и деструкторы не будут встроены.
  • Основной программный блок, инициализация блока и финализация блока блоки не могут быть встроены.
  • Подпрограммы, которые не определены перед использованием, не могут быть встроены.
  • Подпрограммы, принимающие параметры открытого массива, не могут быть встроены.
  • Код может быть встроен в пакеты, однако встраивание никогда не происходит через границы пакета.
  • Не производится встраивание между единицами, которые зависят от круга. это включает в себя косвенный циркуляр зависимости, например, блок А использует блок B, а блок B использует блок C, который в свою очередь использует блок А. В этом примере при компиляции блока A нет кода из блок B или блок C будет встроен в Единица А.
  • Компилятор может встроить код, когда блок находится в круговой зависимости, как до тех пор, пока приходит код для вставки от единицы вне циркуляра отношения. В приведенном выше примере, если блок A также используется блок D, код из блок D может быть встроен в A, так как он не участвует в циркуляре зависимость.
  • Если подпрограмма определена в разделе интерфейса и она осуществляет доступ символы, определенные в реализации раздел, эта рутина не может быть встраиваются.
  • Если в подпрограмме, помеченной inline, используются внешние символы из других единиц, все из этих единиц должны быть перечислены в использует оператор, иначе процедура не может быть встроен.
  • Процедуры и функции, используемые в условных выражениях в while-do и повторять до тех пор, пока заявления не могут быть развернутый.
  • В блоке должно быть определено тело для встроенной функции перед вызовом функции. В противном случае тело функции, который не известен компилятору когда он достигает места вызова, не может быть развернутым.

В вашем случае проверьте это условие:

Процедуры и функции, используемые в условных выражениях в операторах while-do и repeat-till, не могут быть развернуты встроенными.

10 голосов
/ 19 июня 2011

По какой-то причине компилятор не встроил while зацикленные выражения управления. Холвард Вассботн обсуждал проблему некоторое время назад (читайте в конце статьи).

...