Skip to content

JCI: don't load method instructions #3447

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

Conversation

smowton
Copy link
Contributor

@smowton smowton commented Nov 19, 2018

This speeds loading 40000 classes up by around 3x when the consumer isn't interested in the method bodies. (Use case: in the security product we found it useful to inspect class metadata using the same parser as will be used in jbmc, to ensure consistency between the two processes)

@smowton smowton force-pushed the smowton/feature/java-parse-without-instructions branch from 055a9a8 to 30aad53 Compare November 20, 2018 09:48
Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

✔️
Passed Diffblue compatibility checks (cbmc commit: 30aad53).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/91986750

{
REQUIRE(loaded_class.parsed_class.methods.size() == 1);

const auto &method = *loaded_class.parsed_class.methods.begin();
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Add a check here that the loaded class at least has the member variable x
I would also extend to check:

  • accessibility of class
  • inner class loaded
  • accessibility of method
  • annotations on method
  • accessibility / annotations of fields
  • type hierarchy
  • a non constructor

@@ -78,6 +80,7 @@ class java_bytecode_parsert:public parsert
};

std::vector<bytecodet> bytecodes;
bool skip_instructions;
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️

Suggested change
bool skip_instructions;
bool skip_instructions = false;

if someone adds a new constructor and forgets to initialise this field we won't be left in UB

@smowton smowton force-pushed the smowton/feature/java-parse-without-instructions branch from 30aad53 to 37539f2 Compare November 22, 2018 11:38
@smowton
Copy link
Contributor Author

smowton commented Nov 22, 2018

@thk123 I've added a test for a non-constructor -- the other attributes ought to have nothing to do with the dont-load-instructions flag, so I won't include those in this test

@thk123
Copy link
Contributor

thk123 commented Nov 22, 2018

ought to have nothing to do with the dont-load-instructions flag

That's why I thought a test would be good, to ensure doesn't accidentally not load too much - but approved anyway

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

✔️
Passed Diffblue compatibility checks (cbmc commit: 37539f2).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/92286213

@smowton smowton force-pushed the smowton/feature/java-parse-without-instructions branch from 37539f2 to 75d8ee3 Compare November 22, 2018 14:58
@smowton
Copy link
Contributor Author

smowton commented Nov 22, 2018

Ah, got you -- added such checks

"java_bytecode_parse_class_without_instructions",
"[core][java_bytecode][java_bytecode_parser]")
{
null_message_handlert null_out;
Copy link
Collaborator

Choose a reason for hiding this comment

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

We have a global null_message_handler in the unit tests, no need for that one.

@@ -1215,7 +1218,7 @@ void java_bytecode_parsert::rmethod_attribute(methodt &method)

irep_idt attribute_name=pool_entry(attribute_name_index).s;

if(attribute_name=="Code")
if(attribute_name=="Code" && !skip_instructions)
Copy link
Collaborator

Choose a reason for hiding this comment

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

clang-format will require adding space around ==

{
get_bytecodes();
if(!skip_instructions)
get_bytecodes();
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 a bit surprised that we both need a class member and this branch here. But that may just be down to my limited understanding of the code 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.

The method is badly named: this actually initialises a lookup table of possible bytecodes (only used within rbytecodes)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe the if(!skip_instructions) should be moved into this method as if(skip_instructions) return; - you need to know what the method does in order to know whether you can skip it, and therefore to me it would seem better to place the condition with the implementation.

@@ -78,6 +80,7 @@ class java_bytecode_parsert:public parsert
};

std::vector<bytecodet> bytecodes;
bool skip_instructions = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

const ?

@@ -16,10 +16,28 @@ Author: Daniel Kroening, kroening@kroening.com

struct java_bytecode_parse_treet;

/// Attempt to parse a Java class from the given file.
/// \param file: file to load from
/// \param msg: gets log messages
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ "gets" doesn't seem right here, maybe "handles"?

/// \param msg: gets log messages
/// \param skip_instructions: if true, the loaded class's methods will all be
/// empty. Saves time and memory for consumers that only want signature info.
/// \return parse tree, or Empty on failure
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ not sure "Empty" should be capitalized 🦅

/// \param msg: gets log messages
/// \param skip_instructions: if true, the loaded class's methods will all be
/// empty. Saves time and memory for consumers that only want signature info.
/// \return parse tree, or Empty on failure
Copy link
Contributor

Choose a reason for hiding this comment

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

🦅

REQUIRE(loaded_class.is_inner_class);
REQUIRE(loaded_class.outer_class == "Trivial");

const auto &fieldone = *loaded_class.fields.begin();
Copy link
Contributor

Choose a reason for hiding this comment

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

⛏️ field_one or field1

@smowton smowton force-pushed the smowton/feature/java-parse-without-instructions branch from 75d8ee3 to e1388e1 Compare November 22, 2018 15:33

java_bytecode_parse(
const std::string &file,
class message_handlert &msg,
Copy link
Member

Choose a reason for hiding this comment

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

class keyword seems unnecessary (more occurrences)

This speeds loading 40000 classes up by around 3x.
@smowton smowton force-pushed the smowton/feature/java-parse-without-instructions branch from e1388e1 to 8f7f8ae Compare November 22, 2018 16:18
Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

🚫
This PR failed Diffblue compatibility checks (cbmc commit: e1388e1).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/92313175
Status will be re-evaluated on next push.
Please contact @peterschrammel, @thk123, or @allredj for support.

Common spurious failures:

  • the cbmc commit has disappeared in the mean time (e.g. in a force-push)
  • the author is not in the list of contributors (e.g. first-time contributors).

The incompatibility may have been introduced by an earlier PR. In that case merging this
PR should be avoided unless it fixes the current incompatibility.

Copy link
Contributor

@allredj allredj left a comment

Choose a reason for hiding this comment

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

✔️
Passed Diffblue compatibility checks (cbmc commit: 8f7f8ae).
Build URL: https://travis-ci.com/diffblue/test-gen/builds/92316672

@smowton smowton merged commit d7645fd into diffblue:develop Nov 23, 2018
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.

6 participants