Skip to content

Commit ad53c6a

Browse files
Merge pull request #9808 from adrian-prantl/lazy-canonicalization
[lldb] Improve performance of TypeSystemSwiftTypeRef via lazy canonic…
2 parents 876cb85 + be14764 commit ad53c6a

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)