From 854298c7adff7d06063c87096c4aed7d8555c1b6 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Fri, 22 Sep 2023 17:47:14 +0200 Subject: [PATCH] Don't insert receiver NULL checks on GNUStep --- crates/objc2/src/runtime/message_receiver.rs | 30 +++++++------- .../expected/gnustep-x86.s | 16 +++----- .../expected/gnustep-x86_64.s | 12 ++---- .../test_msg_send_id/expected/gnustep-x86.s | 41 ++++++------------- .../expected/gnustep-x86_64.s | 30 ++++---------- 5 files changed, 45 insertions(+), 84 deletions(-) diff --git a/crates/objc2/src/runtime/message_receiver.rs b/crates/objc2/src/runtime/message_receiver.rs index bc637cf15..8d51173f8 100644 --- a/crates/objc2/src/runtime/message_receiver.rs +++ b/crates/objc2/src/runtime/message_receiver.rs @@ -154,6 +154,15 @@ mod msg_send_primitive { args: A, ) -> R { let msg_send_fn = R::MSG_SEND; + // Note: Modern Objective-C compilers have a workaround to ensure that + // messages to `nil` with a struct return produces `mem::zeroed()`, + // see: + // + // + // We _could_ technically do something similar, but since we're + // disallowing messages to `nil` with `debug_assertions` enabled + // anyhow, and since Rust has a much stronger type-system that + // disallows NULL/nil in most cases, we won't bother supporting it. unsafe { A::__invoke(msg_send_fn, receiver, sel, args) } } @@ -206,16 +215,12 @@ mod msg_send_primitive { sel: Sel, args: A, ) -> R { - // If `receiver` is NULL, objc_msg_lookup will return a standard C-method - // taking two arguments, the receiver and the selector. Transmuting and - // calling such a function with multiple parameters is UB, so instead we - // return NULL directly. - if receiver.is_null() { - // SAFETY: Caller guarantees that messages to NULL-receivers only - // return pointers, and a mem::zeroed pointer is just a NULL-pointer. - return unsafe { mem::zeroed() }; - } - + // If `receiver` is NULL, objc_msg_lookup will return a standard + // C-method taking two arguments, the receiver and the selector. + // + // Transmuting and calling such a function with multiple parameters is + // safe as long as the return value is a primitive (and e.g. not a big + // struct or array). let msg_send_fn = unsafe { ffi::objc_msg_lookup(receiver.cast(), sel.as_ptr()) }; let msg_send_fn = unwrap_msg_send_fn(msg_send_fn); unsafe { A::__invoke(msg_send_fn, receiver, sel, args) } @@ -228,11 +233,6 @@ mod msg_send_primitive { sel: Sel, args: A, ) -> R { - if receiver.is_null() { - // SAFETY: Same as in `send`. - return unsafe { mem::zeroed() }; - } - let superclass: *const AnyClass = superclass; let sup = ffi::objc_super { receiver: receiver.cast(), diff --git a/crates/test-assembly/crates/test_msg_send_error/expected/gnustep-x86.s b/crates/test-assembly/crates/test_msg_send_error/expected/gnustep-x86.s index 477d92eab..4dfd7773e 100644 --- a/crates/test-assembly/crates/test_msg_send_error/expected/gnustep-x86.s +++ b/crates/test-assembly/crates/test_msg_send_error/expected/gnustep-x86.s @@ -223,15 +223,13 @@ error_init: push esi sub esp, 16 mov esi, dword ptr [esp + 32] + mov edi, dword ptr [esp + 36] call .L5$pb .L5$pb: pop ebx mov dword ptr [esp + 12], 0 .Ltmp5: add ebx, offset _GLOBAL_OFFSET_TABLE_+(.Ltmp5-.L5$pb) - test esi, esi - je .LBB5_1 - mov edi, dword ptr [esp + 36] sub esp, 8 push edi push esi @@ -244,26 +242,22 @@ error_init: call eax add esp, 16 test eax, eax - je .LBB5_4 + je .LBB5_2 mov edx, eax xor eax, eax -.LBB5_6: +.LBB5_3: add esp, 16 pop esi pop edi pop ebx ret -.LBB5_1: - xor ecx, ecx - jmp .LBB5_5 -.LBB5_4: +.LBB5_2: mov ecx, dword ptr [esp + 12] -.LBB5_5: lea edx, [ebx + .Lanon.[ID].6@GOTOFF] call SYM(objc2[CRATE_ID]::__macro_helpers::msg_send_id::encountered_error::, 0) mov edx, eax mov eax, 1 - jmp .LBB5_6 + jmp .LBB5_3 .Lfunc_end5: .size error_init, .Lfunc_end5-error_init diff --git a/crates/test-assembly/crates/test_msg_send_error/expected/gnustep-x86_64.s b/crates/test-assembly/crates/test_msg_send_error/expected/gnustep-x86_64.s index 06fd47f8d..304ec665a 100644 --- a/crates/test-assembly/crates/test_msg_send_error/expected/gnustep-x86_64.s +++ b/crates/test-assembly/crates/test_msg_send_error/expected/gnustep-x86_64.s @@ -156,30 +156,24 @@ error_init: push r14 push rbx push rax - mov qword ptr [rsp], 0 - test rdi, rdi - je .LBB5_1 mov rbx, rsi mov r14, rdi + mov qword ptr [rsp], 0 call qword ptr [rip + objc_msg_lookup@GOTPCREL] mov rdx, rsp mov rdi, r14 mov rsi, rbx call rax test rax, rax - je .LBB5_4 + je .LBB5_2 mov rdx, rax xor eax, eax add rsp, 8 pop rbx pop r14 ret -.LBB5_1: - xor edi, edi - jmp .LBB5_5 -.LBB5_4: +.LBB5_2: mov rdi, qword ptr [rsp] -.LBB5_5: lea rsi, [rip + .Lanon.[ID].6] call SYM(objc2[CRATE_ID]::__macro_helpers::msg_send_id::encountered_error::, 0) mov rdx, rax diff --git a/crates/test-assembly/crates/test_msg_send_id/expected/gnustep-x86.s b/crates/test-assembly/crates/test_msg_send_id/expected/gnustep-x86.s index 72c27a5e9..c0267d281 100644 --- a/crates/test-assembly/crates/test_msg_send_id/expected/gnustep-x86.s +++ b/crates/test-assembly/crates/test_msg_send_id/expected/gnustep-x86.s @@ -155,14 +155,12 @@ handle_init: push edi push esi mov esi, dword ptr [esp + 16] + mov edi, dword ptr [esp + 20] call .L4$pb .L4$pb: pop ebx .Ltmp4: add ebx, offset _GLOBAL_OFFSET_TABLE_+(.Ltmp4-.L4$pb) - test esi, esi - je .LBB4_2 - mov edi, dword ptr [esp + 20] sub esp, 8 push edi push esi @@ -176,12 +174,6 @@ handle_init: pop edi pop ebx ret -.LBB4_2: - xor eax, eax - pop esi - pop edi - pop ebx - ret .Lfunc_end4: .size handle_init, .Lfunc_end4-handle_init @@ -193,15 +185,13 @@ handle_init_fallible: push ebx push edi push esi - mov esi, dword ptr [esp + 16] mov edi, dword ptr [esp + 20] + mov esi, dword ptr [esp + 16] call .L5$pb .L5$pb: pop ebx .Ltmp5: add ebx, offset _GLOBAL_OFFSET_TABLE_+(.Ltmp5-.L5$pb) - test esi, esi - je .LBB5_2 sub esp, 8 push edi push esi @@ -212,12 +202,12 @@ handle_init_fallible: call eax add esp, 16 test eax, eax - je .LBB5_2 + je .LBB5_1 pop esi pop edi pop ebx ret -.LBB5_2: +.LBB5_1: sub esp, 4 lea eax, [ebx + .Lanon.[ID].3@GOTOFF] push eax @@ -234,28 +224,28 @@ handle_init_fallible: .p2align 4, 0x90 .type handle_alloc_init,@function handle_alloc_init: + push ebp push ebx push edi push esi - mov esi, dword ptr [esp + 16] - mov edi, dword ptr [esp + 20] + sub esp, 12 + mov edi, dword ptr [esp + 40] + mov esi, dword ptr [esp + 32] + mov ebp, dword ptr [esp + 36] call .L6$pb .L6$pb: pop ebx .Ltmp6: add ebx, offset _GLOBAL_OFFSET_TABLE_+(.Ltmp6-.L6$pb) sub esp, 8 - push edi + push ebp push esi call objc_msg_lookup@PLT add esp, 8 - push edi + push ebp push esi call eax add esp, 16 - test eax, eax - je .LBB6_2 - mov edi, dword ptr [esp + 24] mov esi, eax sub esp, 8 push edi @@ -265,16 +255,11 @@ handle_alloc_init: push edi push esi call eax - add esp, 16 - pop esi - pop edi - pop ebx - ret -.LBB6_2: - xor eax, eax + add esp, 28 pop esi pop edi pop ebx + pop ebp ret .Lfunc_end6: .size handle_alloc_init, .Lfunc_end6-handle_alloc_init diff --git a/crates/test-assembly/crates/test_msg_send_id/expected/gnustep-x86_64.s b/crates/test-assembly/crates/test_msg_send_id/expected/gnustep-x86_64.s index d1b75f706..59dabf532 100644 --- a/crates/test-assembly/crates/test_msg_send_id/expected/gnustep-x86_64.s +++ b/crates/test-assembly/crates/test_msg_send_id/expected/gnustep-x86_64.s @@ -103,8 +103,6 @@ handle_alloc_fallible: .p2align 4, 0x90 .type handle_init,@function handle_init: - test rdi, rdi - je .LBB4_1 push r14 push rbx push rax @@ -117,9 +115,6 @@ handle_init: pop rbx pop r14 jmp rax -.LBB4_1: - xor eax, eax - ret .Lfunc_end4: .size handle_init, .Lfunc_end4-handle_init @@ -133,21 +128,17 @@ handle_init_fallible: push rax mov rbx, rsi mov r14, rdi - test rdi, rdi - je .LBB5_2 - mov rdi, r14 - mov rsi, rbx call qword ptr [rip + objc_msg_lookup@GOTPCREL] mov rdi, r14 mov rsi, rbx call rax test rax, rax - je .LBB5_2 + je .LBB5_1 add rsp, 8 pop rbx pop r14 ret -.LBB5_2: +.LBB5_1: lea rdx, [rip + .Lanon.[ID].3] mov rdi, r14 mov rsi, rbx @@ -163,32 +154,29 @@ handle_init_fallible: handle_alloc_init: push r15 push r14 + push r12 push rbx + push rax mov rbx, rdx mov r14, rsi mov r15, rdi - call qword ptr [rip + objc_msg_lookup@GOTPCREL] + mov r12, qword ptr [rip + objc_msg_lookup@GOTPCREL] + call r12 mov rdi, r15 mov rsi, r14 call rax - test rax, rax - je .LBB6_1 mov r14, rax mov rdi, rax mov rsi, rbx - call qword ptr [rip + objc_msg_lookup@GOTPCREL] + call r12 mov rdi, r14 mov rsi, rbx + add rsp, 8 pop rbx + pop r12 pop r14 pop r15 jmp rax -.LBB6_1: - xor eax, eax - pop rbx - pop r14 - pop r15 - ret .Lfunc_end6: .size handle_alloc_init, .Lfunc_end6-handle_alloc_init