@@ -3439,38 +3439,45 @@ static void initObjCClass(ClassMetadata *self,
3439
3439
size_t *fieldOffsets) {
3440
3440
ClassROData *rodata = getROData (self);
3441
3441
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
+ }
3454
3447
3455
- for ( unsigned i = 0 ; i ! = numFields; ++i) {
3456
- auto *eltLayout = fieldTypes[i] ;
3448
+ assert (ivars-> Count = = numFields);
3449
+ assert (ivars-> EntrySize == sizeof (ClassIvarEntry)) ;
3457
3450
3458
- ClassIvarEntry &ivar = ivars-> getIvars ()[i] ;
3451
+ bool copiedIvarList = false ;
3459
3452
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];
3465
3455
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 ;
3473
3476
}
3477
+ ivar.Size = eltLayout->size ;
3478
+ ivar.Type = nullptr ;
3479
+ ivar.Log2Alignment =
3480
+ getLog2AlignmentFromMask (eltLayout->flags .getAlignmentMask ());
3474
3481
}
3475
3482
}
3476
3483
}
0 commit comments