Skip to content

Why is the code size of catch_unwind so large ? #64224

Closed
@gnzlbg

Description

@gnzlbg

While filling #64222 I noticed that we generate more code than C++ for catch_unwind. That did not feel right, since C++'s catch can do much more than Rust's catch unwind, e.g., filtering different types of exceptions, etc.

MWE: C++ (https://gcc.godbolt.org/z/z_dgPg):

extern "C" void foo();

int bar() {
    try {
        foo();
        return 42;
    } catch(...) {
        return 13;
    }
}

generates

bar(): # @bar()
  push rbx
  mov ebx, 42
  call foo
  mov eax, ebx
  pop rbx
  ret
  mov rdi, rax
  call __cxa_begin_catch
  call __cxa_end_catch
  mov ebx, 13
  mov eax, ebx
  pop rbx
  ret

while Rust (https://gcc.godbolt.org/z/4sbc6k):

#![feature(unwind_attributes)]

extern "C" {
    // can unwind:
    #[unwind(allow)] fn foo(); 
}

pub unsafe fn bar() -> i32 {
    std::panic::catch_unwind(|| { foo(); 42 }).unwrap_or(13)
}

generates

example::bar:
  push rbp
  push r14
  push rbx
  sub rsp, 32
  mov qword ptr [rsp + 16], 0
  mov qword ptr [rsp + 24], 0
  lea rdi, [rip + std::panicking::try::do_call]
  lea rsi, [rsp + 12]
  lea rdx, [rsp + 16]
  lea rcx, [rsp + 24]
  call qword ptr [rip + __rust_maybe_catch_panic@GOTPCREL]
  test eax, eax
  je .LBB2_1
  mov rdi, -1
  call qword ptr [rip + std::panicking::update_panic_count@GOTPCREL]
  mov r14, qword ptr [rsp + 16]
  mov rbx, qword ptr [rsp + 24]
  mov rdi, r14
  call qword ptr [rbx]
  mov rsi, qword ptr [rbx + 8]
  mov ebp, 13
  test rsi, rsi
  je .LBB2_5
  mov rdx, qword ptr [rbx + 16]
  mov rdi, r14
  call qword ptr [rip + __rust_dealloc@GOTPCREL]
  jmp .LBB2_5
.LBB2_1:
  mov ebp, dword ptr [rsp + 12]
.LBB2_5:
  mov eax, ebp
  add rsp, 32
  pop rbx
  pop r14
  pop rbp
  ret
  mov rbp, rax
  mov rdi, r14
  mov rsi, rbx
  call alloc::alloc::box_free
  mov rdi, rbp
  call _Unwind_Resume@PLT
  ud2

This appears to be a constant overhead every time catch_unwind is used (e.g. see https://gcc.godbolt.org/z/bAvN24). Maybe we are inlining too much ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-enhancementCategory: An issue proposing an enhancement or a PR with one.I-heavyIssue: Problems and improvements with respect to binary size of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions