<rdar://problem/13119621>

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
This commit is contained in:
Greg Clayton 2013-03-08 01:37:30 +00:00
parent fd7d67e18f
commit c4ffd66f06
4 changed files with 98 additions and 33 deletions

View 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;
};

View 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,

View 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,

View 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)