[Lldb-commits] [lldb] r178601 - <rdar://problem/13563403>
Enrico Granata
egranata at apple.com
Tue Apr 2 18:25:29 PDT 2013
Author: enrico
Date: Tue Apr 2 20:25:29 2013
New Revision: 178601
URL: http://llvm.org/viewvc/llvm-project?rev=178601&view=rev
Log:
<rdar://problem/13563403>
Reimplemented the NSDictionary synthetic children provider for added performance.
Instead of generating pairs by running an expression, we now create a pair type using clang-level APIs and fill in a buffer with the pointers to key and value
This strategy takes the time required to dump a 10k items __NSDictionaryM from ~45s to <4s
Modified:
lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h
lldb/trunk/source/DataFormatters/NSDictionary.cpp
Modified: lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h?rev=178601&r1=178600&r2=178601&view=diff
==============================================================================
--- lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h (original)
+++ lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h Tue Apr 2 20:25:29 2013
@@ -322,9 +322,11 @@ namespace lldb_private {
private:
ExecutionContextRef m_exe_ctx_ref;
uint8_t m_ptr_size;
+ lldb::ByteOrder m_order;
DataDescriptor_32 *m_data_32;
DataDescriptor_64 *m_data_64;
lldb::addr_t m_data_ptr;
+ ClangASTType m_pair_type;
std::vector<DictionaryItemDescriptor> m_children;
};
@@ -378,8 +380,10 @@ namespace lldb_private {
private:
ExecutionContextRef m_exe_ctx_ref;
uint8_t m_ptr_size;
+ lldb::ByteOrder m_order;
DataDescriptor_32 *m_data_32;
DataDescriptor_64 *m_data_64;
+ ClangASTType m_pair_type;
std::vector<DictionaryItemDescriptor> m_children;
};
Modified: lldb/trunk/source/DataFormatters/NSDictionary.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/DataFormatters/NSDictionary.cpp?rev=178601&r1=178600&r2=178601&view=diff
==============================================================================
--- lldb/trunk/source/DataFormatters/NSDictionary.cpp (original)
+++ lldb/trunk/source/DataFormatters/NSDictionary.cpp Tue Apr 2 20:25:29 2013
@@ -25,6 +25,58 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
+static ClangASTType
+GetLLDBNSPairType (TargetSP target_sp)
+{
+ ClangASTType clang_type = ClangASTType();
+
+ ClangASTContext *target_ast_context = target_sp->GetScratchClangASTContext();
+
+ if (!target_ast_context)
+ return clang_type;
+
+ const char* type_name = "__lldb_autogen_nspair";
+
+ clang::IdentifierInfo &myIdent = target_ast_context->getASTContext()->Idents.get(type_name);
+ clang::DeclarationName myName = target_ast_context->getASTContext()->DeclarationNames.getIdentifier(&myIdent);
+
+ clang::DeclContext::lookup_const_result result = target_ast_context->getASTContext()->getTranslationUnitDecl()->lookup(myName);
+
+ clang_type_t opaque_type = NULL;
+
+ for (clang::NamedDecl *named_decl : result)
+ {
+ if (const clang::CXXRecordDecl *record_decl = llvm::dyn_cast<clang::CXXRecordDecl>(named_decl))
+ {
+ opaque_type = clang::QualType(record_decl->getTypeForDecl(), 0).getAsOpaquePtr();
+ break;
+ }
+ else
+ {
+ // somebody else (the user?) has defined a type with the magic name already - fail!!!
+ return clang_type;
+ }
+ }
+
+ if (!opaque_type)
+ {
+ opaque_type = target_ast_context->CreateRecordType(NULL, lldb::eAccessPublic, type_name, clang::TTK_Struct, lldb::eLanguageTypeC);
+
+ if (!opaque_type)
+ return clang_type;
+
+ target_ast_context->StartTagDeclarationDefinition(opaque_type);
+
+ target_ast_context->AddFieldToRecordType(opaque_type, "key", target_ast_context->GetBuiltInType_objc_id(), lldb::eAccessPublic, 0);
+ target_ast_context->AddFieldToRecordType(opaque_type, "value", target_ast_context->GetBuiltInType_objc_id(), lldb::eAccessPublic, 0);
+
+ target_ast_context->CompleteTagDeclarationDefinition(opaque_type);
+ }
+
+ clang_type.SetClangType(target_ast_context->getASTContext(), opaque_type);
+ return clang_type;
+}
+
template<bool name_entries>
bool
lldb_private::formatters::NSDictionarySummaryProvider (ValueObject& valobj, Stream& stream)
@@ -196,8 +248,10 @@ lldb_private::formatters::NSDictionaryIS
SyntheticChildrenFrontEnd(*valobj_sp.get()),
m_exe_ctx_ref(),
m_ptr_size(8),
+m_order(lldb::eByteOrderInvalid),
m_data_32(NULL),
-m_data_64(NULL)
+m_data_64(NULL),
+m_pair_type()
{
if (valobj_sp)
Update();
@@ -256,6 +310,7 @@ lldb_private::formatters::NSDictionaryIS
if (!process_sp)
return false;
m_ptr_size = process_sp->GetAddressByteSize();
+ m_order = process_sp->GetByteOrder();
uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
if (m_ptr_size == 4)
{
@@ -328,12 +383,35 @@ lldb_private::formatters::NSDictionaryIS
DictionaryItemDescriptor &dict_item = m_children[idx];
if (!dict_item.valobj_sp)
{
- // make the new ValueObject
- StreamString expr;
- expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = (id)%" PRIu64 " ; _lldb_valgen_item.value = (id)%" PRIu64 "; _lldb_valgen_item;",dict_item.key_ptr,dict_item.val_ptr);
+ if (!m_pair_type.IsValid())
+ {
+ TargetSP target_sp(m_backend.GetTargetSP());
+ if (!target_sp)
+ return ValueObjectSP();
+ m_pair_type = GetLLDBNSPairType(target_sp);
+ }
+ if (!m_pair_type.IsValid())
+ return ValueObjectSP();
+
+ DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0));
+
+ if (m_ptr_size == 8)
+ {
+ uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
+ *data_ptr = dict_item.key_ptr;
+ *(data_ptr+1) = dict_item.val_ptr;
+ }
+ else
+ {
+ uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
+ *data_ptr = dict_item.key_ptr;
+ *(data_ptr+1) = dict_item.val_ptr;
+ }
+
StreamString idx_name;
idx_name.Printf("[%zu]",idx);
- dict_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
+ DataExtractor data(buffer_sp, m_order, m_ptr_size);
+ dict_item.valobj_sp = ValueObject::CreateValueObjectFromData(idx_name.GetData(), data, m_exe_ctx_ref, m_pair_type);
}
return dict_item.valobj_sp;
}
@@ -342,8 +420,10 @@ lldb_private::formatters::NSDictionaryMS
SyntheticChildrenFrontEnd(*valobj_sp.get()),
m_exe_ctx_ref(),
m_ptr_size(8),
+m_order(lldb::eByteOrderInvalid),
m_data_32(NULL),
-m_data_64(NULL)
+m_data_64(NULL),
+m_pair_type()
{
if (valobj_sp)
Update ();
@@ -402,6 +482,7 @@ lldb_private::formatters::NSDictionaryMS
if (!process_sp)
return false;
m_ptr_size = process_sp->GetAddressByteSize();
+ m_order = process_sp->GetByteOrder();
uint64_t data_location = valobj_sp->GetAddressOf() + m_ptr_size;
if (m_ptr_size == 4)
{
@@ -476,12 +557,35 @@ lldb_private::formatters::NSDictionaryMS
DictionaryItemDescriptor &dict_item = m_children[idx];
if (!dict_item.valobj_sp)
{
- // make the new ValueObject
- StreamString expr;
- expr.Printf("struct __lldb_autogen_nspair { id key; id value; } _lldb_valgen_item; _lldb_valgen_item.key = (id)%" PRIu64 " ; _lldb_valgen_item.value = (id)%" PRIu64 "; _lldb_valgen_item;",dict_item.key_ptr,dict_item.val_ptr);
+ if (!m_pair_type.IsValid())
+ {
+ TargetSP target_sp(m_backend.GetTargetSP());
+ if (!target_sp)
+ return ValueObjectSP();
+ m_pair_type = GetLLDBNSPairType(target_sp);
+ }
+ if (!m_pair_type.IsValid())
+ return ValueObjectSP();
+
+ DataBufferSP buffer_sp(new DataBufferHeap(2*m_ptr_size,0));
+
+ if (m_ptr_size == 8)
+ {
+ uint64_t *data_ptr = (uint64_t *)buffer_sp->GetBytes();
+ *data_ptr = dict_item.key_ptr;
+ *(data_ptr+1) = dict_item.val_ptr;
+ }
+ else
+ {
+ uint32_t *data_ptr = (uint32_t *)buffer_sp->GetBytes();
+ *data_ptr = dict_item.key_ptr;
+ *(data_ptr+1) = dict_item.val_ptr;
+ }
+
StreamString idx_name;
idx_name.Printf("[%zu]",idx);
- dict_item.valobj_sp = ValueObject::CreateValueObjectFromExpression(idx_name.GetData(), expr.GetData(), m_exe_ctx_ref);
+ DataExtractor data(buffer_sp, m_order, m_ptr_size);
+ dict_item.valobj_sp = ValueObject::CreateValueObjectFromData(idx_name.GetData(), data, m_exe_ctx_ref, m_pair_type);
}
return dict_item.valobj_sp;
}
More information about the lldb-commits
mailing list