|
1 |
| -// RUN: %target-swift-frontend -O -primary-file %s -emit-sil -enable-experimental-distributed | %FileCheck %s --dump-input=fail |
| 1 | +// RUN: %target-swift-frontend -module-name default_deinit -primary-file %s -emit-sil -enable-experimental-distributed | %FileCheck %s --enable-var-scope --dump-input=fail |
2 | 2 | // REQUIRES: concurrency
|
3 | 3 | // REQUIRES: distributed
|
4 | 4 |
|
5 | 5 | import _Distributed
|
6 | 6 |
|
7 |
| -@available(SwiftStdlib 5.5, *) |
8 |
| -distributed actor SimpleEmptyDistributedActor { |
| 7 | +class SomeClass {} |
| 8 | + |
| 9 | +@available(macOS 12, *) |
| 10 | +distributed actor MyDistActor { |
| 11 | + let localOnlyField: SomeClass |
| 12 | + |
| 13 | + init(transport: ActorTransport) { |
| 14 | + self.localOnlyField = SomeClass() |
| 15 | + } |
9 | 16 | }
|
10 | 17 |
|
11 |
| -// ==== ------------------------------------------------------------------------ |
12 |
| -// ==== deinit must invoke transport.resignIdentity() when it is local |
13 |
| - |
14 |
| -// CHECK: // SimpleEmptyDistributedActor.deinit |
15 |
| -// sil hidden [available 12.0] @$s36distributed_actor_default_deinit_sil27SimpleEmptyDistributedActorCfd : $@convention(method) (@guaranteed SimpleEmptyDistributedActor) -> @owned Builtin.NativeObject { |
16 |
| -// CHECK: [[SELF:%[0-9]+]] "self" |
17 |
| -// CHECK: bb0(%0 : $SimpleEmptyDistributedActor): |
18 |
| -// CHECK: debug_value %0 : $SimpleEmptyDistributedActor, let, name "self", argno 1 |
19 |
| -// CHECK: [[ID_ADDR:%[0-9]+]] = ref_element_addr %0 : $SimpleEmptyDistributedActor, #SimpleEmptyDistributedActor.id |
20 |
| -// CHECK: [[TRANSPORT_ADDR:%[0-9]+]] = ref_element_addr %0 : $SimpleEmptyDistributedActor, #SimpleEmptyDistributedActor.actorTransport |
21 |
| -// CHECK: %4 = init_existential_ref %0 : $SimpleEmptyDistributedActor : $SimpleEmptyDistributedActor, $AnyObject |
22 |
| -// CHECK: // function_ref swift_distributed_actor_is_remote |
23 |
| -// CHECK: %5 = function_ref @swift_distributed_actor_is_remote : $@convention(thin) (@guaranteed AnyObject) -> Bool |
24 |
| -// CHECK: %6 = apply %5(%4) : $@convention(thin) (@guaranteed AnyObject) -> Bool |
25 |
| -// CHECK: %7 = struct_extract %6 : $Bool, #Bool._value |
26 |
| -// CHECK: cond_br %7, [[REMOTE_BB:bb[0-9]+]], [[LOCAL_BB:bb[0-9]+]] |
27 |
| - |
28 |
| -// If local... |
| 18 | +// MARK: distributed actor check |
| 19 | + |
| 20 | +// This test checks that we resign the identity for local deallocations, |
| 21 | +// destroy only the correct stored properties whether remote or local, and also |
| 22 | +// destroy the executor. |
| 23 | + |
| 24 | +// CHECK-LABEL: sil hidden {{.*}} @$s14default_deinit11MyDistActorCfd : $@convention(method) (@guaranteed MyDistActor) -> @owned Builtin.NativeObject { |
| 25 | +// CHECK: bb0([[SELF:%[0-9]+]] : $MyDistActor): |
| 26 | +// CHECK: [[EXI_SELF:%[0-9]+]] = init_existential_ref [[SELF]] : $MyDistActor |
| 27 | +// CHECK: [[IS_REMOTE_FN:%[0-9]+]] = function_ref @swift_distributed_actor_is_remote |
| 28 | +// CHECK: [[IS_REMOTE:%[0-9]+]] = apply [[IS_REMOTE_FN]]([[EXI_SELF]]) |
| 29 | +// CHECK: [[RAW_BOOL:%[0-9]+]] = struct_extract [[IS_REMOTE]] : $Bool, #Bool._value |
| 30 | +// CHECK: cond_br [[RAW_BOOL]], [[REMOTE_BB:bb[0-9]+]], [[LOCAL_BB:bb[0-9]+]] |
| 31 | + |
| 32 | +// *** If local... invoke transport.resignIdentity() |
29 | 33 | // CHECK: [[LOCAL_BB]]:
|
30 |
| -// CHECK: %9 = open_existential_addr immutable_access %3 : $*ActorTransport to $*@opened({{.*}}) ActorTransport |
31 |
| -// CHECK: %10 = witness_method $@opened({{.*}}) ActorTransport, #ActorTransport.resignIdentity : <Self where Self : ActorTransport> (Self) -> (AnyActorIdentity) -> (), %9 : $*@opened({{.*}}) ActorTransport : $@convention(witness_method: ActorTransport) <τ_0_0 where τ_0_0 : ActorTransport> (@in_guaranteed AnyActorIdentity, @in_guaranteed τ_0_0) -> () |
32 |
| -// CHECK: %11 = apply %10<@opened({{.*}}) ActorTransport>(%2, %9) : $@convention(witness_method: ActorTransport) <τ_0_0 where τ_0_0 : ActorTransport> (@in_guaranteed AnyActorIdentity, @in_guaranteed τ_0_0) -> () |
33 |
| -// CHECK: br bb3 |
| 34 | +// CHECK: [[ID_REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MyDistActor, #MyDistActor.id |
| 35 | +// CHECK: [[TPORT_REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MyDistActor, #MyDistActor.actorTransport |
| 36 | +// CHECK: [[TPORT_OPENED:%[0-9]+]] = open_existential_addr immutable_access [[TPORT_REF]] |
| 37 | +// CHECK: [[RESIGN:%[0-9]+]] = witness_method $@opened({{.*}}) ActorTransport, #ActorTransport.resignIdentity : <Self where Self : ActorTransport> (Self) -> (AnyActorIdentity) -> (), [[TPORT_OPENED]] |
| 38 | +// CHECK: apply [[RESIGN]]<@opened({{.*}}) ActorTransport>([[ID_REF]], [[TPORT_OPENED]]) |
| 39 | +// CHECK: br [[CONTINUE:bb[0-9]+]] |
34 | 40 |
|
35 |
| -// If remote... |
| 41 | +// *** If remote... |
36 | 42 | // CHECK: [[REMOTE_BB]]:
|
37 |
| -// CHECK: br bb3 |
38 |
| - |
39 |
| -// Finish up the destroying... |
40 |
| -// CHECK: bb3: |
41 |
| -// CHECK: destroy_addr [[TRANSPORT_ADDR]] : $*ActorTransport |
42 |
| -// CHECK: destroy_addr [[ID_ADDR]] : $*AnyActorIdentity |
43 |
| -// CHECK: [[_:%[0-9]+]] = builtin "destroyDefaultActor"(%0 : $SimpleEmptyDistributedActor) : $() |
44 |
| -// CHECK: [[SELF:%[0-9]+]] = unchecked_ref_cast %0 : $SimpleEmptyDistributedActor to $Builtin.NativeObject |
45 |
| -// CHECK: return [[SELF]] : $Builtin.NativeObject |
46 |
| -// CHECK: } // end sil function '$s36distributed_actor_default_deinit_sil27SimpleEmptyDistributedActorCfd' |
| 43 | +// CHECK: br [[CONTINUE]] |
| 44 | + |
| 45 | +// Now we deallocate stored properties, and how we do that depends again on |
| 46 | +// being remote or local. Default code emission does another is_remote test, |
| 47 | +// so we check for that here and leave tail-merging to the optimizer, for now. |
| 48 | +// CHECK: [[CONTINUE]]: |
| 49 | + // *** this is entirely copy-pasted from the first check in bb0 *** |
| 50 | +// CHECK: [[EXI_SELF:%[0-9]+]] = init_existential_ref [[SELF]] : $MyDistActor |
| 51 | +// CHECK: [[IS_REMOTE_FN:%[0-9]+]] = function_ref @swift_distributed_actor_is_remote |
| 52 | +// CHECK: [[IS_REMOTE:%[0-9]+]] = apply [[IS_REMOTE_FN]]([[EXI_SELF]]) |
| 53 | +// CHECK: [[RAW_BOOL:%[0-9]+]] = struct_extract [[IS_REMOTE]] : $Bool, #Bool._value |
| 54 | +// CHECK: cond_br [[RAW_BOOL]], [[REMOTE_BB_DEALLOC:bb[0-9]+]], [[LOCAL_BB_DEALLOC:bb[0-9]+]] |
| 55 | + |
| 56 | +// *** only destroy the id and transport if remote *** |
| 57 | +// CHECK: [[REMOTE_BB_DEALLOC]]: |
| 58 | + // *** destroy transport *** |
| 59 | +// CHECK: [[REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MyDistActor, #MyDistActor.actorTransport |
| 60 | +// CHECK: [[ACCESS:%[0-9]+]] = begin_access [deinit] [static] [[REF]] |
| 61 | +// CHECK: destroy_addr [[ACCESS]] : $*ActorTransport |
| 62 | +// CHECK: end_access [[ACCESS]] |
| 63 | + // *** destroy identity *** |
| 64 | +// CHECK: [[REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MyDistActor, #MyDistActor.id |
| 65 | +// CHECK: [[ACCESS:%[0-9]+]] = begin_access [deinit] [static] [[REF]] |
| 66 | +// CHECK: destroy_addr [[ACCESS]] : $*AnyActorIdentity |
| 67 | +// CHECK: end_access [[ACCESS]] |
| 68 | +// CHECK: br [[AFTER_DEALLOC:bb[0-9]+]] |
| 69 | + |
| 70 | +// *** destroy everything if local *** |
| 71 | +// CHECK: [[LOCAL_BB_DEALLOC]]: |
| 72 | + // *** destroy the user-defined field *** |
| 73 | +// CHECK: [[REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MyDistActor, #MyDistActor.localOnlyField |
| 74 | +// CHECK: [[ACCESS:%[0-9]+]] = begin_access [deinit] [static] [[REF]] |
| 75 | +// CHECK: destroy_addr [[ACCESS]] : $*SomeClass |
| 76 | +// CHECK: end_access [[ACCESS]] |
| 77 | + // *** the rest of this part is identical to the remote case *** |
| 78 | +// CHECK: [[REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MyDistActor, #MyDistActor.actorTransport |
| 79 | +// CHECK: [[ACCESS:%[0-9]+]] = begin_access [deinit] [static] [[REF]] |
| 80 | +// CHECK: destroy_addr [[ACCESS]] : $*ActorTransport |
| 81 | +// CHECK: end_access [[ACCESS]] |
| 82 | +// CHECK: [[REF:%[0-9]+]] = ref_element_addr [[SELF]] : $MyDistActor, #MyDistActor.id |
| 83 | +// CHECK: [[ACCESS:%[0-9]+]] = begin_access [deinit] [static] [[REF]] |
| 84 | +// CHECK: destroy_addr [[ACCESS]] : $*AnyActorIdentity |
| 85 | +// CHECK: end_access [[ACCESS]] |
| 86 | +// CHECK: br [[AFTER_DEALLOC]] |
| 87 | + |
| 88 | +// CHECK: [[AFTER_DEALLOC]]: |
| 89 | +// CHECK: builtin "destroyDefaultActor"([[SELF]] : $MyDistActor) |
| 90 | +// CHECK: [[CAST:%[0-9]+]] = unchecked_ref_cast [[SELF]] |
| 91 | +// CHECK: return [[CAST]] : $Builtin.NativeObject |
| 92 | +// CHECK: } // end sil function '$s14default_deinit11MyDistActorCfd' |
| 93 | + |
| 94 | + |
| 95 | +// MARK: local actor check |
| 96 | + |
| 97 | +@available(macOS 12, *) |
| 98 | +actor SimpleActor { |
| 99 | + let someField: SomeClass |
| 100 | + init() { |
| 101 | + self.someField = SomeClass() |
| 102 | + } |
| 103 | +} |
| 104 | + |
| 105 | +// additionally, we add basic coverage for a non-distributed actor's deinit |
| 106 | + |
| 107 | + |
| 108 | +// CHECK-LABEL: sil hidden {{.*}} @$s14default_deinit11SimpleActorCfd : $@convention(method) (@guaranteed SimpleActor) -> @owned Builtin.NativeObject { |
| 109 | +// CHECK: bb0([[SELF:%[0-9]+]] : $SimpleActor): |
| 110 | +// CHECK: [[REF:%[0-9]+]] = ref_element_addr [[SELF]] : $SimpleActor, #SimpleActor.someField |
| 111 | +// CHECK: [[ACCESS:%[0-9]+]] = begin_access [deinit] [static] [[REF]] |
| 112 | +// CHECK: destroy_addr [[ACCESS]] : $*SomeClass |
| 113 | +// CHECK: end_access [[ACCESS]] |
| 114 | +// CHECK: builtin "destroyDefaultActor"([[SELF]] : $SimpleActor) |
| 115 | +// CHECK: [[CAST:%[0-9]+]] = unchecked_ref_cast [[SELF]] |
| 116 | +// CHECK: return [[CAST]] : $Builtin.NativeObject |
| 117 | +// CHECK: } // end sil function '$s14default_deinit11SimpleActorCfd' |
| 118 | + |
| 119 | + |
0 commit comments