Skip to content

Commit d43e49e

Browse files
committed
Eliminate objcImpl field offset vectors
We really don’t need ‘em; the same information should be in the ivars. The runtime entry point currently uses a weird little hack that we will refactor away shortly.
1 parent 666d6d8 commit d43e49e

File tree

7 files changed

+75
-33
lines changed

7 files changed

+75
-33
lines changed

include/swift/Runtime/Metadata.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -788,8 +788,7 @@ Class
788788
swift_updatePureObjCClassMetadata(Class self,
789789
ClassLayoutFlags flags,
790790
size_t numFields,
791-
const TypeLayout * const *fieldTypes,
792-
size_t *fieldOffsets);
791+
const TypeLayout * const *fieldTypes);
793792
#endif
794793

795794
/// Given class metadata, a class descriptor and a method descriptor, look up

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,17 +1437,15 @@ FUNCTION(UpdateClassMetadata2,
14371437
EFFECT(MetaData),
14381438
UNKNOWN_MEMEFFECTS)
14391439

1440-
// objc_class *swift_updatePureObjCClassMetadata(objc_class *self,
1441-
// ClassLayoutFlags flags,
1442-
// size_t numFields,
1443-
// TypeLayout * const *fieldTypes,
1444-
// size_t *fieldOffsets);
1440+
// objc_class *swift_updatePureObjCClassMetadata(
1441+
// objc_class *self,
1442+
// ClassLayoutFlags flags,
1443+
// size_t numFields,
1444+
// TypeLayout * const *fieldTypes);
14451445
FUNCTION(UpdatePureObjCClassMetadata,
14461446
swift_updatePureObjCClassMetadata, SwiftCC, AlwaysAvailable,
14471447
RETURNS(ObjCClassPtrTy),
1448-
ARGS(ObjCClassPtrTy, SizeTy, SizeTy,
1449-
Int8PtrPtrTy->getPointerTo(),
1450-
SizeTy->getPointerTo()),
1448+
ARGS(ObjCClassPtrTy, SizeTy, SizeTy, Int8PtrPtrTy->getPointerTo()),
14511449
ATTRS(NoUnwind),
14521450
EFFECT(MetaData),
14531451
UNKNOWN_MEMEFFECTS)

lib/IRGen/ClassMetadataVisitor.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ template <class Impl> class ClassMetadataVisitor
104104
asImpl().addSuperclass();
105105
asImpl().addClassCacheData();
106106
asImpl().addClassDataPointer();
107-
addClassMembers(Target, Target);
108107
return;
109108
}
110109

@@ -221,10 +220,8 @@ template <class Impl> class ClassMetadataVisitor
221220
rootClass))
222221
return;
223222

224-
if (!isPureObjC()) {
225-
// Add vtable entries.
226-
asImpl().addVTableEntries(theClass);
227-
}
223+
// Add vtable entries.
224+
asImpl().addVTableEntries(theClass);
228225
}
229226

230227
/// Add fields associated with the given class and its bases.

lib/IRGen/GenMeta.cpp

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2953,10 +2953,16 @@ void IRGenFunction::emitInitializeFieldOffsetVector(SILType T,
29532953
bool isVWTMutable,
29542954
MetadataDependencyCollector *collector) {
29552955
auto *target = T.getNominalOrBoundGenericNominal();
2956-
llvm::Value *fieldVector
2957-
= emitAddressOfFieldOffsetVector(*this, metadata, target)
2956+
2957+
llvm::Value *fieldVector = nullptr;
2958+
// @objc @implementation classes don't actually have a field vector; for them,
2959+
// we're just trying to update the direct field offsets.
2960+
if (!isa<ClassDecl>(target)
2961+
|| !cast<ClassDecl>(target)->getObjCImplementationDecl()) {
2962+
fieldVector = emitAddressOfFieldOffsetVector(*this, metadata, target)
29582963
.getAddress();
2959-
2964+
}
2965+
29602966
// Collect the stored properties of the type.
29612967
unsigned numFields = getNumFields(target);
29622968

@@ -3019,19 +3025,22 @@ void IRGenFunction::emitInitializeFieldOffsetVector(SILType T,
30193025
case ClassMetadataStrategy::FixedOrUpdate:
30203026
assert(IGM.Context.LangOpts.EnableObjCInterop);
30213027

3022-
// Call swift_updateClassMetadata(). Note that the static metadata
3023-
// already references the superclass in this case, but we still want
3024-
// to ensure the superclass metadata is initialized first.
3025-
if (classDecl->getObjCImplementationDecl()) {
3026-
Builder.CreateCall(
3027-
IGM.getUpdatePureObjCClassMetadataFunctionPointer(),
3028-
{metadata, IGM.getSize(Size(uintptr_t(flags))), numFieldsV,
3029-
fields.getAddress(), fieldVector});
3030-
} else {
3028+
if (fieldVector) {
3029+
// Call swift_updateClassMetadata(). Note that the static metadata
3030+
// already references the superclass in this case, but we still want
3031+
// to ensure the superclass metadata is initialized first.
30313032
dependency = Builder.CreateCall(
30323033
IGM.getUpdateClassMetadata2FunctionPointer(),
30333034
{metadata, IGM.getSize(Size(uintptr_t(flags))), numFieldsV,
30343035
fields.getAddress(), fieldVector});
3036+
} else {
3037+
// If we don't have a field vector, we must be updating an
3038+
// @objc @implementation class layout. Call
3039+
// swift_updatePureObjCClassMetadata() instead.
3040+
Builder.CreateCall(
3041+
IGM.getUpdatePureObjCClassMetadataFunctionPointer(),
3042+
{metadata, IGM.getSize(Size(uintptr_t(flags))), numFieldsV,
3043+
fields.getAddress()});
30353044
}
30363045
break;
30373046

@@ -4442,12 +4451,14 @@ namespace {
44424451
: super(IGM, theClass, builder, fieldLayout, vtable) {}
44434452

44444453
void addFieldOffset(VarDecl *var) {
4454+
assert(!isPureObjC());
44454455
addFixedFieldOffset(IGM, B, var, [](DeclContext *dc) {
44464456
return dc->getDeclaredTypeInContext();
44474457
});
44484458
}
44494459

44504460
void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
4461+
assert(!isPureObjC());
44514462
llvm_unreachable("Fixed class metadata cannot have missing members");
44524463
}
44534464

@@ -4473,12 +4484,14 @@ namespace {
44734484
: super(IGM, theClass, builder, fieldLayout) {}
44744485

44754486
void addFieldOffset(VarDecl *var) {
4487+
assert(!isPureObjC());
44764488
// Field offsets are either copied from the superclass or calculated
44774489
// at runtime.
44784490
B.addInt(IGM.SizeTy, 0);
44794491
}
44804492

44814493
void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
4494+
assert(!isPureObjC());
44824495
for (unsigned i = 0,
44834496
e = placeholder->getNumberOfFieldOffsetVectorEntries();
44844497
i < e; ++i) {
@@ -4974,11 +4987,13 @@ namespace {
49744987
}
49754988

49764989
void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
4990+
assert(!isPureObjC());
49774991
llvm_unreachable(
49784992
"Prespecialized generic class metadata cannot have missing members");
49794993
}
49804994

49814995
void addFieldOffset(VarDecl *var) {
4996+
assert(!isPureObjC());
49824997
addFixedFieldOffset(IGM, B, var, [&](DeclContext *dc) {
49834998
return dc->mapTypeIntoContext(type);
49844999
});

lib/IRGen/MetadataLayout.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,10 @@ llvm::Value *irgen::emitArgumentPackShapeRef(IRGenFunction &IGF,
280280
Address irgen::emitAddressOfFieldOffsetVector(IRGenFunction &IGF,
281281
llvm::Value *metadata,
282282
NominalTypeDecl *decl) {
283+
assert(!isa<ClassDecl>(decl)
284+
|| !cast<ClassDecl>(decl)->getObjCImplementationDecl()
285+
&& "objcImpl classes don't have a field offset vector");
286+
283287
auto &layout = IGF.IGM.getMetadataLayout(decl);
284288
auto offset = [&]() {
285289
if (isa<ClassDecl>(decl)) {

stdlib/public/runtime/Metadata.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4070,12 +4070,36 @@ static void initObjCClass(ObjCClass *self,
40704070
}
40714071
}
40724072

4073+
static void populateInitialFieldOffsets(ObjCClass *self,
4074+
size_t numFields,
4075+
size_t *fieldOffsets) {
4076+
ClassROData *rodata = getROData(self);
4077+
4078+
ClassIvarList *ivars = rodata->IvarList;
4079+
if (!ivars) {
4080+
assert(numFields == 0);
4081+
return;
4082+
}
4083+
4084+
assert(ivars->Count == numFields);
4085+
assert(ivars->EntrySize == sizeof(ClassIvarEntry));
4086+
4087+
for (unsigned i = 0; i != numFields; ++i) {
4088+
ClassIvarEntry *ivar = &ivars->getIvars()[i];
4089+
4090+
if (ivar->Offset) {
4091+
fieldOffsets[i] = *ivar->Offset;
4092+
} else {
4093+
fieldOffsets[i] = 0;
4094+
}
4095+
}
4096+
}
4097+
40734098
Class
40744099
swift::swift_updatePureObjCClassMetadata(Class cls,
40754100
ClassLayoutFlags flags,
40764101
size_t numFields,
4077-
const TypeLayout * const *fieldTypes,
4078-
size_t *fieldOffsets) {
4102+
const TypeLayout * const *fieldTypes) {
40794103
auto self = (ObjCClass *)cls;
40804104
bool requiresUpdate = SWIFT_RUNTIME_WEAK_CHECK(_objc_realizeClassFromSwift);
40814105

@@ -4108,6 +4132,11 @@ swift::swift_updatePureObjCClassMetadata(Class cls,
41084132
// which point at field offset globals and not the field offset vector.
41094133
swift_getInitializedObjCClass((Class)self);
41104134
} else {
4135+
// Fake up a field offsets vector based on the ivars.
4136+
// FIXME: Temporary; we should just combine the other two functions' logic.
4137+
size_t *fieldOffsets = (size_t *)alloca(numFields * sizeof(size_t));
4138+
populateInitialFieldOffsets(self, numFields, fieldOffsets);
4139+
41114140
// Update the field offset vector using runtime type information; the layout
41124141
// of resilient types might be different than the statically-emitted layout.
41134142
initClassFieldOffsetVector(self, numFields, fieldTypes, fieldOffsets);

test/IRGen/objc_implementation.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
// CHECK: [[_PROPERTIES_ImplClass:@[^, ]+]] = internal constant { i32, i32, [1 x { ptr, ptr }] } { i32 16, i32 1, [1 x { ptr, ptr }] [{ ptr, ptr } { ptr @.str.12.implProperty, ptr @".str.18.Ti,N,VimplProperty" }] }, section "__DATA, __objc_const", align 8
2929
// FIXME: Should just be @_PROTOCOLS_ImplClass, but an IRGen bug causes the protocol list to be emitted twice.
3030
// CHECK: [[_DATA_ImplClass:@[^, ]+]] = internal constant { i32, i32, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr } { i32 388, i32 8, i32 24, i32 0, ptr null, ptr @.str.9.ImplClass, ptr [[_INSTANCE_METHODS_ImplClass]], ptr @_PROTOCOLS_ImplClass.{{[0-9]+}}, ptr [[_IVARS_ImplClass]], ptr null, ptr [[_PROPERTIES_ImplClass]] }, section "__DATA, __objc_data", align 8
31-
// CHECK: @"OBJC_CLASS_$_ImplClass" = global <{ i64, ptr, ptr, ptr, ptr, i64, i64 }> <{ i64 ptrtoint (ptr @"OBJC_METACLASS_$_ImplClass" to i64), ptr @"OBJC_CLASS_$_NSObject", ptr @_objc_empty_cache, ptr null, ptr [[_DATA_ImplClass]], i64 8, i64 16 }>, section "__DATA,__objc_data, regular", align 8
31+
// CHECK: @"OBJC_CLASS_$_ImplClass" = global <{ i64, ptr, ptr, ptr, ptr }> <{ i64 ptrtoint (ptr @"OBJC_METACLASS_$_ImplClass" to i64), ptr @"OBJC_CLASS_$_NSObject", ptr @_objc_empty_cache, ptr null, ptr [[_DATA_ImplClass]] }>, section "__DATA,__objc_data, regular", align 8
3232

3333
// Swift metadata
3434
// NEGATIVE-NOT: OBJC_CLASS_$_ImplClass.{{[0-9]}}
@@ -92,7 +92,7 @@
9292
// CHECK: @_IVARS_NoInitImplClass = internal constant { i32, i32, [4 x { ptr, ptr, ptr, i32, i32 }] } { i32 32, i32 4, [4 x { ptr, ptr, ptr, i32, i32 }] [{ ptr, ptr, ptr, i32, i32 } { ptr @"$sSo15NoInitImplClassC19objc_implementationE2s1SSvpWvd", ptr @.str.2.s1, ptr @.str.0., i32 3, i32 16 }, { ptr, ptr, ptr, i32, i32 } { ptr @"$sSo15NoInitImplClassC19objc_implementationE2s2SSvpWvd", ptr @.str.2.s2, ptr @.str.0., i32 3, i32 16 }, { ptr, ptr, ptr, i32, i32 } { ptr @"$sSo15NoInitImplClassC19objc_implementationE2s3SSvpWvd", ptr @.str.2.s3, ptr @.str.0., i32 3, i32 16 }, { ptr, ptr, ptr, i32, i32 } { ptr @"$sSo15NoInitImplClassC19objc_implementationE2s4SSvpWvd", ptr @.str.2.s4, ptr @.str.0., i32 3, i32 16 }] }, section "__DATA, __objc_const", align 8
9393
// CHECK: @_PROPERTIES_NoInitImplClass = internal constant { i32, i32, [4 x { ptr, ptr }] } { i32 16, i32 4, [4 x { ptr, ptr }] [{ ptr, ptr } { ptr @.str.2.s1, ptr @".str.16.T@\22NSString\22,N,R" }, { ptr, ptr } { ptr @.str.2.s2, ptr @".str.16.T@\22NSString\22,N,C" }, { ptr, ptr } { ptr @.str.2.s3, ptr @".str.16.T@\22NSString\22,N,R" }, { ptr, ptr } { ptr @.str.2.s4, ptr @".str.16.T@\22NSString\22,N,C" }] }, section "__DATA, __objc_const", align 8
9494
// CHECK: @_DATA_NoInitImplClass = internal constant { i32, i32, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr } { i32 388, i32 8, i32 72, i32 0, ptr null, ptr @.str.15.NoInitImplClass, ptr @_INSTANCE_METHODS_NoInitImplClass, ptr null, ptr @_IVARS_NoInitImplClass, ptr null, ptr @_PROPERTIES_NoInitImplClass }, section "__DATA, __objc_data", align 8
95-
// CHECK: @"OBJC_CLASS_$_NoInitImplClass" = global <{ i64, ptr, ptr, ptr, ptr, i64, i64, i64, i64 }> <{ i64 ptrtoint (ptr @"OBJC_METACLASS_$_NoInitImplClass" to i64), ptr @"OBJC_CLASS_$_NSObject", ptr @_objc_empty_cache, ptr null, ptr @_DATA_NoInitImplClass, i64 8, i64 24, i64 40, i64 56 }>, section "__DATA,__objc_data, regular", align 8
95+
// CHECK: @"OBJC_CLASS_$_NoInitImplClass" = global <{ i64, ptr, ptr, ptr, ptr }> <{ i64 ptrtoint (ptr @"OBJC_METACLASS_$_NoInitImplClass" to i64), ptr @"OBJC_CLASS_$_NSObject", ptr @_objc_empty_cache, ptr null, ptr @_DATA_NoInitImplClass }>, section "__DATA,__objc_data, regular", align 8
9696
@_objcImplementation extension NoInitImplClass {
9797
@objc let s1 = "s1v"
9898
@objc var s2 = "s2v"
@@ -142,7 +142,7 @@ open class SwiftSubclass: ImplClass {
142142
// Class
143143
// CHECK: @_IVARS_ImplClassWithResilientStoredProperty = internal constant { i32, i32, [4 x { ptr, ptr, ptr, i32, i32 }] } { i32 32, i32 4, [4 x { ptr, ptr, ptr, i32, i32 }] [{ ptr, ptr, ptr, i32, i32 } { ptr @"$sSo36ImplClassWithResilientStoredPropertyC19objc_implementationE9beforeInts5Int32VvpWvd", ptr @.str.9.beforeInt, ptr @.str.0., i32 2, i32 4 }, { ptr, ptr, ptr, i32, i32 } { ptr @"$sSo36ImplClassWithResilientStoredPropertyC19objc_implementationE6mirrors6MirrorVSgvpWvd", ptr @.str.6.mirror, ptr @.str.0., i32 0, i32 0 }, { ptr, ptr, ptr, i32, i32 } { ptr @"$sSo36ImplClassWithResilientStoredPropertyC19objc_implementationE13afterIntFinals5Int32VvpWvd", ptr @.str.13.afterIntFinal, ptr @.str.0., i32 2, i32 4 }, { ptr, ptr, ptr, i32, i32 } { ptr @"$sSo36ImplClassWithResilientStoredPropertyC19objc_implementationE8afterInts5Int32VvpWvd", ptr @.str.8.afterInt, ptr @.str.0., i32 2, i32 4 }] }, section "__DATA, __objc_const", align 8
144144
// CHECK: @_DATA_ImplClassWithResilientStoredProperty = internal constant { i32, i32, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr } { i32 452, i32 8, i32 20, i32 0, ptr null, ptr @.str.36.ImplClassWithResilientStoredProperty, ptr @_INSTANCE_METHODS_ImplClassWithResilientStoredProperty, ptr null, ptr @_IVARS_ImplClassWithResilientStoredProperty, ptr null, ptr @_PROPERTIES_ImplClassWithResilientStoredProperty, ptr @"$sSo36ImplClassWithResilientStoredPropertyCMU" }, section "__DATA, __objc_data", align 8
145-
// CHECK: @"OBJC_CLASS_$_ImplClassWithResilientStoredProperty" = global <{ i64, ptr, ptr, ptr, i64, i64, i64, i64, i64 }> <{ i64 ptrtoint (ptr @"OBJC_METACLASS_$_ImplClassWithResilientStoredProperty" to i64), ptr @"OBJC_CLASS_$_NSObject", ptr @_objc_empty_cache, ptr null, i64 add (i64 ptrtoint (ptr @_DATA_ImplClassWithResilientStoredProperty to i64), i64 1), i64 0, i64 0, i64 0, i64 0 }>, section "__DATA,__objc_data, regular", align 8
145+
// CHECK: @"OBJC_CLASS_$_ImplClassWithResilientStoredProperty" = global <{ i64, ptr, ptr, ptr, i64 }> <{ i64 ptrtoint (ptr @"OBJC_METACLASS_$_ImplClassWithResilientStoredProperty" to i64), ptr @"OBJC_CLASS_$_NSObject", ptr @_objc_empty_cache, ptr null, i64 add (i64 ptrtoint (ptr @_DATA_ImplClassWithResilientStoredProperty to i64), i64 1) }>, section "__DATA,__objc_data, regular", align 8
146146

147147
@_objcImplementation extension ImplClassWithResilientStoredProperty {
148148
@objc var beforeInt: Int32 = 0
@@ -323,7 +323,7 @@ public func fn(impl: ImplClass, swiftSub: SwiftSubclass) {
323323
// CHECK: store ptr {{%[0-9]+}}, ptr {{%[0-9]+}}
324324
// CHECK: store ptr getelementptr inbounds (ptr, ptr @"$sBi32_WV", i32 8), ptr {{%[0-9]+}}
325325
// CHECK: store ptr getelementptr inbounds (ptr, ptr @"$sBi32_WV", i32 8), ptr {{%[0-9]+}}
326-
// CHECK: {{%[0-9]+}} = call swiftcc ptr @swift_updatePureObjCClassMetadata(ptr @"OBJC_CLASS_$_ImplClassWithResilientStoredProperty", i64 256, i64 4, ptr [[FIELDS_ARRAY]], ptr getelementptr inbounds (i64, ptr @"OBJC_CLASS_$_ImplClassWithResilientStoredProperty", i64 5))
326+
// CHECK: {{%[0-9]+}} = call swiftcc ptr @swift_updatePureObjCClassMetadata(ptr @"OBJC_CLASS_$_ImplClassWithResilientStoredProperty", i64 256, i64 4, ptr [[FIELDS_ARRAY]])
327327
//
328328
// This function should not invoke the metadata accessor.
329329
// CHECK-NOT: sSo36ImplClassWithResilientStoredPropertyCMa

0 commit comments

Comments
 (0)