forked from qt-creator/qt-creator
Debugger: Simplify removal of outdated L&E items
This removes the need of bookkeeping on the engine side. It's basically a kind of mark-and-sweep: On update begin mark items that are expected to change as outdated, while data arrives, undo that marking, and update end remove all remaining marked items. Change-Id: I739b84869033d511d5c9a80605c079e87ef4f6a7 Reviewed-by: David Schulz <david.schulz@theqtcompany.com>
This commit is contained in:
@@ -1340,7 +1340,7 @@ void CdbEngine::doUpdateLocals(const UpdateParameters &updateParameters)
|
||||
return;
|
||||
}
|
||||
|
||||
watchHandler()->notifyUpdateStarted();
|
||||
watchHandler()->notifyUpdateStarted(updateParameters.partialVariables());
|
||||
|
||||
/* Watchers: Forcibly discard old symbol group as switching from
|
||||
* thread 0/frame 0 -> thread 1/assembly -> thread 0/frame 0 will otherwise re-use it
|
||||
@@ -1775,7 +1775,6 @@ void CdbEngine::handleRegistersExt(const CdbResponse &response)
|
||||
|
||||
void CdbEngine::handleLocals(const CdbResponse &response, bool partialUpdate)
|
||||
{
|
||||
watchHandler()->notifyUpdateFinished();
|
||||
if (response.success) {
|
||||
if (boolSetting(VerboseLog))
|
||||
showMessage(QLatin1String("Locals: ") + QString::fromLatin1(response.extensionReply), LogDebug);
|
||||
@@ -1796,6 +1795,7 @@ void CdbEngine::handleLocals(const CdbResponse &response, bool partialUpdate)
|
||||
} else {
|
||||
showMessage(QString::fromLatin1(response.errorMessage), LogWarning);
|
||||
}
|
||||
watchHandler()->notifyUpdateFinished();
|
||||
}
|
||||
|
||||
void CdbEngine::handleExpandLocals(const CdbResponse &response)
|
||||
|
||||
@@ -1944,12 +1944,6 @@ void DebuggerEngine::updateLocalsView(const GdbMi &all)
|
||||
}
|
||||
}
|
||||
|
||||
QSet<QByteArray> toDelete;
|
||||
if (!partial) {
|
||||
foreach (WatchItem *item, handler->model()->itemsAtLevel<WatchItem *>(2))
|
||||
toDelete.insert(item->iname);
|
||||
}
|
||||
|
||||
GdbMi data = all["data"];
|
||||
foreach (const GdbMi &child, data.children()) {
|
||||
WatchItem *item = new WatchItem(child);
|
||||
@@ -1958,7 +1952,6 @@ void DebuggerEngine::updateLocalsView(const GdbMi &all)
|
||||
item->size = ti.size;
|
||||
|
||||
handler->insertItem(item);
|
||||
toDelete.remove(item->iname);
|
||||
}
|
||||
|
||||
GdbMi ns = all["qtnamespace"];
|
||||
@@ -1967,8 +1960,6 @@ void DebuggerEngine::updateLocalsView(const GdbMi &all)
|
||||
showMessage(_("FOUND NAMESPACED QT: " + ns.data()));
|
||||
}
|
||||
|
||||
handler->purgeOutdatedItems(toDelete);
|
||||
|
||||
static int count = 0;
|
||||
showMessage(_("<Rebuild Watchmodel %1 @ %2 >")
|
||||
.arg(++count).arg(LogWindow::logTimeStamp()), LogMiscInput);
|
||||
|
||||
@@ -120,6 +120,14 @@ class UpdateParameters
|
||||
public:
|
||||
UpdateParameters() {}
|
||||
|
||||
QList<QByteArray> partialVariables() const
|
||||
{
|
||||
QList<QByteArray> result;
|
||||
if (!partialVariable.isEmpty())
|
||||
result.append(partialVariable);
|
||||
return result;
|
||||
}
|
||||
|
||||
QByteArray partialVariable;
|
||||
};
|
||||
|
||||
|
||||
@@ -4660,7 +4660,7 @@ void GdbEngine::doUpdateLocals(const UpdateParameters ¶ms)
|
||||
{
|
||||
m_pendingBreakpointRequests = 0;
|
||||
|
||||
watchHandler()->notifyUpdateStarted();
|
||||
watchHandler()->notifyUpdateStarted(params.partialVariables());
|
||||
|
||||
DebuggerCommand cmd("showData");
|
||||
watchHandler()->appendFormatRequests(&cmd);
|
||||
@@ -4716,7 +4716,6 @@ void GdbEngine::doUpdateLocals(const UpdateParameters ¶ms)
|
||||
|
||||
void GdbEngine::handleStackFrame(const DebuggerResponse &response)
|
||||
{
|
||||
watchHandler()->notifyUpdateFinished();
|
||||
if (response.resultClass == ResultDone) {
|
||||
QByteArray out = response.consoleStreamOutput;
|
||||
while (out.endsWith(' ') || out.endsWith('\n'))
|
||||
@@ -4735,6 +4734,7 @@ void GdbEngine::handleStackFrame(const DebuggerResponse &response)
|
||||
} else {
|
||||
showMessage(_("DUMPER FAILED: " + response.toString()));
|
||||
}
|
||||
watchHandler()->notifyUpdateFinished();
|
||||
}
|
||||
|
||||
QString GdbEngine::msgPtraceError(DebuggerStartMode sm)
|
||||
|
||||
@@ -447,8 +447,8 @@ void LldbEngine::handleResponse(const QByteArray &response)
|
||||
foreach (const GdbMi &item, all.children()) {
|
||||
const QByteArray name = item.name();
|
||||
if (name == "all") {
|
||||
watchHandler()->notifyUpdateFinished();
|
||||
updateLocalsView(item);
|
||||
watchHandler()->notifyUpdateFinished();
|
||||
} else if (name == "dumpers") {
|
||||
watchHandler()->addDumpers(item);
|
||||
setupInferiorStage2();
|
||||
@@ -864,7 +864,7 @@ void LldbEngine::doUpdateLocals(const UpdateParameters ¶ms)
|
||||
return;
|
||||
}
|
||||
|
||||
watchHandler()->notifyUpdateStarted();
|
||||
watchHandler()->notifyUpdateStarted(params.partialVariables());
|
||||
|
||||
DebuggerCommand cmd("updateData");
|
||||
cmd.arg("nativeMixed", isNativeMixedActive());
|
||||
|
||||
@@ -572,17 +572,10 @@ void PdbEngine::refreshLocals(const GdbMi &vars)
|
||||
WatchHandler *handler = watchHandler();
|
||||
handler->resetValueCache();
|
||||
|
||||
QSet<QByteArray> toDelete;
|
||||
foreach (WatchItem *item, handler->model()->itemsAtLevel<WatchItem *>(2))
|
||||
toDelete.insert(item->iname);
|
||||
foreach (const GdbMi &child, vars.children())
|
||||
handler->insertItem(new WatchItem(child));
|
||||
|
||||
foreach (const GdbMi &child, vars.children()) {
|
||||
WatchItem *item = new WatchItem(child);
|
||||
handler->insertItem(item);
|
||||
toDelete.remove(item->iname);
|
||||
}
|
||||
|
||||
handler->purgeOutdatedItems(toDelete);
|
||||
handler->notifyUpdateFinished();
|
||||
|
||||
DebuggerToolTipManager::updateEngine(this);
|
||||
}
|
||||
|
||||
@@ -131,7 +131,8 @@ WatchData::WatchData() :
|
||||
elided(0),
|
||||
wantsChildren(false),
|
||||
valueEnabled(true),
|
||||
valueEditable(true)
|
||||
valueEditable(true),
|
||||
outdated(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -119,6 +119,7 @@ public:
|
||||
bool wantsChildren;
|
||||
bool valueEnabled; // Value will be enabled or not
|
||||
bool valueEditable; // Value will be editable
|
||||
bool outdated; // \internal item is to be removed.
|
||||
|
||||
Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::WatchHandler)
|
||||
};
|
||||
|
||||
@@ -1221,8 +1221,20 @@ void WatchHandler::resetWatchers()
|
||||
loadSessionData();
|
||||
}
|
||||
|
||||
void WatchHandler::notifyUpdateStarted()
|
||||
void WatchHandler::notifyUpdateStarted(const QList<QByteArray> &inames)
|
||||
{
|
||||
auto marker = [](TreeItem *it) { static_cast<WatchItem *>(it)->outdated = true; };
|
||||
|
||||
if (inames.isEmpty()) {
|
||||
foreach (auto item, m_model->itemsAtLevel<WatchItem *>(2))
|
||||
item->walkTree(marker);
|
||||
} else {
|
||||
foreach (auto iname, inames) {
|
||||
if (WatchItem *item = m_model->findItem(iname))
|
||||
item->walkTree(marker);
|
||||
}
|
||||
}
|
||||
|
||||
m_model->m_requestUpdateTimer.start(80);
|
||||
m_model->m_contentsValid = false;
|
||||
updateWatchersWindow();
|
||||
@@ -1230,25 +1242,32 @@ void WatchHandler::notifyUpdateStarted()
|
||||
|
||||
void WatchHandler::notifyUpdateFinished()
|
||||
{
|
||||
struct OutDatedItemsFinder : public TreeItemVisitor
|
||||
{
|
||||
bool preVisit(TreeItem *item)
|
||||
{
|
||||
auto watchItem = static_cast<WatchItem *>(item);
|
||||
if (level() <= 1 || !watchItem->outdated)
|
||||
return true;
|
||||
toRemove.append(watchItem);
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<WatchItem *> toRemove;
|
||||
} finder;
|
||||
|
||||
m_model->root()->walkTree(&finder);
|
||||
|
||||
foreach (auto item, finder.toRemove)
|
||||
delete m_model->takeItem(item);
|
||||
|
||||
m_model->m_contentsValid = true;
|
||||
updateWatchersWindow();
|
||||
m_model->reexpandItems();
|
||||
m_model->m_requestUpdateTimer.stop();
|
||||
emit m_model->updateFinished();
|
||||
}
|
||||
|
||||
void WatchHandler::purgeOutdatedItems(const QSet<QByteArray> &inames)
|
||||
{
|
||||
foreach (const QByteArray &iname, inames) {
|
||||
WatchItem *item = findItem(iname);
|
||||
delete m_model->takeItem(item);
|
||||
}
|
||||
|
||||
m_model->layoutChanged();
|
||||
m_model->reexpandItems();
|
||||
m_model->m_contentsValid = true;
|
||||
updateWatchersWindow();
|
||||
}
|
||||
|
||||
void WatchHandler::removeItemByIName(const QByteArray &iname)
|
||||
{
|
||||
WatchItem *item = m_model->findItem(iname);
|
||||
|
||||
@@ -197,9 +197,9 @@ public:
|
||||
void removeAllData(bool includeInspectData = false);
|
||||
void resetValueCache();
|
||||
void resetWatchers();
|
||||
void notifyUpdateStarted();
|
||||
|
||||
void notifyUpdateStarted(const QList<QByteArray> &inames = {});
|
||||
void notifyUpdateFinished();
|
||||
void purgeOutdatedItems(const QSet<QByteArray> &inames);
|
||||
|
||||
private:
|
||||
WatchModel *m_model; // Owned.
|
||||
|
||||
Reference in New Issue
Block a user