Skip to content

Commit d8e8b3d

Browse files
authored
Merge pull request #30105 from jckarter/objc-opt-self
IRGen: Invoke objc_opt_self directly when available.
2 parents 13487ed + e844771 commit d8e8b3d

File tree

11 files changed

+66
-17
lines changed

11 files changed

+66
-17
lines changed

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,12 @@ FUNCTION(ProtocolAddProtocol, protocol_addProtocol,
13131313
ARGS(ProtocolDescriptorPtrTy, ProtocolDescriptorPtrTy),
13141314
ATTRS(NoUnwind))
13151315

1316+
FUNCTION(ObjCOptSelf, objc_opt_self,
1317+
C_CC, AlwaysAvailable,
1318+
RETURNS(ObjCClassPtrTy),
1319+
ARGS(ObjCClassPtrTy),
1320+
ATTRS(NoUnwind))
1321+
13161322
FUNCTION(Malloc, malloc, C_CC, AlwaysAvailable,
13171323
RETURNS(Int8PtrTy),
13181324
ARGS(SizeTy),

lib/IRGen/GenHeap.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,32 @@ llvm::Constant *IRGenModule::getFixLifetimeFn() {
12441244
return fixLifetime;
12451245
}
12461246

1247+
llvm::Constant *IRGenModule::getFixedClassInitializationFn() {
1248+
if (FixedClassInitializationFn)
1249+
return *FixedClassInitializationFn;
1250+
1251+
// If ObjC interop is disabled, we don't need to do fixed class
1252+
// initialization.
1253+
llvm::Constant *fn;
1254+
if (!ObjCInterop) {
1255+
fn = nullptr;
1256+
} else {
1257+
// In new enough ObjC runtimes, objc_opt_self provides a direct fast path
1258+
// to realize a class.
1259+
if (getAvailabilityContext()
1260+
.isContainedIn(Context.getSwift51Availability())) {
1261+
fn = getObjCOptSelfFn();
1262+
}
1263+
// Otherwise, the Swift runtime always provides a `get
1264+
else {
1265+
fn = getGetInitializedObjCClassFn();
1266+
}
1267+
}
1268+
1269+
FixedClassInitializationFn = fn;
1270+
return fn;
1271+
}
1272+
12471273
/// Fix the lifetime of a live value. This communicates to the LLVM level ARC
12481274
/// optimizer not to touch this value.
12491275
void IRGenFunction::emitFixLifetime(llvm::Value *value) {

lib/IRGen/IRGenModule.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,13 +1224,17 @@ private: \
12241224
llvm::Constant *Id##Fn = nullptr;
12251225
#include "swift/Runtime/RuntimeFunctions.def"
12261226

1227+
Optional<llvm::Constant *> FixedClassInitializationFn;
1228+
12271229
llvm::Constant *FixLifetimeFn = nullptr;
12281230

12291231
mutable Optional<SpareBitVector> HeapPointerSpareBits;
12301232

12311233
//--- Generic ---------------------------------------------------------------
12321234
public:
12331235
llvm::Constant *getFixLifetimeFn();
1236+
1237+
llvm::Constant *getFixedClassInitializationFn();
12341238

12351239
/// The constructor used when generating code.
12361240
///

lib/IRGen/MetadataRequest.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -587,7 +587,7 @@ llvm::Value *irgen::emitObjCHeapMetadataRef(IRGenFunction &IGF,
587587
if (allowUninitialized) return classObject;
588588

589589
// TODO: memoize this the same way that we memoize Swift type metadata?
590-
return IGF.Builder.CreateCall(IGF.IGM.getGetInitializedObjCClassFn(),
590+
return IGF.Builder.CreateCall(IGF.IGM.getFixedClassInitializationFn(),
591591
classObject);
592592
}
593593

@@ -612,7 +612,7 @@ emitIdempotentClassMetadataInitialization(IRGenFunction &IGF,
612612
llvm::Value *metadata) {
613613
if (IGF.IGM.ObjCInterop) {
614614
metadata = IGF.Builder.CreateBitCast(metadata, IGF.IGM.ObjCClassPtrTy);
615-
metadata = IGF.Builder.CreateCall(IGF.IGM.getGetInitializedObjCClassFn(),
615+
metadata = IGF.Builder.CreateCall(IGF.IGM.getFixedClassInitializationFn(),
616616
metadata);
617617
metadata = IGF.Builder.CreateBitCast(metadata, IGF.IGM.TypeMetadataPtrTy);
618618
}

test/ClangImporter/objc_ir.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func propertyAccess(b b: B) {
8787
// CHECK-LABEL: define hidden swiftcc %TSo1BC* @"$s7objc_ir8downcast1aSo1BCSo1AC_tF"(
8888
func downcast(a a: A) -> B {
8989
// CHECK: [[CLASS:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_B"
90-
// CHECK: [[T0:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[CLASS]])
90+
// CHECK: [[T0:%.*]] = call %objc_class* @{{.*}}(%objc_class* [[CLASS]])
9191
// CHECK: [[T1:%.*]] = bitcast %objc_class* [[T0]] to i8*
9292
// CHECK: call i8* @swift_dynamicCastObjCClassUnconditional(i8* [[A:%.*]], i8* [[T1]], {{.*}}) [[NOUNWIND:#[0-9]+]]
9393
return a as! B
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-frontend -target x86_64-apple-macosx10.15 -module-name main -emit-ir %s | %FileCheck --check-prefix=CHECK --check-prefix=HAS_OPT_SELF %s
2+
// RUN: %target-swift-frontend -target x86_64-apple-macosx10.14 -module-name main -emit-ir %s | %FileCheck --check-prefix=CHECK --check-prefix=NO_OPT_SELF %s
3+
4+
// REQUIRES: objc_interop
5+
// REQUIRES: OS=macosx
6+
7+
class C {
8+
var x: Int = 0
9+
}
10+
11+
public func foof() -> Any.Type {
12+
return C.self
13+
}
14+
15+
// CHECK-LABEL: define {{.*}} %swift.metadata_response @"$s4main1CCMa"
16+
// HAS_OPT_SELF: call {{.*}} @objc_opt_self
17+
// NO_OPT_SELF: call {{.*}} @swift_getInitializedObjCClass

test/IRGen/objc_casts.sil

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ bb0(%unused : $@thick T.Type, %obj : $NSObject):
3636
// TODO: is this really necessary? also, this really shouldn't use a direct reference
3737
// CHECK-NEXT: [[T1:%.*]] = bitcast %objc_object* [[T0]] to i8*
3838
// CHECK-NEXT: [[T2a:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_Foo"
39-
// CHECK-NEXT: [[T2:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[T2a]])
39+
// CHECK-NEXT: [[T2:%.*]] = call %objc_class* @{{.*}}(%objc_class* [[T2a]])
4040
// CHECK-NEXT: [[T3:%.*]] = bitcast %objc_class* [[T2]] to i8*
4141
// CHECK-NEXT: call i8* @swift_dynamicCastObjCClassUnconditional(i8* [[T1]], i8* [[T3]], {{.*}})
4242
sil hidden @metatype_to_objc_class : $@convention(thin) <T> (@thick T.Type) -> () {
@@ -52,7 +52,7 @@ bb0(%metatype : $@thick T.Type):
5252
// TODO: is this really necessary? also, this really shouldn't use a direct reference
5353
// CHECK-NEXT: [[T1:%.*]] = bitcast %objc_object* [[T0]] to i8*
5454
// CHECK-NEXT: [[T2a:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_Foo"
55-
// CHECK-NEXT: [[T2:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[T2a]])
55+
// CHECK-NEXT: [[T2:%.*]] = call %objc_class* @{{.*}}(%objc_class* [[T2a]])
5656
// CHECK-NEXT: [[T3:%.*]] = bitcast %objc_class* [[T2]] to i8*
5757
// CHECK-NEXT: call i8* @swift_dynamicCastObjCClassUnconditional(i8* [[T1]], i8* [[T3]], {{.*}})
5858
sil hidden @opt_metatype_to_objc_class : $@convention(thin) <T> (Optional<@thick T.Type>) -> () {

test/IRGen/objc_generic_class_metadata.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ entry:
3939
apply %z<GenericClass<NSObject>>(%b) : $@convention(thin) <T> (@thick T.Type) -> ()
4040

4141
// CHECK: [[T0:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_GenericClass",
42-
// CHECK: [[OBJC_CLASS:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[T0]])
42+
// CHECK: [[OBJC_CLASS:%.*]] = call %objc_class* @{{.*}}(%objc_class* [[T0]])
4343
// CHECK: call swiftcc void @objc_class_sink(%objc_class* [[OBJC_CLASS]], %swift.type* [[METADATA]])
4444
%c = metatype $@objc_metatype GenericClass<NSString>.Type
4545
apply %y<GenericClass<NSString>>(%c) : $@convention(thin) <T: AnyObject> (@objc_metatype T.Type) -> ()

test/IRGen/objc_properties_jit.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ extension NSString {
1515

1616
// CHECK-LABEL: define{{( dllexport)?}}{{( protected)?}} private void @runtime_registration
1717
// CHECK: [[NSOBJECT_UNINIT:%.*]] = load %objc_class*, %objc_class** @"OBJC_CLASS_REF_$_NSString"
18-
// CHECK: [[NSOBJECT:%.*]] = call %objc_class* @swift_getInitializedObjCClass(%objc_class* [[NSOBJECT_UNINIT]])
18+
// CHECK: [[NSOBJECT:%.*]] = call %objc_class* @{{.*}}(%objc_class* [[NSOBJECT_UNINIT]])
1919
// CHECK: [[GET_CLASS_PROP:%.*]] = call i8* @sel_registerName({{.*}}(classProp)
2020
// CHECK: call i8* @class_replaceMethod(%objc_class* @"OBJC_METACLASS_$_NSString", i8* [[GET_CLASS_PROP]]
2121
// CHECK: [[SET_CLASS_PROP:%.*]] = call i8* @sel_registerName({{.*}}(setClassProp:)

validation-test/Reflection/reflect_empty_struct.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-build-swift -lswiftSwiftReflectionTest -I %S/Inputs/EmptyStruct/ %s -o %t/reflect_empty_struct -target x86_64-apple-macosx10.99.0
2+
// RUN: %target-build-swift -lswiftSwiftReflectionTest -I %S/Inputs/EmptyStruct/ %s -o %t/reflect_empty_struct
33
// RUN: %target-codesign %t/reflect_empty_struct
44

55
// RUN: %target-run %target-swift-reflection-test %t/reflect_empty_struct | %FileCheck %s --check-prefix=CHECK-%target-ptrsize --dump-input fail
@@ -32,13 +32,13 @@ reflect(object: obj)
3232
// CHECK-64: Type info:
3333
// CHECK-64: (class_instance size=80 alignment=8 stride=80 num_extra_inhabitants=0 bitwise_takable=1
3434
// CHECK-64: (field name=a offset=16
35-
// CHECK-64: (builtin size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
35+
// CHECK-64: ({{builtin|struct}} size=0 alignment={{1|4}} stride=1 num_extra_inhabitants=0 bitwise_takable=1))
3636
// CHECK-64: (field name=b offset=16
3737
// CHECK-64: (opaque_existential size=32 alignment=8 stride=32 num_extra_inhabitants=2147483647 bitwise_takable=1
3838
// CHECK-64: (field name=metadata offset=24
3939
// CHECK-64: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=2147483647 bitwise_takable=1))))
4040
// CHECK-64: (field name=c offset=48
41-
// CHECK-64: (builtin size=0 alignment=4 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
41+
// CHECK-64: ({{builtin|struct}} size=0 alignment={{1|4}} stride=1 num_extra_inhabitants=0 bitwise_takable=1))
4242
// CHECK-64: (field name=d offset=48
4343
// CHECK-64: (opaque_existential size=32 alignment=8 stride=32 num_extra_inhabitants=2147483647 bitwise_takable=1
4444
// CHECK-64: (field name=metadata offset=24
@@ -52,13 +52,13 @@ reflect(object: obj)
5252
// CHECK-32: Type info:
5353
// CHECK-32: (class_instance size=40 alignment=4 stride=40 num_extra_inhabitants=0 bitwise_takable=1
5454
// CHECK-32: (field name=a offset=8
55-
// CHECK-32: (builtin size=0 alignment=1 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
55+
// CHECK-32: ({{builtin|struct}} size=0 alignment={{1|4}} stride=1 num_extra_inhabitants=0 bitwise_takable=1))
5656
// CHECK-32: (field name=b offset=8
5757
// CHECK-32: (opaque_existential size=16 alignment=4 stride=16 num_extra_inhabitants=4096 bitwise_takable=1
5858
// CHECK-32: (field name=metadata offset=12
5959
// CHECK-32: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096 bitwise_takable=1))))
6060
// CHECK-32: (field name=c offset=24
61-
// CHECK-32: (builtin size=0 alignment=4 stride=1 num_extra_inhabitants=0 bitwise_takable=1))
61+
// CHECK-32: ({{builtin|struct}} size=0 alignment={{1|4}} stride=1 num_extra_inhabitants=0 bitwise_takable=1))
6262
// CHECK-32: (field name=d offset=24
6363
// CHECK-32: (opaque_existential size=16 alignment=4 stride=16 num_extra_inhabitants=4096 bitwise_takable=1
6464
// CHECK-32: (field name=metadata offset=12

validation-test/Reflection/reflect_empty_struct_compat.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
// RUN: %empty-directory(%t)
22

3-
// RUN: %target-build-swift -lswiftSwiftReflectionTest -I %S/Inputs/EmptyStruct/ %s -o %t/reflect_empty_struct -target x86_64-apple-macosx10.15.0
4-
// RUN: %target-codesign %t/reflect_empty_struct
5-
// RUN: %target-run %target-swift-reflection-test %t/reflect_empty_struct | %FileCheck %s --check-prefix=CHECK-%target-ptrsize --dump-input fail
6-
7-
// RUN: %target-build-swift -lswiftSwiftReflectionTest -I %S/Inputs/EmptyStruct/ %s -o %t/reflect_empty_struct -target x86_64-apple-macosx10.14.0
3+
// RUN: %target-build-swift -lswiftSwiftReflectionTest -I %S/Inputs/EmptyStruct/ %s -o %t/reflect_empty_struct
84
// RUN: %target-codesign %t/reflect_empty_struct
95
// RUN: %target-run %target-swift-reflection-test %t/reflect_empty_struct | %FileCheck %s --check-prefix=CHECK-%target-ptrsize --dump-input fail
106

0 commit comments

Comments
 (0)