Merge pull request #21929 from slavapestov/cache-superclass-decl-request-5.0

AST: Cache SuperclassDeclRequest [5.0]
diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h
index f8e96a1..206dcd9 100644
--- a/include/swift/AST/Decl.h
+++ b/include/swift/AST/Decl.h
@@ -3569,11 +3569,16 @@
   void createObjCMethodLookup();
 
   struct {
+    /// The superclass decl and a bit to indicate whether the
+    /// superclass was computed yet or not.
+    llvm::PointerIntPair<ClassDecl *, 1, bool> SuperclassDecl;
+
     /// The superclass type and a bit to indicate whether the
     /// superclass was computed yet or not.
-    llvm::PointerIntPair<Type, 1, bool> Superclass;
+    llvm::PointerIntPair<Type, 1, bool> SuperclassType;
   } LazySemanticInfo;
 
+  friend class SuperclassDeclRequest;
   friend class SuperclassTypeRequest;
   friend class TypeChecker;
 
@@ -3898,11 +3903,16 @@
   bool existentialTypeSupportedSlow(LazyResolver *resolver);
 
   struct {
+    /// The superclass decl and a bit to indicate whether the
+    /// superclass was computed yet or not.
+    llvm::PointerIntPair<ClassDecl *, 1, bool> SuperclassDecl;
+
     /// The superclass type and a bit to indicate whether the
     /// superclass was computed yet or not.
-    llvm::PointerIntPair<Type, 1, bool> Superclass;
+    llvm::PointerIntPair<Type, 1, bool> SuperclassType;
   } LazySemanticInfo;
 
+  friend class SuperclassDeclRequest;
   friend class SuperclassTypeRequest;
   friend class TypeChecker;
 
diff --git a/include/swift/AST/NameLookupRequests.h b/include/swift/AST/NameLookupRequests.h
index 7f73230..5f7177a 100644
--- a/include/swift/AST/NameLookupRequests.h
+++ b/include/swift/AST/NameLookupRequests.h
@@ -133,7 +133,7 @@
 /// Request the superclass declaration for the given class.
 class SuperclassDeclRequest :
     public SimpleRequest<SuperclassDeclRequest,
-                         CacheKind::Uncached, // FIXME: Cache these
+                         CacheKind::SeparatelyCached,
                          ClassDecl *,
                          NominalTypeDecl *> {
 public:
@@ -149,6 +149,8 @@
 public:
   // Caching
   bool isCached() const { return true; }
+  Optional<ClassDecl *> getCachedResult() const;
+  void cacheResult(ClassDecl *value) const;
 
   // Cycle handling
   void diagnoseCycle(DiagnosticEngine &diags) const;
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index c92e02d..19f5f7e 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -3919,7 +3919,10 @@
 void ProtocolDecl::setSuperclass(Type superclass) {
   assert((!superclass || !superclass->hasArchetype())
          && "superclass must be interface type");
-  LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
+  LazySemanticInfo.SuperclassType.setPointerAndInt(superclass, true);
+  LazySemanticInfo.SuperclassDecl.setPointerAndInt(
+    superclass ? superclass->getClassOrBoundGenericClass() : nullptr,
+    true);
 }
 
 bool ProtocolDecl::walkInheritedProtocols(
@@ -6437,7 +6440,10 @@
 void ClassDecl::setSuperclass(Type superclass) {
   assert((!superclass || !superclass->hasArchetype())
          && "superclass must be interface type");
-  LazySemanticInfo.Superclass.setPointerAndInt(superclass, true);
+  LazySemanticInfo.SuperclassType.setPointerAndInt(superclass, true);
+  LazySemanticInfo.SuperclassDecl.setPointerAndInt(
+    superclass ? superclass->getClassOrBoundGenericClass() : nullptr,
+    true);
 }
 
 ClangNode Decl::getClangNodeImpl() const {
diff --git a/lib/AST/NameLookupRequests.cpp b/lib/AST/NameLookupRequests.cpp
index 245e6ca..0a82db6 100644
--- a/lib/AST/NameLookupRequests.cpp
+++ b/lib/AST/NameLookupRequests.cpp
@@ -74,6 +74,30 @@
 //----------------------------------------------------------------------------//
 // Superclass declaration computation.
 //----------------------------------------------------------------------------//
+Optional<ClassDecl *> SuperclassDeclRequest::getCachedResult() const {
+  auto nominalDecl = std::get<0>(getStorage());
+
+  if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
+    if (classDecl->LazySemanticInfo.SuperclassDecl.getInt())
+      return classDecl->LazySemanticInfo.SuperclassDecl.getPointer();
+
+  if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
+    if (protocolDecl->LazySemanticInfo.SuperclassDecl.getInt())
+      return protocolDecl->LazySemanticInfo.SuperclassDecl.getPointer();
+
+  return None;
+}
+
+void SuperclassDeclRequest::cacheResult(ClassDecl *value) const {
+  auto nominalDecl = std::get<0>(getStorage());
+
+  if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
+    classDecl->LazySemanticInfo.SuperclassDecl.setPointerAndInt(value, true);
+
+  if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
+    protocolDecl->LazySemanticInfo.SuperclassDecl.setPointerAndInt(value, true);
+}
+
 void SuperclassDeclRequest::diagnoseCycle(DiagnosticEngine &diags) const {
   // FIXME: Improve this diagnostic.
   auto subjectDecl = std::get<0>(getStorage());
@@ -87,7 +111,7 @@
 }
 
 //----------------------------------------------------------------------------//
-// Superclass declaration computation.
+// Extended nominal computation.
 //----------------------------------------------------------------------------//
 Optional<NominalTypeDecl *> ExtendedNominalRequest::getCachedResult() const {
   // Note: if we fail to compute any nominal declaration, it's considered
diff --git a/lib/AST/TypeCheckRequests.cpp b/lib/AST/TypeCheckRequests.cpp
index 442adcb..466ff7c 100644
--- a/lib/AST/TypeCheckRequests.cpp
+++ b/lib/AST/TypeCheckRequests.cpp
@@ -125,12 +125,12 @@
   auto nominalDecl = std::get<0>(getStorage());
 
   if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
-    if (classDecl->LazySemanticInfo.Superclass.getInt())
-      return classDecl->LazySemanticInfo.Superclass.getPointer();
+    if (classDecl->LazySemanticInfo.SuperclassType.getInt())
+      return classDecl->LazySemanticInfo.SuperclassType.getPointer();
 
   if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
-    if (protocolDecl->LazySemanticInfo.Superclass.getInt())
-      return protocolDecl->LazySemanticInfo.Superclass.getPointer();
+    if (protocolDecl->LazySemanticInfo.SuperclassType.getInt())
+      return protocolDecl->LazySemanticInfo.SuperclassType.getPointer();
 
   return None;
 }
@@ -139,10 +139,10 @@
   auto nominalDecl = std::get<0>(getStorage());
 
   if (auto *classDecl = dyn_cast<ClassDecl>(nominalDecl))
-    classDecl->LazySemanticInfo.Superclass.setPointerAndInt(value, true);
+    classDecl->LazySemanticInfo.SuperclassType.setPointerAndInt(value, true);
 
   if (auto *protocolDecl = dyn_cast<ProtocolDecl>(nominalDecl))
-    protocolDecl->LazySemanticInfo.Superclass.setPointerAndInt(value, true);
+    protocolDecl->LazySemanticInfo.SuperclassType.setPointerAndInt(value, true);
 }
 
 //----------------------------------------------------------------------------//
diff --git a/test/Misc/stats_dir_tracer.swift b/test/Misc/stats_dir_tracer.swift
index 12795d8..90be632 100644
--- a/test/Misc/stats_dir_tracer.swift
+++ b/test/Misc/stats_dir_tracer.swift
@@ -2,9 +2,9 @@
 // RUN: %target-swiftc_driver -o %t/main -module-name main -stats-output-dir %t %s -trace-stats-events
 // RUN: %FileCheck -input-file %t/*.csv %s
 
-// CHECK: {{[0-9]+,[0-9]+,"exit","typecheck-expr","Sema.NumTypesDeserialized",[0-9]+,[0-9]+,"Call","\[.*stats_dir_tracer.swift.*\]"}}
-// CHECK: {{[0-9]+,[0-9]+,"exit","typecheck-expr","Sema.NumConstraintScopes",[0-9]+,[0-9]+,"Sequence","\[.*stats_dir_tracer.swift.*\]"}}
-// CHECK: {{[0-9]+,[0-9]+,"exit","SuperclassDeclRequest","Sema.SuperclassDeclRequest",[0-9]+,[0-9]+,"Bar","\[.*stats_dir_tracer.swift.*\]"}}
+// CHECK-DAG: {{[0-9]+,[0-9]+,"exit","typecheck-expr","Sema.NumTypesDeserialized",[0-9]+,[0-9]+,"Call","\[.*stats_dir_tracer.swift.*\]"}}
+// CHECK-DAG: {{[0-9]+,[0-9]+,"exit","typecheck-expr","Sema.NumConstraintScopes",[0-9]+,[0-9]+,"Sequence","\[.*stats_dir_tracer.swift.*\]"}}
+// CHECK-DAG: {{[0-9]+,[0-9]+,"exit","SuperclassDeclRequest","Sema.SuperclassDeclRequest",[0-9]+,[0-9]+,"Bar","\[.*stats_dir_tracer.swift.*\]"}}
 
 public func foo() {
     print("hello")