--- old/src/java.base/share/classes/java/util/Base64.java 2020-07-27 19:47:13.150913188 -0500 +++ new/src/java.base/share/classes/java/util/Base64.java 2020-07-27 19:47:13.040919810 -0500 @@ -741,9 +741,34 @@ return 3 * (int) ((len + 3L) / 4) - paddings; } - private int decode0(byte[] src, int sp, int sl, byte[] dst) { + // decodeBlock() can be overridden by an arch-specific intrinsic. + // decodeBlock is allowed to not decode all the (legal) bytes that + // are passed to it. It can choose to decode all, none, or a + // variable-sized prefix of the data. This allows the intrinsic to + // decode in chunks of the source that of a favorable size for the + // specific processor it's running on. For example, some + // processors may do better at decoding 256 byte blocks at a time, + // and another type may choose 32 bytes at a time, leaving the (sl + // % block_size) bytes for decodeBlockSlow to finish up. + // + // If any illegal base64 bytes are encountered in the src by the + // intrinsic, the intrinsic can simply return a data length of zero + // or any number of bytes before the place where the illegal + // base64 byte was encountered. In this case, decodeBlockSlow will + // be called to pinpoint the exact cause of the problem, starting + // at the source byte calculated by the returned data length. + // + // If the intrinsic function does not process all of the bytes, + // it should process a multiple of four of the input characters, + // making the returned destination length a multiple of three. + // + @HotSpotIntrinsicCandidate + private int decodeBlock(byte[] src, int sp, int sl, byte[] dst, boolean isURL) { + return 0; + } + + private int decodeBlockSlow(byte[] src, int sp, int sl, byte[] dst, int dp) { int[] base64 = isURL ? fromBase64URL : fromBase64; - int dp = 0; int bits = 0; int shiftto = 18; // pos of first byte of 4-byte atom @@ -820,6 +845,42 @@ } return dp; } + + private int decode0(byte[] src, int sp, int sl, byte[] dst) { + if (isMIME) { + // TODO? Add HotSpot intrinsic candidate for the isMIME == true case + return decodeBlockSlow(src, sp, sl, dst, 0); + } else { + int dl = decodeBlock(src, sp, sl, dst, isURL); + // Calculate how many characters were processed by how + // many bytes of data were returned. + int chars_decoded = ((dl + 2) / 3) * 4; + if (sl > chars_decoded) { + // Base64 characters always come in groups of four, + // producing three bytes of binary data (except for + // on the final four-character piece where it can + // produce one to three data bytes depending on how + // many fill characters there - zero, one, or + // two). The only case where there should be a + // non-multiple of three returned is if the + // intrinsic has processed all of the characters + // passed to it. At this point in the logic, + // however, we know the instrinsic hasn't processed + // all of the chracters. + // + // Round dl down to the nearest three-byte boundary + dl = (dl / 3) * 3; + + // Recalculate chars_decoded based on the rounded dl + chars_decoded = (dl / 3) * 4; + + // Finish the process using decodeBlockSlow + return decodeBlockSlow(src, sp + chars_decoded, sl, dst, dl); + } else { + return dl; + } + } + } } /*