Commit d48ac14f authored by hjk's avatar hjk

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: default avatarDavid Schulz <david.schulz@theqtcompany.com>
parent 1587c171
......@@ -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 &params)
{
m_pendingBreakpointRequests = 0;
watchHandler()->notifyUpdateStarted();
watchHandler()->notifyUpdateStarted(params.partialVariables());
DebuggerCommand cmd("showData");
watchHandler()->appendFormatRequests(&cmd);
......@@ -4716,7 +4716,6 @@ void GdbEngine::doUpdateLocals(const UpdateParameters &params)
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 &params)
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()) {
WatchItem *item = new WatchItem(child);
handler->insertItem(item);
toDelete.remove(item->iname);
}
foreach (const GdbMi &child, vars.children())
handler->insertItem(new WatchItem(child));
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,23 +1242,30 @@ void WatchHandler::notifyUpdateStarted()
void WatchHandler::notifyUpdateFinished()
{
m_model->m_contentsValid = true;
updateWatchersWindow();
m_model->m_requestUpdateTimer.stop();
emit m_model->updateFinished();
}
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;
}
void WatchHandler::purgeOutdatedItems(const QSet<QByteArray> &inames)
{
foreach (const QByteArray &iname, inames) {
WatchItem *item = findItem(iname);
QList<WatchItem *> toRemove;
} finder;
m_model->root()->walkTree(&finder);
foreach (auto item, finder.toRemove)
delete m_model->takeItem(item);
}
m_model->layoutChanged();
m_model->reexpandItems();
m_model->m_contentsValid = true;
updateWatchersWindow();
m_model->reexpandItems();
m_model->m_requestUpdateTimer.stop();
emit m_model->updateFinished();
}
void WatchHandler::removeItemByIName(const QByteArray &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.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment