the compiler does not seem to be able to tell when a calling an isolated method that does not read or mutate the actor state on all code paths is the same as calling a nonisolated version of it that explicitly does not acquire the actor lock if not needed:
public
actor A
{
var i:Int
init()
{
self.i = 0
}
}
extension A
{
nonisolated public
func set1(i:Int) async
{
if i != 0
{
await self.set(i: i)
}
}
public
func set2(i:Int)
{
if i != 0
{
self.set(i: i)
}
}
private
func set(i:Int)
{
self.i = i
}
}
public
func test1(a:A, i:Int) async
{
await a.set1(i: i)
}
public
func test2(a:A, i:Int) async
{
await a.set2(i: i)
}
output:
output.test1(a: output.A, i: Swift.Int) async -> ():
mov rcx, r14
mov qword ptr [r14 + 24], rsi
mov qword ptr [r14 + 16], rdi
test rsi, rsi
je .LBB14_2 // returns early without acquiring lock
mov rax, rdi
lea rdi, [rip + ((1) suspend resume partial function for output.test1(a: output.A, i: Swift.Int) async -> ())]
mov r14, rcx
mov rsi, rax
xor edx, edx
jmp swift_task_switch@PLT
.LBB14_2:
mov r14, rcx
jmp qword ptr [rcx + 8]
(1) suspend resume partial function for output.test1(a: output.A, i: Swift.Int) async -> ():
push rax
mov r13, qword ptr [r14 + 16]
mov rdi, qword ptr [r14 + 24]
mov rax, qword ptr [r13]
call qword ptr [rax + 80]
mov rax, r14
pop rcx
jmp qword ptr [rax + 8]
output.test2(a: output.A, i: Swift.Int) async -> ():
mov rax, rdi
mov qword ptr [r14 + 24], rsi
mov qword ptr [r14 + 16], rdi
lea rdi, [rip + ((1) suspend resume partial function for output.test2(a: output.A, i: Swift.Int) async -> ())]
mov rsi, rax
xor edx, edx
jmp swift_task_switch@PLT
(1) suspend resume partial function for output.test2(a: output.A, i: Swift.Int) async -> ():
push rax
mov rax, r14
mov rdi, qword ptr [r14 + 24]
test rdi, rdi
je .LBB17_2 // returns after acquiring lock
mov r13, qword ptr [rax + 16]
mov r14, rax
mov rax, qword ptr [r13]
call qword ptr [rax + 80]
mov rax, r14
.LBB17_2:
mov r14, rax
pop rcx
jmp qword ptr [rax + 8]
is this a missed optimization opportunity? is there a reason why test2
must acquire the actor lock on all paths?