Fixes for performance to data formatters - Python < 3.0 is much slower when using True/False as compared to 1/0 for logical values. Wexploit this to our advantage. Other minor tweaks

llvm-svn: 157209
This commit is contained in:
Enrico Granata 2012-05-21 21:52:38 +00:00
parent 0259e51287
commit 7c015e1020
1 changed files with 110 additions and 114 deletions

View File

@ -21,19 +21,19 @@ class Utilities:
content = process.ReadCStringFromMemory(pointer,max_len,error)
except:
pass
if content == None or len(content) == 0 or error.fail == True:
if content is None or len(content) == 0 or error.fail:
return None
return content
@staticmethod
def is_valid_pointer(pointer, pointer_size, allow_tagged=False, allow_NULL=False):
def is_valid_pointer(pointer, pointer_size, allow_tagged=0, allow_NULL=0):
logger = lldb.formatters.Logger.Logger()
if pointer == None:
return False
if pointer is None:
return 0
if pointer == 0:
return allow_NULL
if allow_tagged and (pointer % 2) == 1:
return True
return 1
return ((pointer % pointer_size) == 0)
# Objective-C runtime has a rule that pointers in a class_t will only have bits 0 thru 46 set
@ -41,15 +41,17 @@ class Utilities:
@staticmethod
def is_allowed_pointer(pointer):
logger = lldb.formatters.Logger.Logger()
if pointer == None:
return False
if pointer is None:
return 0
return ((pointer & 0xFFFF800000000000) == 0)
@staticmethod
def read_child_of(valobj,offset,type):
logger = lldb.formatters.Logger.Logger()
if offset == 0 and type.GetByteSize() == valobj.GetByteSize():
return valobj.GetValueAsUnsigned()
child = valobj.CreateChildAtOffset("childUNK",offset,type)
if child == None or child.IsValid() == False:
if child is None or child.IsValid() == 0:
return None;
return child.GetValueAsUnsigned()
@ -74,10 +76,10 @@ class Utilities:
# assume the only thing that has a Foundation.framework is a Mac
# assume anything < Lion does not even exist
mod = target.module['Foundation']
if mod == None or mod.IsValid() == False:
if mod is None or mod.IsValid() == 0:
return None
ver = mod.GetVersion()
if ver == None or ver == []:
if ver is None or ver == []:
return None
return (ver[0] < 900)
@ -88,18 +90,18 @@ class Utilities:
def prepare_class_detection(valobj,statistics):
logger = lldb.formatters.Logger.Logger()
class_data = ObjCRuntime(valobj)
if class_data.is_valid() == False:
if class_data.is_valid() == 0:
statistics.metric_hit('invalid_pointer',valobj)
wrapper = InvalidPointer_Description(valobj.GetValueAsUnsigned(0) == 0)
return class_data,wrapper
class_data = class_data.read_class_data()
if class_data.is_valid() == False:
if class_data.is_valid() == 0:
statistics.metric_hit('invalid_isa',valobj)
wrapper = InvalidISA_Description()
return class_data,wrapper
if class_data.is_kvo():
class_data = class_data.get_superclass()
if class_data.is_valid() == False:
if class_data.is_valid() == 0:
statistics.metric_hit('invalid_isa',valobj)
wrapper = InvalidISA_Description()
return class_data,wrapper
@ -109,7 +111,7 @@ class Utilities:
class RoT_Data:
def __init__(self,rot_pointer,params):
logger = lldb.formatters.Logger.Logger()
if (Utilities.is_valid_pointer(rot_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=False)):
if (Utilities.is_valid_pointer(rot_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
self.sys_params = params
self.valobj = rot_pointer
#self.flags = Utilities.read_child_of(self.valobj,0,self.sys_params.uint32_t)
@ -118,22 +120,22 @@ class RoT_Data:
offset = 24 if self.sys_params.is_64_bit else 16
#self.ivarLayoutPtr = Utilities.read_child_of(self.valobj,offset,self.sys_params.addr_ptr_type)
self.namePointer = Utilities.read_child_of(self.valobj,offset,self.sys_params.types_cache.addr_ptr_type)
self.check_valid()
self.valid = 1 # self.check_valid()
else:
logger >> "Marking as invalid - rot is invalid"
self.valid = False
self.valid = 0
if self.valid:
self.name = Utilities.read_ascii(self.valobj.GetTarget().GetProcess(),self.namePointer)
if not(Utilities.is_valid_identifier(self.name)):
logger >> "Marking as invalid - name is invalid"
self.valid = False
self.valid = 0
# perform sanity checks on the contents of this class_ro_t
def check_valid(self):
self.valid = True
self.valid = 1
# misaligned pointers seem to be possible for this field
#if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=False)):
# self.valid = False
#if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=0)):
# self.valid = 0
# pass
def __str__(self):
@ -145,14 +147,14 @@ class RoT_Data:
def is_valid(self):
return self.valid
def instance_size(self,align=False):
def instance_size(self,align=0):
logger = lldb.formatters.Logger.Logger()
if self.is_valid() == False:
if self.is_valid() == 0:
return None
if self.instanceSize == None:
if self.instanceSize is None:
self.instanceSize = Utilities.read_child_of(self.valobj,8,self.sys_params.types_cache.uint32_t)
if align:
unalign = self.instance_size(False)
unalign = self.instance_size(0)
if self.sys_params.is_64_bit:
return ((unalign + 7) & ~7) % 0x100000000
else:
@ -163,7 +165,7 @@ class RoT_Data:
class RwT_Data:
def __init__(self,rwt_pointer,params):
logger = lldb.formatters.Logger.Logger()
if (Utilities.is_valid_pointer(rwt_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=False)):
if (Utilities.is_valid_pointer(rwt_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
self.sys_params = params
self.valobj = rwt_pointer
#self.flags = Utilities.read_child_of(self.valobj,0,self.sys_params.uint32_t)
@ -172,7 +174,7 @@ class RwT_Data:
self.check_valid()
else:
logger >> "Marking as invalid - rwt is invald"
self.valid = False
self.valid = 0
if self.valid:
self.rot = self.valobj.CreateValueFromData("rot",lldb.SBData.CreateDataFromUInt64Array(self.sys_params.endianness, self.sys_params.pointer_size, [self.roPointer]),self.sys_params.types_cache.addr_ptr_type)
# self.rot = self.valobj.CreateValueFromAddress("rot",self.roPointer,self.sys_params.types_cache.addr_ptr_type).AddressOf()
@ -181,10 +183,10 @@ class RwT_Data:
# perform sanity checks on the contents of this class_rw_t
def check_valid(self):
logger = lldb.formatters.Logger.Logger()
self.valid = True
if not(Utilities.is_valid_pointer(self.roPointer,self.sys_params.pointer_size,allow_tagged=False)):
self.valid = 1
if not(Utilities.is_valid_pointer(self.roPointer,self.sys_params.pointer_size,allow_tagged=0)):
logger >> "Marking as invalid - ropointer is invalid"
self.valid = False
self.valid = 0
def __str__(self):
logger = lldb.formatters.Logger.Logger()
@ -195,18 +197,18 @@ class RwT_Data:
logger = lldb.formatters.Logger.Logger()
if self.valid:
return self.data.is_valid()
return False
return 0
class Class_Data_V2:
def __init__(self,isa_pointer,params):
logger = lldb.formatters.Logger.Logger()
if (isa_pointer != None) and (Utilities.is_valid_pointer(isa_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=False)):
if (isa_pointer != None) and (Utilities.is_valid_pointer(isa_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
self.sys_params = params
self.valobj = isa_pointer
self.check_valid()
else:
logger >> "Marking as invalid - isa is invalid or None"
self.valid = False
self.valid = 0
if self.valid:
self.rwt = self.valobj.CreateValueFromData("rwt",lldb.SBData.CreateDataFromUInt64Array(self.sys_params.endianness, self.sys_params.pointer_size, [self.dataPointer]),self.sys_params.types_cache.addr_ptr_type)
# self.rwt = self.valobj.CreateValueFromAddress("rwt",self.dataPointer,self.sys_params.types_cache.addr_ptr_type).AddressOf()
@ -217,56 +219,56 @@ class Class_Data_V2:
# that we have an invalid object, we stop reading
def check_valid(self):
logger = lldb.formatters.Logger.Logger()
self.valid = True
self.valid = 1
self.isaPointer = Utilities.read_child_of(self.valobj,0,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.isaPointer,self.sys_params.pointer_size,allow_tagged=False)):
if not(Utilities.is_valid_pointer(self.isaPointer,self.sys_params.pointer_size,allow_tagged=0)):
logger >> "Marking as invalid - isaPointer is invalid"
self.valid = False
self.valid = 0
return
if not(Utilities.is_allowed_pointer(self.isaPointer)):
logger >> "Marking as invalid - isaPointer is not allowed"
self.valid = False
self.valid = 0
return
self.cachePointer = Utilities.read_child_of(self.valobj,2*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.cachePointer,self.sys_params.pointer_size,allow_tagged=False)):
if not(Utilities.is_valid_pointer(self.cachePointer,self.sys_params.pointer_size,allow_tagged=0)):
logger >> "Marking as invalid - cachePointer is invalid"
self.valid = False
self.valid = 0
return
if not(Utilities.is_allowed_pointer(self.cachePointer)):
logger >> "Marking as invalid - cachePointer is not allowed"
self.valid = False
self.valid = 0
return
self.vtablePointer = Utilities.read_child_of(self.valobj,3*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.vtablePointer,self.sys_params.pointer_size,allow_tagged=False)):
if not(Utilities.is_valid_pointer(self.vtablePointer,self.sys_params.pointer_size,allow_tagged=0)):
logger >> "Marking as invalid - vtablePointer is invalid"
self.valid = False
self.valid = 0
return
if not(Utilities.is_allowed_pointer(self.vtablePointer)):
logger >> "Marking as invalid - vtablePointer is not allowed"
self.valid = False
self.valid = 0
return
self.dataPointer = Utilities.read_child_of(self.valobj,4*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.dataPointer,self.sys_params.pointer_size,allow_tagged=False)):
if not(Utilities.is_valid_pointer(self.dataPointer,self.sys_params.pointer_size,allow_tagged=0)):
logger >> "Marking as invalid - dataPointer is invalid"
self.valid = False
self.valid = 0
return
if not(Utilities.is_allowed_pointer(self.dataPointer)):
logger >> "Marking as invalid - dataPointer is not allowed"
self.valid = False
self.valid = 0
return
self.superclassIsaPointer = Utilities.read_child_of(self.valobj,1*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.superclassIsaPointer,self.sys_params.pointer_size,allow_tagged=False, allow_NULL=True)):
if not(Utilities.is_valid_pointer(self.superclassIsaPointer,self.sys_params.pointer_size,allow_tagged=0, allow_NULL=1)):
logger >> "Marking as invalid - superclassIsa is invalid"
self.valid = False
self.valid = 0
return
if not(Utilities.is_allowed_pointer(self.superclassIsaPointer)):
logger >> "Marking as invalid - superclassIsa is not allowed"
self.valid = False
self.valid = 0
return
# in general, KVO is implemented by transparently subclassing
@ -277,8 +279,8 @@ class Class_Data_V2:
logger = lldb.formatters.Logger.Logger()
if self.is_valid():
if self.class_name().startswith("NSKVONotifying_"):
return True
return False
return 1
return 0
# some CF classes have a valid ObjC isa in their CFRuntimeBase
# but instead of being class-specific this isa points to a match-'em-all class
@ -310,7 +312,7 @@ class Class_Data_V2:
logger = lldb.formatters.Logger.Logger()
if self.valid:
return self.data.is_valid()
return False
return 0
def __str__(self):
logger = lldb.formatters.Logger.Logger()
@ -321,11 +323,11 @@ class Class_Data_V2:
"data = " + hex(self.dataPointer)
def is_tagged(self):
return False
return 0
def instance_size(self,align=False):
def instance_size(self,align=0):
logger = lldb.formatters.Logger.Logger()
if self.is_valid() == False:
if self.is_valid() == 0:
return None
return self.rwt.rot.instance_size(align)
@ -333,40 +335,40 @@ class Class_Data_V2:
class Class_Data_V1:
def __init__(self,isa_pointer,params):
logger = lldb.formatters.Logger.Logger()
if (isa_pointer != None) and (Utilities.is_valid_pointer(isa_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=False)):
self.valid = True
if (isa_pointer != None) and (Utilities.is_valid_pointer(isa_pointer.GetValueAsUnsigned(),params.pointer_size, allow_tagged=0)):
self.valid = 1
self.sys_params = params
self.valobj = isa_pointer
self.check_valid()
else:
logger >> "Marking as invalid - isaPointer is invalid or None"
self.valid = False
self.valid = 0
if self.valid:
self.name = Utilities.read_ascii(self.valobj.GetTarget().GetProcess(),self.namePointer)
if not(Utilities.is_valid_identifier(self.name)):
logger >> "Marking as invalid - name is not valid"
self.valid = False
self.valid = 0
# perform sanity checks on the contents of this class_t
def check_valid(self):
logger = lldb.formatters.Logger.Logger()
self.valid = True
self.valid = 1
self.isaPointer = Utilities.read_child_of(self.valobj,0,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.isaPointer,self.sys_params.pointer_size,allow_tagged=False)):
if not(Utilities.is_valid_pointer(self.isaPointer,self.sys_params.pointer_size,allow_tagged=0)):
logger >> "Marking as invalid - isaPointer is invalid"
self.valid = False
self.valid = 0
return
self.superclassIsaPointer = Utilities.read_child_of(self.valobj,1*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
if not(Utilities.is_valid_pointer(self.superclassIsaPointer,self.sys_params.pointer_size,allow_tagged=False,allow_NULL=True)):
if not(Utilities.is_valid_pointer(self.superclassIsaPointer,self.sys_params.pointer_size,allow_tagged=0,allow_NULL=1)):
logger >> "Marking as invalid - superclassIsa is invalid"
self.valid = False
self.valid = 0
return
self.namePointer = Utilities.read_child_of(self.valobj,2*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
#if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=False,allow_NULL=False)):
# self.valid = False
#if not(Utilities.is_valid_pointer(self.namePointer,self.sys_params.pointer_size,allow_tagged=0,allow_NULL=0)):
# self.valid = 0
# return
# in general, KVO is implemented by transparently subclassing
@ -377,8 +379,8 @@ class Class_Data_V1:
logger = lldb.formatters.Logger.Logger()
if self.is_valid():
if self.class_name().startswith("NSKVONotifying_"):
return True
return False
return 1
return 0
# some CF classes have a valid ObjC isa in their CFRuntimeBase
# but instead of being class-specific this isa points to a match-'em-all class
@ -417,16 +419,16 @@ class Class_Data_V1:
"instanceSize = " + hex(self.instanceSize()) + "\n"
def is_tagged(self):
return False
return 0
def instance_size(self,align=False):
def instance_size(self,align=0):
logger = lldb.formatters.Logger.Logger()
if self.is_valid() == False:
if self.is_valid() == 0:
return None
if self.instanceSize == None:
if self.instanceSize is None:
self.instanceSize = Utilities.read_child_of(self.valobj,5*self.sys_params.pointer_size,self.sys_params.types_cache.addr_ptr_type)
if align:
unalign = self.instance_size(False)
unalign = self.instance_size(0)
if self.sys_params.is_64_bit:
return ((unalign + 7) & ~7) % 0x100000000
else:
@ -452,7 +454,7 @@ class TaggedClass_Data:
def __init__(self,pointer,params):
logger = lldb.formatters.Logger.Logger()
global TaggedClass_Values_Lion,TaggedClass_Values_NMOS
self.valid = True
self.valid = 1
self.name = None
self.sys_params = params
self.valobj = pointer
@ -465,13 +467,13 @@ class TaggedClass_Data:
self.name = TaggedClass_Values_Lion[self.class_bits]
else:
logger >> "Marking as invalid - not a good tagged pointer for Lion"
self.valid = False
self.valid = 0
else:
if self.class_bits in TaggedClass_Values_NMOS:
self.name = TaggedClass_Values_NMOS[self.class_bits]
else:
logger >> "Marking as invalid - not a good tagged pointer for NMOS"
self.valid = False
self.valid = 0
def is_valid(self):
@ -482,7 +484,7 @@ class TaggedClass_Data:
if self.is_valid():
return self.name
else:
return False
return 0
def value(self):
return self.val if self.is_valid() else None
@ -491,10 +493,10 @@ class TaggedClass_Data:
return self.i_bits if self.is_valid() else None
def is_kvo(self):
return False
return 0
def is_cftype(self):
return False
return 0
# we would need to go around looking for the superclass or ask the runtime
# for now, we seem not to require support for this operation so we will merrily
@ -504,12 +506,12 @@ class TaggedClass_Data:
# anything that is handled here is tagged
def is_tagged(self):
return True
return 1
# it seems reasonable to say that a tagged pointer is the size of a pointer
def instance_size(self,align=False):
def instance_size(self,align=0):
logger = lldb.formatters.Logger.Logger()
if self.is_valid() == False:
if self.is_valid() == 0:
return None
return self.sys_params.pointer_size
@ -518,7 +520,7 @@ class InvalidClass_Data:
def __init__(self):
pass
def is_valid(self):
return False
return 0
@functools.total_ordering
class Version:
@ -544,14 +546,14 @@ class Version:
def __lt__(self,other):
if (self.major < other.major):
return True
return 1
if (self.minor < other.minor):
return True
return 1
if (self.release < other.release):
return True
return 1
# build strings are not compared since they are heavily platform-dependent and might not always
# be available
return False
return 0
def __eq__(self,other):
return (self.major == other.major) and \
@ -595,7 +597,7 @@ class SystemParameters:
if types_caches.look_for_key(self.pid):
self.types_cache = types_caches.get_value(self.pid)
else:
self.types_cache = lldb.formatters.attrib_fromdict.AttributesDictionary(allow_reset=False)
self.types_cache = lldb.formatters.attrib_fromdict.AttributesDictionary(allow_reset=0)
self.types_cache.addr_type = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
self.types_cache.addr_ptr_type = self.types_cache.addr_type.GetPointerType()
self.types_cache.uint32_t = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
@ -632,7 +634,7 @@ class ObjCRuntime:
@staticmethod
def runtime_version(process):
logger = lldb.formatters.Logger.Logger()
if process.IsValid() == False:
if process.IsValid() == 0:
logger >> "No process - bailing out"
return None
target = process.GetTarget()
@ -643,7 +645,7 @@ class ObjCRuntime:
if module.GetFileSpec().GetFilename() == 'libobjc.A.dylib':
module_objc = module
break
if module_objc == None or module_objc.IsValid() == False:
if module_objc is None or module_objc.IsValid() == 0:
logger >> "no libobjc - bailing out"
return None
num_sections = module.GetNumSections()
@ -681,17 +683,17 @@ class ObjCRuntime:
def is_tagged(self):
logger = lldb.formatters.Logger.Logger()
if self.valobj is None:
return False
return (Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=True) and \
not(Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=False)))
return 0
return (Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=1) and \
not(Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=0)))
def is_valid(self):
logger = lldb.formatters.Logger.Logger()
if self.valobj is None:
return False
if self.valobj.IsInScope() == False:
return False
return Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=True)
return 0
if self.valobj.IsInScope() == 0:
return 0
return Utilities.is_valid_pointer(self.unsigned_value,self.sys_params.pointer_size, allow_tagged=1)
def is_nil(self):
return self.unsigned_value == 0
@ -701,17 +703,17 @@ class ObjCRuntime:
if self.isa_value != None:
logger >> "using cached isa"
return self.isa_value
isa_pointer = self.valobj.CreateChildAtOffset("cfisa",
self.isa_pointer = self.valobj.CreateChildAtOffset("cfisa",
0,
self.sys_params.types_cache.addr_ptr_type)
if isa_pointer == None or isa_pointer.IsValid() == False:
if self.isa_pointer is None or self.isa_pointer.IsValid() == 0:
logger >> "invalid isa - bailing out"
return None;
if isa_pointer.GetValueAsUnsigned(1) == 1:
self.isa_value = self.isa_pointer.GetValueAsUnsigned(1)
if self.isa_value == 1:
logger >> "invalid isa value - bailing out"
return None;
self.isa_value = isa_pointer
return isa_pointer
return Ellipsis
def read_class_data(self):
logger = lldb.formatters.Logger.Logger()
@ -733,25 +735,19 @@ class ObjCRuntime:
else:
logger >> "on v1 and tagged - error"
return InvalidClass_Data()
if self.is_valid() == False:
if self.is_valid() == 0 or self.read_isa() is None:
return InvalidClass_Data()
isa = self.read_isa()
if isa == None:
return InvalidClass_Data()
isa_value = isa.GetValueAsUnsigned(1)
if isa_value == 1:
return InvalidClass_Data()
data = self.sys_params.isa_cache.get_value(isa_value,default=None)
data = self.sys_params.isa_cache.get_value(self.isa_value,default=None)
if data != None:
return data
if self.sys_params.runtime_version == 2:
data = Class_Data_V2(isa,self.sys_params)
data = Class_Data_V2(self.isa_pointer,self.sys_params)
else:
data = Class_Data_V1(isa,self.sys_params)
if data == None:
data = Class_Data_V1(self.isa_pointer,self.sys_params)
if data is None:
return InvalidClass_Data()
if data.is_valid():
self.sys_params.isa_cache.add_item(isa_value,data,ok_to_replace=True)
self.sys_params.isa_cache.add_item(self.isa_value,data,ok_to_replace=1)
return data
# these classes below can be used by the data formatters to provide a consistent message that describes a given runtime-generated situation