Skip to content

Commit

Permalink
Don't insert receiver NULL checks on GNUStep
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Sep 24, 2023
1 parent f0591af commit b84f25d
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 86 deletions.
32 changes: 15 additions & 17 deletions crates/objc2/src/runtime/message_receiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
// <https://www.sealiesoftware.com/blog/archive/2012/2/29/objc_explain_return_value_of_message_to_nil.html>
//
// 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) }
}

Expand All @@ -180,8 +189,6 @@ mod msg_send_primitive {

#[cfg(feature = "gnustep-1-7")]
mod msg_send_primitive {
use core::mem;

use crate::encode::{EncodeArguments, EncodeReturn};
use crate::ffi;
use crate::runtime::{AnyClass, AnyObject, Imp, Sel};
Expand All @@ -206,16 +213,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) }
Expand All @@ -228,11 +231,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(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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::<objc2[CRATE_ID]::runtime::AnyObject>, 0)
mov edx, eax
mov eax, 1
jmp .LBB5_6
jmp .LBB5_3
.Lfunc_end5:
.size error_init, .Lfunc_end5-error_init

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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::<objc2[CRATE_ID]::runtime::AnyObject>, 0)
mov rdx, rax
Expand Down
41 changes: 13 additions & 28 deletions crates/test-assembly/crates/test_msg_send_id/expected/gnustep-x86.s
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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
Expand All @@ -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

Expand Down

0 comments on commit b84f25d

Please sign in to comment.