JDK-8056950 : Compiled code (64-bit) on SPARC should sign extend INT parameters passed on registers to runtime or native methods.
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 9
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: sparc
  • Submitted: 2014-08-29
  • Updated: 2017-08-09
  • Resolved: 2016-07-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9 b131Fixed
Related Reports
Relates :  
Relates :  
Description
SPARC ABI says:

http://docs.oracle.com/cd/E26502_01/html/E28387/gentextid-2734.html#scrolltoc

"Integer data types smaller then a slot are passed in the lower part of that slot. For 64-bit code, where a smaller integer type (int, short, char) parameter is passed in a register, the caller must sign extend or zero extend the value to the full 64-bit slot width. Similarly, in 64-bit code where a smaller integer type is returned in a register, the callee must sign extend or zero extend the value to the full 64-bit slot width. In 32-bit code, there is no requirement for sign or zero extensions, and only the lower bits of the values should be used."

Both GCC and SunStudio compilers do that. Unfortunately JITed (and other) code in Hotspot does not do that.

In 8049542 case compiled code reads integer field value -1 (0x00000000ffffffff) using LDUW instruction and then adds +2 which produces huge long value (0x0000000100000001). It is passed then the value in O1 register to runtime method (new_array_C). Without sign extension when expanding INT argument to LONG (as runtime code produced by GCC does) we get huge value (new array length) instead of 0x2.

What saved us before is SunStudio compilers do sign extension of INT arguments in callee method when expanding INT to LONG.

Comments
There are three parts to this: 1.) generate_native_wrapper(). The native wrapper should do the sign extensions for the smaller ints. This was missing when 8056950 was opened, but fixed by "8148353: [linux-sparc] Crash in libawt.so on Linux SPARC" in the meantime. http://hg.openjdk.java.net/jdk9/hs/hotspot/rev/1f4f4866aee0 2.) Stubs called directly like updateBytesCRC32C. If the C2 compiler passes an int to these it is not correctly sign extended. updateBytesCRC32C and most others are implemented in assembly, so one can assure proper 32-bit instructions are used. A problem are stubs implemented in C, as montgomery_square() on ppc. On ppc we solved this with a trick in the platform implementations, see sharedRuntime_ppc.cpp:3445, "len = len & 0x7fffFFFF;" Montgomery is not implemented on sparc, though. I did not find any other similar on sparc. 3.) The optoStubs generated by the C2 compiler. The C2 compiler will insert proper casts here if CCallingConventionRequiresIntsAsLongs is set. So this needs to be set on sparc.
11-07-2016

Now that ppc64 has introduced CCallingConventionRequiresIntsAsLongs, will setting it to true fix this bug?
18-12-2015

ILW=Generating faulty code, some cases when getting an overflow, none=HLH=P2
02-09-2014