[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