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