Skip to content

Commit 1f37941

Browse files
committed
SILGen: Always reference allocating entry points when calling class constructors
Previously we would emit an alloc_ref_dynamic followed by a call of the initializing entry point when calling an @objc dynamic initializer in a class. However this is unnecessary now that the allocating entry point does the right alloc_ref_dynamic.
1 parent ffc26fb commit 1f37941

File tree

3 files changed

+24
-43
lines changed

3 files changed

+24
-43
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,12 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
10191019
if (!ctor->isRequired())
10201020
return false;
10211021

1022+
// @objc dynamic initializers are statically dispatched (we're
1023+
// calling the allocating entry point, which is a thunk that
1024+
// does the dynamic dispatch for us).
1025+
if (ctor->isObjCDynamic())
1026+
return false;
1027+
10221028
// Required constructors are statically dispatched when the 'self'
10231029
// value is statically derived.
10241030
ApplyExpr *thisCallSite = callSites.back();
@@ -1032,64 +1038,32 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
10321038
}
10331039

10341040
void processClassMethod(DeclRefExpr *e, AbstractFunctionDecl *afd) {
1035-
SILDeclRef::Kind kind;
1036-
bool requiresAllocRefDynamic = false;
1037-
1038-
if (isa<FuncDecl>(afd)) {
1039-
kind = SILDeclRef::Kind::Func;
1040-
} else {
1041-
if (requiresForeignEntryPoint(afd)) {
1042-
// When we're performing Objective-C dispatch, we don't have an
1043-
// allocating constructor to call. So, perform an alloc_ref_dynamic
1044-
// and pass that along to the initializer.
1045-
requiresAllocRefDynamic = true;
1046-
kind = SILDeclRef::Kind::Initializer;
1047-
} else {
1048-
kind = SILDeclRef::Kind::Allocator;
1049-
}
1050-
}
1051-
10521041
ApplyExpr *thisCallSite = callSites.back();
10531042
callSites.pop_back();
10541043

1055-
// If we require a dynamic allocation of the object here, do so now.
1056-
if (requiresAllocRefDynamic) {
1057-
SILLocation loc = thisCallSite->getArg();
1058-
RValue selfMetatype = SGF.emitRValue(thisCallSite->getArg());
1059-
auto selfValue =
1060-
allocateObject(std::move(selfMetatype).getAsSingleValue(SGF, loc),
1061-
loc, /*objc*/ true);
1062-
RValue self = RValue(SGF, loc, selfValue.getType().getASTType(),
1063-
selfValue);
1064-
ArgumentSource selfArgSource(thisCallSite->getArg(), std::move(self));
1065-
setSelfParam(std::move(selfArgSource), thisCallSite);
1066-
} else {
1067-
ArgumentSource selfArgSource(thisCallSite->getArg());
1068-
setSelfParam(std::move(selfArgSource), thisCallSite);
1069-
}
1044+
ArgumentSource selfArgSource(thisCallSite->getArg());
1045+
setSelfParam(std::move(selfArgSource), thisCallSite);
10701046

10711047
// Directly dispatch to calls of the replaced function inside of
10721048
// '@_dynamicReplacement(for:)' methods.
10731049
bool isObjCReplacementCall = false;
10741050
if (isCallToReplacedInDynamicReplacement(SGF, afd, isObjCReplacementCall) &&
10751051
thisCallSite->getArg()->isSelfExprOf(
10761052
cast<AbstractFunctionDecl>(SGF.FunctionDC->getAsDecl()), false)) {
1077-
auto constant = SILDeclRef(afd, kind).asForeign(
1053+
auto constant = SILDeclRef(afd).asForeign(
10781054
!isObjCReplacementCall && requiresForeignEntryPoint(e->getDecl()));
10791055
auto subs = e->getDeclRef().getSubstitutions();
10801056
if (isObjCReplacementCall)
10811057
setCallee(Callee::forDirect(SGF, constant, subs, e));
10821058
else
10831059
setCallee(Callee::forDirect(
10841060
SGF,
1085-
SILDeclRef(cast<AbstractFunctionDecl>(SGF.FunctionDC->getAsDecl()),
1086-
kind),
1061+
SILDeclRef(cast<AbstractFunctionDecl>(SGF.FunctionDC->getAsDecl())),
10871062
subs, e, true));
10881063
return;
10891064
}
10901065

1091-
auto constant = SILDeclRef(afd, kind)
1092-
.asForeign(requiresForeignEntryPoint(afd));
1066+
auto constant = SILDeclRef(afd).asForeign(requiresForeignEntryPoint(afd));
10931067

10941068
auto subs = e->getDeclRef().getSubstitutions();
10951069
setCallee(Callee::forClassMethod(SGF, constant, subs, e));

test/SILGen/dynamic_self.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,11 @@ class ObjCInit {
117117
@objc dynamic required init() { }
118118
}
119119

120-
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self12testObjCInit{{[_0-9a-zA-Z]*}}F : $@convention(thin) (@thick ObjCInit.Type) -> ()
120+
// CHECK-LABEL: sil hidden [ossa] @$s12dynamic_self12testObjCInit4metayAA0dE0Cm_tF : $@convention(thin) (@thick ObjCInit.Type) -> ()
121121
func testObjCInit(meta: ObjCInit.Type) {
122122
// CHECK: bb0([[THICK_META:%[0-9]+]] : $@thick ObjCInit.Type):
123-
// CHECK: [[OBJC_META:%[0-9]+]] = thick_to_objc_metatype [[THICK_META]] : $@thick ObjCInit.Type to $@objc_metatype ObjCInit.Type
124-
// CHECK: [[OBJ:%[0-9]+]] = alloc_ref_dynamic [objc] [[OBJC_META]] : $@objc_metatype ObjCInit.Type, $ObjCInit
125-
// CHECK: [[INIT:%[0-9]+]] = objc_method [[OBJ]] : $ObjCInit, #ObjCInit.init!initializer.1.foreign : (ObjCInit.Type) -> () -> ObjCInit, $@convention(objc_method) (@owned ObjCInit) -> @owned ObjCInit
126-
// CHECK: [[RESULT_OBJ:%[0-9]+]] = apply [[INIT]]([[OBJ]]) : $@convention(objc_method) (@owned ObjCInit) -> @owned ObjCInit
123+
// CHECK: [[INIT:%[0-9]+]] = function_ref @$s12dynamic_self8ObjCInitCACycfC : $@convention(method) (@thick ObjCInit.Type) -> @owned ObjCInit
124+
// CHECK: [[RESULT_OBJ:%[0-9]+]] = apply [[INIT]]([[THICK_META]]) : $@convention(method) (@thick ObjCInit.Type) -> @owned ObjCInit
127125
// CHECK: [[RESULT:%[0-9]+]] = tuple ()
128126
// CHECK: return [[RESULT]] : $()
129127
_ = meta.init()

test/SILGen/objc_dynamic_init.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,16 @@ final class Bobamathing: Thingamabob {
4545
}
4646
}
4747

48-
48+
// CHECK-LABEL: sil hidden [ossa] @$s17objc_dynamic_init8callInityyF : $@convention(thin) () -> ()
49+
// CHECK: [[METATYPE:%.*]] = metatype $@thick Gadget.Type
50+
// CHECK: [[CTOR:%.*]] = function_ref @$s17objc_dynamic_init6GadgetCACycfC
51+
// CHECK: [[INSTANCE:%.*]] = apply [[CTOR]]([[METATYPE]])
52+
// CHECK: destroy_value [[INSTANCE]]
53+
54+
func callInit() {
55+
let metatype = Gadget.self
56+
_ = metatype.init()
57+
}
4958

5059
// CHECK-LABEL: sil_vtable Gadget {
5160
// CHECK-NOT: #Gadget.init!allocator.1

0 commit comments

Comments
 (0)