<rdar://problem/13119621>
authorGreg Clayton <gclayton@apple.com>
Fri, 8 Mar 2013 01:37:30 +0000 (01:37 +0000)
committerGreg Clayton <gclayton@apple.com>
Fri, 8 Mar 2013 01:37:30 +0000 (01:37 +0000)
Make dynamic type detection faster by using the AST metadata to help out and allow us not to complete types when we don't need to.

After running "purge" on a MacOSX system, the Xcode variables view now populates more than 3x faster with this fix.

llvm-svn: 176676

lldb/include/lldb/Symbol/ClangExternalASTSourceCommon.h
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
lldb/source/Symbol/ClangASTContext.cpp

index de96f9f..b3ef130 100644 (file)
@@ -50,10 +50,23 @@ public:
         m_union_is_user_id(false),
         m_union_is_isa_ptr(false),
         m_has_object_ptr(false),
-        m_is_self (false)
+        m_is_self (false),
+        m_is_dynamic_cxx (true)
     {
     }
-    
+
+    bool
+    GetIsDynamicCXXType () const
+    {
+        return m_is_dynamic_cxx;
+    }
+
+    void
+    SetIsDynamicCXXType (bool b)
+    {
+        m_is_dynamic_cxx = b;
+    }
+
     void
     SetUserID (lldb::user_id_t user_id)
     {
@@ -136,7 +149,8 @@ private:
     bool m_union_is_user_id : 1,
          m_union_is_isa_ptr : 1,
          m_has_object_ptr : 1,
-         m_is_self : 1;
+         m_is_self : 1,
+         m_is_dynamic_cxx : 1;
     
 };
 
index a8d97d3..94cc838 100644 (file)
@@ -1372,7 +1372,7 @@ public:
         const char             *property_setter_name,
         const char             *property_getter_name,
         uint32_t                property_attributes,
-        const ClangASTMetadata       *metadata
+        const ClangASTMetadata *metadata
     ) :
         m_ast                   (ast),
         m_class_opaque_type     (class_opaque_type),
@@ -1386,7 +1386,7 @@ public:
         if (metadata != NULL)
         {
             m_metadata_ap.reset(new ClangASTMetadata());
-            *(m_metadata_ap.get()) = *metadata;
+            *m_metadata_ap = *metadata;
         }
     }
     
@@ -1409,22 +1409,22 @@ public:
         if (rhs.m_metadata_ap.get())
         {
             m_metadata_ap.reset (new ClangASTMetadata());
-            *(m_metadata_ap.get()) = *(rhs.m_metadata_ap.get());
+            *m_metadata_ap = *rhs.m_metadata_ap;
         }
         return *this;
     }
     
     bool Finalize() const
     {
-        return ClangASTContext::AddObjCClassProperty(m_ast,
-                                                     m_class_opaque_type,
-                                                     m_property_name,
-                                                     m_property_opaque_type,
-                                                     m_ivar_decl,
-                                                     m_property_setter_name,
-                                                     m_property_getter_name,
-                                                     m_property_attributes,
-                                                     m_metadata_ap.get());
+        return ClangASTContext::AddObjCClassProperty (m_ast,
+                                                      m_class_opaque_type,
+                                                      m_property_name,
+                                                      m_property_opaque_type,
+                                                      m_ivar_decl,
+                                                      m_property_setter_name,
+                                                      m_property_getter_name,
+                                                      m_property_attributes,
+                                                      m_metadata_ap.get());
     }
 private:
     clang::ASTContext      *m_ast;
@@ -1435,7 +1435,7 @@ private:
     const char             *m_property_setter_name;
     const char             *m_property_getter_name;
     uint32_t                m_property_attributes;
-    std::auto_ptr<ClangASTMetadata>        m_metadata_ap;
+    std::auto_ptr<ClangASTMetadata> m_metadata_ap;
 };
 
 struct BitfieldInfo
@@ -1456,6 +1456,36 @@ struct BitfieldInfo
     }
 };
 
+
+bool
+SymbolFileDWARF::ClassOrStructIsVirtual (DWARFCompileUnit* dwarf_cu,
+                                         const DWARFDebugInfoEntry *parent_die)
+{
+    if (parent_die)
+    {
+        for (const DWARFDebugInfoEntry *die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
+        {
+            dw_tag_t tag = die->Tag();
+            bool check_virtuality = false;
+            switch (tag)
+            {
+                case DW_TAG_inheritance:
+                case DW_TAG_subprogram:
+                    check_virtuality = true;
+                    break;
+                default:
+                    break;
+            }
+            if (check_virtuality)
+            {
+                if (die->GetAttributeValueAsUnsigned(this, dwarf_cu, DW_AT_virtuality, 0) != 0)
+                    return true;
+            }
+        }
+    }
+    return false;
+}
+
 size_t
 SymbolFileDWARF::ParseChildMembers
 (
@@ -5868,6 +5898,10 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
                                 accessibility = default_accessibility;
                         }
 
+                        ClangASTMetadata metadata;
+                        metadata.SetUserID(MakeUserID(die->GetOffset()));
+                        metadata.SetIsDynamicCXXType(ClassOrStructIsVirtual (dwarf_cu, die));
+
                         if (type_name_cstr && strchr (type_name_cstr, '<'))
                         {
                             ClangASTContext::TemplateParameterInfos template_param_infos;
@@ -5886,16 +5920,14 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
                                 clang_type = ast.CreateClassTemplateSpecializationType (class_specialization_decl);
                                 clang_type_was_created = true;
                                 
-                                GetClangASTContext().SetMetadataAsUserID ((uintptr_t)class_template_decl, MakeUserID(die->GetOffset()));
-                                GetClangASTContext().SetMetadataAsUserID ((uintptr_t)class_specialization_decl, MakeUserID(die->GetOffset()));
+                                GetClangASTContext().SetMetadata ((uintptr_t)class_template_decl, metadata);
+                                GetClangASTContext().SetMetadata ((uintptr_t)class_specialization_decl, metadata);
                             }
                         }
 
                         if (!clang_type_was_created)
                         {
                             clang_type_was_created = true;
-                            ClangASTMetadata metadata;
-                            metadata.SetUserID(MakeUserID(die->GetOffset()));
                             clang_type = ast.CreateRecordType (decl_ctx, 
                                                                accessibility, 
                                                                type_name_cstr, 
index f4703e8..b4bbf93 100644 (file)
@@ -338,6 +338,10 @@ protected:
     class DelayedAddObjCClassProperty;
     typedef std::vector <DelayedAddObjCClassProperty> DelayedPropertyList;
     
+    bool                    ClassOrStructIsVirtual (
+                                DWARFCompileUnit* dwarf_cu,
+                                const DWARFDebugInfoEntry *parent_die);
+
     size_t                  ParseChildMembers(
                                 const lldb_private::SymbolContext& sc,
                                 DWARFCompileUnit* dwarf_cu,
index 1853c30..30fa9bb 100644 (file)
@@ -1126,7 +1126,12 @@ ClangASTContext::GetTypeForDecl (ObjCInterfaceDecl *decl)
 #pragma mark Structure, Unions, Classes
 
 clang_type_t
-ClangASTContext::CreateRecordType (DeclContext *decl_ctx, AccessType access_type, const char *name, int kind, LanguageType language, ClangASTMetadata *metadata)
+ClangASTContext::CreateRecordType (DeclContext *decl_ctx,
+                                   AccessType access_type,
+                                   const char *name,
+                                   int kind,
+                                   LanguageType language,
+                                   ClangASTMetadata *metadata)
 {
     ASTContext *ast = getASTContext();
     assert (ast != NULL);
@@ -1154,16 +1159,20 @@ ClangASTContext::CreateRecordType (DeclContext *decl_ctx, AccessType access_type
                                                  SourceLocation(),
                                                  name && name[0] ? &ast->Idents.get(name) : NULL);
     
-    if (decl && metadata)
-        SetMetadata(ast, (uintptr_t)decl, *metadata);
-    
-    if (decl_ctx)
+    if (decl)
     {
+        if (metadata)
+            SetMetadata(ast, (uintptr_t)decl, *metadata);
+
         if (access_type != eAccessNone)
             decl->setAccess (ConvertAccessTypeToAccessSpecifier (access_type));
-        decl_ctx->addDecl (decl);
+    
+        if (decl_ctx)
+            decl_ctx->addDecl (decl);
+
+        return ast->getTagDeclType(decl).getAsOpaquePtr();
     }
-    return ast->getTagDeclType(decl).getAsOpaquePtr();
+    return NULL;
 }
 
 static TemplateParameterList *
@@ -5732,16 +5741,22 @@ ClangASTContext::IsPossibleDynamicType (clang::ASTContext *ast,
                         if (cxx_record_decl)
                         {
                             bool is_complete = cxx_record_decl->isCompleteDefinition();
-                            if (!is_complete)
-                                is_complete = ClangASTContext::GetCompleteType (ast, pointee_qual_type.getAsOpaquePtr());
-
+                            
                             if (is_complete)
-                            {
                                 success = cxx_record_decl->isDynamicClass();
-                            }
                             else
                             {
-                                success = false;
+                                ClangASTMetadata *metadata = GetMetadata (ast, (uintptr_t)cxx_record_decl);
+                                if (metadata)
+                                    success = metadata->GetIsDynamicCXXType();
+                                else
+                                {
+                                    is_complete = ClangASTContext::GetCompleteType (ast, pointee_qual_type.getAsOpaquePtr());
+                                    if (is_complete)
+                                        success = cxx_record_decl->isDynamicClass();
+                                    else
+                                        success = false;
+                                }
                             }
 
                             if (success)