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