Skip to content

Commit 22d1090

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-rebranch
2 parents cfb014b + ab2152b commit 22d1090

File tree

4 files changed

+506
-35
lines changed

4 files changed

+506
-35
lines changed

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,11 @@ class DIMemoryObjectInfo {
176176
MemoryInst->isDerivedClassSelfOnly();
177177
}
178178

179+
/// True if this memory object is the 'self' of a root class init method.
180+
bool isRootClassSelf() const {
181+
return isClassInitSelf() && MemoryInst->isRootSelf();
182+
}
183+
179184
/// True if this memory object is the 'self' of a non-root class init method.
180185
bool isNonRootClassSelf() const {
181186
return isClassInitSelf() && !MemoryInst->isRootSelf();

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 111 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,7 +1072,13 @@ void LifetimeChecker::handleStoreUse(unsigned UseID) {
10721072
// it for later. Once we've collected all of the conditional init/assigns,
10731073
// we can insert a single control variable for the memory object for the
10741074
// whole function.
1075-
if (!Use.onlyTouchesTrivialElements(TheMemory))
1075+
//
1076+
// For root class initializers, we must keep track of initializations of
1077+
// trivial stored properties also, since we need to know when the object
1078+
// has been fully initialized when deciding if a strong_release should
1079+
// lower to a partial_dealloc_ref.
1080+
if (TheMemory.isRootClassSelf() ||
1081+
!Use.onlyTouchesTrivialElements(TheMemory))
10761082
HasConditionalInitAssign = true;
10771083
return;
10781084
}
@@ -2186,12 +2192,12 @@ static void updateControlVariable(SILLocation Loc,
21862192
}
21872193

21882194
/// Test a bit in the control variable at the current insertion point.
2189-
static SILValue testControlVariable(SILLocation Loc,
2190-
unsigned Elt,
2191-
SILValue ControlVariableAddr,
2192-
Identifier &ShiftRightFn,
2193-
Identifier &TruncateFn,
2194-
SILBuilder &B) {
2195+
static SILValue testControlVariableBit(SILLocation Loc,
2196+
unsigned Elt,
2197+
SILValue ControlVariableAddr,
2198+
Identifier &ShiftRightFn,
2199+
Identifier &TruncateFn,
2200+
SILBuilder &B) {
21952201
SILValue ControlVariable =
21962202
B.createLoad(Loc, ControlVariableAddr, LoadOwnershipQualifier::Trivial);
21972203

@@ -2224,6 +2230,32 @@ static SILValue testControlVariable(SILLocation Loc,
22242230
{}, CondVal);
22252231
}
22262232

2233+
/// Test if all bits in the control variable are set at the current
2234+
/// insertion point.
2235+
static SILValue testAllControlVariableBits(SILLocation Loc,
2236+
SILValue ControlVariableAddr,
2237+
Identifier &CmpEqFn,
2238+
SILBuilder &B) {
2239+
SILValue ControlVariable =
2240+
B.createLoad(Loc, ControlVariableAddr, LoadOwnershipQualifier::Trivial);
2241+
2242+
SILValue CondVal = ControlVariable;
2243+
CanBuiltinIntegerType IVType = CondVal->getType().castTo<BuiltinIntegerType>();
2244+
2245+
if (IVType->getFixedWidth() == 1)
2246+
return CondVal;
2247+
2248+
SILValue AllBitsSet = B.createIntegerLiteral(Loc, CondVal->getType(), -1);
2249+
if (!CmpEqFn.get())
2250+
CmpEqFn = getBinaryFunction("cmp_eq", CondVal->getType(),
2251+
B.getASTContext());
2252+
SILValue Args[] = { CondVal, AllBitsSet };
2253+
2254+
return B.createBuiltin(Loc, CmpEqFn,
2255+
SILType::getBuiltinIntegerType(1, B.getASTContext()),
2256+
{}, Args);
2257+
}
2258+
22272259
/// handleConditionalInitAssign - This memory object has some stores
22282260
/// into (some element of) it that is either an init or an assign based on the
22292261
/// control flow path through the function, or have a destroy event that happens
@@ -2285,7 +2317,13 @@ SILValue LifetimeChecker::handleConditionalInitAssign() {
22852317
// If this ambiguous store is only of trivial types, then we don't need to
22862318
// do anything special. We don't even need keep the init bit for the
22872319
// element precise.
2288-
if (Use.onlyTouchesTrivialElements(TheMemory))
2320+
//
2321+
// For root class initializers, we must keep track of initializations of
2322+
// trivial stored properties also, since we need to know when the object
2323+
// has been fully initialized when deciding if a strong_release should
2324+
// lower to a partial_dealloc_ref.
2325+
if (!TheMemory.isRootClassSelf() &&
2326+
Use.onlyTouchesTrivialElements(TheMemory))
22892327
continue;
22902328

22912329
B.setInsertionPoint(Use.Inst);
@@ -2324,9 +2362,9 @@ SILValue LifetimeChecker::handleConditionalInitAssign() {
23242362
// initialization.
23252363
for (unsigned Elt = Use.FirstElement, e = Elt+Use.NumElements;
23262364
Elt != e; ++Elt) {
2327-
auto CondVal = testControlVariable(Loc, Elt, ControlVariableAddr,
2328-
ShiftRightFn, TruncateFn,
2329-
B);
2365+
auto CondVal = testControlVariableBit(Loc, Elt, ControlVariableAddr,
2366+
ShiftRightFn, TruncateFn,
2367+
B);
23302368

23312369
SILBasicBlock *TrueBB, *FalseBB, *ContBB;
23322370
InsertCFGDiamond(CondVal, Loc, B,
@@ -2395,7 +2433,7 @@ SILValue LifetimeChecker::handleConditionalInitAssign() {
23952433
void LifetimeChecker::
23962434
handleConditionalDestroys(SILValue ControlVariableAddr) {
23972435
SILBuilderWithScope B(TheMemory.getUninitializedValue());
2398-
Identifier ShiftRightFn, TruncateFn;
2436+
Identifier ShiftRightFn, TruncateFn, CmpEqFn;
23992437

24002438
unsigned NumMemoryElements = TheMemory.getNumElements();
24012439

@@ -2465,9 +2503,9 @@ handleConditionalDestroys(SILValue ControlVariableAddr) {
24652503

24662504
// Insert a load of the liveness bitmask and split the CFG into a diamond
24672505
// right before the destroy_addr, if we haven't already loaded it.
2468-
auto CondVal = testControlVariable(Loc, Elt, ControlVariableAddr,
2469-
ShiftRightFn, TruncateFn,
2470-
B);
2506+
auto CondVal = testControlVariableBit(Loc, Elt, ControlVariableAddr,
2507+
ShiftRightFn, TruncateFn,
2508+
B);
24712509

24722510
SILBasicBlock *ReleaseBlock, *DeallocBlock, *ContBlock;
24732511

@@ -2486,11 +2524,11 @@ handleConditionalDestroys(SILValue ControlVariableAddr) {
24862524
// depending on if the self box was initialized or not.
24872525
auto emitReleaseOfSelfWhenNotConsumed = [&](SILLocation Loc,
24882526
SILInstruction *Release) {
2489-
auto CondVal = testControlVariable(Loc, SelfInitializedElt,
2490-
ControlVariableAddr,
2491-
ShiftRightFn,
2492-
TruncateFn,
2493-
B);
2527+
auto CondVal = testControlVariableBit(Loc, SelfInitializedElt,
2528+
ControlVariableAddr,
2529+
ShiftRightFn,
2530+
TruncateFn,
2531+
B);
24942532

24952533
SILBasicBlock *ReleaseBlock, *ConsumedBlock, *ContBlock;
24962534

@@ -2522,12 +2560,50 @@ handleConditionalDestroys(SILValue ControlVariableAddr) {
25222560
// Just conditionally destroy each memory element, and for classes,
25232561
// also free the partially initialized object.
25242562
if (!TheMemory.isNonRootClassSelf()) {
2525-
destroyMemoryElements(Loc, Availability);
2526-
processUninitializedRelease(Release, false, B.getInsertionPoint());
2563+
assert(!Availability.isAllYes() &&
2564+
"Should not end up here if fully initialized");
2565+
2566+
// For root class initializers, we check if all proeprties were
2567+
// dynamically initialized, and if so, treat this as a release of
2568+
// an initialized 'self', instead of tearing down the fields
2569+
// one by one and deallocating memory.
2570+
//
2571+
// This is required for correctness, since the condition that
2572+
// allows 'self' to escape is that all stored properties were
2573+
// initialized. So we cannot deallocate the memory if 'self' may
2574+
// have escaped.
2575+
//
2576+
// This also means the deinitializer will run if all stored
2577+
// properties were initialized.
2578+
if (TheMemory.isClassInitSelf() &&
2579+
Availability.hasAny(DIKind::Partial)) {
2580+
auto CondVal = testAllControlVariableBits(Loc, ControlVariableAddr,
2581+
CmpEqFn, B);
2582+
2583+
SILBasicBlock *ReleaseBlock, *DeallocBlock, *ContBlock;
2584+
2585+
InsertCFGDiamond(CondVal, Loc, B,
2586+
ReleaseBlock, DeallocBlock, ContBlock);
2587+
2588+
// If true, self was fully initialized and must be released.
2589+
B.setInsertionPoint(ReleaseBlock->begin());
2590+
B.setCurrentDebugScope(ReleaseBlock->begin()->getDebugScope());
2591+
Release->moveBefore(&*B.getInsertionPoint());
2592+
2593+
// If false, self is uninitialized and must be freed.
2594+
B.setInsertionPoint(DeallocBlock->begin());
2595+
B.setCurrentDebugScope(DeallocBlock->begin()->getDebugScope());
2596+
destroyMemoryElements(Loc, Availability);
2597+
processUninitializedRelease(Release, false, B.getInsertionPoint());
2598+
} else {
2599+
destroyMemoryElements(Loc, Availability);
2600+
processUninitializedRelease(Release, false, B.getInsertionPoint());
2601+
2602+
// The original strong_release or destroy_addr instruction is
2603+
// always dead at this point.
2604+
deleteDeadRelease(CDElt.ReleaseID);
2605+
}
25272606

2528-
// The original strong_release or destroy_addr instruction is
2529-
// always dead at this point.
2530-
deleteDeadRelease(CDElt.ReleaseID);
25312607
continue;
25322608
}
25332609

@@ -2573,11 +2649,11 @@ handleConditionalDestroys(SILValue ControlVariableAddr) {
25732649
// self.init or super.init may or may not have been called.
25742650
// We have not yet stored 'self' into the box.
25752651

2576-
auto CondVal = testControlVariable(Loc, SuperInitElt,
2577-
ControlVariableAddr,
2578-
ShiftRightFn,
2579-
TruncateFn,
2580-
B);
2652+
auto CondVal = testControlVariableBit(Loc, SuperInitElt,
2653+
ControlVariableAddr,
2654+
ShiftRightFn,
2655+
TruncateFn,
2656+
B);
25812657

25822658
SILBasicBlock *ConsumedBlock, *DeallocBlock, *ContBlock;
25832659

@@ -2607,11 +2683,11 @@ handleConditionalDestroys(SILValue ControlVariableAddr) {
26072683
// self.init or super.init may or may not have been called.
26082684
// We may or may have stored 'self' into the box.
26092685

2610-
auto CondVal = testControlVariable(Loc, SuperInitElt,
2611-
ControlVariableAddr,
2612-
ShiftRightFn,
2613-
TruncateFn,
2614-
B);
2686+
auto CondVal = testControlVariableBit(Loc, SuperInitElt,
2687+
ControlVariableAddr,
2688+
ShiftRightFn,
2689+
TruncateFn,
2690+
B);
26152691

26162692
SILBasicBlock *LiveBlock, *DeallocBlock, *ContBlock;
26172693

0 commit comments

Comments
 (0)