ProgramMemory: only copy mValues on write#6646
ProgramMemory: only copy mValues on write#6646chrchr-github merged 6 commits intocppcheck-opensource:mainfrom
mValues on write#6646Conversation
|
Some unit tests (e.g. There may also be unnecessary copies introduced by my changes related to |
| copyOnWrite(); | ||
| pm.copyOnWrite(); | ||
|
|
||
| mValues->swap(*pm.mValues); |
There was a problem hiding this comment.
Should be mValues.swap(pm.mValues).
|
|
||
| void ProgramMemory::copyOnWrite() | ||
| { | ||
| if (!mCopyValues) |
There was a problem hiding this comment.
There is no need for the mCopyValues variable. Just check mValues.use_count() == 1 instead.
| mValues = other.mValues; | ||
| mCopyValues = true; | ||
| return *this; | ||
| } |
There was a problem hiding this comment.
Just use the default-generated copy constructor and assignment.
There was a problem hiding this comment.
Without the need for mCopyValues I can do taht now.
It would have also required the move constructor/assignment.
| using ProgramState = ProgramMemory::Map; | ||
|
|
||
| virtual ProgramState getProgramState() const = 0; | ||
| virtual std::shared_ptr<ProgramState> getProgramState() const = 0; |
There was a problem hiding this comment.
Why is this changed to a shared_ptr? Its never shared.
There was a problem hiding this comment.
Because it is used to construct a ProgramMemory object in ValueFlowAnalyzer::evaluateInt().
There was a problem hiding this comment.
But you can just move it instead.
mValues [skip ci]mValues
|
With the first round of review comments addressed the unit tests now all pass. Here some preliminary numbers (without having looked at the profiling data if everything is on the up and up).
Clang 17 The example from https://trac.cppcheck.net/ticket/10765#comment:4: Clang 17 |
| ProgramMemory() : mValues(new Map()) {} | ||
|
|
||
| explicit ProgramMemory(Map values) : mValues(std::move(values)) {} | ||
| explicit ProgramMemory(std::shared_ptr<Map> values) : mValues(std::move(values)) {} |
There was a problem hiding this comment.
This should not need to be changed to a shared_ptr, you can implement it as:
explicit ProgramMemory(Map values) : mValues(new Map()) {
*mValues = std::move(values);
}There was a problem hiding this comment.
Done. Did it even simpler by moving it into the constructor.
|
|
||
| Map::iterator begin() { | ||
| return mValues.begin(); | ||
| return mValues->begin(); |
There was a problem hiding this comment.
lacks copyOnWrite() as it returns something mutable.
|
|
||
| Map::iterator end() { | ||
| return mValues.end(); | ||
| return mValues->end(); |
There was a problem hiding this comment.
lacks copyOnWrite() as it returns something mutable.
6704722 to
25ec10a
Compare
|
I added some more early outs (might split those into a separate commit later) and removed some unused code. |
30284cc to
4454389
Compare
mValuesmValues on write
|
Unfortunately this does not seem to help much with the selfcheck. ☹ |
Co-authored-by: Paul Fultz II <paul.fultz@amd.com>
…ang-tidy warning
| // TODO: how to delay until we actuallly modify? | ||
| copyOnWrite(); | ||
|
|
||
| for (auto it = mValues->begin(); it != mValues->end();) { |
There was a problem hiding this comment.
Can't this be written as remove-erase?
There was a problem hiding this comment.
Possibly but that would not fix the TODO and just clean up the code.
There was a problem hiding this comment.
If the call to remove_if() returns end(), no modification takes place, or am I missing something?
There was a problem hiding this comment.
But we would have to determine if a modification happens, then make the copy and afterwards iterate it again because the existing result is based on a different container.
We only need to make this optimization if it is a hot spot.
There was a problem hiding this comment.
remove_if wouldn't work here anyway: https://stackoverflow.com/questions/9210014/remove-elements-from-an-unordered-map-fulfilling-a-predicate
| ProgramMemory() : mValues(new Map()) {} | ||
|
|
||
| explicit ProgramMemory(Map values) : mValues(std::move(values)) {} | ||
| explicit ProgramMemory(Map values) : mValues(new Map(std::move(values))) {} |
There was a problem hiding this comment.
That would construct a shared_ptr object with an shared_ptr which is unnecessary.
No description provided.