Skip to content

Commit 543a2cd

Browse files
committed
Fix caching bug in MemoryBufferSerializedModuleLoader
By populating the memory cache before loading the module, we can avoid a cycle where a module is imported that is an overlay, which then triggers ClangImporter, which then (redundantly) triggers the import of the overlay module, which would reimport the module again, since it's import is still underway and it hasn't been entered into the cache yet. rdar://118846313
1 parent 5ce824f commit 543a2cd

File tree

14 files changed

+86
-17
lines changed

14 files changed

+86
-17
lines changed

include/swift/AST/ASTContext.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,13 @@ class ASTContext final {
12501250
/// in this context.
12511251
void addLoadedModule(ModuleDecl *M);
12521252

1253+
/// Remove an externally-sourced module from the set of known loaded modules
1254+
/// in this context. Modules are added to the cache before being loaded to
1255+
/// avoid loading a module twice when there is a cyclic dependency between an
1256+
/// overlay and its Clang module. If a module import fails, the non-imported
1257+
/// module should be removed from the cache again.
1258+
void removeLoadedModule(Identifier RealName);
1259+
12531260
/// Change the behavior of all loaders to ignore swiftmodules next to
12541261
/// swiftinterfaces.
12551262
void setIgnoreAdjacentModules(bool value);

lib/AST/ASTContext.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2267,6 +2267,10 @@ void ASTContext::addLoadedModule(ModuleDecl *M) {
22672267
getImpl().LoadedModules[M->getRealName()] = M;
22682268
}
22692269

2270+
void ASTContext::removeLoadedModule(Identifier RealName) {
2271+
getImpl().LoadedModules.erase(RealName);
2272+
}
2273+
22702274
void ASTContext::setIgnoreAdjacentModules(bool value) {
22712275
IgnoreAdjacentModules = value;
22722276
}

lib/Serialization/SerializedModuleLoader.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,21 +1527,23 @@ MemoryBufferSerializedModuleLoader::loadModule(SourceLoc importLoc,
15271527

15281528
auto *M = ModuleDecl::create(moduleID.Item, Ctx);
15291529
SWIFT_DEFER { M->setHasResolvedImports(); };
1530+
if (AllowMemoryCache)
1531+
Ctx.addLoadedModule(M);
15301532

15311533
auto *file = loadAST(*M, moduleID.Loc, /*moduleInterfacePath=*/"",
15321534
/*moduleInterfaceSourcePath=*/"",
15331535
std::move(moduleInputBuffer), {}, {}, isFramework);
1534-
if (!file)
1536+
if (!file) {
1537+
Ctx.removeLoadedModule(moduleID.Item);
15351538
return nullptr;
1539+
}
15361540

15371541
// The MemoryBuffer loader is used by LLDB during debugging. Modules imported
15381542
// from .swift_ast sections are never produced from textual interfaces. By
15391543
// disabling resilience the debugger can directly access private members.
15401544
if (BypassResilience)
15411545
M->setBypassResilience();
15421546
M->addFile(*file);
1543-
if (AllowMemoryCache)
1544-
Ctx.addLoadedModule(M);
15451547
return M;
15461548
}
15471549

test/DWARFImporter/basic.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@
1616
// RUN: %lldb-moduleimport-test -verbose -dump-module %t/a.out \
1717
// RUN: -dummy-dwarfimporter | %FileCheck %s --check-prefix=SWIFTONLY
1818

19-
// CHECK: Importing basic... ok!
20-
// FAIL: Importing basic... ok!
21-
// SWIFTONLY: Importing basic... ok!
19+
// CHECK: Importing basic...
20+
// CHECK: Import successful!
21+
// FAIL: Importing basic...
22+
// FAIL: Import successful!
23+
// SWIFTONLY: Importing basic...
24+
// SWIFTONLY: Import successful!
25+
2226
import ObjCModule
2327

2428
let pureSwift = Int32(42)

test/DebugInfo/ASTSection-multi.swift

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,11 @@
4242
// RUN: %t/a3.o %t/a3-mod.o
4343

4444
// RUN: %lldb-moduleimport-test -verbose %t/a.out | %FileCheck %s
45-
// CHECK: Importing a0... ok!
46-
// CHECK: Importing a1... ok!
47-
// CHECK: Importing a2... ok!
48-
// CHECK: Importing a3... ok!
45+
// CHECK-DAG: Importing a0...
46+
// CHECK-DAG: Import successful!
47+
// CHECK-DAG: Importing a1...
48+
// CHECK-DAG: Import successful!
49+
// CHECK-DAG: Importing a2...
50+
// CHECK-DAG: Import successful!
51+
// CHECK-DAG: Importing a3...
4952

test/DebugInfo/ASTSection-single.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@
1111

1212
// RUN: %lldb-moduleimport-test -verbose %t/a0-mod.o | %FileCheck %s
1313
// CHECK: Path: {{.*}}/Inputs, framework=false, system=false
14-
// CHECK: Importing a0... ok!
14+
// CHECK: Importing a0...
15+
// CHECK: Import successful!

test/DebugInfo/ASTSection.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ func objCUser(_ obj: ObjCClass) {}
2626
#endif
2727

2828
// CHECK: - Target: {{.+}}-{{.+}}-{{.+}}
29-
// CHECK: Importing ASTSection... ok!
29+
// CHECK: Importing ASTSection...
30+
// CHECK: Import successful!
3031

3132
// LINETABLE-CHECK-NOT: ASTSection
3233

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// REQUIRES: executable_test
2+
// REQUIRES: objc_interop
3+
4+
// RUN: %empty-directory(%t)
5+
// RUN: %target-build-swift -emit-module %S/Inputs/overlay.swift -module-name ClangModuleWithOverlay -I %S/Inputs -emit-module-path %t/ClangModuleWithOverlay.swiftmodule
6+
// RUN: %target-build-swift -c %S/Inputs/overlay.swift -module-name ClangModuleWithOverlay -I %S/Inputs -o %t/ClangModuleWithOverlay.o -parse-as-library
7+
// RUN: %target-build-swift -emit-executable %s %t/ClangModuleWithOverlay.o -I %t -g -o %t/ASTSectionOverlay -module-name ASTSectionOverlay -emit-module -Xlinker -add_ast_path -Xlinker %t/ClangModuleWithOverlay.swiftmodule
8+
9+
// RUN: %lldb-moduleimport-test -verbose %t/ASTSectionOverlay | %FileCheck %s
10+
// CHECK: Loading ClangModuleWithOverlay
11+
// CHECK-NOT: Loading (overlay) ClangModuleWithOverlay
12+
// CHECK-NOT: Loading{{.*}}ClangModuleWithOverlay
13+
14+
import ClangModuleWithOverlay
15+
let c = ClangType(i: 0)
16+
fromSwiftOverlay()

test/DebugInfo/ASTSection_ObjC.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
// RUN: %lldb-moduleimport-test -verbose %t/ASTSection | %FileCheck %s --allow-empty --check-prefix=LINETABLE-CHECK
1515

1616
// CHECK: - Target: {{.+}}-{{.+}}-{{.+}}
17-
// CHECK: Importing ASTSection... ok!
17+
// CHECK: Importing ASTSection...
18+
// CHECK: Import successful!
1819

1920
// LINETABLE-CHECK-NOT: ASTSection

test/DebugInfo/ASTSection_linker.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@
2121
// CHECK: - Target: {{.+}}-{{.+}}-{{.+}}
2222
// CHECK: - SDK path: {{.*}}MacOS{{.*}}.sdk
2323
// CHECK: - -Xcc options: -working-directory {{.+}} -DA -DB
24-
// CHECK: Importing ASTSection... ok!
24+
// CHECK: Importing ASTSection...
25+
// CHECK: Import successful!
26+

0 commit comments

Comments
 (0)