Skip to content
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

[TG-2356] skip basic block instrumentation from virtual call removal #1812

Conversation

mgudemann
Copy link
Contributor

@mgudemann mgudemann commented Feb 8, 2018

When a virtual function call is encountered in Java, we replace it by explicit calls to all possible implementing object types.

The coverage instrumentation does not allow for a single bytecode index (the virtual call) to be instrumented several times, which makes sense, as only a single such instrumentation can be placed at the bytecode.

In the current implementation, a coverage property was placed right after the first guarded GOTO, but not on succeeding ones, leading to the situation that coverage was reported differently, depending on the order implementing classes were found. This patch removes instrumentation of GOTO instructions generated via remove_virtual_functions altogether, the function call is considered to be completed and covered if the final target t_final is reached. This is the target for each concrete function call.

{
return get_bool(ID_C_java_removed_virtual_call);
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm failing to parse the commit message for this one, and I'm not too happy to have Java-specific APIs enter something as general as a source_locationt? You might play the same game as is done with various other irept-children and introduce a java_source_locationt that has those extra functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@tautschnig I don't mind, but please note that source_locationt already has get_java_bytecode_index

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe you can fix that all in one go?

Copy link
Contributor

Choose a reason for hiding this comment

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

As this is a fairly large refactoring I've raised an issue (#1824) to tackle this separately.

@mgudemann mgudemann force-pushed the feature/skip_basic_blocks_from_virtual_call_removal branch 5 times, most recently from 2b16c13 to 9690e9c Compare February 8, 2018 16:07
Copy link
Contributor

@thk123 thk123 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, but the final commit should be squashed into the unit tests commit (or introduced before it) so that each commit compiles (also confusingly GH shows Add possibility to mark instructions to source_locationt before Skip instructions from virtual call removal from instrumentation but this is just GH being weird.

THEN("instrumentation assertions are inserted")
{
REQUIRE(
!instrument_cover_goals(
Copy link
Contributor

Choose a reason for hiding this comment

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

What does this check? REQUIRE_FALSE might be clearer here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nothing much beyond verifying that instrumentation has been done

// originating from a java virtual function call removal
if(
i_it->source_location == source_locationt::nil() ||
!i_it->source_location.get_java_removed_virtual_call())
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this commit may be in the wrong order as I don't think this function has been introduced yet.

{
return get_bool(ID_C_java_removed_virtual_call);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

As this is a fairly large refactoring I've raised an issue (#1824) to tackle this separately.

REQUIRE(function != new_goto_functions.function_map.end());

const goto_programt &goto_program = function->second.body;
for(auto it = goto_program.instructions.begin();
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this not just be a range based for loop?

Copy link
Contributor

Choose a reason for hiding this comment

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

Or since you are actually just looking for a specific find, perhaps:

std::find(
  goto_program.instructions.begin(), 
  goto_program.instructions.end(), 
  [](const instructiont &instruction) {
    return instruction.type==goto_program_instruction_typet::GOTO &&
      instruction.guard.id() == ID_equal;
  });

This has the advantage you can require that you find the relevant instruction and make it clear you're only looking for the first equal guarded goto.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

converted to std::find_if

@@ -94,12 +94,12 @@ INCLUDES= -I ..

LIBS =

CLEANFILES = goto-instrument$(EXEEXT)
CLEANFILES = goto-instrument$(EXEEXT) goto-instrument$(LIBEXT)
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps the intent was already there, but this should be squashed with the commit that introduces the unit tests so that they compile.

instrument(goto_program, i_it, basic_blocks);
// do not instrument if instruction has a source location but is marked as
// originating from a java virtual function call removal
if(
Copy link
Member

Choose a reason for hiding this comment

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

This is misplaced - it should be implemented as a goal filter, see e.g. https://github.com/diffblue/cbmc/blob/develop/src/goto-instrument/cover_filter.cpp#L96

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done, it's now part of bool internal_goals_filtert::operator()(const source_locationt &source_location) const

@mgudemann mgudemann force-pushed the feature/skip_basic_blocks_from_virtual_call_removal branch 4 times, most recently from 8a15359 to ca7cbbf Compare February 13, 2018 14:56
Matthias Güdemann added 4 commits February 13, 2018 17:19
@mgudemann mgudemann force-pushed the feature/skip_basic_blocks_from_virtual_call_removal branch from ca7cbbf to e7cf6c6 Compare February 13, 2018 16:26
"call and there is no GOTO ASSERT")
{
const source_locationt &loc = it->source_location;
REQUIRE(
Copy link
Contributor

Choose a reason for hiding this comment

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

The printer deals better with simple statements, perhaps:

REQUIRE(loc != source_locationt::nil());
REQUIRE_FALSE(loc.get_java_bytecode_index().empty());

@mgudemann mgudemann force-pushed the feature/skip_basic_blocks_from_virtual_call_removal branch from e7cf6c6 to d0aea6e Compare February 13, 2018 16:38
Copy link
Member

@peterschrammel peterschrammel left a comment

Choose a reason for hiding this comment

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

Apart from #1824, this looks ok. The underlying problem that this tries to solve is more generally solved in #1830, though. So, I actually think that this PR is redundant.

@mgudemann
Copy link
Contributor Author

@peterschrammel I see the point, #1830 seems to be more generic. On the other hand, it might introduce a superfluous coverage property, e.g., for virtual calls the first guarded GOTO will always be reached so this basic block is always covered. Then again, this is likely harmless.

@peterschrammel
Copy link
Member

Yes, #1830 is not optimal. We measured on tika that we could decrease the number of coverage goals by 15-20% by making the instrumentation proposed in #1830 more sparse.

@NlightNFotis
Copy link
Contributor

Hello.

I'm closing this PR as it appears stale and no longer in sync with the repository. Feel free to reopen it if you feel it adds enough value and should be merged, but in that case this will need to be rebased on top of branch develop first.

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