Почему LLVM ARC постоянно сохраняет объекты перед тем, как их бросать? - PullRequest
1 голос
/ 07 апреля 2019

Рассмотрим следующие простые функции:

void simple_throw(id object) {
    @throw object;
}

void extra_throw(id object) {
    id tmp0 = object;
    id tmp1 = tmp0;
    id tmp2 = tmp1;
    @throw tmp2;
}

Сначала я подумал, что обе эти функции должны компилироваться в одну и ту же сборку, и обе должны быть эквивалентны простому вызову objc_exception_throw(object) (поскольку функция аргументы autorelease по умолчанию в ARC ), возможно, с одним добавленным objc_retain(object) (поскольку ARC не является безопасным для исключения и по умолчанию имеет утечку).

Но этоне тот случайВот сборка (удаление некоторых из лишних пухов и директив .cfi_*; аргументы лязга: -fobjc-arc -Ofast -fomit-frame-pointer -S):

_simple_throw:
    pushq   %rax
    callq   *_objc_retain@GOTPCREL(%rip)
    movq    %rax, %rdi
    callq   _objc_retainAutorelease
    movq    %rax, %rdi
    callq   _objc_exception_throw

_extra_throw:
    pushq   %rbx
    movq    _objc_retain@GOTPCREL(%rip), %rbx
    callq   *%rbx
    movq    %rax, %rdi
    callq   *%rbx
    movq    %rax, %rdi
    callq   *%rbx
    movq    %rax, %rdi
    callq   *%rbx
    movq    %rax, %rdi
    callq   _objc_retainAutorelease
    movq    %rax, %rdi
    callq   _objc_exception_throw

simple_throw сохраняет object дважды , иextra_throw сохраняет object 5 раз!

Это приводит к двум вопросам:

  1. Какова оптимальная сборка (с точки зрения удержания и авто-выпусков) для simple_throw, чтокомпилятор должен генерировать (при условии, что мы хотим, чтобы сгенерированный код был ARC-совместимым)?
  2. Почему присвоения локальным переменным в extra_throw приводят к дополнительному сохранению?Я склонен думать, что это ошибка компилятора.
...