Skip to content

Commit b85cdc1

Browse files
authored
Merge pull request #68871 from mikeash/lazy-copy-ivar-list-5.10
[5.10][Runtime] Lazily copy ivar list in initObjCClass.
2 parents 21c907d + ad76246 commit b85cdc1

File tree

1 file changed

+34
-27
lines changed

1 file changed

+34
-27
lines changed

stdlib/public/runtime/Metadata.cpp

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)