mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Stop leaking memory from Module and FileUnit.
Also, disallow creating Modules and FileUnits on the stack. They must always live as long as the ASTContext. <rdar://problem/15596964> Swift SVN r13671
This commit is contained in:
@@ -392,6 +392,13 @@ public:
|
||||
/// Add a cleanup function to be called when the ASTContext is deallocated.
|
||||
void addCleanup(std::function<void(void)> cleanup);
|
||||
|
||||
/// Add a cleanup to run the given object's destructor when the ASTContext is
|
||||
/// deallocated.
|
||||
template<typename T>
|
||||
void addDestructorCleanup(T &object) {
|
||||
addCleanup([&object]{ object.~T(); });
|
||||
}
|
||||
|
||||
/// Create a context for the initializer of a non-local variable,
|
||||
/// like a global or a field. To reduce memory usage, if the
|
||||
/// context goes unused, it should be returned to the ASTContext
|
||||
|
||||
@@ -172,13 +172,12 @@ private:
|
||||
// FIXME: Do we really need to bloat all modules with this?
|
||||
DebuggerClient *DebugClient = nullptr;
|
||||
|
||||
// FIXME: This storage is never freed, because Modules are allocated on the
|
||||
// ASTContext.
|
||||
TinyPtrVector<FileUnit *> Files;
|
||||
|
||||
Module(Identifier name, ASTContext &ctx);
|
||||
public:
|
||||
Module(Identifier Name, ASTContext &C)
|
||||
: DeclContext(DeclContextKind::Module, nullptr), Ctx(C), Name(Name) {
|
||||
static Module *create(Identifier name, ASTContext &ctx) {
|
||||
return new (ctx) Module(name, ctx);
|
||||
}
|
||||
|
||||
ArrayRef<FileUnit *> getFiles() {
|
||||
@@ -413,9 +412,9 @@ protected:
|
||||
: DeclContext(DeclContextKind::FileUnit, &M), Kind(kind) {
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~FileUnit() = default;
|
||||
|
||||
public:
|
||||
FileUnitKind getKind() const {
|
||||
return Kind;
|
||||
}
|
||||
@@ -571,6 +570,8 @@ private:
|
||||
/// May be -1, to indicate no association with a buffer.
|
||||
int BufferID;
|
||||
|
||||
friend ASTContext;
|
||||
~SourceFile();
|
||||
public:
|
||||
/// The list of top-level declarations in the source file.
|
||||
std::vector<Decl*> Decls;
|
||||
@@ -606,7 +607,6 @@ public:
|
||||
|
||||
SourceFile(Module &M, SourceFileKind K, Optional<unsigned> bufferID,
|
||||
bool hasBuiltinModuleAccess = false);
|
||||
~SourceFile();
|
||||
|
||||
ArrayRef<std::pair<Module::ImportedModule, bool>> getImports() const {
|
||||
assert(ASTStage >= Parsed || Kind == SourceFileKind::SIL);
|
||||
@@ -714,6 +714,9 @@ private:
|
||||
std::unique_ptr<LookupCache> Cache;
|
||||
LookupCache &getCache() const;
|
||||
|
||||
friend ASTContext;
|
||||
~BuiltinUnit() = default;
|
||||
|
||||
public:
|
||||
explicit BuiltinUnit(Module &M);
|
||||
|
||||
@@ -733,6 +736,7 @@ public:
|
||||
/// Represents an externally-loaded file of some kind.
|
||||
class LoadedFile : public FileUnit {
|
||||
protected:
|
||||
~LoadedFile() = default;
|
||||
LoadedFile(FileUnitKind Kind, Module &M) noexcept
|
||||
: FileUnit(Kind, M) {
|
||||
assert(classof(this) && "invalid kind");
|
||||
|
||||
@@ -37,6 +37,8 @@ class ClangModuleUnit final : public LoadedFile {
|
||||
|
||||
Module *getAdapterModule() const;
|
||||
|
||||
~ClangModuleUnit() = default;
|
||||
|
||||
public:
|
||||
ClangModuleUnit(Module &M, ClangImporter &owner,
|
||||
clang::Module *clangModule);
|
||||
|
||||
@@ -132,6 +132,8 @@ class SerializedASTFile final : public LoadedFile {
|
||||
|
||||
ModuleFile &File;
|
||||
|
||||
~SerializedASTFile() = default;
|
||||
|
||||
SerializedASTFile(Module &M, ModuleFile &file)
|
||||
: LoadedFile(FileUnitKind::SerializedAST, M), File(file) {}
|
||||
|
||||
|
||||
@@ -244,7 +244,7 @@ ConstraintCheckerArenaRAII::~ConstraintCheckerArenaRAII() {
|
||||
}
|
||||
|
||||
static Module *createBuiltinModule(ASTContext &ctx) {
|
||||
auto M = new (ctx) Module(ctx.getIdentifier("Builtin"), ctx);
|
||||
auto M = Module::create(ctx.getIdentifier("Builtin"), ctx);
|
||||
M->addFile(*new (ctx) BuiltinUnit(*M));
|
||||
return M;
|
||||
}
|
||||
|
||||
@@ -84,6 +84,7 @@ void BuiltinUnit::LookupCache::lookupValue(Identifier Name, NLKind LookupKind,
|
||||
// Out-of-line because std::unique_ptr wants LookupCache to be complete.
|
||||
BuiltinUnit::BuiltinUnit(Module &M)
|
||||
: FileUnit(FileUnitKind::Builtin, M) {
|
||||
M.Ctx.addDestructorCleanup(*this);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -269,6 +270,12 @@ void SourceLookupCache::lookupClassMember(AccessPathTy accessPath,
|
||||
// Module Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
Module::Module(Identifier name, ASTContext &ctx)
|
||||
: DeclContext(DeclContextKind::Module, nullptr), Ctx(ctx), Name(name) {
|
||||
ctx.addDestructorCleanup(*this);
|
||||
}
|
||||
|
||||
|
||||
void Module::addFile(FileUnit &newFile) {
|
||||
// Require Main and REPL files to be the first file added.
|
||||
assert(Files.empty() ||
|
||||
@@ -1099,6 +1106,7 @@ SourceFile::SourceFile(Module &M, SourceFileKind K,
|
||||
Optional<unsigned> bufferID, bool hasBuiltinModuleAccess)
|
||||
: FileUnit(FileUnitKind::Source, M),
|
||||
BufferID(bufferID ? *bufferID : -1), Kind(K) {
|
||||
M.Ctx.addDestructorCleanup(*this);
|
||||
performAutoImport(*this, hasBuiltinModuleAccess);
|
||||
}
|
||||
|
||||
|
||||
@@ -304,7 +304,7 @@ Module *ClangImporter::loadModule(
|
||||
// FIXME: The name of this module could end up as a key in the ASTContext,
|
||||
// but that's not correct for submodules.
|
||||
Identifier name = Impl.SwiftContext.getIdentifier((*clangModule).Name);
|
||||
auto result = new (Impl.SwiftContext) Module(name, Impl.SwiftContext);
|
||||
auto result = Module::create(name, Impl.SwiftContext);
|
||||
|
||||
auto file = new (Impl.SwiftContext) ClangModuleUnit(*result, *this,
|
||||
clangModule);
|
||||
@@ -332,7 +332,7 @@ ClangImporter::Implementation::getWrapperForModule(ClangImporter &importer,
|
||||
|
||||
// FIXME: Handle hierarchical names better.
|
||||
Identifier name = SwiftContext.getIdentifier(underlying->Name);
|
||||
auto wrapper = new (SwiftContext) Module(name, SwiftContext);
|
||||
auto wrapper = Module::create(name, SwiftContext);
|
||||
|
||||
auto file = new (SwiftContext) ClangModuleUnit(*wrapper, importer,
|
||||
underlying);
|
||||
|
||||
@@ -161,7 +161,7 @@ bool swift::CompilerInstance::setup(const CompilerInvocation &Invok) {
|
||||
void CompilerInstance::performParse() {
|
||||
const SourceFileKind Kind = Invocation.getInputKind();
|
||||
Identifier ID = Context->getIdentifier(Invocation.getModuleName());
|
||||
MainModule = new (*Context) Module(ID, *Context);
|
||||
MainModule = Module::create(ID, *Context);
|
||||
Context->LoadedModules[ID.str()] = MainModule;
|
||||
|
||||
if (Kind == SourceFileKind::SIL) {
|
||||
|
||||
@@ -33,8 +33,8 @@ bool ide::isSourceInputComplete(std::unique_ptr<llvm::MemoryBuffer> MemBuf) {
|
||||
ASTContext Ctx(LangOpts, SearchPathOpts, SM, Diags);
|
||||
auto ModName = Ctx.getIdentifier("input");
|
||||
|
||||
Module Mod(ModName, Ctx);
|
||||
SourceFile SF(Mod, SourceFileKind::Main, BufferID);
|
||||
Module &Mod = *Module::create(ModName, Ctx);
|
||||
SourceFile &SF = *new (Ctx) SourceFile(Mod, SourceFileKind::Main, BufferID);
|
||||
|
||||
PersistentParserState PersistentState;
|
||||
Parser P(BufferID, SF, /*SIL=*/nullptr, &PersistentState);
|
||||
|
||||
@@ -93,7 +93,7 @@ Module *SourceLoader::loadModule(SourceLoc importLoc,
|
||||
else
|
||||
bufferID = Ctx.SourceMgr.addNewSourceBuffer(inputFile.take());
|
||||
|
||||
auto *importMod = new (Ctx) Module(moduleID.first, Ctx);
|
||||
auto *importMod = Module::create(moduleID.first, Ctx);
|
||||
Ctx.LoadedModules[moduleID.first.str()] = importMod;
|
||||
|
||||
auto *importFile = new (Ctx) SourceFile(*importMod, SourceFileKind::Library,
|
||||
|
||||
@@ -218,7 +218,7 @@ Module *SerializedModuleLoader::loadModule(SourceLoc importLoc,
|
||||
|
||||
assert(inputFile);
|
||||
|
||||
auto M = new (Ctx) Module(moduleID.first, Ctx);
|
||||
auto M = Module::create(moduleID.first, Ctx);
|
||||
Ctx.LoadedModules[moduleID.first.str()] = M;
|
||||
|
||||
(void)loadAST(*M, moduleID.second, std::move(inputFile));
|
||||
|
||||
Reference in New Issue
Block a user