Skip to content

Commit b0f387b

Browse files
committed
[Member name lookup] Eliminate non-lazy member loading.
Lazy member loading has been in use and the default for several years now. However, the lazy loading was disabled for any type whose primary definition was parsed even though some of its extensions could have been deserialized, e.g., from a Clang module. Moreover, the non-lazy path walked all of the extensions of such a type for all member name lookup operations. Faced with a large number of extensions to the same type (in my example, 6,000), this walk of the list of the extensions could dominate type-checking time. Eliminate all effects of the `-disable-named-lazy-member-loading` flag, and always use the "lazy" path, which effectively does no work for parsed type definitions and extensions thereof. The example with 6,000 extensions of a single type goes from type checking in 6 seconds down to type checking in 0.6 seconds, and name lookup completely disappears from the profiling trace. The deleted tests relied on the flag that is now inert. They aren't by themselves providing much value nowadays, and it's better to have the simpler (and more efficient) implementation of member name lookup be the only one. (cherry picked from commit 234534e)
1 parent 19cdab4 commit b0f387b

18 files changed

+21
-285
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,6 @@ namespace swift {
333333
/// Flags for developers
334334
///
335335

336-
/// Enable named lazy member loading.
337-
bool NamedLazyMemberLoading = true;
338-
339336
/// Whether to record request references for incremental builds.
340337
bool RecordRequestReferences = true;
341338

lib/AST/NameLookup.cpp

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,9 @@ class swift::MemberLookupTable : public ASTAllocated<swift::MemberLookupTable> {
12181218
/// Lookup table mapping names to the set of declarations with that name.
12191219
LookupTable Lookup;
12201220

1221+
/// List of containers that have lazily-loaded members
1222+
llvm::SmallVector<ExtensionDecl *, 2> ExtensionsWithLazyMembers;
1223+
12211224
/// The set of names of lazily-loaded members that the lookup table has a
12221225
/// complete accounting of with respect to all known extensions of its
12231226
/// parent nominal type.
@@ -1246,6 +1249,14 @@ class swift::MemberLookupTable : public ASTAllocated<swift::MemberLookupTable> {
12461249
/// Add the given members to the lookup table.
12471250
void addMembers(DeclRange members);
12481251

1252+
void addExtensionWithLazyMembers(ExtensionDecl *ext) {
1253+
ExtensionsWithLazyMembers.push_back(ext);
1254+
}
1255+
1256+
ArrayRef<ExtensionDecl *> getExtensionsWithLazyMembers() const {
1257+
return ExtensionsWithLazyMembers;
1258+
}
1259+
12491260
/// Returns \c true if the lookup table has a complete accounting of the
12501261
/// given name.
12511262
bool isLazilyComplete(DeclBaseName name) const {
@@ -1435,10 +1446,11 @@ void NominalTypeDecl::addedExtension(ExtensionDecl *ext) {
14351446
auto *table = LookupTable.getPointer();
14361447
assert(table);
14371448

1438-
if (ext->hasLazyMembers()) {
1449+
if (ext->wasDeserialized() || ext->hasClangNode()) {
14391450
table->addMembers(ext->getCurrentMembersWithoutLoading());
14401451
table->clearLazilyCompleteCache();
14411452
table->clearLazilyCompleteForMacroExpansionCache();
1453+
table->addExtensionWithLazyMembers(ext);
14421454
} else {
14431455
table->addMembers(ext->getMembers());
14441456
}
@@ -1534,6 +1546,9 @@ populateLookupTableEntryFromLazyIDCLoader(ASTContext &ctx,
15341546
MemberLookupTable &LookupTable,
15351547
DeclBaseName name,
15361548
IterableDeclContext *IDC) {
1549+
if (!IDC->hasLazyMembers())
1550+
return;
1551+
15371552
auto ci = ctx.getOrCreateLazyIterableContextData(IDC,
15381553
/*lazyLoader=*/nullptr);
15391554
auto res = ci->loader->loadNamedMembers(IDC, name, ci->memberData);
@@ -1553,7 +1568,7 @@ populateLookupTableEntryFromExtensions(ASTContext &ctx,
15531568
assert(!table.isLazilyComplete(name) &&
15541569
"Should not be searching extensions for complete name!");
15551570

1556-
for (auto e : nominal->getExtensions()) {
1571+
for (auto e : table.getExtensionsWithLazyMembers()) {
15571572
// If there's no lazy members to look at, all the members of this extension
15581573
// are present in the lookup table.
15591574
if (!e->hasLazyMembers()) {
@@ -1789,6 +1804,7 @@ void NominalTypeDecl::prepareLookupTable() {
17891804
// LazyMemberLoader::loadNamedMembers().
17901805
if (e->wasDeserialized() || e->hasClangNode()) {
17911806
table->addMembers(e->getCurrentMembersWithoutLoading());
1807+
table->addExtensionWithLazyMembers(e);
17921808
continue;
17931809
}
17941810

@@ -1848,21 +1864,14 @@ DirectLookupRequest::evaluate(Evaluator &evaluator,
18481864
const auto flags = desc.Options;
18491865
auto *decl = desc.DC;
18501866

1851-
// We only use NamedLazyMemberLoading when a user opts-in and we have
1852-
// not yet loaded all the members into the IDC list in the first place.
18531867
ASTContext &ctx = decl->getASTContext();
1854-
const bool useNamedLazyMemberLoading = (ctx.LangOpts.NamedLazyMemberLoading &&
1855-
decl->hasLazyMembers());
18561868
const bool includeAttrImplements =
18571869
flags.contains(NominalTypeDecl::LookupDirectFlags::IncludeAttrImplements);
18581870
const bool excludeMacroExpansions =
18591871
flags.contains(NominalTypeDecl::LookupDirectFlags::ExcludeMacroExpansions);
18601872

18611873
LLVM_DEBUG(llvm::dbgs() << decl->getNameStr() << ".lookupDirect("
18621874
<< name << ")"
1863-
<< ", hasLazyMembers()=" << decl->hasLazyMembers()
1864-
<< ", useNamedLazyMemberLoading="
1865-
<< useNamedLazyMemberLoading
18661875
<< ", excludeMacroExpansions="
18671876
<< excludeMacroExpansions
18681877
<< "\n");
@@ -1875,15 +1884,7 @@ DirectLookupRequest::evaluate(Evaluator &evaluator,
18751884
decl->prepareExtensions();
18761885

18771886
auto &Table = *decl->getLookupTable();
1878-
if (!useNamedLazyMemberLoading) {
1879-
// Make sure we have the complete list of members (in this nominal and in
1880-
// all extensions).
1881-
(void)decl->getMembers();
1882-
1883-
for (auto E : decl->getExtensions())
1884-
(void)E->getMembers();
1885-
1886-
} else if (!Table.isLazilyComplete(name.getBaseName())) {
1887+
if (!Table.isLazilyComplete(name.getBaseName())) {
18871888
DeclBaseName baseName(name.getBaseName());
18881889

18891890
if (isa_and_nonnull<clang::NamespaceDecl>(decl->getClangDecl())) {

lib/Frontend/CompilerInvocation.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -649,8 +649,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
649649
/*default*/ false);
650650
Opts.UseClangFunctionTypes |= Args.hasArg(OPT_use_clang_function_types);
651651

652-
Opts.NamedLazyMemberLoading &= !Args.hasArg(OPT_disable_named_lazy_member_loading);
653-
654652
if (Args.hasArg(OPT_emit_fine_grained_dependency_sourcefile_dot_files))
655653
Opts.EmitFineGrainedDependencySourcefileDotFiles = true;
656654

test/ClangImporter/attr-swift_name-errors.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/custom-modules -typecheck %s -disable-named-lazy-member-loading \
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/custom-modules -typecheck %s \
22
// RUN: -verify -verify-additional-file %S/Inputs/custom-modules/ConflictingNames.h -verify-ignore-unknown
33

44
// REQUIRES: objc_interop

test/ClangImporter/attr-swift_name.swift

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %empty-directory(%t.mcp)
2-
// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/custom-modules -Xcc -w -typecheck %s -module-cache-path %t.mcp -disable-named-lazy-member-loading 2>&1 | %FileCheck %s
2+
// RUN: not %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs/custom-modules -Xcc -w -typecheck %s -module-cache-path %t.mcp 2>&1 | %FileCheck %s
33

44
// REQUIRES: objc_interop
55

@@ -26,12 +26,6 @@ func test(_ i: Int) {
2626
// CHECK: note: please report this issue to the owners of 'ObjCIRExtras'
2727
// CHECK-NOT: warning:
2828

29-
// CHECK: warning: too few parameters in swift_name attribute (expected 2; got 1)
30-
// CHECK: + (instancetype)testW:(id)x out:(id *)outObject SWIFT_NAME(ww(_:));
31-
// CHECK-NOT: warning:
32-
// CHECK: note: please report this issue to the owners of 'ObjCIRExtras'
33-
// CHECK-NOT: warning:
34-
3529
// CHECK: warning: cycle detected while resolving 'CircularName' in swift_name attribute for 'CircularName'
3630
// CHECK: SWIFT_NAME(CircularName.Inner) @interface CircularName : NSObject @end
3731
// CHECK-NOT: {{warning|note}}:

test/NameLookup/named_lazy_member_loading_objc_category.swift

Lines changed: 0 additions & 20 deletions
This file was deleted.

test/NameLookup/named_lazy_member_loading_objc_interface.swift

Lines changed: 0 additions & 32 deletions
This file was deleted.

test/NameLookup/named_lazy_member_loading_objc_protocol.swift

Lines changed: 0 additions & 23 deletions
This file was deleted.

test/NameLookup/named_lazy_member_loading_protocol_mirroring.swift

Lines changed: 0 additions & 40 deletions
This file was deleted.

test/NameLookup/named_lazy_member_loading_swift_class.swift

Lines changed: 0 additions & 15 deletions
This file was deleted.

test/NameLookup/named_lazy_member_loading_swift_class_type.swift

Lines changed: 0 additions & 15 deletions
This file was deleted.

test/NameLookup/named_lazy_member_loading_swift_derived_class.swift

Lines changed: 0 additions & 15 deletions
This file was deleted.

test/NameLookup/named_lazy_member_loading_swift_derived_class_type.swift

Lines changed: 0 additions & 15 deletions
This file was deleted.

test/NameLookup/named_lazy_member_loading_swift_enum.swift

Lines changed: 0 additions & 15 deletions
This file was deleted.

test/NameLookup/named_lazy_member_loading_swift_proto.swift

Lines changed: 0 additions & 15 deletions
This file was deleted.

test/NameLookup/named_lazy_member_loading_swift_struct.swift

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)