--- old/src/java.base/share/classes/java/util/Base64.java 2020-08-17 12:17:11.866235575 -0500 +++ new/src/java.base/share/classes/java/util/Base64.java 2020-08-17 12:17:11.756242195 -0500 @@ -741,9 +741,44 @@ return 3 * (int) ((len + 3L) / 4) - paddings; } - private int decode0(byte[] src, int sp, int sl, byte[] dst) { + /** + * Decodes base64 characters, and returns the number of data bytes + * produced by the base64 decode intrinsic. + * + * decodeBlock() can be overridden by an arch-specific intrinsic. + * decodeBlock can choose to decode all, none, or a variable-sized + * prefix of the source bytes. This allows the intrinsic to decode + * in chunks of the source that are of a favorable size for the + * specific processor it's running on. + * + * If the intrinsic function does not process all of the source + * bytes, it should process a multiple of four of them, making the + * returned destination length a multiple of three. + * + * If any illegal base64 bytes are encountered in the source by the + * intrinsic, the intrinsic can return a data length of zero or any + * number of bytes before the place where the illegal base64 byte + * was encountered. + * + * @param src + * the source byte array of Base64 encoded bytes + * @param sp + * the offset into src array to begin processing + * @param sl + * the total length of source array + * @param dst + * the destination byte array of decoded data bytes + * @param isURL + * boolean, when true decode RFC4648 URL-safe base64 characters + * @return the number of destination data bytes produced + */ + @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 +855,45 @@ } 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; + } + } + } } /*