Always put SILFunctions into a zombie list, when they are erased.

This removes the function body, but preserves the SILFunction object, which may be still referenced by different kinds of meta-information e.g. debug info for inlined functions, generic specializations information, etc.

Doing this unconditionally simplifies the code and makes it less error-prone to reference SILFunctions from any kind of meta-information. It just works. No need to set any special flags, etc.
This commit is contained in:
Roman Levenstein
2017-08-11 11:14:19 -07:00
parent ca6f9f6d55
commit bae290cdab
3 changed files with 18 additions and 51 deletions

View File

@@ -200,12 +200,6 @@ private:
/// after the pass runs, we only see a semantic-arc world.
bool HasQualifiedOwnership = true;
/// True if this function is referenced by any kind of meta-information. This
/// is the case e.g. when a function is referenced by the specialization
/// information. Setting this flag ensures that the functions becomes a zombie
/// function later.
bool ReferencedByMetainformation = false;
SILFunction(SILModule &module, SILLinkage linkage, StringRef mangledName,
CanSILFunctionType loweredType, GenericEnvironment *genericEnv,
Optional<SILLocation> loc, IsBare_t isBareSILFunction,
@@ -297,26 +291,13 @@ public:
/// Mark this function as removed from the module's function list, but kept
/// as "zombie" for debug info or vtable stub generation.
void setZombie() {
assert((isInlined() || isExternallyUsedSymbol() ||
isReferencedByMetainformation()) &&
"Function should be deleted instead of getting a zombie");
assert(!isZombie() && "Function is a zombie function already");
Zombie = true;
}
/// Returns true if this function is dead, but kept in the module's zombie list.
bool isZombie() const { return Zombie; }
/// Mark this function as referenced by meta-information.
void setReferencedByMetainformation() {
ReferencedByMetainformation = true;
}
/// Returns true if this function is referenced by any kind of
/// meta-information.
bool isReferencedByMetainformation() const {
return ReferencedByMetainformation;
}
/// Returns true if this function has qualified ownership instructions in it.
bool hasQualifiedOwnership() const { return HasQualifiedOwnership; }

View File

@@ -2231,13 +2231,7 @@ void KeyPathInst::dropReferencedPattern() {
GenericSpecializationInformation::GenericSpecializationInformation(
SILFunction *Caller, SILFunction *Parent, SubstitutionList Subs)
: Caller(Caller), Parent(Parent), Subs(Subs) {
// Specialization information may reference these functions, even
// if they are removed by means of e.g. dead function elimination.
if (Caller)
Caller->setReferencedByMetainformation();
Parent->setReferencedByMetainformation();
}
: Caller(Caller), Parent(Parent), Subs(Subs) {}
const GenericSpecializationInformation *
GenericSpecializationInformation::create(SILFunction *Caller,

View File

@@ -555,32 +555,24 @@ void SILModule::removeFromZombieList(StringRef Name) {
/// Erase a function from the module.
void SILModule::eraseFunction(SILFunction *F) {
assert(! F->isZombie() && "zombie function is in list of alive functions");
if (F->isInlined() || F->isExternallyUsedSymbol() ||
F->isReferencedByMetainformation()) {
// The owner of the function's Name is the FunctionTable key. As we remove
// the function from the table we have to store the name string elsewhere:
// in zombieFunctionNames.
StringRef copiedName = F->getName().copy(zombieFunctionNames);
FunctionTable.erase(F->getName());
F->Name = copiedName;
// The owner of the function's Name is the FunctionTable key. As we remove
// the function from the table we have to store the name string elsewhere:
// in zombieFunctionNames.
StringRef copiedName = F->getName().copy(zombieFunctionNames);
FunctionTable.erase(F->getName());
F->Name = copiedName;
// The function is dead, but we need it later (at IRGen) for debug info
// or vtable stub generation. So we move it into the zombie list.
getFunctionList().remove(F);
zombieFunctions.push_back(F);
ZombieFunctionTable[copiedName] = F;
F->setZombie();
// The function is dead, but we need it later (at IRGen) for debug info
// or vtable stub generation. So we move it into the zombie list.
getFunctionList().remove(F);
zombieFunctions.push_back(F);
ZombieFunctionTable[copiedName] = F;
F->setZombie();
// This opens dead-function-removal opportunities for called functions.
// (References are not needed anymore.)
F->dropAllReferences();
} else {
FunctionTable.erase(F->getName());
getFunctionList().erase(F);
}
// This opens dead-function-removal opportunities for called functions.
// (References are not needed anymore.)
F->dropAllReferences();
}
void SILModule::invalidateFunctionInSILCache(SILFunction *F) {