mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Call SILFunction destructor when we cleanup functions so that if the function contains a function_ref, the function referenced by the function_ref has its refcount properly decrement.
Otherwise a function_ref which was supposed to be deallocated would keep functions alive. rdar://16287331 Swift SVN r16192
This commit is contained in:
@@ -134,6 +134,13 @@ public:
|
||||
/// \brief Remove all block arguments.
|
||||
void dropAllArgs() { BBArgList.clear(); }
|
||||
|
||||
/// \brief Drops all uses that belong to this basic block.
|
||||
void dropAllReferences() {
|
||||
dropAllArgs();
|
||||
for (SILInstruction &I : *this)
|
||||
I.dropAllReferences();
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Predecessors and Successors
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
@@ -124,6 +124,14 @@ public:
|
||||
void incrementRefCount() { RefCount++; }
|
||||
void decrementRefCount() { RefCount--; }
|
||||
|
||||
/// Drops all uses belonging to instructions in this function. The only valid
|
||||
/// operation performable on this object after this is called is called the
|
||||
/// destructor or deallocation.
|
||||
void dropAllReferences() {
|
||||
for (SILBasicBlock &BB : *this)
|
||||
BB.dropAllReferences();
|
||||
}
|
||||
|
||||
/// Returns the calling convention used by this entry point.
|
||||
AbstractCC getAbstractCC() const {
|
||||
return getLoweredFunctionType()->getAbstractCC();
|
||||
@@ -281,7 +289,7 @@ public:
|
||||
SILFunction *provideInitialHead() const { return createSentinel(); }
|
||||
SILFunction *ensureHead(SILFunction*) const { return createSentinel(); }
|
||||
static void noteHead(SILFunction*, SILFunction*) {}
|
||||
static void deleteNode(SILFunction *V) {}
|
||||
static void deleteNode(SILFunction *V) { V->~SILFunction(); }
|
||||
|
||||
private:
|
||||
void createNode(const SILFunction &);
|
||||
|
||||
@@ -597,6 +597,8 @@ public:
|
||||
/// Return the referenced function.
|
||||
SILFunction *getReferencedFunction() const { return Function; }
|
||||
|
||||
void dropReferencedFunction();
|
||||
|
||||
/// getType() is ok since this is known to only have one type.
|
||||
SILType getType(unsigned i = 0) const { return ValueBase::getType(i); }
|
||||
|
||||
|
||||
@@ -98,15 +98,29 @@ private:
|
||||
/// The swift Module associated with this SILModule.
|
||||
Module *TheSwiftModule;
|
||||
|
||||
/// Lookup table for SIL functions. This needs to be declared before \p
|
||||
/// functions so that the destructor of \p functions is called first.
|
||||
llvm::StringMap<SILFunction *> FunctionTable;
|
||||
|
||||
/// The list of SILFunctions in the module.
|
||||
FunctionListType functions;
|
||||
|
||||
/// Lookup table for SIL vtables from class decls.
|
||||
llvm::DenseMap<const ClassDecl *, SILVTable *> VTableLookupTable;
|
||||
|
||||
/// The list of SILVTables in the module.
|
||||
VTableListType vtables;
|
||||
|
||||
/// Lookup table for SIL witness tables from conformances.
|
||||
llvm::DenseMap<const NormalProtocolConformance *, SILWitnessTable *>
|
||||
WitnessTableLookupCache;
|
||||
|
||||
/// The list of SILWitnessTables in the module.
|
||||
WitnessTableListType witnessTables;
|
||||
|
||||
/// Lookup table for SIL Global Variables.
|
||||
llvm::StringMap<SILGlobalVariable *> GlobalVariableTable;
|
||||
|
||||
/// The list of SILGlobalVariables in the module.
|
||||
/// FIXME: Merge with 'globals'.
|
||||
GlobalListType silGlobals;
|
||||
@@ -115,19 +129,6 @@ private:
|
||||
/// FIXME: Remove this when SILGlobalVariable is ready.
|
||||
llvm::SetVector<VarDecl*> globals;
|
||||
|
||||
/// Lookup table for SIL functions.
|
||||
llvm::StringMap<SILFunction*> FunctionTable;
|
||||
|
||||
/// Lookup table for SIL global variables.
|
||||
llvm::StringMap<SILGlobalVariable*> GlobalVariableTable;
|
||||
|
||||
/// Lookup table for SIL witness tables from conformances.
|
||||
llvm::DenseMap<const NormalProtocolConformance *, SILWitnessTable *>
|
||||
WitnessTableLookupCache;
|
||||
|
||||
/// Lookup table for SIL vtables from class decls.
|
||||
llvm::DenseMap<const ClassDecl *, SILVTable *> VTableLookupTable;
|
||||
|
||||
/// This is a cache of intrinsic Function declarations to numeric ID mappings.
|
||||
llvm::DenseMap<Identifier, IntrinsicInfo> IntrinsicIDCache;
|
||||
|
||||
@@ -181,7 +182,6 @@ public:
|
||||
|
||||
/// Erase a function from the module.
|
||||
void eraseFunction(SILFunction *F) {
|
||||
FunctionTable.erase(F->getName());
|
||||
getFunctionList().erase(F);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,8 +72,15 @@ SILFunction::SILFunction(SILModule &Module, SILLinkage Linkage,
|
||||
}
|
||||
|
||||
SILFunction::~SILFunction() {
|
||||
#ifndef NDEBUG
|
||||
// If the function is recursive, a function_ref inst inside of the function
|
||||
// will give the function a non-zero ref count triggering the assertion. Thus
|
||||
// we drop all instruction references before we erase.
|
||||
dropAllReferences();
|
||||
assert(RefCount == 0 &&
|
||||
"Function cannot be deleted while function_ref's still exist");
|
||||
#endif
|
||||
|
||||
getModule().FunctionTable.erase(Name);
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,14 @@ void SILInstruction::dropAllReferences() {
|
||||
OpE = PossiblyDeadOps.end(); OpI != OpE; ++OpI) {
|
||||
OpI->drop();
|
||||
}
|
||||
|
||||
// If we have a function ref inst, we need to especially drop its function
|
||||
// argument so that it gets a proper ref decement.
|
||||
auto *FRI = dyn_cast<FunctionRefInst>(this);
|
||||
if (!FRI || !FRI->getReferencedFunction())
|
||||
return;
|
||||
|
||||
FRI->dropReferencedFunction();
|
||||
}
|
||||
|
||||
namespace {
|
||||
@@ -624,9 +632,16 @@ FunctionRefInst::FunctionRefInst(SILLocation Loc, SILFunction *F)
|
||||
}
|
||||
|
||||
FunctionRefInst::~FunctionRefInst() {
|
||||
if (Function)
|
||||
Function->decrementRefCount();
|
||||
}
|
||||
|
||||
void FunctionRefInst::dropReferencedFunction() {
|
||||
if (Function)
|
||||
Function->decrementRefCount();
|
||||
Function = nullptr;
|
||||
}
|
||||
|
||||
SILGlobalAddrInst::SILGlobalAddrInst(SILLocation Loc, SILGlobalVariable *Global)
|
||||
: LiteralInst(ValueKind::SILGlobalAddrInst, Loc,
|
||||
Global->getLoweredType().getAddressType()),
|
||||
|
||||
@@ -91,6 +91,15 @@ SILModule::SILModule(Module *SwiftModule)
|
||||
}
|
||||
|
||||
SILModule::~SILModule() {
|
||||
// Drop everything functions in this module reference.
|
||||
//
|
||||
// This is necessary since the functions may reference each other. We don't
|
||||
// need to worry about sil_witness_tables since witness tables reference each
|
||||
// other via protocol conformances and sil_vtables don't reference each other
|
||||
// at all.
|
||||
for (SILFunction &F : *this)
|
||||
F.dropAllReferences();
|
||||
|
||||
delete (SILTypeListUniquingType*)TypeListUniquing;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user