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

8297689: Fix incorrect result of Short.reverseBytes() call in loops #11427

Closed
wants to merge 1 commit into from

Conversation

pfustc
Copy link
Member

@pfustc pfustc commented Nov 30, 2022

Recently, we find calling Short.reverseBytes() in loops may generate incorrect result if the code is compiled by C2. Below is a simple case to reproduce.

class Foo {
  static final int SIZE = 50;
  static int a[] = new int[SIZE];

  static void test() {
    for (int i = 0; i < SIZE; i++) {
      a[i] = Short.reverseBytes((short) a[i]);
    }
  }

  public static void main(String[] args) throws Exception {
    Class.forName("java.lang.Short");
    a[25] = 16;
    test();
    System.out.println(a[25]);
  }
}

// $ java -Xint Foo
// 4096
// $ java -Xcomp -XX:-TieredCompilation -XX:CompileOnly=Foo.test Foo
// 268435456

In this case, the reverseBytes() call is intrinsified and transformed into a ReverseBytesS node. But then C2 compiler incorrectly vectorizes it into ReverseBytesV with int type. C2 Op_ReverseBytes* has short, char, int and long versions. Their behaviors are different for different data sizes. In superword, subword operation itself doesn't have precise data size info. Instead, the data size info comes from memory operations in its use-def chain. Hence, vectorization of reverseBytes() is valid only if the data size is consistent with the type size of the caller's class. But current C2 compiler code lacks fine-grained type checks for ReverseBytes* in vector transformation. It results in reverseBytes() call from Short or Character class with int load/store gets vectorized incorrectly in above case.

To fix the issue, this patch adds more checks in VectorNode::opcode(). T_BYTE is a special case for Op_ReverseBytes*. As the Java Byte class doesn't have reverseBytes() method so there's no Op_ReverseBytesB. But T_BYTE may still appear in VectorAPI calls. In this patch we still use Op_ReverseBytesI for T_BYTE to ensure vector intrinsification succeeds.

Tested with hotspot::hotspot_all_no_apps, jdk tier1~3 and langtools tier1 on x86 and AArch64, no issue is found.


Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed (2 reviews required, with at least 1 Reviewer, 1 Author)

Issue

  • JDK-8297689: Fix incorrect result of Short.reverseBytes() call in loops

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/11427/head:pull/11427
$ git checkout pull/11427

Update a local copy of the PR:
$ git checkout pull/11427
$ git pull https://git.openjdk.org/jdk pull/11427/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 11427

View PR using the GUI difftool:
$ git pr show -t 11427

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/11427.diff

Recently, we find calling `Short.reverseBytes()` in loops may generate
incorrect result if the code is compiled by C2. Below is a simple case
to reproduce.

```
class Foo {
  static final int SIZE = 50;
  static int a[] = new int[SIZE];

  static void test() {
    for (int i = 0; i < SIZE; i++) {
      a[i] = Short.reverseBytes((short) a[i]);
    }
  }

  public static void main(String[] args) throws Exception {
    Class.forName("java.lang.Short");
    a[25] = 16;
    test();
    System.out.println(a[25]);
  }
}

// $ java -Xint Foo
// 4096
// $ java -Xcomp -XX:-TieredCompilation -XX:CompileOnly=Foo.test Foo
// 268435456
```

In this case, the `reverseBytes()` call is intrinsified and transformed
into a `ReverseBytesS` node. But then C2 compiler incorrectly vectorizes
it into `ReverseBytesV` with int type. C2 `Op_ReverseBytes*` has short,
char, int and long versions. Their behaviors are different for different
data sizes. In superword, subword operation itself doesn't have precise
data size info. Instead, the data size info comes from memory operations
in its use-def chain. Hence, vectorization of `reverseBytes()` is valid
only if the data size is consistent with the type size of the caller's
class. But current C2 compiler code lacks fine-grained type checks for
`ReverseBytes*` in vector transformation. It results in `reverseBytes()`
call from Short or Character class with int load/store gets vectorized
incorrectly in above case.

To fix the issue, this patch adds more checks in `VectorNode::opcode()`.
T_BYTE is a special case for `Op_ReverseBytes*`. As the Java Byte class
doesn't have `reverseBytes()` method so there's no `Op_ReverseBytesB`.
But T_BYTE may still appear in VectorAPI calls. In this patch we still
use `Op_ReverseBytesI` for T_BYTE to ensure vector intrinsification
succeeds.

Tested with hotspot::hotspot_all_no_apps, jdk tier1~3 and langtools
tier1 on x86 and AArch64, no issue is found.
@bridgekeeper
Copy link

bridgekeeper bot commented Nov 30, 2022

👋 Welcome back pli! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk openjdk bot added the rfr Pull request is ready for review label Nov 30, 2022
@openjdk
Copy link

openjdk bot commented Nov 30, 2022

@pfustc The following label will be automatically applied to this pull request:

  • hotspot

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added the hotspot hotspot-dev@openjdk.org label Nov 30, 2022
@pfustc
Copy link
Member Author

pfustc commented Nov 30, 2022

/cc hotspot-compiler

@openjdk openjdk bot added the hotspot-compiler hotspot-compiler-dev@openjdk.org label Nov 30, 2022
@openjdk
Copy link

openjdk bot commented Nov 30, 2022

@pfustc
The hotspot-compiler label was successfully added.

@mlbridge
Copy link

mlbridge bot commented Nov 30, 2022

Webrevs

Copy link
Member

@TobiHartmann TobiHartmann left a comment

Choose a reason for hiding this comment

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

This looks reasonable to me but I'm not an expert in that code.

@TobiHartmann
Copy link
Member

/reviewers 2

@openjdk
Copy link

openjdk bot commented Nov 30, 2022

@pfustc This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8297689: Fix incorrect result of Short.reverseBytes() call in loops

Reviewed-by: thartmann, jbhateja

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 98 new commits pushed to the master branch:

  • 73baadc: 8295044: Implementation of Foreign Function and Memory API (Second Preview)
  • bd38188: 8297766: Remove UseMallocOnly development option
  • b9eec96: 8281214: Unsafe use of long in VMThread::setup_periodic_safepoint_if_needed
  • e7e0354: 8297767: Assert JNICritical_lock/safepoint-1 and AdapterHandlerLibrary_lock/safepoint-1
  • f9e0f1d: 8297763: Fix missing stub code expansion before align() in shared trampolines
  • 2300ed4: 8291769: Translation of switch with record patterns could be improved
  • eab0ada: 8296545: C2 Blackholes should allow load optimizations
  • dea2161: 8297959: Provide better descriptions for some Operating System JFR events
  • d523d9d: 8297864: Dead code elimination
  • 777fb52: 8297974: ClassCastException in com.sun.tools.javac.comp.AttrRecover.doRecovery
  • ... and 88 more: https://git.openjdk.org/jdk/compare/abe532a89cbdd2b959789611cecbad7c94f6a870...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Nov 30, 2022
@openjdk
Copy link

openjdk bot commented Nov 30, 2022

@TobiHartmann
The total number of required reviews for this PR (including the jcheck configuration and the last /reviewers command) is now set to 2 (with at least 1 Reviewer, 1 Author).

@openjdk openjdk bot removed the ready Pull request is ready to be integrated label Nov 30, 2022
@pfustc
Copy link
Member Author

pfustc commented Dec 5, 2022

@jatin-bhateja Do you have any comments on this change?

@jatin-bhateja
Copy link
Member

@jatin-bhateja Do you have any comments on this change?

LGTM. Thanks.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Dec 5, 2022
@pfustc
Copy link
Member Author

pfustc commented Dec 6, 2022

Thanks @jatin-bhateja for your review. I will integrate this.

@pfustc
Copy link
Member Author

pfustc commented Dec 6, 2022

/integrate

@openjdk
Copy link

openjdk bot commented Dec 6, 2022

Going to push as commit a613998.
Since your change was applied there have been 119 commits pushed to the master branch:

  • f8f4630: 8297963: Partially fix string expansion issues in UTIL_DEFUN_NAMED and related macros
  • 2a243a3: 8267617: Certificate's IP x509 NameConstraints raises ArrayIndexOutOfBoundsException
  • 923c746: 8298057: (fs) Remove PollingWatchService.POLLING_INIT_DELAY
  • 0bd04a6: 8297951: C2: Create skeleton predicates for all If nodes in loop predication
  • f5ad515: 8297247: Add GarbageCollectorMXBean for Remark and Cleanup pause time in G1
  • e975418: 8298102: Remove DirtyCardToOopClosure::_last_explicit_min_done
  • 04012c4: 8298111: Cleanups after UseMallocOnly removal
  • ee9ba74: 8295184: Printing messages with a RecordComponentElement does not include position
  • ba2d28e: 8298027: Remove SCCS id's from awt jtreg tests
  • 8d8a28f: 8296489: tools/jpackage/windows/WinL10nTest.java fails with timeout
  • ... and 109 more: https://git.openjdk.org/jdk/compare/abe532a89cbdd2b959789611cecbad7c94f6a870...master

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Dec 6, 2022
@openjdk openjdk bot closed this Dec 6, 2022
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Dec 6, 2022
@openjdk
Copy link

openjdk bot commented Dec 6, 2022

@pfustc Pushed as commit a613998.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

@pfustc pfustc deleted the reversebytes branch December 14, 2022 07:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hotspot hotspot-dev@openjdk.org hotspot-compiler hotspot-compiler-dev@openjdk.org integrated Pull request has been integrated
3 participants