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

Different approach for param analysis #320

Merged
merged 2 commits into from
Jun 17, 2019

Conversation

shubhamugare
Copy link
Contributor

@shubhamugare shubhamugare commented Jun 10, 2019

Using a different approach for param nullness analysis in jar-infer
• Pre-calculate all the params that are guaranteed to be non-null in each basic block ( Using the already existing checks)
• looks for a path from entry to exit that doesn't dereference the parameter, if it doesn't exist, it's @NonNull
• This covers all the cases from the current approach. Might take more time in execution than the current approach. computeDerefParamList uses this approach and computeDerefParamListUsingPDom uses the previous approach. Constant flag USE_EXTENDED_APPROACH can be used to switch these approaches.

Added tests

Copy link
Collaborator

@lazaroclapp lazaroclapp left a comment

Choose a reason for hiding this comment

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

Nice approach!

One thing, though: the comments and description don't really match what the code is doing, and I was actually confused for a while trying to build a test case that would fail given the described approach. The actual approach is "look for a path from entry to exit that doesn't dereference the parameter, if it doesn't exist, it's @NonNull". That seems right to me (or, at least, strictly more right than the original approach), but please change the description and comments to more properly document it.

});

// for each param check if there is a path from entry to exit going through basic blocks
// which do not guarantee that the param is non-null
Copy link
Collaborator

Choose a reason for hiding this comment

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

So, not sure this comment is right, the way I understand the code below, it says:

"For each param p, if no path exists from the entry block to the exit block which traverses only basic blocks which do not dereference p, then mark p as @NonNull"

Copy link
Collaborator

Choose a reason for hiding this comment

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

Other than the comment being confusing, this approach actually looks broadly correct to me, with the only issues being:

a) Code sets the argument p when it originally is null such as:

public void test(String s, String t) {
   Objects.requireNonNull(s);
   if (t == null) {
     t = s;
   }
   t.toString();
}

(It's probably fine that we don't handle this, but worth checking if this produces a lot of new false positives for monorepo)

b) The whole other issue about exceptional control flow being pruned that might start to matter the more stuff our analysis catches otherwise.

Also, probably worth checking the performance impact of this vs the original approach. I don't think it should be too bad, since all the time probably went into building the IR and GFG either way, but I think it's worth keeping track.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

a) works because of SSA, since variables are assigned only one time. A new variable(v8) is created

public void test(String s, String t) {
   Objects.requireNonNull(s);
   if (t == null) {
     t = s;
   }
   Objects.requireNonNull(t);
}

13:41:12.302 [DEBUG] [TestEventLogger]                v8 = phi  v3,v2
13:41:12.303 [DEBUG] [TestEventLogger]     9   v10 = invokestatic < Application, Ljava/util/Objects, requireNonNull(Ljava/lang/Object;)Ljava/lang/Object; > v8 @12 exception:v9(line 17)

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh, right, that makes sense. Nice! Could we add that example as a test then? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes.. adding.

Set<Integer> derefedParamList = new HashSet<>();
Map<ISSABasicBlock, Set<Integer>> blockToDerefSetMap = new HashMap<>();

// find which params are definitely non-null in each block
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit, slightly clearer: "find which params are dereferenced (and thus non-null) in each block"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

actually, we test more things than just dereferencing, like precondition and assertions, hence I phrased it like this. And maybe in future we might add more checks which are not just deref too.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe "find which params are treated as being non-null inside each basic block", then? :)

And for the comment on the filter:

"For each param p, if no path exists from the entry block to the exit block which traverses only basic blocks which do not require p being non-null (e.g. by dereferencing it), then mark p as @NonNull"

The main problem I have with "params are definitely non-null in each block" is that it's not clear that they are expected to be non-null on entry vs guaranteed to be non-null by the block.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah..makes sense

@navahgar
Copy link
Contributor

LGTM. Nice Work. Once Lazaro's comments are addressed, I am okay with accepting this.

@shubhamugare shubhamugare force-pushed the param_analysis branch 2 times, most recently from 20865e8 to 1815084 Compare June 12, 2019 20:18
@lazaroclapp
Copy link
Collaborator

@shas19 Travis CI should be fixed by #322 . Can you rebase, please? 😅

Copy link
Contributor

@navahgar navahgar left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Collaborator

@lazaroclapp lazaroclapp left a comment

Choose a reason for hiding this comment

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

Approved!

@shubhamugare shubhamugare merged commit f1b0e3c into uber:master Jun 17, 2019
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.

None yet

3 participants