Debugger: Save a few cycles in watch data

Change-Id: I1fada2767bedb5c9a90bd8f4f2db6b2c881f111e
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
hjk
2023-01-03 14:09:44 +01:00
parent b00442e946
commit e1ae96647d
4 changed files with 124 additions and 146 deletions

View File

@@ -15,106 +15,88 @@
namespace Debugger::Internal { namespace Debugger::Internal {
bool isPointerType(const QString &type) bool isPointerType(const QStringView type)
{ {
return type.endsWith('*') || type.endsWith("* const"); return type.endsWith('*') || type.endsWith(u"* const");
} }
bool isIntType(const QString &type) bool isIntType(const QStringView type)
{ {
if (type.isEmpty()) if (type.isEmpty())
return false; return false;
switch (type.at(0).unicode()) { switch (type.at(0).unicode()) {
case 'b': case 'b':
return type == "bool"; return type == u"bool";
case 'c': case 'c':
return type.startsWith("char") && return type.startsWith(u"char") &&
( type == "char" ( type == u"char"
|| type == "char8_t" || type == u"char8_t"
|| type == "char16_t" || type == u"char16_t"
|| type == "char32_t" ); || type == u"char32_t" );
case 'i': case 'i':
return type.startsWith("int") && return type.startsWith(u"int") &&
( type == "int" ( type == u"int"
|| type == "int8_t" || type == u"int8_t"
|| type == "int16_t" || type == u"int16_t"
|| type == "int32_t" || type == u"int32_t"
|| type == "int64_t"); || type == u"int64_t");
case 'l': case 'l':
return type == "long" return type == u"long"
|| type == "long int" || type == u"long int"
|| type == "long unsigned int"; || type == u"long unsigned int";
case 'p': case 'p':
return type == "ptrdiff_t"; return type == u"ptrdiff_t";
case 'q': case 'q':
return type == "qint8" || type == "quint8" return type == u"qint8" || type == u"quint8"
|| type == "qint16" || type == "quint16" || type == u"qint16" || type == u"quint16"
|| type == "qint32" || type == "quint32" || type == u"qint32" || type == u"quint32"
|| type == "qint64" || type == "quint64" || type == u"qint64" || type == u"quint64"
|| type == "qlonglong" || type == "qulonglong"; || type == u"qlonglong" || type == u"qulonglong";
case 's': case 's':
return type == "short" return type == u"short"
|| type == "signed" || type == u"signed"
|| type == "size_t" || type == u"size_t"
|| type == "std::size_t" || type == u"std::size_t"
|| type == "std::ptrdiff_t" || type == u"std::ptrdiff_t"
|| (type.startsWith("signed") && || (type.startsWith(u"signed") &&
( type == "signed char" ( type == u"signed char"
|| type == "signed short" || type == u"signed short"
|| type == "signed short int" || type == u"signed short int"
|| type == "signed long" || type == u"signed long"
|| type == "signed long int" || type == u"signed long int"
|| type == "signed long long" || type == u"signed long long"
|| type == "signed long long int")); || type == u"signed long long int"));
case 'u': case 'u':
return type == "unsigned" return type == u"unsigned"
|| (type.startsWith("unsigned") && || (type.startsWith(u"unsigned") &&
( type == "unsigned char" ( type == u"unsigned char"
|| type == "unsigned short" || type == u"unsigned short"
|| type == "unsigned short int" || type == u"unsigned short int"
|| type == "unsigned int" || type == u"unsigned int"
|| type == "unsigned long" || type == u"unsigned long"
|| type == "unsigned long int" || type == u"unsigned long int"
|| type == "unsigned long long" || type == u"unsigned long long"
|| type == "unsigned long long int")) || type == u"unsigned long long int"))
|| (type.startsWith("uint") && || (type.startsWith(u"uint") &&
( type == "uint8_t" ( type == u"uint8_t"
|| type == "uint16_t" || type == u"uint16_t"
|| type == "uint32_t" || type == u"uint32_t"
|| type == "uint64_t")); || type == u"uint64_t"));
default: default:
return false; return false;
} }
} }
bool isFloatType(const QString &type) bool isFloatType(const QStringView type)
{ {
return type == "float" || type == "double" || type == "qreal" || type == "number"; return type == u"float" || type == u"double" || type == u"qreal" || type == u"number";
} }
bool isIntOrFloatType(const QString &type) bool isIntOrFloatType(const QStringView type)
{ {
return isIntType(type) || isFloatType(type); return isIntType(type) || isFloatType(type);
} }
WatchItem::WatchItem() :
id(WatchItem::InvalidId),
address(0),
origaddr(0),
size(0),
bitpos(0),
bitsize(0),
elided(0),
arrayIndex(-1),
sortGroup(0),
wantsChildren(false),
valueEnabled(true),
valueEditable(true),
autoDerefCount(0),
outdated(false)
{
}
bool WatchItem::isVTablePointer() const bool WatchItem::isVTablePointer() const
{ {
// First case: Cdb only. No user type can be named like this, this is safe. // First case: Cdb only. No user type can be named like this, this is safe.

View File

@@ -18,7 +18,7 @@ class GdbMi;
class WatchItem : public Utils::TypedTreeItem<WatchItem, WatchItem> class WatchItem : public Utils::TypedTreeItem<WatchItem, WatchItem>
{ {
public: public:
WatchItem(); WatchItem() {}
void parse(const GdbMi &input, bool maySort); void parse(const GdbMi &input, bool maySort);
@@ -54,29 +54,29 @@ public:
QString key() const { return address ? hexAddress() : iname; } QString key() const { return address ? hexAddress() : iname; }
public: public:
qint64 id; // Token for the engine for internal mapping qint64 id = InvalidId; // Token for the engine for internal mapping
QString iname; // Internal name sth like 'local.baz.public.a' QString iname; // Internal name sth like 'local.baz.public.a'
QString exp; // The expression QString exp; // The expression
QString name; // Displayed name QString name; // Displayed name
QString value; // Displayed value QString value; // Displayed value
QString editvalue; // Displayed value QString editvalue; // Displayed value
QString editformat; // Format of displayed value QString editformat; // Format of displayed value
DebuggerEncoding editencoding; // Encoding of displayed value DebuggerEncoding editencoding; // Encoding of displayed value
QString type; // Type for further processing QString type; // Type for further processing
quint64 address; // Displayed address of the actual object quint64 address; // Displayed address of the actual object
quint64 origaddr; // Address of the pointer referencing this item (gdb auto-deref) quint64 origaddr; // Address of the pointer referencing this item (gdb auto-deref)
uint size; // Size uint size; // Size
uint bitpos; // Position within bit fields uint bitpos = 0; // Position within bit fields
uint bitsize; // Size in case of bit fields uint bitsize = 0; // Size in case of bit fields
int elided; // Full size if value was cut off, -1 if cut on unknown size, 0 otherwise uint autoDerefCount = 0; // number of levels of automatic dereferencing that has taken place (for pointer types)
int arrayIndex; // -1 if not an array member int elided = 0; // Full size if value was cut off, -1 if cut on unknown size, 0 otherwise
uchar sortGroup; // 0 - ordinary member, 1 - vptr, 2 - base class int arrayIndex = -1; // -1 if not an array member
bool wantsChildren; uchar sortGroup = 0; // 0 - ordinary member, 1 - vptr, 2 - base class
bool valueEnabled; // Value will be enabled or not bool wantsChildren = false;
bool valueEditable; // Value will be editable bool valueEnabled = true; // Value will be enabled or not
uint autoDerefCount; // number of levels of automatic dereferencing that has taken place (for pointer types) bool valueEditable = true; // Value will be editable
bool outdated; // \internal item is to be removed. bool outdated = false; // \internal item is to be removed.
double time = 0; // Time used on the dumper side to produce this item double time = 0; // Time used on the dumper side to produce this item
private: private:
void parseHelper(const GdbMi &input, bool maySort); void parseHelper(const GdbMi &input, bool maySort);

View File

@@ -14,8 +14,7 @@
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
namespace Debugger { namespace Debugger::Internal{
namespace Internal {
QString removeObviousSideEffects(const QString &expIn) QString removeObviousSideEffects(const QString &expIn)
{ {
@@ -143,7 +142,7 @@ bool isLetterOrNumber(int c)
|| (c >= '0' && c <= '9'); || (c >= '0' && c <= '9');
} }
bool hasLetterOrNumber(const QString &exp) bool hasLetterOrNumber(const QStringView exp)
{ {
const QChar underscore = '_'; const QChar underscore = '_';
for (int i = exp.size(); --i >= 0; ) for (int i = exp.size(); --i >= 0; )
@@ -152,66 +151,66 @@ bool hasLetterOrNumber(const QString &exp)
return false; return false;
} }
bool hasSideEffects(const QString &exp) bool hasSideEffects(const QStringView exp)
{ {
// FIXME: complete? // FIXME: complete?
return exp.contains("-=") return exp.contains(u"-=")
|| exp.contains("+=") || exp.contains(u"+=")
|| exp.contains("/=") || exp.contains(u"/=")
|| exp.contains("%=") || exp.contains(u"%=")
|| exp.contains("*=") || exp.contains(u"*=")
|| exp.contains("&=") || exp.contains(u"&=")
|| exp.contains("|=") || exp.contains(u"|=")
|| exp.contains("^=") || exp.contains(u"^=")
|| exp.contains("--") || exp.contains(u"--")
|| exp.contains("++"); || exp.contains(u"++");
} }
bool isKeyWord(const QString &exp) bool isKeyWord(const QStringView exp)
{ {
// FIXME: incomplete. // FIXME: incomplete.
if (!exp.isEmpty()) if (!exp.isEmpty())
return false; return false;
switch (exp.at(0).toLatin1()) { switch (exp.at(0).toLatin1()) {
case 'a': case 'a':
return exp == "auto"; return exp == u"auto";
case 'b': case 'b':
return exp == "break"; return exp == u"break";
case 'c': case 'c':
return exp == "case" || exp == "class" || exp == "const" || exp == "constexpr" return exp == u"case" || exp == u"class" || exp == u"const" || exp == u"constexpr"
|| exp == "catch" || exp == "continue" || exp == "const_cast"; || exp == u"catch" || exp == u"continue" || exp == u"const_cast";
case 'd': case 'd':
return exp == "do" || exp == "default" || exp == "delete" || exp == "decltype" return exp == u"do" || exp == u"default" || exp == u"delete" || exp == u"decltype"
|| exp == "dynamic_cast"; || exp == u"dynamic_cast";
case 'e': case 'e':
return exp == "else" || exp == "extern" || exp == "enum" || exp == "explicit"; return exp == u"else" || exp == u"extern" || exp == u"enum" || exp == u"explicit";
case 'f': case 'f':
return exp == "for" || exp == "friend" || exp == "final"; return exp == u"for" || exp == u"friend" || exp == u"final";
case 'g': case 'g':
return exp == "goto"; return exp == u"goto";
case 'i': case 'i':
return exp == "if" || exp == "inline"; return exp == u"if" || exp == u"inline";
case 'n': case 'n':
return exp == "new" || exp == "namespace" || exp == "noexcept"; return exp == u"new" || exp == u"namespace" || exp == u"noexcept";
case 'm': case 'm':
return exp == "mutable"; return exp == u"mutable";
case 'o': case 'o':
return exp == "operator" || exp == "override"; return exp == u"operator" || exp == u"override";
case 'p': case 'p':
return exp == "public" || exp == "protected" || exp == "private"; return exp == u"public" || exp == u"protected" || exp == u"private";
case 'r': case 'r':
return exp == "return" || exp == "register" || exp == "reinterpret_cast"; return exp == u"return" || exp == u"register" || exp == u"reinterpret_cast";
case 's': case 's':
return exp == "struct" || exp == "switch" || exp == "static_cast"; return exp == u"struct" || exp == u"switch" || exp == u"static_cast";
case 't': case 't':
return exp == "template" || exp == "typename" || exp == "try" return exp == u"template" || exp == u"typename" || exp == u"try"
|| exp == "throw" || exp == "typedef"; || exp == u"throw" || exp == u"typedef";
case 'u': case 'u':
return exp == "union" || exp == "using"; return exp == u"union" || exp == u"using";
case 'v': case 'v':
return exp == "void" || exp == "volatile" || exp == "virtual"; return exp == u"void" || exp == u"volatile" || exp == u"virtual";
case 'w': case 'w':
return exp == "while"; return exp == u"while";
} }
return false; return false;
} }
@@ -277,5 +276,4 @@ QString escapeUnprintable(const QString &str, int unprintableBase)
return encoded; return encoded;
} }
} // namespace Internal } // Debugger::Internal
} // namespace Debugger

View File

@@ -8,24 +8,22 @@
#include <QString> #include <QString>
namespace Debugger { namespace Debugger::Internal {
namespace Internal {
bool isSkippableFunction(const QStringView funcName, const QStringView fileName); bool isSkippableFunction(const QStringView funcName, const QStringView fileName);
bool isLeavableFunction(const QStringView funcName, const QStringView fileName); bool isLeavableFunction(const QStringView funcName, const QStringView fileName);
bool hasLetterOrNumber(const QString &exp); bool hasLetterOrNumber(const QStringView exp);
bool hasSideEffects(const QString &exp); bool hasSideEffects(const QStringView exp);
bool isKeyWord(const QString &exp); bool isKeyWord(const QStringView exp);
bool isPointerType(const QString &type); bool isPointerType(const QStringView type);
bool isFloatType(const QString &type); bool isFloatType(const QStringView type);
bool isIntOrFloatType(const QString &type); bool isIntOrFloatType(const QStringView type);
bool isIntType(const QString &type); bool isIntType(const QStringView type);
QString formatToolTipAddress(quint64 a); QString formatToolTipAddress(quint64 a);
QString removeObviousSideEffects(const QString &exp); QString removeObviousSideEffects(const QString &exp);
QString escapeUnprintable(const QString &str, int unprintableBase = -1); QString escapeUnprintable(const QString &str, int unprintableBase = -1);
} // namespace Internal } // Debugger::Internal
} // namespace Debugger