@@ -3439,38 +3439,45 @@ static void initObjCClass(ClassMetadata *self,
34393439 size_t *fieldOffsets) {
34403440 ClassROData *rodata = getROData (self);
34413441
3442- // Always clone the ivar descriptors.
3443- if (numFields) {
3444- const ClassIvarList *dependentIvars = rodata->IvarList ;
3445- assert (dependentIvars->Count == numFields);
3446- assert (dependentIvars->EntrySize == sizeof (ClassIvarEntry));
3447-
3448- auto ivarListSize = sizeof (ClassIvarList) +
3449- numFields * sizeof (ClassIvarEntry);
3450- auto ivars = (ClassIvarList*) getResilientMetadataAllocator ()
3451- .Allocate (ivarListSize, alignof (ClassIvarList));
3452- memcpy (ivars, dependentIvars, ivarListSize);
3453- rodata->IvarList = ivars;
3442+ ClassIvarList *ivars = rodata->IvarList ;
3443+ if (!ivars) {
3444+ assert (numFields == 0 );
3445+ return ;
3446+ }
34543447
3455- for ( unsigned i = 0 ; i ! = numFields; ++i) {
3456- auto *eltLayout = fieldTypes[i] ;
3448+ assert (ivars-> Count = = numFields);
3449+ assert (ivars-> EntrySize == sizeof (ClassIvarEntry)) ;
34573450
3458- ClassIvarEntry &ivar = ivars-> getIvars ()[i] ;
3451+ bool copiedIvarList = false ;
34593452
3460- // Fill in the field offset global, if this ivar has one.
3461- if (ivar.Offset ) {
3462- if (*ivar.Offset != fieldOffsets[i])
3463- *ivar.Offset = fieldOffsets[i];
3464- }
3453+ for (unsigned i = 0 ; i != numFields; ++i) {
3454+ auto *eltLayout = fieldTypes[i];
34653455
3466- // If the ivar's size doesn't match the field layout we
3467- // computed, overwrite it and give it better type information.
3468- if (ivar.Size != eltLayout->size ) {
3469- ivar.Size = eltLayout->size ;
3470- ivar.Type = nullptr ;
3471- ivar.Log2Alignment =
3472- getLog2AlignmentFromMask (eltLayout->flags .getAlignmentMask ());
3456+ ClassIvarEntry &ivar = ivars->getIvars ()[i];
3457+
3458+ // Fill in the field offset global, if this ivar has one.
3459+ if (ivar.Offset ) {
3460+ if (*ivar.Offset != fieldOffsets[i])
3461+ *ivar.Offset = fieldOffsets[i];
3462+ }
3463+
3464+ // If the ivar's size doesn't match the field layout we
3465+ // computed, overwrite it and give it better type information.
3466+ if (ivar.Size != eltLayout->size ) {
3467+ // If we're going to modify the ivar list, we need to copy it first.
3468+ if (!copiedIvarList) {
3469+ auto ivarListSize = sizeof (ClassIvarList) +
3470+ numFields * sizeof (ClassIvarEntry);
3471+ ivars = (ClassIvarList*) getResilientMetadataAllocator ()
3472+ .Allocate (ivarListSize, alignof (ClassIvarList));
3473+ memcpy (ivars, rodata->IvarList , ivarListSize);
3474+ rodata->IvarList = ivars;
3475+ copiedIvarList = true ;
34733476 }
3477+ ivar.Size = eltLayout->size ;
3478+ ivar.Type = nullptr ;
3479+ ivar.Log2Alignment =
3480+ getLog2AlignmentFromMask (eltLayout->flags .getAlignmentMask ());
34743481 }
34753482 }
34763483}
0 commit comments