Xcode often gets in a state where the debugger is completely unresponsive
authorjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Jul 2013 17:28:43 +0000 (17:28 +0000)
committerjer.noble@apple.com <jer.noble@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 3 Jul 2013 17:28:43 +0000 (17:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=118157

The GetPointeeData() operations we use to retrieve strings is extremely expensive.
Rather than pull the character data out of the debugger one byte at a time
through the GetPointeeData() API, retrieve the memory contents of the string through
the ReadMemory() API, and convert the retrieved memory into a python string.

Reviewed by Anders Carlsson.

* lldb/lldb_webkit.py:
(__lldb_init_module.lldb_webkit):
(guess_string_length):
(ustring_to_string):
(lstring_to_string):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@152366 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/lldb/lldb_webkit.py

index 201ff8c..518bcef 100644 (file)
@@ -1,3 +1,21 @@
+2013-07-03  Jer Noble  <jer.noble@apple.com>
+
+        Xcode often gets in a state where the debugger is completely unresponsive
+        https://bugs.webkit.org/show_bug.cgi?id=118157
+
+        The GetPointeeData() operations we use to retrieve strings is extremely expensive.
+        Rather than pull the character data out of the debugger one byte at a time
+        through the GetPointeeData() API, retrieve the memory contents of the string through
+        the ReadMemory() API, and convert the retrieved memory into a python string.
+
+        Reviewed by Anders Carlsson.
+
+        * lldb/lldb_webkit.py:
+        (__lldb_init_module.lldb_webkit):
+        (guess_string_length):
+        (ustring_to_string):
+        (lstring_to_string):
+
 2013-07-03  Morten Stenshorne  <mstensho@opera.com>
 
         [GTK] Let F5 refresh the page in MiniBrowser
index aac3da6..7fb3158 100644 (file)
@@ -30,7 +30,7 @@
 """
 
 import lldb
-
+import struct
 
 def __lldb_init_module(debugger, dict):
     debugger.HandleCommand('type summary add --expand -F lldb_webkit.WTFString_SummaryProvider WTF::String')
@@ -41,7 +41,6 @@ def __lldb_init_module(debugger, dict):
     debugger.HandleCommand('type synthetic add -x "WTF::Vector<.+>$" --python-class lldb_webkit.WTFVectorProvider')
     debugger.HandleCommand('type synthetic add -x "WTF::HashTable<.+>$" --python-class lldb_webkit.WTFHashTableProvider')
 
-
 def WTFString_SummaryProvider(valobj, dict):
     provider = WTFStringProvider(valobj, dict)
     return "{ length = %d, contents = '%s' }" % (provider.get_length(), provider.to_string())
@@ -74,44 +73,55 @@ def WTFHashTable_SummaryProvider(valobj, dict):
 # def JSCJSString_SummaryProvider(valobj, dict):
 
 
-def guess_string_length(valobj, error):
+def guess_string_length(valobj, charSize, error):
     if not valobj.GetValue():
         return 0
 
-    for i in xrange(0, 2048):
-        if valobj.GetPointeeData(i, 1).GetUnsignedInt16(error, 0) == 0:
-            return i
+    maxLength = 256
 
-    return 256
+    pointer = valobj.GetValueAsUnsigned()
+    contents = valobj.GetProcess().ReadMemory(pointer, maxLength * charSize, lldb.SBError())
+    format = 'B' if charSize == 1 else 'H'
 
+    for i in xrange(0, maxLength):
+        if not struct.unpack_from(format, contents, i * charSize)[0]:
+            return i
+
+    return maxLength
 
 def ustring_to_string(valobj, error, length=None):
     if length is None:
-        length = guess_string_length(valobj, error)
+        length = guess_string_length(valobj, 2, error)
     else:
         length = int(length)
 
-    out_string = u""
-    for i in xrange(0, length):
-        char_value = valobj.GetPointeeData(i, 1).GetUnsignedInt16(error, 0)
-        out_string = out_string + unichr(char_value)
-
-    return out_string.encode('utf-8')
+    pointer = valobj.GetValueAsUnsigned()
+    contents = valobj.GetProcess().ReadMemory(pointer, length * 2, lldb.SBError())
 
+    # lldb does not (currently) support returning unicode from python summary providers,
+    # so potentially convert this to ascii by escaping
+    string = contents.decode('utf16')
+    try:
+        return str(string)
+    except:
+        return string.encode('unicode_escape')
 
 def lstring_to_string(valobj, error, length=None):
     if length is None:
-        length = guess_string_length(valobj, error)
+        length = guess_string_length(valobj, 1, error)
     else:
         length = int(length)
 
-    out_string = u""
-    for i in xrange(0, length):
-        char_value = valobj.GetPointeeData(i, 1).GetUnsignedInt8(error, 0)
-        out_string = out_string + unichr(char_value)
-
-    return out_string.encode('utf-8')
+    pointer = valobj.GetValueAsUnsigned()
+    contents = valobj.GetProcess().ReadMemory(pointer, length, lldb.SBError())
 
+    # lldb does not (currently) support returning unicode from python summary providers,
+    # so potentially convert this to ascii by escaping
+    string = contents.decode('utf8')
+    try:
+        return str(string)
+    except:
+        return string.encode('unicode_escape')
 
 class WTFStringImplProvider:
     def __init__(self, valobj, dict):