Skip to content

Fix functions marked 'DANGEROUS' in irep #834

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from

Conversation

reuk
Copy link
Contributor

@reuk reuk commented Apr 15, 2017

This patch introduces a class which abstracts copy-on-write behaviour. This class allows the user to specify whether write should make the object non-shareable. This modified write method makes it safe to give away references to internal fields of the irep. (The technique is discussed here, though the approach has been modified to re-use the small intrusive shared pointer from #786.)

The observable effect of this patch is that code such as the following no longer has unexpected behaviour.

irept a;
auto& comments = a.get_comments();
const auto b(a);
comments.<some mutating method>();
// prior to this patch, b would be modified here
// with the patch applied, b is unaffected

Other benefits of this patch are that it uses RAII properly (all allocation and freeing takes place in constructors and destructors respectively), and that it separates the details of resource management into simple, reusable (unit-testable) classes.

As a side effect of this change, I discovered a bug in ansi-c/padding where the insert on line 262 invalidates the iterators in the vector, which had the possibility of making the reference on line 206 dangle, leading to undefined behaviour on line 269 when the reference was passed to a function. Taking a copy instead of a reference fixes the bug.

@reuk reuk force-pushed the small-shared-ptr branch 5 times, most recently from 6b86d5e to 4c222b4 Compare April 15, 2017 19:42
@tautschnig
Copy link
Collaborator

Overall this now looks good to me. Yet, as said before, those changes need a proper performance test to be in place. Thus it would be great to factor out the bug fix of the padding code into a separate pull request as that should be merged as soon as possible.

@reuk
Copy link
Contributor Author

reuk commented Apr 16, 2017

The fix for the padding bug is now in #836.

Regarding the performance test: This patch fixes a bug in irep's copy-on-write implementation, and improves the modularity and readability of the code, while keeping the memory usage the same as the existing irep. I'd argue that, even if this change is slightly slower, it's still worthwhile in terms of maintainability and avoiding programmer error. I understand that performance is important, but it should not come at the expense of correctness.

@tautschnig
Copy link
Collaborator

I am not in a position to make the ultimate call, but I'd refuse a change to this core data structure without proper performance testing. Indeed the performance might even improve here - but "slightly slower" would be a major difference when talking about 10^10 calls, which we see even on small benchmarks.

This is no criticism of any sorts, and indeed I highly appreciate this work and the improvements it is bringing about. As this isn't a beauty contest, we need data, not high judgement.

@reuk reuk force-pushed the small-shared-ptr branch from 4c222b4 to c9a7297 Compare April 18, 2017 12:56
@tautschnig tautschnig changed the base branch from master to develop August 22, 2017 12:30
@reuk reuk force-pushed the small-shared-ptr branch 3 times, most recently from 2d11ecf to 3e6b79e Compare August 24, 2017 09:30
@tautschnig
Copy link
Collaborator

@reuk Could you please rebase this one? It should be a trivial rebase, but I'd like to run a decent performance comparison against current develop. An initial run with the current state looks good, but I'd like to be clinical here.

@reuk
Copy link
Contributor Author

reuk commented Dec 4, 2017

@tautschnig This is rebased now

@tautschnig tautschnig assigned tautschnig and unassigned reuk Dec 4, 2017
@tautschnig
Copy link
Collaborator

I have run the performance comparison and would estimate the overhead (if any) at 1%, which seems acceptable to me. I still need to properly re-read the code, it's been a while.

@tautschnig
Copy link
Collaborator

(And of course the Travis failures are worrying ...)

@reuk
Copy link
Contributor Author

reuk commented Dec 4, 2017

The segfaults appear to be because ireps are now shared more conservatively, and copies are made more frequently. The first segfault I found looks like this:

  exprt &op0=code.op0().op0();

  op0.operands().push_back(exprt("cpp-this"));
  op0.type()=
    pointer_type(cpp_namet(parent_base_name, source_location).as_type());
  op0.add_source_location()=source_location;

  code.operands().push_back(exprt("explicit-typecast"));
  exprt &op1=code.op1();

  op0.type()=
    pointer_type(cpp_namet(parent_base_name, source_location).as_type());

We take a reference into a vector op0, then call push_back on the vector, and finally try to write to the initial object. This shouldn't work for any type with value semantics (we shouldn't depend on references staying valid after calling push_back), so it's not surprising that it breaks here. However, fixing all of these segfaults may be kind of time-consuming.

@reuk
Copy link
Contributor Author

reuk commented Dec 4, 2017

I've got the go-ahead from @pkesseli to spend half a day on this. I'll try to fix as many of the segfaults as I can, after which I may have to delegate this work to someone else.

@reuk
Copy link
Contributor Author

reuk commented Dec 4, 2017

Looks like all the segfaults have the same cause... which was a copy-paste bug I introduced a few months ago while I was 'fixing' code to do with setting pointer_typet invariants. Sorry about that.

@reuk
Copy link
Contributor Author

reuk commented Dec 5, 2017

@tautschnig This passes CI now, could you take another look please?

@reuk reuk force-pushed the small-shared-ptr branch 2 times, most recently from 83f4f2c to 286e576 Compare December 5, 2017 15:39
@reuk
Copy link
Contributor Author

reuk commented Dec 5, 2017

@tautschnig this should be ready for re-review now

Copy link
Collaborator

@tautschnig tautschnig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Assigning to @kroening for a final opinion.

@tautschnig tautschnig removed their assignment Dec 5, 2017
@kroening
Copy link
Member

kroening commented Dec 7, 2017

Squash 286e5765 into c2b1b00?

@reuk reuk force-pushed the small-shared-ptr branch from d1b5653 to ec4f0ff Compare December 7, 2017 14:34
@reuk
Copy link
Contributor Author

reuk commented Dec 7, 2017

@kroening done

reuk added 3 commits December 7, 2017 17:21
Calling push_back on a vector invalidates references that previously
pointed to objects stored in the vector.
@reuk reuk force-pushed the small-shared-ptr branch from ec4f0ff to 20692b0 Compare December 7, 2017 17:22
@reuk reuk requested review from forejtv and thk123 as code owners December 7, 2017 17:22
@tautschnig
Copy link
Collaborator

@reuk Could you please drop 20692b0 so that this can be merged?

@tautschnig tautschnig assigned reuk and unassigned kroening Dec 8, 2017
@reuk reuk force-pushed the small-shared-ptr branch from 20692b0 to 3a6c0fd Compare December 9, 2017 10:39
@reuk
Copy link
Contributor Author

reuk commented Dec 11, 2017

This should be mergeable now

@reuk
Copy link
Contributor Author

reuk commented Dec 11, 2017

Sorry, I think an edit to the second commit got lost somewhere. Hold off on this for now

@smowton
Copy link
Contributor

smowton commented Jan 5, 2018

@reuk are you still attending to these, or should someone take it over?

@reuk
Copy link
Contributor Author

reuk commented Jan 7, 2018

Yes, someone should take ownership of this. In the second commit, the method call should be on op1 instead of op0 - I introduced a typo a while ago (check git blame on that file). Other than that, it's ready to go.

@tautschnig
Copy link
Collaborator

I have created #1704 to selectively fix the typo. @reuk, would it be feasible (given you might have totally different commitments these days) for you to just drop the second commit from this PR? I would seemingly be the most efficient approach.

@owen-mc-diffblue
Copy link
Contributor

owen-mc-diffblue commented Jan 16, 2018

I asked @reuk about this yesterday and he said it would be better if other people took over his branches. I've made #1742 which is a rebased copy of this PR with the commit that @tautschnig mentioned dropped.

@tautschnig
Copy link
Collaborator

@owen-jones-diffblue, @reuk Thank you!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants