@@ -3974,76 +3974,95 @@ swift::swift_updateClassMetadata2(ClassMetadata *self,
3974
3974
/* allowDependency*/ true );
3975
3975
}
3976
3976
3977
- static void initClassFieldOffsetVector (ObjCClass *self,
3978
- size_t numFields,
3979
- const TypeLayout * const *fieldTypes,
3980
- size_t *fieldOffsets) {
3981
- size_t size, alignMask;
3977
+ Class
3978
+ swift::swift_updatePureObjCClassMetadata (Class cls,
3979
+ ClassLayoutFlags flags,
3980
+ size_t numFields,
3981
+ const TypeLayout * const *fieldTypes) {
3982
+ auto self = (ObjCClass *)cls;
3983
+ bool requiresUpdate = SWIFT_RUNTIME_WEAK_CHECK (_objc_realizeClassFromSwift);
3982
3984
3983
- ClassROData *rodata = getROData (self);
3985
+ // Realize the superclass first.
3986
+ (void )swift_getInitializedObjCClass ((Class)self->Isa );
3984
3987
3985
- // Start layout from our static notion of where the superclass starts.
3986
- // Objective-C expects us to have generated a correct ivar layout, which it
3987
- // will simply slide if it needs to.
3988
- assert (self->Superclass && " Swift cannot implement a root class" );
3989
- size = rodata->InstanceStart ;
3990
- alignMask = 0xF ; // malloc alignment guarantee
3988
+ // The Swift bit has been set so that we use Swift class initialization paths,
3989
+ // but from here on in, we want to treat this as a pure ObjC class. Clear it.
3990
+ auto rodata = getROData (self);
3991
+ self->RODataAndFlags = (uintptr_t )rodata;
3991
3992
3992
- // Okay, now do layout.
3993
- for (unsigned i = 0 ; i != numFields; ++i) {
3994
- auto *eltLayout = fieldTypes[i];
3993
+ // If we're running on a older Objective-C runtime, just realize
3994
+ // the class.
3995
+ if (!requiresUpdate) {
3996
+ // If we don't have a backward deployment layout, we cannot proceed here.
3997
+ if (rodata->InstanceSize == 0 ) {
3998
+ fatalError (0 , " class %s does not have a fragile layout; "
3999
+ " the deployment target was newer than this OS\n " ,
4000
+ rodata->Name );
4001
+ }
3995
4002
3996
- // Skip empty fields.
3997
- if (fieldOffsets[i] == 0 && eltLayout->size == 0 )
3998
- continue ;
3999
- auto offset = roundUpToAlignMask (size,
4000
- eltLayout->flags .getAlignmentMask ());
4001
- fieldOffsets[i] = offset;
4002
- size = offset + eltLayout->size ;
4003
- alignMask = std::max (alignMask, eltLayout->flags .getAlignmentMask ());
4003
+ // Realize the class. This causes the runtime to slide the field offsets
4004
+ // stored in the field offset globals.
4005
+ //
4006
+ // Note that the field offset vector is *not* updated; however in
4007
+ // Objective-C interop mode, we don't actually use the field offset vector
4008
+ // of non-generic classes.
4009
+ //
4010
+ // In particular, class mirrors always use the Objective-C ivar descriptors,
4011
+ // which point at field offset globals and not the field offset vector.
4012
+ swift_getInitializedObjCClass ((Class)self);
4013
+ return cls;
4004
4014
}
4005
4015
4006
- // Save the size into the Objective-C metadata.
4007
- if (rodata->InstanceSize != size)
4008
- rodata->InstanceSize = size;
4009
- }
4010
-
4011
- // / Non-generic classes only. Initialize the Objective-C ivar descriptors and
4012
- // / field offset globals. Does *not* register the class with the Objective-C
4013
- // / runtime; that must be done by the caller.
4014
- // /
4015
- // / This function copies the ivar descriptors and updates each ivar global with
4016
- // / the corresponding offset in \p fieldOffsets, before asking the Objective-C
4017
- // / runtime to realize the class. The Objective-C runtime will then slide the
4018
- // / offsets stored in those globals.
4019
- // /
4020
- // / Note that \p fieldOffsets remains unchanged in this case.
4021
- static void initObjCClass (ObjCClass *self,
4022
- size_t numFields,
4023
- const TypeLayout * const *fieldTypes,
4024
- size_t *fieldOffsets) {
4025
- ClassROData *rodata = getROData (self);
4026
-
4016
+ // Update the field offset globals using runtime type information; the layout
4017
+ // of resilient types might be different than the statically-emitted layout.
4027
4018
ClassIvarList *ivars = rodata->IvarList ;
4028
4019
if (!ivars) {
4029
4020
assert (numFields == 0 );
4030
- return ;
4021
+
4022
+ // See remark above about how this slides field offset globals.
4023
+ SWIFT_RUNTIME_WEAK_USE (_objc_realizeClassFromSwift (cls, cls));
4024
+
4025
+ return cls;
4031
4026
}
4032
4027
4033
4028
assert (ivars->Count == numFields);
4034
4029
assert (ivars->EntrySize == sizeof (ClassIvarEntry));
4035
4030
4036
4031
bool copiedIvarList = false ;
4037
4032
4038
- for (unsigned i = 0 ; i != numFields; ++i) {
4039
- auto *eltLayout = fieldTypes[i];
4033
+ // Update the field offset globals using runtime type information; the layout
4034
+ // of resilient types might be different than the statically-emitted layout.
4035
+ size_t size, alignMask;
4040
4036
4037
+ // Start layout from our static notion of where the superclass starts.
4038
+ // Objective-C expects us to have generated a correct ivar layout, which it
4039
+ // will simply slide if it needs to.
4040
+ assert (self->Superclass && " Swift cannot implement a root class" );
4041
+ size = rodata->InstanceStart ;
4042
+ alignMask = 0xF ; // malloc alignment guarantee
4043
+
4044
+ // Okay, now do layout.
4045
+ for (unsigned i = 0 ; i != numFields; ++i) {
4041
4046
ClassIvarEntry *ivar = &ivars->getIvars ()[i];
4042
4047
4043
- // Fill in the field offset global, if this ivar has one.
4048
+ size_t offset = 0 ;
4044
4049
if (ivar->Offset ) {
4045
- if (*ivar->Offset != fieldOffsets[i])
4046
- *ivar->Offset = fieldOffsets[i];
4050
+ offset = *ivar->Offset ;
4051
+ }
4052
+
4053
+ auto *eltLayout = fieldTypes[i];
4054
+
4055
+ // Skip empty fields.
4056
+ if (offset != 0 || eltLayout->size != 0 ) {
4057
+ offset = roundUpToAlignMask (size, eltLayout->flags .getAlignmentMask ());
4058
+ size = offset + eltLayout->size ;
4059
+ alignMask = std::max (alignMask, eltLayout->flags .getAlignmentMask ());
4060
+
4061
+ // Fill in the field offset global, if this ivar has one.
4062
+ if (ivar->Offset ) {
4063
+ if (*ivar->Offset != offset)
4064
+ *ivar->Offset = offset;
4065
+ }
4047
4066
}
4048
4067
4049
4068
// If the ivar's size doesn't match the field layout we
@@ -4068,85 +4087,13 @@ static void initObjCClass(ObjCClass *self,
4068
4087
getLog2AlignmentFromMask (eltLayout->flags .getAlignmentMask ());
4069
4088
}
4070
4089
}
4071
- }
4072
-
4073
- static void populateInitialFieldOffsets (ObjCClass *self,
4074
- size_t numFields,
4075
- size_t *fieldOffsets) {
4076
- ClassROData *rodata = getROData (self);
4077
4090
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
-
4098
- Class
4099
- swift::swift_updatePureObjCClassMetadata (Class cls,
4100
- ClassLayoutFlags flags,
4101
- size_t numFields,
4102
- const TypeLayout * const *fieldTypes) {
4103
- auto self = (ObjCClass *)cls;
4104
- bool requiresUpdate = SWIFT_RUNTIME_WEAK_CHECK (_objc_realizeClassFromSwift);
4105
-
4106
- // Realize the superclass first.
4107
- (void )swift_getInitializedObjCClass ((Class)self->Isa );
4108
-
4109
- // The Swift bit has been set so that we use Swift class initialization paths,
4110
- // but from here on in, we want to treat this as a pure ObjC class. Clear it.
4111
- auto ROData = getROData (self);
4112
- self->RODataAndFlags = (uintptr_t )ROData;
4113
-
4114
- // If we're running on a older Objective-C runtime, just realize
4115
- // the class.
4116
- if (!requiresUpdate) {
4117
- // If we don't have a backward deployment layout, we cannot proceed here.
4118
- if (ROData->InstanceSize == 0 ) {
4119
- fatalError (0 , " class %s does not have a fragile layout; "
4120
- " the deployment target was newer than this OS\n " ,
4121
- ROData->Name );
4122
- }
4123
-
4124
- // Realize the class. This causes the runtime to slide the field offsets
4125
- // stored in the field offset globals.
4126
- //
4127
- // Note that the field offset vector is *not* updated; however in
4128
- // Objective-C interop mode, we don't actually use the field offset vector
4129
- // of non-generic classes.
4130
- //
4131
- // In particular, class mirrors always use the Objective-C ivar descriptors,
4132
- // which point at field offset globals and not the field offset vector.
4133
- swift_getInitializedObjCClass ((Class)self);
4134
- } 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
-
4140
- // Update the field offset vector using runtime type information; the layout
4141
- // of resilient types might be different than the statically-emitted layout.
4142
- initClassFieldOffsetVector (self, numFields, fieldTypes, fieldOffsets);
4143
-
4144
- // Copy field offset vector entries to the field offset globals.
4145
- initObjCClass (self, numFields, fieldTypes, fieldOffsets);
4091
+ // Save the size into the Objective-C metadata.
4092
+ if (rodata->InstanceSize != size)
4093
+ rodata->InstanceSize = size;
4146
4094
4147
- // See remark above about how this slides field offset globals.
4148
- SWIFT_RUNTIME_WEAK_USE (_objc_realizeClassFromSwift (cls, cls));
4149
- }
4095
+ // See remark above about how this slides field offset globals.
4096
+ SWIFT_RUNTIME_WEAK_USE (_objc_realizeClassFromSwift (cls, cls));
4150
4097
4151
4098
return cls;
4152
4099
}
0 commit comments