Debugger: Reduce number of function calls in QLocale display

Change-Id: Ib186dafbee148b9c4aaf69124a3642404e16c002
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
hjk
2016-09-15 12:31:28 +02:00
committed by hjk
parent 0768ef7382
commit 1a9919a208
5 changed files with 123 additions and 36 deletions

View File

@@ -2518,7 +2518,7 @@ class DumperBase:
return return
if typeobj.isEnumType(): if typeobj.isEnumType():
#warn("ENUM VALUE: %s" % value) #warn("ENUM VALUE: %s" % value.stringify())
self.putType(typeobj.name) self.putType(typeobj.name)
self.putValue(value.display()) self.putValue(value.display())
self.putNumChild(0) self.putNumChild(0)
@@ -2651,24 +2651,22 @@ class DumperBase:
error("INCONSISTENT TYPE: %s" % type(self.type)) error("INCONSISTENT TYPE: %s" % type(self.type))
def __str__(self): def __str__(self):
#error("Not implemented")
return self.stringify()
def stringify(self):
self.check() self.check()
addr = "None" if self.laddress is None else ("0x%x" % self.laddress) addr = "None" if self.laddress is None else ("0x%x" % self.laddress)
#return self.display()
return "Value(name='%s',type=%s,data=%s,address=%s,nativeValue=%s)" \ return "Value(name='%s',type=%s,data=%s,address=%s,nativeValue=%s)" \
% (self.name, self.type, self.dumper.hexencode(self.ldata), % (self.name, self.type, self.dumper.hexencode(self.ldata),
addr, self.nativeValue) addr, self.nativeValue)
def display(self): def display(self):
if self.type.lEnumType:
return self.type.enumDisplay(self.extractInteger(self.type.size() * 8, False))
simple = self.value() simple = self.value()
if simple is not None: if simple is not None:
return str(simple) return str(simple)
if self.type.lEnumType:
if self.nativeValue is not None:
if self.dumper.isLldb:
return "%s (%d)" % (self.nativeValue.GetValue(), self.nativeValue.GetValueAsSigned())
else:
return "%s (%d)" % (self.nativeValue, self.nativeValue)
return self.integer()
if self.type.lComplexType: if self.type.lComplexType:
if self.nativeValue is not None: if self.nativeValue is not None:
if self.dumper.isLldb: if self.dumper.isLldb:
@@ -2854,6 +2852,19 @@ class DumperBase:
return val return val
error("BAD DATA TO DEREFERENCE: %s %s" % (self.type, type(self))) error("BAD DATA TO DEREFERENCE: %s %s" % (self.type, type(self)))
def extend(self, size):
if self.type.size() < size:
val = self.dumper.Value(self.dumper)
val.laddress = None
if sys.version_info[0] == 3:
val.ldata = self.ldata + bytes('\0' * (size - self.type.size()), encoding='latin1')
else:
val.ldata = self.ldata + bytes('\0' * (size - self.type.size()))
return val
if self.type.size() == size:
return self
error("NOT IMPLEMENTED")
def cast(self, typish): def cast(self, typish):
self.check() self.check()
typeobj = self.dumper.createType(typish) typeobj = self.dumper.createType(typish)
@@ -2886,7 +2897,14 @@ class DumperBase:
self.check() self.check()
if self.ldata is not None: if self.ldata is not None:
if len(self.ldata) > 0: if len(self.ldata) > 0:
return self.ldata if size is None:
return self.ldata
if size == len(self.ldata):
return self.ldata
if size < len(self.ldata):
return self.ldata[:size]
error("DATA PRESENT, BUT NOT BIG ENOUGH: %s WANT: %s"
% (self.stringify(), size))
if self.laddress is not None: if self.laddress is not None:
if size is None: if size is None:
size = self.type.size() size = self.type.size()
@@ -2918,7 +2936,12 @@ class DumperBase:
if code is None: if code is None:
return None return None
rawBytes = self.data(size) rawBytes = self.data(size)
return struct.unpack_from(code, rawBytes, 0)[0] try:
return struct.unpack_from(code, rawBytes, 0)[0]
except:
pass
error("Cannot extract: Code: %s Bytes: %s Bitsize: %s Size: %s"
% (code, self.dumper.hexencode(rawBytes), bitsize, size))
def extractSomething(self, code, bitsize): def extractSomething(self, code, bitsize):
self.check() self.check()
@@ -2984,6 +3007,11 @@ class DumperBase:
def __str__(self): def __str__(self):
self.check() self.check()
return self.name return self.name
#error("Not implemented")
def stringify(self):
return "Type(name='%s',bsize=%s,bpos=%s,enum=%s,native=%s)" \
% (self.name, self.lbitsize, self.lbitpos, self.lEnumType, self.nativeType is not None)
def __getitem__(self, index): def __getitem__(self, index):
if self.dumper.isInt(index): if self.dumper.isInt(index):
@@ -3202,6 +3230,11 @@ class DumperBase:
return True return True
return strippedName == "QStringList" and self.dumper.qtVersion() >= 0x050000 return strippedName == "QStringList" and self.dumper.qtVersion() >= 0x050000
def enumDisplay(self, intval):
if self.nativeType is not None:
return self.dumper.nativeTypeEnumDisplay(self.nativeType, intval)
return "%d" % intval
class Field: class Field:
def __init__(self, dumper): def __init__(self, dumper):
self.dumper = dumper self.dumper = dumper
@@ -3271,6 +3304,11 @@ class DumperBase:
typish.check() typish.check()
return typish return typish
if isinstance(typish, str): if isinstance(typish, str):
if typish.startswith("enum "):
typish = typish[5:]
isEnum = True
else:
isEnum = False
if typish[0] == 'Q': if typish[0] == 'Q':
if typish in ("QByteArray", "QString", "QList", "QStringList"): if typish in ("QByteArray", "QString", "QList", "QStringList"):
typish = self.qtNamespace() + typish typish = self.qtNamespace() + typish
@@ -3287,14 +3325,12 @@ class DumperBase:
elif typish == "QChar": elif typish == "QChar":
typish = self.qtNamespace() + typish typish = self.qtNamespace() + typish
size = 2 size = 2
#res.lEnumType = False
elif typish in ("quint32", "qint32"): elif typish in ("quint32", "qint32"):
typish = self.qtNamespace() + typish typish = self.qtNamespace() + typish
size = 4 size = 4
#typeobj = self.Type(self) #typeobj = self.Type(self)
#typeobj.name = typish #typeobj.name = typish
#warn("CREATE TYPE: %s" % typish)
nativeType = self.lookupNativeType(typish) # FIXME: Remove? nativeType = self.lookupNativeType(typish) # FIXME: Remove?
#warn("FOUND NAT TYPE: %s" % dir(nativeType)) #warn("FOUND NAT TYPE: %s" % dir(nativeType))
if nativeType is not None: if nativeType is not None:
@@ -3306,6 +3342,8 @@ class DumperBase:
typeobj.name = typish typeobj.name = typish
if size is not None: if size is not None:
typeobj.lbitsize = 8 * size typeobj.lbitsize = 8 * size
#warn("CREATE TYPE: %s" % typeobj)
typeobj.lEnumType = isEnum
typeobj.check() typeobj.check()
return typeobj return typeobj
error("NEED TYPE, NOT %s" % type(typish)) error("NEED TYPE, NOT %s" % type(typish))

View File

@@ -379,6 +379,13 @@ class Dumper(DumperBase):
if len(nativeFields) and nativeFields[0].is_base_class: if len(nativeFields) and nativeFields[0].is_base_class:
return self.fromNativeType(nativeFields[0].type) return self.fromNativeType(nativeFields[0].type)
def nativeTypeEnumDisplay(self, nativeType, intval):
try:
val = gdb.parse_and_eval("(%s)%d" % (nativeType.name, intval))
return "%s (%d)" % (val, intval)
except:
return "%d" % intval
def nativeTypeFields(self, nativeType): def nativeTypeFields(self, nativeType):
#warn("TYPE: %s" % nativeType) #warn("TYPE: %s" % nativeType)
fields = [] fields = []

View File

@@ -351,6 +351,18 @@ class Dumper(DumperBase):
#warn(" GOT BASE FROM: %s" % t) #warn(" GOT BASE FROM: %s" % t)
return self.fromNativeType(nativeType.GetDirectBaseClassAtIndex(0).GetType()) return self.fromNativeType(nativeType.GetDirectBaseClassAtIndex(0).GetType())
def nativeTypeEnumDisplay(self, nativeType, intval):
if hasattr(nativeType, 'get_enum_members_array'):
for enumMember in nativeType.get_enum_members_array():
# Even when asking for signed we get unsigned with LLDB 3.8.
diff = enumMember.GetValueAsSigned() - intval
mask = (1 << nativeType.GetByteSize() * 8) - 1
if diff & mask == 0:
path = nativeType.GetName().split('::')
path[-1] = enumMember.GetName()
return "%s (%d)" % ('::'.join(path), intval)
return "%d" % intval
def stateName(self, s): def stateName(self, s):
try: try:
# See db.StateType # See db.StateType

View File

@@ -620,12 +620,9 @@ def qdump__QFiniteStack(d, value):
def qdump__QFlags(d, value): def qdump__QFlags(d, value):
i = value["i"] i = value.split('{int}')[0]
try: enumType = value.type[0]
enumType = value.type.unqualified()[0] d.putValue(i.cast('enum ' + enumType.name).display())
d.putValue("%s (%s)" % (i.cast(enumType), i))
except:
d.putValue("%s" % i)
d.putNumChild(0) d.putNumChild(0)
@@ -923,25 +920,36 @@ def qdump__QLocale(d, value):
# index = int(value["d"]["d"]["m_data"]...) # index = int(value["d"]["d"]["m_data"]...)
#d.check(index >= 0) #d.check(index >= 0)
#d.check(index <= qqLocalesCount) #d.check(index <= qqLocalesCount)
dd = value.extractPointer()
ns = d.qtNamespace()
prefix = "enum " + ns + "QLocale::"
(data, ref, numberOptions) = d.split("pi{int}", dd)
(languageId, scriptId, countryId,
decimal, group, listt, percent, zero,
minus, plus, exponential) \
= d.split('{short}{short}{QChar}'
+ '{QChar}{QChar}{short}{QChar}{QChar}'
+ '{QChar}{QChar}{QChar}', data)
d.putStringValue(d.call("const char *", value, "name")) d.putStringValue(d.call("const char *", value, "name"))
d.putNumChild(1) d.putNumChild(1)
if d.isExpanded(): if d.isExpanded():
ns = d.qtNamespace() with Children(d):
with Children(d, childType=d.lookupType(ns + "QChar"), childNumChild=0): d.putSubItem("country", countryId.extend(4).cast(prefix + "Country"))
d.putCallItem("country", value, "country") d.putSubItem("language", languageId.extend(4).cast(prefix + "Language"))
d.putCallItem("language", value, "language") d.putSubItem("numberOptions", numberOptions.cast(prefix + "NumberOptions"))
d.putCallItem("measurementSystem", value, "measurementSystem") d.putSubItem("decimalPoint", decimal)
d.putCallItem("numberOptions", value, "numberOptions") d.putSubItem("exponential", exponential)
d.putCallItem("timeFormat_(short)", value, d.putSubItem("percent", percent)
"timeFormat", ns + "QLocale::ShortFormat") d.putSubItem("zeroDigit", zero)
d.putCallItem("timeFormat_(long)", value, d.putSubItem("groupSeparator", group)
"timeFormat", ns + "QLocale::LongFormat") d.putSubItem("negativeSign", minus)
d.putCallItem("decimalPoint", value, "decimalPoint") d.putSubItem("positiveSign", plus)
d.putCallItem("exponential", value, "exponential") d.putCallItem("measurementSystem", ns + "QLocale::MeasurementSystem",
d.putCallItem("percent", value, "percent") value, "measurementSystem")
d.putCallItem("zeroDigit", value, "zeroDigit") d.putCallItem("timeFormat_(short)", ns + "QString",
d.putCallItem("groupSeparator", value, "groupSeparator") value, "timeFormat", ns + "QLocale::ShortFormat")
d.putCallItem("negativeSign", value, "negativeSign") d.putCallItem("timeFormat_(long)", ns + "QString",
value, "timeFormat", ns + "QLocale::LongFormat")
d.putFields(value) d.putFields(value)

View File

@@ -2216,10 +2216,19 @@ void tst_Dumpers::dumper_data()
"QLocale::MeasurementSystem m1 = loc1.measurementSystem();\n" "QLocale::MeasurementSystem m1 = loc1.measurementSystem();\n"
"unused(&loc0, &loc, &m, &loc1, &m1);\n") "unused(&loc0, &loc, &m, &loc1, &m1);\n")
+ CoreProfile() + CoreProfile()
// + Check("loc0", "\"en_US\"", "@QLocale") FIXME
+ CheckType("loc", "@QLocale") + CheckType("loc", "@QLocale")
+ CheckType("m", "@QLocale::MeasurementSystem") + CheckType("m", "@QLocale::MeasurementSystem")
+ Check("loc1", "\"en_US\"", "@QLocale") + Check("loc1", "\"en_US\"", "@QLocale")
+ Check("loc1.country", "@QLocale::UnitedStates (225)", "@QLocale::Country")
+ Check("loc1.language", "@QLocale::English (31)", "@QLocale::Language")
+ Check("loc1.numberOptions", "@QLocale::DefaultNumberOptions (0)", "@QLocale::NumberOptions")
+ Check("loc1.decimalPoint", "46", "@QChar") // .
+ Check("loc1.exponential", "101", "@QChar") // e
+ Check("loc1.percent", "37", "@QChar") // %
+ Check("loc1.zeroDigit", "48", "@QChar") // 0
+ Check("loc1.groupSeparator", "44", "@QChar") // ,
+ Check("loc1.negativeSign", "45", "@QChar") // -
+ Check("loc1.positiveSign", "43", "@QChar") // +
+ Check("m1", ValuePattern(".*Imperial.*System (1)"), Pattern(".*MeasurementSystem")); + Check("m1", ValuePattern(".*Imperial.*System (1)"), Pattern(".*MeasurementSystem"));
@@ -4855,6 +4864,19 @@ void tst_Dumpers::dumper_data()
+ Check("s32s", "-2147483648", "@qint32"); + Check("s32s", "-2147483648", "@qint32");
QTest::newRow("Enum")
<< Data("\n"
"enum Foo { a = -1000, b, c = 1, d };\n",
"Foo fa = a; unused(&fa);\n"
"Foo fb = b; unused(&fb);\n"
"Foo fc = c; unused(&fc);\n"
"Foo fd = d; unused(&fd);\n")
+ Check("fa", "a (-1000)", "Foo")
+ Check("fb", "b (-999)", "Foo")
+ Check("fc", "c (1)", "Foo")
+ Check("fd", "d (2)", "Foo");
QTest::newRow("Array") QTest::newRow("Array")
<< Data("double a1[3][3];\n" << Data("double a1[3][3];\n"
"for (int i = 0; i != 3; ++i)\n" "for (int i = 0; i != 3; ++i)\n"