25
25
#include " MetadataCache.h"
26
26
#include " BytecodeLayouts.h"
27
27
#include " swift/ABI/TypeIdentity.h"
28
+ #include " swift/Basic/Defer.h"
28
29
#include " swift/Basic/MathUtils.h"
29
30
#include " swift/Basic/Lazy.h"
30
31
#include " swift/Basic/Range.h"
@@ -3974,76 +3975,90 @@ swift::swift_updateClassMetadata2(ClassMetadata *self,
3974
3975
/* allowDependency*/ true );
3975
3976
}
3976
3977
3977
- static void initClassFieldOffsetVector (ObjCClass *self,
3978
- size_t numFields,
3979
- const TypeLayout * const *fieldTypes,
3980
- size_t *fieldOffsets) {
3981
- size_t size, alignMask;
3978
+ Class
3979
+ swift::swift_updatePureObjCClassMetadata (Class cls,
3980
+ ClassLayoutFlags flags,
3981
+ size_t numFields,
3982
+ const TypeLayout * const *fieldTypes) {
3983
+ auto self = (ObjCClass *)cls;
3984
+ bool requiresUpdate = SWIFT_RUNTIME_WEAK_CHECK (_objc_realizeClassFromSwift);
3982
3985
3983
- ClassROData *rodata = getROData (self);
3986
+ // Realize the superclass first.
3987
+ (void )swift_getInitializedObjCClass ((Class)self->Isa );
3984
3988
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
3989
+ auto rodata = getROData (self);
3991
3990
3992
- // Okay, now do layout.
3993
- for (unsigned i = 0 ; i != numFields; ++i) {
3994
- auto *eltLayout = fieldTypes[i];
3991
+ // If we're running on a older Objective-C runtime, just realize
3992
+ // the class.
3993
+ if (!requiresUpdate) {
3994
+ // If we don't have a backward deployment layout, we cannot proceed here.
3995
+ if (rodata->InstanceSize == 0 ) {
3996
+ fatalError (0 , " class %s does not have a fragile layout; "
3997
+ " the deployment target was newer than this OS\n " ,
3998
+ rodata->Name );
3999
+ }
3995
4000
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 ());
4001
+ // Realize the class. This causes the runtime to slide the field offsets
4002
+ // stored in the field offset globals.
4003
+ //
4004
+ // Note that the field offset vector is *not* updated; however in
4005
+ // Objective-C interop mode, we don't actually use the field offset vector
4006
+ // of non-generic classes.
4007
+ //
4008
+ // In particular, class mirrors always use the Objective-C ivar descriptors,
4009
+ // which point at field offset globals and not the field offset vector.
4010
+ swift_getInitializedObjCClass ((Class)self);
4011
+ return cls;
4004
4012
}
4005
4013
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);
4014
+ SWIFT_DEFER {
4015
+ // Realize the class. This causes the runtime to slide the field offsets
4016
+ // stored in the field offset globals.
4017
+ SWIFT_RUNTIME_WEAK_USE (_objc_realizeClassFromSwift (cls, cls));
4018
+ };
4026
4019
4020
+ // Update the field offset globals using runtime type information; the layout
4021
+ // of resilient types might be different than the statically-emitted layout.
4027
4022
ClassIvarList *ivars = rodata->IvarList ;
4028
4023
if (!ivars) {
4029
4024
assert (numFields == 0 );
4030
- return ;
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
+ // Start layout from our static notion of where the superclass starts.
4034
+ // Objective-C expects us to have generated a correct ivar layout, which it
4035
+ // will simply slide if it needs to.
4036
+ assert (self->Superclass && " Swift cannot implement a root class" );
4037
+ size_t size = rodata->InstanceStart ;
4038
+ size_t alignMask = 0xF ; // malloc alignment guarantee
4040
4039
4040
+ // Okay, now do layout.
4041
+ for (unsigned i = 0 ; i != numFields; ++i) {
4041
4042
ClassIvarEntry *ivar = &ivars->getIvars ()[i];
4042
4043
4043
- // Fill in the field offset global, if this ivar has one.
4044
+ size_t offset = 0 ;
4044
4045
if (ivar->Offset ) {
4045
- if (*ivar->Offset != fieldOffsets[i])
4046
- *ivar->Offset = fieldOffsets[i];
4046
+ offset = *ivar->Offset ;
4047
+ }
4048
+
4049
+ auto *eltLayout = fieldTypes[i];
4050
+
4051
+ // Skip empty fields.
4052
+ if (offset != 0 || eltLayout->size != 0 ) {
4053
+ offset = roundUpToAlignMask (size, eltLayout->flags .getAlignmentMask ());
4054
+ size = offset + eltLayout->size ;
4055
+ alignMask = std::max (alignMask, eltLayout->flags .getAlignmentMask ());
4056
+
4057
+ // Fill in the field offset global, if this ivar has one.
4058
+ if (ivar->Offset ) {
4059
+ if (*ivar->Offset != offset)
4060
+ *ivar->Offset = offset;
4061
+ }
4047
4062
}
4048
4063
4049
4064
// If the ivar's size doesn't match the field layout we
@@ -4068,82 +4083,10 @@ static void initObjCClass(ObjCClass *self,
4068
4083
getLog2AlignmentFromMask (eltLayout->flags .getAlignmentMask ());
4069
4084
}
4070
4085
}
4071
- }
4072
-
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
-
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
- auto ROData = getROData (self);
4110
-
4111
- // If we're running on a older Objective-C runtime, just realize
4112
- // the class.
4113
- if (!requiresUpdate) {
4114
- // If we don't have a backward deployment layout, we cannot proceed here.
4115
- if (ROData->InstanceSize == 0 ) {
4116
- fatalError (0 , " class %s does not have a fragile layout; "
4117
- " the deployment target was newer than this OS\n " ,
4118
- ROData->Name );
4119
- }
4120
-
4121
- // Realize the class. This causes the runtime to slide the field offsets
4122
- // stored in the field offset globals.
4123
- //
4124
- // Note that the field offset vector is *not* updated; however in
4125
- // Objective-C interop mode, we don't actually use the field offset vector
4126
- // of non-generic classes.
4127
- //
4128
- // In particular, class mirrors always use the Objective-C ivar descriptors,
4129
- // which point at field offset globals and not the field offset vector.
4130
- swift_getInitializedObjCClass ((Class)self);
4131
- } else {
4132
- // Fake up a field offsets vector based on the ivars.
4133
- // FIXME: Temporary; we should just combine the other two functions' logic.
4134
- size_t *fieldOffsets = (size_t *)alloca (numFields * sizeof (size_t ));
4135
- populateInitialFieldOffsets (self, numFields, fieldOffsets);
4136
-
4137
- // Update the field offset vector using runtime type information; the layout
4138
- // of resilient types might be different than the statically-emitted layout.
4139
- initClassFieldOffsetVector (self, numFields, fieldTypes, fieldOffsets);
4140
4086
4141
- // Copy field offset vector entries to the field offset globals.
4142
- initObjCClass (self, numFields, fieldTypes, fieldOffsets);
4143
-
4144
- // See remark above about how this slides field offset globals.
4145
- SWIFT_RUNTIME_WEAK_USE (_objc_realizeClassFromSwift (cls, cls));
4146
- }
4087
+ // Save the size into the Objective-C metadata.
4088
+ if (rodata->InstanceSize != size)
4089
+ rodata->InstanceSize = size;
4147
4090
4148
4091
return cls;
4149
4092
}
0 commit comments