summaryrefslogtreecommitdiffstats
path: root/lldb/examples/summaries/cocoa/CFArray.py
diff options
context:
space:
mode:
authorEnrico Granata <egranata@apple.com>2012-03-05 19:56:33 +0000
committerEnrico Granata <egranata@apple.com>2012-03-05 19:56:33 +0000
commitcfdafa37b4d3552268a92d7dfd107ed92d3dca51 (patch)
tree92e111d6a1450a643d22c851f599a0e4e3a567ae /lldb/examples/summaries/cocoa/CFArray.py
parent35e2ab60397ec15d9a2ce31ad71614ecc62f34b6 (diff)
downloadbcm5719-llvm-cfdafa37b4d3552268a92d7dfd107ed92d3dca51.tar.gz
bcm5719-llvm-cfdafa37b4d3552268a92d7dfd107ed92d3dca51.zip
Several performance-oriented changes to the introspecting data formatters:
(a) the SystemParameters object is now passed around to the formatters; doing so enables the formatters to reuse computed values for things such as pointer-size and endianness instead of repeatedly computing these on their own (b) replacing the global ISA cache with a per-process one (c) providing a per-process types cache where each formatter can store the types it needs to operate, and be sure to find them the next time without recalculating them this also enables formatters to share types if they agree on a local naming convention (d) lazy fetching of data from Objective-C runtime data structures data is fetched as needed and we stop reading as soon as we determine that an ISA is actually garbage llvm-svn: 152052
Diffstat (limited to 'lldb/examples/summaries/cocoa/CFArray.py')
-rw-r--r--lldb/examples/summaries/cocoa/CFArray.py215
1 files changed, 33 insertions, 182 deletions
diff --git a/lldb/examples/summaries/cocoa/CFArray.py b/lldb/examples/summaries/cocoa/CFArray.py
index 4545a1b2370..0721e76b9f8 100644
--- a/lldb/examples/summaries/cocoa/CFArray.py
+++ b/lldb/examples/summaries/cocoa/CFArray.py
@@ -16,17 +16,14 @@ statistics.add_metric('code_notrun')
class NSArrayKVC_SynthProvider:
def adjust_for_architecture(self):
- self.is_64_bit = (self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8)
- self.is_little = (self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle)
- self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize()
+ pass
- def __init__(self, valobj, dict):
+ def __init__(self, valobj, dict, params):
self.valobj = valobj;
self.update()
def update(self):
self.adjust_for_architecture();
- self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
def num_children(self):
stream = lldb.SBStream()
@@ -34,199 +31,78 @@ class NSArrayKVC_SynthProvider:
num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
return num_children_vo.GetValueAsUnsigned(0)
- def get_child_index(self,name):
- if name == "len":
- return self.num_children();
- else:
- return None
-
- def get_child_at_index(self, index):
- return None
-
-
-
# much less functional than the other two cases below
# just runs code to get to the count and then returns
# no children
class NSArrayCF_SynthProvider:
def adjust_for_architecture(self):
- self.is_64_bit = (self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8)
- self.is_little = (self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle)
- self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize()
- self.cfruntime_size = self.size_of_cfruntime_base()
-
- # CFRuntimeBase is defined as having an additional
- # 4 bytes (padding?) on LP64 architectures
- # to get its size we add up sizeof(pointer)+4
- # and then add 4 more bytes if we are on a 64bit system
- def size_of_cfruntime_base(self):
- if self.is_64_bit == True:
- return 8+4+4;
- else:
- return 4+4;
+ pass
- def __init__(self, valobj, dict):
+ def __init__(self, valobj, dict, params):
self.valobj = valobj;
+ self.sys_params = params
+ if not (self.sys_params.types_cache.ulong):
+ self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.update()
def update(self):
self.adjust_for_architecture();
- self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
def num_children(self):
num_children_vo = self.valobj.CreateChildAtOffset("count",
- self.cfruntime_size,
- self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong))
+ self.sys_params.cfruntime_size,
+ self.sys_params.types_cache.ulong)
return num_children_vo.GetValueAsUnsigned(0)
- def get_child_index(self,name):
- if name == "len":
- return self.num_children();
- else:
- return None
-
- def get_child_at_index(self, index):
- return None
-
-
class NSArrayI_SynthProvider:
-
def adjust_for_architecture(self):
- self.is_64_bit = (self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8)
- self.is_little = (self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle)
- self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize()
+ pass
- def __init__(self, valobj, dict):
+ def __init__(self, valobj, dict, params):
self.valobj = valobj;
+ self.sys_params = params
+ if not(self.sys_params.types_cache.long):
+ self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
self.update()
def update(self):
self.adjust_for_architecture();
- self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
# skip the isa pointer and get at the size
def num_children(self):
- offset = self.pointer_size;
- datatype = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
count = self.valobj.CreateChildAtOffset("count",
- offset,
- datatype);
- return int(count.GetValue(), 0)
-
- def get_child_index(self,name):
- if name == "len":
- return self.num_children();
- else:
- return int(name.lstrip('[').rstrip(']'), 0)
-
- def get_child_at_index(self, index):
- if index == self.num_children():
- return self.valobj.CreateValueFromExpression("len",
- str(index))
- offset = 2 * self.pointer_size + self.id_type.GetByteSize()*index
- return self.valobj.CreateChildAtOffset('[' + str(index) + ']',
- offset,
- self.id_type)
-
+ self.sys_params.pointer_size,
+ self.sys_params.types_cache.long);
+ return count.GetValueAsUnsigned(0)
class NSArrayM_SynthProvider:
-
def adjust_for_architecture(self):
- self.is_64_bit = (self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8)
- self.is_little = (self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle)
- self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize()
+ pass
- def __init__(self, valobj, dict):
+ def __init__(self, valobj, dict, params):
self.valobj = valobj;
- self.update();
+ self.sys_params = params
+ if not(self.sys_params.types_cache.long):
+ self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
+ self.update()
def update(self):
self.adjust_for_architecture();
- self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
# skip the isa pointer and get at the size
def num_children(self):
- offset = self.pointer_size;
- datatype = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
count = self.valobj.CreateChildAtOffset("count",
- offset,
- datatype);
- return int(count.GetValue(), 0)
-
- def get_child_index(self,name):
- if name == "len":
- return self.num_children();
- else:
- return int(name.lstrip('[').rstrip(']'), 0)
-
- def data_offset(self):
- offset = self.pointer_size; # isa
- offset += self.pointer_size; # _used
- offset += self.pointer_size; # _doHardRetain, _doWeakAccess, _size
- offset += self.pointer_size; # _hasObjects, _hasStrongReferences, _offset
- offset += self.pointer_size; # _mutations
- return offset;
-
- # the _offset field is used to calculate the actual offset
- # when reading a value out of the array. we need to read it
- # to do so we read a whole pointer_size of data from the
- # right spot, and then zero out the two LSB
- def read_offset_field(self):
- disp = self.pointer_size; # isa
- disp += self.pointer_size; # _used
- disp += self.pointer_size; # _doHardRetain, _doWeakAccess, _size
- offset = self.valobj.CreateChildAtOffset("offset",
- disp,
- self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong))
- offset_value = int(offset.GetValue(), 0)
- offset_value = ctypes.c_uint32((offset_value & 0xFFFFFFFC) >> 2).value
- return offset_value
-
- # the _used field tells how many items are in the array
- # but since this is a mutable array, it allocates more space
- # for performance reasons. we need to get the real _size of
- # the array to calculate the actual offset of each element
- # in get_child_at_index() (see NSArray.m for details)
- def read_size_field(self):
- disp = self.pointer_size; # isa
- disp += self.pointer_size; # _used
- size = self.valobj.CreateChildAtOffset("size",
- disp,
- self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong))
- size_value = int(size.GetValue(), 0)
- size_value = ctypes.c_uint32((size_value & 0xFFFFFFFA) >> 2).value
- return size_value
-
- def get_child_at_index(self, index):
- if index == self.num_children():
- return self.valobj.CreateValueFromExpression("len",
- str(index))
- size = self.read_size_field()
- offset = self.read_offset_field()
- phys_idx = offset + index
- if size <= phys_idx:
- phys_idx -=size;
- # we still need to multiply by element size to do a correct pointer read
- phys_idx *= self.id_type.GetByteSize()
- list_ptr = self.valobj.CreateChildAtOffset("_list",
- self.data_offset(),
- self.id_type.GetBasicType(lldb.eBasicTypeUnsignedLongLong))
- list_addr = int(list_ptr.GetValue(), 0)
- return self.valobj.CreateValueFromAddress('[' + str(index) + ']',
- list_addr + phys_idx,
- self.id_type)
+ self.sys_params.pointer_size,
+ self.sys_params.types_cache.long);
+ return count.GetValueAsUnsigned(0)
# this is the actual synth provider, but is just a wrapper that checks
# whether valobj is an instance of __NSArrayI or __NSArrayM and sets up an
# appropriate backend layer to do the computations
class NSArray_SynthProvider:
-
def adjust_for_architecture(self):
- self.is_64_bit = (self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8)
- self.is_little = (self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle)
- self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize()
- self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
+ pass
def __init__(self, valobj, dict):
self.valobj = valobj;
@@ -234,16 +110,6 @@ class NSArray_SynthProvider:
self.wrapper = self.make_wrapper(valobj,dict)
self.invalid = (self.wrapper == None)
- def get_child_at_index(self, index):
- if self.wrapper == None:
- return None;
- return self.wrapper.get_child_at_index(index)
-
- def get_child_index(self,name):
- if self.wrapper == None:
- return None;
- return self.wrapper.get_child_index(name)
-
def num_children(self):
if self.wrapper == None:
return 0;
@@ -251,23 +117,8 @@ class NSArray_SynthProvider:
def update(self):
if self.wrapper == None:
- return None;
- return self.wrapper.update()
-
- def read_ascii(self, pointer):
- process = self.valobj.GetTarget().GetProcess()
- error = lldb.SBError()
- pystr = ''
- # cannot do the read at once because there is no length byte
- while True:
- content = process.ReadMemory(pointer, 1, error)
- new_bytes = bytearray(content)
- b0 = new_bytes[0]
- pointer = pointer + 1
- if b0 == 0:
- break
- pystr = pystr + chr(b0)
- return pystr
+ return
+ self.wrapper.update()
# this code acts as our defense against NULL and unitialized
# NSArray pointers, which makes it much longer than it would be otherwise
@@ -292,16 +143,16 @@ class NSArray_SynthProvider:
name_string = class_data.class_name()
if name_string == '__NSArrayI':
- wrapper = NSArrayI_SynthProvider(valobj, dict)
+ wrapper = NSArrayI_SynthProvider(valobj, dict, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
elif name_string == '__NSArrayM':
- wrapper = NSArrayM_SynthProvider(valobj, dict)
+ wrapper = NSArrayM_SynthProvider(valobj, dict, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
elif name_string == '__NSCFArray':
- wrapper = NSArrayCF_SynthProvider(valobj, dict)
+ wrapper = NSArrayCF_SynthProvider(valobj, dict, class_data.sys_params)
statistics.metric_hit('code_notrun',valobj)
else:
- wrapper = NSArrayKVC_SynthProvider(valobj, dict)
+ wrapper = NSArrayKVC_SynthProvider(valobj, dict, class_data.sys_params)
statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
return wrapper;
OpenPOWER on IntegriCloud