Skip to content
Closed
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -734,8 +734,9 @@ public Void visitUnary(UnaryTree tree, AnnotatedTypeMirror type) {
// explicit nullable annotations are left intact for the visitor to inspect.
@Override
public Void visitNewClass(NewClassTree tree, AnnotatedTypeMirror type) {
// The constructor return type should already be NONNULL, so in most cases this will do
// nothing.
if (type.hasEffectiveAnnotation(NONNULL)) {
return null;
}
type.addMissingAnnotation(NONNULL);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

addMissingAnnotation already checks whether the annotation is present, so this change doesn't achieve anything.

Do you actually see any performance differences?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for the detailed discussion.

I added a small perf harness to measure the effect of the extra hasEffectiveAnnotation(NONNULL) fast-path.

  • Test file: checker/jtreg/nullness/perf/NewClassPerf.java
    This generates a synthetic source with thousands of new expressions and compares two variants:

    • A = fast-path enabled (extra if)
    • B = fast-path disabled (-Dcf.skipNonnullFastPath=true)
  • How to run:

    ../jtreg/bin/jtreg \
      -workDir:checker/build/jtreg/perf/work \
      -reportDir:checker/build/jtreg/perf/report \
      -verbose:summary -samevm '-keywords:!ignore' \
      "-javacoptions:-classpath checker/dist/checker.jar" \
      "-vmoptions:-classpath checker/dist/checker.jar -Xms2g -Xmx2g \
        -Dperf.runs=10 -Dperf.groups=400" \
      -timeoutFactor:4 \
      checker/jtreg/nullness/perf/NewClassPerf.java
  • Results (10×400 runs, fixed 2 GB heap, JDK 17, macOS arm64):
    Across both AB and BA interleaved protocols, variant B was consistently as fast or slightly faster (≈2–3% median). In other words, the new if does not bring a measurable benefit, as you mentioned addMissingAnnotation already checks for existing annotations, so the extra condition only adds overhead.

Final conclusion: After all these investigations, it shows that the repeated visitNewClass calls are expected: multiple sub-checkers walk the same AST. This is not a defect, and at this point we don’t see a straightforward or sound optimization to reduce it. I’ll therefore retitle this PR as an investigation and propose to close it.

return null;
}
Expand All @@ -745,7 +746,9 @@ public Void visitNewClass(NewClassTree tree, AnnotatedTypeMirror type) {
@Override
public Void visitNewArray(NewArrayTree tree, AnnotatedTypeMirror type) {
super.visitNewArray(tree, type);
type.addMissingAnnotation(NONNULL);
if (!type.hasEffectiveAnnotation(NONNULL)) {
type.addMissingAnnotation(NONNULL);
}
return null;
}

Expand Down