Skip to content

Commit d86eea6

Browse files
author
Your Name
committed
Cache the findExpressionChanged
1 parent 3fea32a commit d86eea6

2 files changed

Lines changed: 27 additions & 9 deletions

File tree

lib/programmemory.cpp

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ static ProgramMemory getInitialProgramState(const Token* tok,
513513
return pm;
514514
}
515515

516-
ProgramMemoryState::ProgramMemoryState(const Settings& s) : settings(s)
516+
ProgramMemoryState::ProgramMemoryState(const Settings& s) : settings(s), changedCache(std::make_shared<ChangedCache>())
517517
{}
518518

519519
void ProgramMemoryState::replace(ProgramMemory pm, const Token* origin)
@@ -564,26 +564,36 @@ void ProgramMemoryState::assume(const Token* tok, bool b, bool isEmpty, const To
564564
replace(std::move(pm), origin);
565565
}
566566

567-
void ProgramMemoryState::removeModifiedVars(const Token* tok)
567+
const Token* ProgramMemoryState::findExpressionChanged(const Token* expr, const Token* start, const Token* tok) const
568568
{
569-
const ProgramMemory& pm = state;
569+
// Memoized structural pre-filter (a superset) gates the expensive dead-code-aware walk.
570+
const auto key = std::make_tuple(expr, start, tok);
571+
auto it = changedCache->find(key);
572+
if (it == changedCache->end())
573+
it = changedCache->emplace(key, ::findExpressionChanged(expr, start, tok, settings)).first;
574+
if (!it->second)
575+
return nullptr;
570576
auto eval = [&](const Token* cond) -> std::vector<MathLib::bigint> {
571-
ProgramMemory pm2 = pm;
572-
auto result = execute(cond, pm2, settings);
577+
ProgramMemory pm2 = state;
578+
const auto result = execute(cond, pm2, settings);
573579
if (isTrue(result))
574580
return {1};
575581
if (isFalse(result))
576582
return {0};
577583
return {};
578584
};
585+
return ::findExpressionChangedSkipDeadCode(expr, start, tok, settings, eval);
586+
}
587+
588+
void ProgramMemoryState::removeModifiedVars(const Token* tok)
589+
{
579590
state.erase_if([&](const ExprIdToken& e) {
580591
const Token* start = origins[e.getExpressionId()];
581592
const Token* expr = e.tok;
582-
if (!expr || findExpressionChangedSkipDeadCode(expr, start, tok, settings, eval)) {
593+
const bool changed = !expr || findExpressionChanged(expr, start, tok);
594+
if (changed)
583595
origins.erase(e.getExpressionId());
584-
return true;
585-
}
586-
return false;
596+
return changed;
587597
});
588598
}
589599

lib/programmemory.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <map>
2929
#include <memory>
3030
#include <string>
31+
#include <tuple>
3132
#include <unordered_map>
3233
#include <utility>
3334
#include <vector>
@@ -161,9 +162,13 @@ struct CPPCHECKLIB ProgramMemory {
161162
};
162163

163164
struct ProgramMemoryState {
165+
using ChangedCache = std::map<std::tuple<const Token*, const Token*, const Token*>, const Token*>;
166+
164167
ProgramMemory state;
165168
std::map<nonneg int, const Token*> origins;
166169
const Settings& settings;
170+
// Memoized findExpressionChanged() pre-filter; structural, so never invalidated.
171+
std::shared_ptr<ChangedCache> changedCache;
167172

168173
explicit ProgramMemoryState(const Settings& s);
169174

@@ -175,6 +180,9 @@ struct ProgramMemoryState {
175180

176181
void removeModifiedVars(const Token* tok);
177182

183+
// Token modifying expr between start and tok, or nullptr.
184+
const Token* findExpressionChanged(const Token* expr, const Token* start, const Token* tok) const;
185+
178186
ProgramMemory get(const Token* tok, const Token* ctx, const ProgramMemory::Map& vars) const;
179187
};
180188

0 commit comments

Comments
 (0)