[9] RFR(S): 8158228: C1 incorrectly folds mismatched loads from stable arrays

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Fri Jun 3 13:28:43 UTC 2016

>> Primarily to keep the code sane :-) Unsafe accesses are the source of mismatched accesses and additional checks are required to filter out all problematic cases. So, I decided to leave them out when enabled constant folding of unsafe loads. My main motivation for the change was to make method handles for field / array element accesses as fast as using bytecode, and mismatched accesses didn't justify all the complications they cause.
> Okay, but in the case of the getChar intrinsic it should be safe to fold the mismatched access without additional checks, right?
Yes, it will. But naive Java implementation does the job as good.

C2 intrinsic has the following code [1]:

bool LibraryCallKit::inline_string_char_access(bool is_store) {
   // Bail when getChar over constants is requested: constant folding would
   // reject folding mismatched char access over byte[]. A normal 
inlining for getChar
   // Java method would constant fold nicely instead.
   if (!is_store && value->is_Con() && index->is_Con()) {
     return false;

You can do the same in C1.

While browsing the code, I noticed the following in j.l.StringUTF16:

     public static char getChar(byte[] val, int index) {
         index <<= 1;
         return (char)(((val[index++] & 0xff) << HI_BYTE_SHIFT) |
                       ((val[index]   & 0xff) << LO_BYTE_SHIFT));

     public static char charAt(byte[] value, int index) {
         if (index < 0 || index >= value.length >> 1) {
             throw new StringIndexOutOfBoundsException(index);
         return getChar(value, index);

_getCharStringU doesn't do any out-of-bounds checks, but 
StringUTF16.getChar() is pervasively used across java.lang.

Is it intentional? I'd expect to see StringUTF16.getChar() private and 
users calling StringUTF16.charAt().

Best regards,
Vladimir Ivanov


More information about the hotspot-compiler-dev mailing list