mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Two changes:
- Fix a misunderstanding I had about ownership requirements in my previous patch: now any references to value-promoted self do a retain and use a ManagedValue, just like the semantic load path used to. This is the change to visitLoadExpr - Second, change argument lowering to drop the "self" argument of normal class methods into a constant reference, instead of making a box for it. This greatly reduces the amount of SIL generated for class methods. The argument lowering piece is somewhat hacky because initializations really want to be dealing with memory, but it seemed like the best approach given the current design. Review appreciated. Swift SVN r10984
This commit is contained in:
@@ -414,6 +414,14 @@ struct InitializationForPattern
|
|||||||
if (isa<LValueType>(varType))
|
if (isa<LValueType>(varType))
|
||||||
return InitializationPtr(new InOutInitialization(vd));
|
return InitializationPtr(new InOutInitialization(vd));
|
||||||
|
|
||||||
|
// If this is a 'self' argument for a class method (not struct method), emit
|
||||||
|
// it as a constant value. Since it is a constant value, there is no memory
|
||||||
|
// location associated with it, and thus we don't need an initialization -
|
||||||
|
// the store will provide the value directly into the VarLocs map.
|
||||||
|
if (vd->isImplicit() && vd->getName().str() == "self" &&
|
||||||
|
vd->getType()->hasReferenceSemantics())
|
||||||
|
return InitializationPtr(new BlackHoleInitialization());
|
||||||
|
|
||||||
// Otherwise, we have a normal local-variable initialization.
|
// Otherwise, we have a normal local-variable initialization.
|
||||||
auto varInit = Gen.emitLocalVariableWithCleanup(vd);
|
auto varInit = Gen.emitLocalVariableWithCleanup(vd);
|
||||||
|
|
||||||
@@ -484,6 +492,26 @@ CleanupHandle SILGenFunction::enterDeallocStackCleanup(SILLocation loc,
|
|||||||
return Cleanups.getTopCleanup();
|
return Cleanups.getTopCleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CleanupCaptureBox : public Cleanup {
|
||||||
|
SILValue box;
|
||||||
|
public:
|
||||||
|
CleanupCaptureBox(SILValue box) : box(box) {}
|
||||||
|
void emit(SILGenFunction &gen, CleanupLocation l) override {
|
||||||
|
gen.B.emitStrongRelease(l, box);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CleanupCaptureValue : public Cleanup {
|
||||||
|
SILValue v;
|
||||||
|
public:
|
||||||
|
CleanupCaptureValue(SILValue v) : v(v) {}
|
||||||
|
void emit(SILGenFunction &gen, CleanupLocation l) override {
|
||||||
|
gen.B.emitDestroyValueOperation(l, v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/// A visitor for traversing a pattern, creating
|
/// A visitor for traversing a pattern, creating
|
||||||
@@ -608,8 +636,25 @@ struct ArgumentInitVisitor :
|
|||||||
}
|
}
|
||||||
|
|
||||||
SILValue visitNamedPattern(NamedPattern *P, Initialization *I) {
|
SILValue visitNamedPattern(NamedPattern *P, Initialization *I) {
|
||||||
return makeArgumentInto(P->getType(), f.begin(),
|
VarDecl *vd = P->getDecl();
|
||||||
P->getDecl(), I);
|
|
||||||
|
// If this is a 'self' argument for a class method (not struct method), emit
|
||||||
|
// it as a constant value. Since it is a constant value, there is no memory
|
||||||
|
// location associated with it, and thus we don't need an initialization -
|
||||||
|
// the store will provide the value directly into the VarLocs map.
|
||||||
|
if (vd->isImplicit() && vd->getName().str() == "self" &&
|
||||||
|
vd->getType()->hasReferenceSemantics()) {
|
||||||
|
SILLocation loc = vd;
|
||||||
|
loc.markAsPrologue();
|
||||||
|
SILValue arg = makeArgument(P->getType(), f.begin(), loc);
|
||||||
|
assert(!gen.VarLocs.count(vd) && "Already emitted a this vardecl?");
|
||||||
|
gen.VarLocs[vd] = SILGenFunction::VarLoc::getConstant(arg);
|
||||||
|
gen.Cleanups.pushCleanup<CleanupCaptureValue>(arg);
|
||||||
|
I->finishInitialization(gen);
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
return makeArgumentInto(P->getType(), f.begin(), vd, I);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PATTERN(Id, Parent)
|
#define PATTERN(Id, Parent)
|
||||||
@@ -621,25 +666,7 @@ struct ArgumentInitVisitor :
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CleanupCaptureBox : public Cleanup {
|
static void emitCaptureArguments(SILGenFunction & gen, ValueDecl *capture) {
|
||||||
SILValue box;
|
|
||||||
public:
|
|
||||||
CleanupCaptureBox(SILValue box) : box(box) {}
|
|
||||||
void emit(SILGenFunction &gen, CleanupLocation l) override {
|
|
||||||
gen.B.emitStrongRelease(l, box);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class CleanupCaptureValue : public Cleanup {
|
|
||||||
SILValue v;
|
|
||||||
public:
|
|
||||||
CleanupCaptureValue(SILValue v) : v(v) {}
|
|
||||||
void emit(SILGenFunction &gen, CleanupLocation l) override {
|
|
||||||
gen.B.emitDestroyValueOperation(l, v);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void emitCaptureArguments(SILGenFunction &gen, ValueDecl *capture) {
|
|
||||||
ASTContext &c = capture->getASTContext();
|
ASTContext &c = capture->getASTContext();
|
||||||
switch (getDeclCaptureKind(capture)) {
|
switch (getDeclCaptureKind(capture)) {
|
||||||
case CaptureKind::None:
|
case CaptureKind::None:
|
||||||
|
|||||||
@@ -139,40 +139,38 @@ static void destroyRValue(SILGenFunction &SGF, CleanupLocation loc,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getLoadPropagatedValue - If a LoadExpr of the specified subexpression will
|
static VarDecl *isLoadPropagatedValue(Expr *SubExpr, SILGenFunction &SGF) {
|
||||||
/// be folded into a constant, return that value. Otherwise, it returns a null
|
// Look through parens.
|
||||||
/// SILValue.
|
|
||||||
static SILValue getLoadPropagatedValue(Expr *SubExpr, SILGenFunction &SGF) {
|
|
||||||
|
|
||||||
// Look through parens.
|
|
||||||
while (auto *PE = dyn_cast<ParenExpr>(SubExpr))
|
while (auto *PE = dyn_cast<ParenExpr>(SubExpr))
|
||||||
SubExpr = PE->getSubExpr();
|
SubExpr = PE->getSubExpr();
|
||||||
|
|
||||||
// If this is a load of a local constant decl, just produce the value.
|
// If this is a load of a local constant decl, just produce the value.
|
||||||
if (auto *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
|
if (auto *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
|
||||||
if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
|
if (auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
|
||||||
|
// FIXME: This should be a bit on vardecl, not presence in VarLocs.
|
||||||
auto It = SGF.VarLocs.find(VD);
|
auto It = SGF.VarLocs.find(VD);
|
||||||
if (It != SGF.VarLocs.end() && It->second.isConstant())
|
if (It != SGF.VarLocs.end() && It->second.isConstant())
|
||||||
return It->second.getConstant();
|
return VD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is a use of super that is a constant, just produce the value.
|
// If this is a use of super that is a constant, just produce the value.
|
||||||
if (auto *SRE = dyn_cast<SuperRefExpr>(SubExpr)) {
|
if (auto *SRE = dyn_cast<SuperRefExpr>(SubExpr)) {
|
||||||
if (auto *VD = dyn_cast<VarDecl>(SRE->getSelf())) {
|
if (auto *VD = dyn_cast<VarDecl>(SRE->getSelf())) {
|
||||||
|
// FIXME: This should be a bit on vardecl, not presence in VarLocs.
|
||||||
auto It = SGF.VarLocs.find(VD);
|
auto It = SGF.VarLocs.find(VD);
|
||||||
if (It != SGF.VarLocs.end() && It->second.isConstant())
|
if (It != SGF.VarLocs.end() && It->second.isConstant())
|
||||||
return It->second.getConstant();
|
return VD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nullptr;
|
||||||
return SILValue();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SILGenFunction::emitExprInto(Expr *E, Initialization *I) {
|
void SILGenFunction::emitExprInto(Expr *E, Initialization *I) {
|
||||||
// Handle the special case of copying an lvalue.
|
// Handle the special case of copying an lvalue.
|
||||||
if (auto load = dyn_cast<LoadExpr>(E))
|
if (auto load = dyn_cast<LoadExpr>(E))
|
||||||
if (!getLoadPropagatedValue(load->getSubExpr(), *this)) {
|
if (!isLoadPropagatedValue(load->getSubExpr(), *this)) {
|
||||||
auto lv = emitLValue(load->getSubExpr());
|
auto lv = emitLValue(load->getSubExpr());
|
||||||
emitCopyLValueInto(E, lv, I);
|
emitCopyLValueInto(E, lv, I);
|
||||||
return;
|
return;
|
||||||
@@ -578,8 +576,16 @@ RValue RValueEmitter::visitStringLiteralExpr(StringLiteralExpr *E,
|
|||||||
|
|
||||||
RValue RValueEmitter::visitLoadExpr(LoadExpr *E, SGFContext C) {
|
RValue RValueEmitter::visitLoadExpr(LoadExpr *E, SGFContext C) {
|
||||||
// If we can and must fold this, do so.
|
// If we can and must fold this, do so.
|
||||||
if (SILValue V = getLoadPropagatedValue(E->getSubExpr(), SGF))
|
if (VarDecl *VD = isLoadPropagatedValue(E->getSubExpr(), SGF)) {
|
||||||
return RValue(SGF, E, ManagedValue(V, ManagedValue::Unmanaged));
|
auto &Entry = SGF.VarLocs[VD];
|
||||||
|
assert(Entry.isConstant() && "Not a load propagated vardecl");
|
||||||
|
SILValue V = Entry.getConstant();
|
||||||
|
|
||||||
|
auto &TL = SGF.getTypeLowering(VD->getType());
|
||||||
|
// The value must be copied for the duration of the expression.
|
||||||
|
V = TL.emitLoweredCopyValue(SGF.B, E, V, false);
|
||||||
|
return RValue(SGF, E, SGF.emitManagedRValueWithCleanup(V, TL));
|
||||||
|
}
|
||||||
|
|
||||||
LValue lv = SGF.emitLValue(E->getSubExpr());
|
LValue lv = SGF.emitLValue(E->getSubExpr());
|
||||||
auto result = SGF.emitLoadOfLValue(E, lv, C);
|
auto result = SGF.emitLoadOfLValue(E, lv, C);
|
||||||
@@ -3036,7 +3042,7 @@ RValue RValueEmitter::visitAssignExpr(AssignExpr *E, SGFContext C) {
|
|||||||
if (auto *LE = dyn_cast<LoadExpr>(E->getSrc())) {
|
if (auto *LE = dyn_cast<LoadExpr>(E->getSrc())) {
|
||||||
if (!isa<TupleExpr>(E->getDest())
|
if (!isa<TupleExpr>(E->getDest())
|
||||||
&& E->getDest()->getType()->isEqual(LE->getSubExpr()->getType()) &&
|
&& E->getDest()->getType()->isEqual(LE->getSubExpr()->getType()) &&
|
||||||
!getLoadPropagatedValue(LE->getSubExpr(), SGF)) {
|
!isLoadPropagatedValue(LE->getSubExpr(), SGF)) {
|
||||||
SGF.emitAssignLValueToLValue(E,
|
SGF.emitAssignLValueToLValue(E,
|
||||||
SGF.emitLValue(cast<LoadExpr>(E->getSrc())->getSubExpr()),
|
SGF.emitLValue(cast<LoadExpr>(E->getSrc())->getSubExpr()),
|
||||||
SGF.emitLValue(E->getDest()));
|
SGF.emitLValue(E->getDest()));
|
||||||
|
|||||||
Reference in New Issue
Block a user