Skip to content

Commit be14764

Browse files
committed
[lldb] Improve performance of TypeSystemSwiftTypeRef via lazy canonicalization
Most of the queries in TypeSystemSwiftTypeRef request a full canonicalized type, which involves resolving all nested type aliases (which kicks off expensive DWARF lookups), but they only look at the outermost node. This patch introduces DemangleCanonicalOutermostType() to avoid this redundant work.
1 parent 846c433 commit be14764

File tree

2 files changed

+106
-64
lines changed

2 files changed

+106
-64
lines changed

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp

Lines changed: 93 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,7 +1064,7 @@ TypeSystemSwiftTypeRef::GetTupleElement(lldb::opaque_compiler_type_t type,
10641064
TupleElement result;
10651065
using namespace swift::Demangle;
10661066
Demangler dem;
1067-
NodePointer node = TypeSystemSwiftTypeRef::DemangleCanonicalType(dem, type);
1067+
NodePointer node = TypeSystemSwiftTypeRef::DemangleCanonicalOutermostType(dem, type);
10681068
if (!node || node->getKind() != Node::Kind::Tuple)
10691069
return {};
10701070
if (node->getNumChildren() < idx)
@@ -1170,60 +1170,66 @@ Desugar(swift::Demangle::Demangler &dem, swift::Demangle::NodePointer node,
11701170
return desugared;
11711171
}
11721172

1173+
swift::Demangle::NodePointer
1174+
TypeSystemSwiftTypeRef::Canonicalize(swift::Demangle::Demangler &dem,
1175+
swift::Demangle::NodePointer node) {
1176+
assert(node);
1177+
auto kind = node->getKind();
1178+
switch (kind) {
1179+
case Node::Kind::SugaredOptional:
1180+
// FIXME: Factor these three cases out.
1181+
assert(node->getNumChildren() == 1);
1182+
if (node->getNumChildren() != 1)
1183+
return node;
1184+
return Desugar(dem, node, Node::Kind::BoundGenericEnum, Node::Kind::Enum,
1185+
"Optional");
1186+
case Node::Kind::SugaredArray: {
1187+
assert(node->getNumChildren() == 1);
1188+
if (node->getNumChildren() != 1)
1189+
return node;
1190+
return Desugar(dem, node, Node::Kind::BoundGenericStructure,
1191+
Node::Kind::Structure, "Array");
1192+
}
1193+
case Node::Kind::SugaredDictionary:
1194+
// FIXME: This isnt covered by any test.
1195+
assert(node->getNumChildren() == 2);
1196+
if (node->getNumChildren() != 2)
1197+
return node;
1198+
return Desugar(dem, node, Node::Kind::BoundGenericStructure,
1199+
Node::Kind::Structure, "Dictionary");
1200+
case Node::Kind::SugaredParen:
1201+
assert(node->getNumChildren() == 1);
1202+
if (node->getNumChildren() != 1)
1203+
return node;
1204+
return node->getFirstChild();
1205+
1206+
case Node::Kind::BoundGenericTypeAlias:
1207+
case Node::Kind::TypeAlias: {
1208+
auto node_clangtype = ResolveTypeAlias(dem, node);
1209+
if (CompilerType clang_type = node_clangtype.second) {
1210+
if (auto result = GetClangTypeNode(clang_type, dem))
1211+
return result;
1212+
else
1213+
return node;
1214+
}
1215+
if (node_clangtype.first)
1216+
return node_clangtype.first;
1217+
return node;
1218+
}
1219+
default:
1220+
break;
1221+
}
1222+
return node;
1223+
}
1224+
11731225
/// Iteratively resolve all type aliases in \p node by looking up their
11741226
/// desugared types in the debug info of module \p M.
11751227
swift::Demangle::NodePointer
11761228
TypeSystemSwiftTypeRef::GetCanonicalNode(swift::Demangle::Demangler &dem,
11771229
swift::Demangle::NodePointer node) {
11781230
using namespace swift::Demangle;
1179-
return TypeSystemSwiftTypeRef::Transform(dem, node, [&](NodePointer node) {
1180-
auto kind = node->getKind();
1181-
switch (kind) {
1182-
case Node::Kind::SugaredOptional:
1183-
// FIXME: Factor these three cases out.
1184-
assert(node->getNumChildren() == 1);
1185-
if (node->getNumChildren() != 1)
1186-
return node;
1187-
return Desugar(dem, node, Node::Kind::BoundGenericEnum, Node::Kind::Enum,
1188-
"Optional");
1189-
case Node::Kind::SugaredArray: {
1190-
assert(node->getNumChildren() == 1);
1191-
if (node->getNumChildren() != 1)
1192-
return node;
1193-
return Desugar(dem, node, Node::Kind::BoundGenericStructure,
1194-
Node::Kind::Structure, "Array");
1195-
}
1196-
case Node::Kind::SugaredDictionary:
1197-
// FIXME: This isnt covered by any test.
1198-
assert(node->getNumChildren() == 2);
1199-
if (node->getNumChildren() != 2)
1200-
return node;
1201-
return Desugar(dem, node, Node::Kind::BoundGenericStructure,
1202-
Node::Kind::Structure, "Dictionary");
1203-
case Node::Kind::SugaredParen:
1204-
assert(node->getNumChildren() == 1);
1205-
if (node->getNumChildren() != 1)
1206-
return node;
1207-
return node->getFirstChild();
1208-
1209-
case Node::Kind::BoundGenericTypeAlias:
1210-
case Node::Kind::TypeAlias: {
1211-
auto node_clangtype = ResolveTypeAlias(dem, node);
1212-
if (CompilerType clang_type = node_clangtype.second) {
1213-
if (auto result = GetClangTypeNode(clang_type, dem))
1214-
return result;
1215-
else
1216-
return node;
1217-
}
1218-
if (node_clangtype.first)
1219-
return node_clangtype.first;
1220-
return node;
1221-
}
1222-
default:
1223-
break;
1224-
}
1225-
return node;
1226-
});
1231+
return TypeSystemSwiftTypeRef::Transform(
1232+
dem, node, [&](NodePointer node) { return Canonicalize(dem, node); });
12271233
}
12281234

12291235
/// Return the demangle tree representation of this type's canonical
@@ -2427,6 +2433,7 @@ template <> bool Equivalent<CompilerType>(CompilerType l, CompilerType r) {
24272433
ast_ctx->ReconstructType(l.GetMangledTypeName()))
24282434
.value_or(nullptr)) == r.GetOpaqueQualType())
24292435
return true;
2436+
24302437
ConstString lhs = l.GetMangledTypeName();
24312438
ConstString rhs = r.GetMangledTypeName();
24322439
if (lhs == ConstString("$sSiD") && rhs == ConstString("$sSuD"))
@@ -2442,6 +2449,7 @@ template <> bool Equivalent<CompilerType>(CompilerType l, CompilerType r) {
24422449
TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, l_node));
24432450
auto r_mangling = swift::Demangle::mangleNode(
24442451
TypeSystemSwiftTypeRef::CanonicalizeSugar(dem, r_node));
2452+
24452453
if (!l_mangling.isSuccess() || !r_mangling.isSuccess()) {
24462454
llvm::dbgs() << "TypeSystemSwiftTypeRef diverges from SwiftASTContext "
24472455
"(mangle error): "
@@ -2705,6 +2713,25 @@ swift::Demangle::NodePointer TypeSystemSwiftTypeRef::DemangleCanonicalType(
27052713
return GetDemangledType(dem, type.GetMangledTypeName().GetStringRef());
27062714
}
27072715

2716+
swift::Demangle::NodePointer
2717+
TypeSystemSwiftTypeRef::DemangleCanonicalOutermostType(
2718+
swift::Demangle::Demangler &dem, lldb::opaque_compiler_type_t type) {
2719+
using namespace swift::Demangle;
2720+
NodePointer node = GetDemangledType(dem, AsMangledName(type));
2721+
if (!node)
2722+
return nullptr;
2723+
NodePointer canonical = Canonicalize(dem, node);
2724+
if (canonical &&
2725+
canonical->getKind() == swift::Demangle::Node::Kind::TypeAlias) {
2726+
// If this is a typealias defined in the expression evaluator,
2727+
// then we don't have debug info to resolve it from.
2728+
CompilerType ast_type =
2729+
ReconstructType({weak_from_this(), type}, nullptr).GetCanonicalType();
2730+
return GetDemangledType(dem, ast_type.GetMangledTypeName());
2731+
}
2732+
return canonical;
2733+
}
2734+
27082735
CompilerType
27092736
TypeSystemSwiftTypeRef::CreateGenericTypeParamType(unsigned int depth,
27102737
unsigned int index) {
@@ -2730,7 +2757,7 @@ bool TypeSystemSwiftTypeRef::IsArrayType(opaque_compiler_type_t type,
27302757
auto impl = [&]() {
27312758
using namespace swift::Demangle;
27322759
Demangler dem;
2733-
NodePointer node = DemangleCanonicalType(dem, type);
2760+
NodePointer node = DemangleCanonicalOutermostType(dem, type);
27342761
if (!node || node->getNumChildren() != 2 ||
27352762
node->getKind() != Node::Kind::BoundGenericStructure)
27362763
return false;
@@ -2756,7 +2783,9 @@ bool TypeSystemSwiftTypeRef::IsArrayType(opaque_compiler_type_t type,
27562783
return false;
27572784
elem_node = elem_node->getFirstChild();
27582785
if (element_type)
2759-
*element_type = RemangleAsType(dem, elem_node);
2786+
// FIXME: This expensive canonicalization is only there for
2787+
// SwiftASTContext compatibility.
2788+
*element_type = RemangleAsType(dem, elem_node).GetCanonicalType();
27602789

27612790
if (is_incomplete)
27622791
*is_incomplete = true;
@@ -2773,7 +2802,7 @@ bool TypeSystemSwiftTypeRef::IsAggregateType(opaque_compiler_type_t type) {
27732802
auto impl = [&]() -> bool {
27742803
using namespace swift::Demangle;
27752804
Demangler dem;
2776-
NodePointer node = DemangleCanonicalType(dem, type);
2805+
NodePointer node = DemangleCanonicalOutermostType(dem, type);
27772806

27782807
if (!node)
27792808
return false;
@@ -2811,7 +2840,7 @@ bool TypeSystemSwiftTypeRef::IsFunctionType(opaque_compiler_type_t type) {
28112840
auto impl = [&]() -> bool {
28122841
using namespace swift::Demangle;
28132842
Demangler dem;
2814-
NodePointer node = DemangleCanonicalType(dem, type);
2843+
NodePointer node = DemangleCanonicalOutermostType(dem, type);
28152844
// Note: There are a number of other candidates, and this list may need
28162845
// updating. Ex: `NoEscapeFunctionType`, `ThinFunctionType`, etc.
28172846
return node && (node->getKind() == Node::Kind::FunctionType ||
@@ -2826,7 +2855,7 @@ size_t TypeSystemSwiftTypeRef::GetNumberOfFunctionArguments(
28262855
auto impl = [&]() -> size_t {
28272856
using namespace swift::Demangle;
28282857
Demangler dem;
2829-
NodePointer node = DemangleCanonicalType(dem, type);
2858+
NodePointer node = DemangleCanonicalOutermostType(dem, type);
28302859
if (!node || (node->getKind() != Node::Kind::FunctionType &&
28312860
node->getKind() != Node::Kind::NoEscapeFunctionType &&
28322861
node->getKind() != Node::Kind::ImplFunctionType))
@@ -2856,7 +2885,7 @@ TypeSystemSwiftTypeRef::GetFunctionArgumentAtIndex(opaque_compiler_type_t type,
28562885
auto impl = [&]() -> CompilerType {
28572886
using namespace swift::Demangle;
28582887
Demangler dem;
2859-
NodePointer node = DemangleCanonicalType(dem, type);
2888+
NodePointer node = DemangleCanonicalOutermostType(dem, type);
28602889
if (!node || (node->getKind() != Node::Kind::FunctionType &&
28612890
node->getKind() != Node::Kind::NoEscapeFunctionType &&
28622891
node->getKind() != Node::Kind::ImplFunctionType))
@@ -2982,7 +3011,7 @@ bool TypeSystemSwiftTypeRef::IsPointerType(opaque_compiler_type_t type,
29823011
auto impl = [&]() {
29833012
using namespace swift::Demangle;
29843013
Demangler dem;
2985-
NodePointer node = DemangleCanonicalType(dem, type);
3014+
NodePointer node = DemangleCanonicalOutermostType(dem, type);
29863015
if (!node || node->getKind() != Node::Kind::BuiltinTypeName ||
29873016
!node->hasText())
29883017
return false;
@@ -2998,7 +3027,7 @@ bool TypeSystemSwiftTypeRef::IsVoidType(opaque_compiler_type_t type) {
29983027
auto impl = [&]() {
29993028
using namespace swift::Demangle;
30003029
Demangler dem;
3001-
NodePointer node = DemangleCanonicalType(dem, type);
3030+
NodePointer node = DemangleCanonicalOutermostType(dem, type);
30023031
return node && node->getNumChildren() == 0 &&
30033032
node->getKind() == Node::Kind::Tuple;
30043033
};
@@ -3176,7 +3205,7 @@ TypeSystemSwiftTypeRef::GetFunctionReturnType(opaque_compiler_type_t type) {
31763205
auto impl = [&]() -> CompilerType {
31773206
using namespace swift::Demangle;
31783207
Demangler dem;
3179-
NodePointer node = DemangleCanonicalType(dem, type);
3208+
NodePointer node = DemangleCanonicalOutermostType(dem, type);
31803209
if (!node || (node->getKind() != Node::Kind::FunctionType &&
31813210
node->getKind() != Node::Kind::NoEscapeFunctionType &&
31823211
node->getKind() != Node::Kind::ImplFunctionType))
@@ -3407,7 +3436,7 @@ lldb::Encoding TypeSystemSwiftTypeRef::GetEncoding(opaque_compiler_type_t type,
34073436

34083437
using namespace swift::Demangle;
34093438
Demangler dem;
3410-
auto *node = DemangleCanonicalType(dem, type);
3439+
auto *node = DemangleCanonicalOutermostType(dem, type);
34113440
if (!node)
34123441
return lldb::eEncodingInvalid;
34133442
auto kind = node->getKind();
@@ -3983,7 +4012,7 @@ TypeSystemSwiftTypeRef::GetNumTemplateArguments(opaque_compiler_type_t type,
39834012
auto impl = [&]() -> size_t {
39844013
using namespace swift::Demangle;
39854014
Demangler dem;
3986-
NodePointer node = DemangleCanonicalType(dem, type);
4015+
NodePointer node = DemangleCanonicalOutermostType(dem, type);
39874016

39884017
if (!node)
39894018
return 0;
@@ -4121,7 +4150,7 @@ bool TypeSystemSwiftTypeRef::IsExistentialType(
41214150
lldb::opaque_compiler_type_t type) {
41224151
using namespace swift::Demangle;
41234152
Demangler dem;
4124-
NodePointer node = DemangleCanonicalType(dem, type);
4153+
NodePointer node = DemangleCanonicalOutermostType(dem, type);
41254154
if (!node || node->getNumChildren() != 1)
41264155
return false;
41274156
switch (node->getKind()) {
@@ -4148,7 +4177,7 @@ bool TypeSystemSwiftTypeRef::IsErrorType(opaque_compiler_type_t type) {
41484177
auto impl = [&]() -> bool {
41494178
using namespace swift::Demangle;
41504179
Demangler dem;
4151-
NodePointer protocol_list = DemangleCanonicalType(dem, type);
4180+
NodePointer protocol_list = DemangleCanonicalOutermostType(dem, type);
41524181
if (protocol_list && protocol_list->getKind() == Node::Kind::ProtocolList)
41534182
for (auto type_list : *protocol_list)
41544183
if (type_list && type_list->getKind() == Node::Kind::TypeList)
@@ -4918,7 +4947,7 @@ bool TypeSystemSwiftTypeRef::IsReferenceType(opaque_compiler_type_t type,
49184947
auto impl = [&]() {
49194948
using namespace swift::Demangle;
49204949
Demangler dem;
4921-
NodePointer node = DemangleCanonicalType(dem, type);
4950+
NodePointer node = DemangleCanonicalOutermostType(dem, type);
49224951
if (!node || node->getNumChildren() != 1 ||
49234952
node->getKind() != Node::Kind::InOut)
49244953
return false;
@@ -4945,7 +4974,7 @@ TypeSystemSwiftTypeRef::GetGenericArgumentType(opaque_compiler_type_t type,
49454974
size_t idx) {
49464975
auto impl = [&]() -> CompilerType {
49474976
Demangler dem;
4948-
NodePointer node = DemangleCanonicalType(dem, type);
4977+
NodePointer node = DemangleCanonicalOutermostType(dem, type);
49494978
if (!node || node->getNumChildren() != 2)
49504979
return {};
49514980

lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,10 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
438438
/// Cast \p opaque_type as a mangled name.
439439
static const char *AsMangledName(lldb::opaque_compiler_type_t type);
440440

441+
/// Helper function that canonicalizes node, but doesn't look at its
442+
/// children.
443+
swift::Demangle::NodePointer Canonicalize(swift::Demangle::Demangler &dem,
444+
swift::Demangle::NodePointer node);
441445

442446
/// Demangle the mangled name of the canonical type of \p type and
443447
/// drill into the Global(TypeMangling(Type())).
@@ -447,6 +451,15 @@ class TypeSystemSwiftTypeRef : public TypeSystemSwift {
447451
DemangleCanonicalType(swift::Demangle::Demangler &dem,
448452
lldb::opaque_compiler_type_t type);
449453

454+
/// Demangle the mangled name of \p type after canonicalizing its
455+
/// outermost type node and drill into the
456+
/// Global(TypeMangling(Type())).
457+
///
458+
/// \return the child of Type or a nullptr.
459+
swift::Demangle::NodePointer
460+
DemangleCanonicalOutermostType(swift::Demangle::Demangler &dem,
461+
lldb::opaque_compiler_type_t type);
462+
450463
/// If \p node is a Struct/Class/Typedef in the __C module, return a
451464
/// Swiftified node by looking up the name in the corresponding APINotes and
452465
/// optionally putting it into the correctly named module.

0 commit comments

Comments
 (0)