r176820 - Improve the caching of debuginfo Objective C interface types.

Adrian Prantl aprantl at apple.com
Mon Mar 11 11:33:46 PDT 2013


Author: adrian
Date: Mon Mar 11 13:33:46 2013
New Revision: 176820

URL: http://llvm.org/viewvc/llvm-project?rev=176820&view=rev
Log:
Improve the caching of debuginfo Objective C interface types.
Generate forward declarations that are RAUW'd by finalize().
We thus avoid outputting the same type several times in multiple
stages of completion.

Modified:
    cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
    cfe/trunk/lib/CodeGen/CGDebugInfo.h
    cfe/trunk/test/CodeGenObjC/debug-info-ivars-extension.m

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=176820&r1=176819&r2=176820&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Mar 11 13:33:46 2013
@@ -1314,7 +1314,7 @@ llvm::DIType CGDebugInfo::getOrCreateInt
                                                    SourceLocation Loc) {
   assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
   llvm::DIType T = getOrCreateType(D, getOrCreateFile(Loc));
-  DBuilder.retainType(T);
+  RetainedTypes.push_back(D.getAsOpaquePtr());
   return T;
 }
 
@@ -1778,6 +1778,13 @@ llvm::DIType CGDebugInfo::getTypeOrNull(
   Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
   
   // Check for existing entry.
+  if (Ty->getTypeClass() == Type::ObjCInterface) {
+    llvm::Value *V = getCachedInterfaceTypeOrNull(Ty);
+    if (V)
+      return llvm::DIType(cast<llvm::MDNode>(V));
+    else return llvm::DIType();
+  }
+
   llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
     TypeCache.find(Ty.getAsOpaquePtr());
   if (it != TypeCache.end()) {
@@ -1803,16 +1810,7 @@ llvm::DIType CGDebugInfo::getCompletedTy
   if (it != CompletedTypeCache.end())
     V = it->second;
   else {
-    // Is there a cached interface that hasn't changed?
-    llvm::DenseMap<void *, std::pair<llvm::WeakVH, unsigned > >
-      ::iterator it1 = ObjCInterfaceCache.find(Ty.getAsOpaquePtr());
-
-    if (it1 != ObjCInterfaceCache.end())
-      if (ObjCInterfaceDecl* Decl = getObjCInterfaceDecl(Ty))
-	if (Checksum(Decl) == it1->second.second) {
-	  // Return cached type.
-	  V = it1->second.first;
-	}
+    V = getCachedInterfaceTypeOrNull(Ty);
   }
 
   // Verify that any cached debug info still exists.
@@ -1822,6 +1820,21 @@ llvm::DIType CGDebugInfo::getCompletedTy
   return llvm::DIType();
 }
 
+/// getCachedInterfaceTypeOrNull - Get the type from the interface
+/// cache, unless it needs to regenerated. Otherwise return null.
+llvm::Value *CGDebugInfo::getCachedInterfaceTypeOrNull(QualType Ty) {
+  // Is there a cached interface that hasn't changed?
+  llvm::DenseMap<void *, std::pair<llvm::WeakVH, unsigned > >
+    ::iterator it1 = ObjCInterfaceCache.find(Ty.getAsOpaquePtr());
+
+  if (it1 != ObjCInterfaceCache.end())
+    if (ObjCInterfaceDecl* Decl = getObjCInterfaceDecl(Ty))
+      if (Checksum(Decl) == it1->second.second)
+        // Return cached forward declaration.
+        return it1->second.first;
+
+  return 0;
+}
 
 /// getOrCreateType - Get the type from the cache or create a new
 /// one if necessary.
@@ -1839,27 +1852,39 @@ llvm::DIType CGDebugInfo::getOrCreateTyp
 
   // Otherwise create the type.
   llvm::DIType Res = CreateTypeNode(Ty, Unit);
+  void* TyPtr = Ty.getAsOpaquePtr();
+
+  // And update the type cache.
+  TypeCache[TyPtr] = Res;
 
   llvm::DIType TC = getTypeOrNull(Ty);
   if (TC.Verify() && TC.isForwardDecl())
-    ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(),
-                                        static_cast<llvm::Value*>(TC)));
-  
-  // Do not cache the type if it may be incomplete.
-  if (ObjCInterfaceDecl* Decl = getObjCInterfaceDecl(Ty)) {
-    // clang::ParseAST handles each TopLevelDecl immediately after it was parsed.
-    // A subsequent implementation may add more ivars to an interface, which is
-    // why we cache it together with a checksum to see if it changed.
-    ObjCInterfaceCache[Ty.getAsOpaquePtr()] =
-      std::make_pair(Res, Checksum(Decl));
-    return Res;
+    ReplaceMap.push_back(std::make_pair(TyPtr, static_cast<llvm::Value*>(TC)));
+  else if (ObjCInterfaceDecl* Decl = getObjCInterfaceDecl(Ty)) {
+    // Interface types may have elements added to them by a
+    // subsequent implementation or extension, so we keep them in
+    // the ObjCInterfaceCache together with a checksum. Instead of
+    // the (possibly) incomplete interace type, we return a forward
+    // declaration that gets RAUW'd in CGDebugInfo::finalize().
+    llvm::DenseMap<void *, std::pair<llvm::WeakVH, unsigned > >
+      ::iterator it = ObjCInterfaceCache.find(TyPtr);
+    if (it != ObjCInterfaceCache.end())
+      TC = llvm::DIType(cast<llvm::MDNode>(it->second.first));
+    else
+      TC = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
+				      Decl->getName(), TheCU, Unit,
+				      getLineNumber(Decl->getLocation()),
+				      TheCU.getLanguage());
+    // Store the forward declaration in the cache.
+    ObjCInterfaceCache[TyPtr] = std::make_pair(TC, Checksum(Decl));
+
+    // Register the type for replacement in finalize().
+    ReplaceMap.push_back(std::make_pair(TyPtr, static_cast<llvm::Value*>(TC)));
+    return TC;
   }
 
-  // And update the type cache.
-  TypeCache[Ty.getAsOpaquePtr()] = Res;
-
   if (!Res.isForwardDecl())
-    CompletedTypeCache[Ty.getAsOpaquePtr()] = Res;
+    CompletedTypeCache[TyPtr] = Res;
 
   return Res;
 }
@@ -2929,10 +2954,17 @@ void CGDebugInfo::finalize() {
       if (llvm::Value *V = it->second)
         RepTy = llvm::DIType(cast<llvm::MDNode>(V));
     }
-    
+
     if (Ty.Verify() && Ty.isForwardDecl() && RepTy.Verify()) {
       Ty.replaceAllUsesWith(RepTy);
     }
   }
+
+  // We keep our own list of retained types, because we need to look
+  // up the final type in the type cache.
+  for (std::vector<void *>::const_iterator RI = RetainedTypes.begin(),
+         RE = RetainedTypes.end(); RI != RE; ++RI)
+    DBuilder.retainType(llvm::DIType(cast<llvm::MDNode>(TypeCache[*RI])));
+
   DBuilder.finalize();
 }

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=176820&r1=176819&r2=176820&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Mon Mar 11 13:33:46 2013
@@ -66,6 +66,9 @@ class CGDebugInfo {
   llvm::DenseMap<void *, std::pair<llvm::WeakVH, unsigned > >
     ObjCInterfaceCache;
 
+  /// RetainedTypes - list of interfaces we want to keep even if orphaned.
+  std::vector<void *> RetainedTypes;
+
   /// CompleteTypeCache - Cache of previously constructed complete RecordTypes.
   llvm::DenseMap<void *, llvm::WeakVH> CompletedTypeCache;
 
@@ -131,6 +134,7 @@ class CGDebugInfo {
                                      const Type *Ty, QualType PointeeTy,
                                      llvm::DIFile F);
 
+  llvm::Value *getCachedInterfaceTypeOrNull(const QualType Ty);
   llvm::DIType getOrCreateStructPtrType(StringRef Name, llvm::DIType &Cache);
 
   llvm::DISubprogram CreateCXXMemberFunction(const CXXMethodDecl *Method,

Modified: cfe/trunk/test/CodeGenObjC/debug-info-ivars-extension.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/debug-info-ivars-extension.m?rev=176820&r1=176819&r2=176820&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/debug-info-ivars-extension.m (original)
+++ cfe/trunk/test/CodeGenObjC/debug-info-ivars-extension.m Mon Mar 11 13:33:46 2013
@@ -24,5 +24,10 @@ void gorf (I* pg) {
     int _b = pg->b;
 }
 
+// CHECK: metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata !"I", {{.*}}} ; [ DW_TAG_structure_type ]
+// Check for "a".
 // CHECK: metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata !"a", metadata !{{[0-9]*}}, i32 7, i64 32, i64 32, i64 0, i32 0, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [a] [line 7, size 32, align 32, offset 0] [from int]
+// Make sure we don't output the same type twice.
+// CHECK-NOT: metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata !"I", {{.*}}} ; [ DW_TAG_structure_type ]
+// Check for "b".
 // CHECK: metadata !{i32 {{[0-9]*}}, metadata !{{[0-9]*}}, metadata !"b", metadata !{{[0-9]*}}, i32 18, i64 32, i64 32, i64 0, i32 0, metadata !{{[0-9]*}}, null} ; [ DW_TAG_member ] [b] [line 18, size 32, align 32, offset 0] [from int]





More information about the cfe-commits mailing list