8274242: Implement fast-path for ASCII-compatible CharsetEncoders on x86

Reviewed-by: naoto, thartmann
This commit is contained in:
Claes Redestad 2021-09-29 12:58:14 +00:00
parent c4d115701d
commit aaa36cc006
28 changed files with 428 additions and 391 deletions

View file

@ -46,7 +46,7 @@ class StringCoding {
@IntrinsicCandidate
public static int implEncodeISOArray(byte[] sa, int sp,
byte[] da, int dp, int len) {
byte[] da, int dp, int len) {
int i = 0;
for (; i < len; i++) {
char c = StringUTF16.getChar(sa, sp++);
@ -57,4 +57,18 @@ class StringCoding {
return i;
}
@IntrinsicCandidate
public static int implEncodeAsciiArray(char[] sa, int sp,
byte[] da, int dp, int len)
{
int i = 0;
for (; i < len; i++) {
char c = sa[sp++];
if (c >= '\u0080')
break;
da[dp++] = (byte)c;
}
return i;
}
}

View file

@ -2419,6 +2419,10 @@ public final class System {
return String.decodeASCII(src, srcOff, dst, dstOff, len);
}
public int encodeASCII(char[] src, int srcOff, byte[] dst, int dstOff, int len) {
return StringCoding.implEncodeAsciiArray(src, srcOff, dst, dstOff, len);
}
public void setCause(Throwable t, Throwable cause) {
t.setCause(cause);
}

View file

@ -356,6 +356,15 @@ public interface JavaLangAccess {
*/
int decodeASCII(byte[] src, int srcOff, char[] dst, int dstOff, int len);
/**
* Encodes ASCII codepoints as possible from the source array into
* the destination byte array, assuming that the encoding is ASCII
* compatible
*
* @return the number of bytes successfully encoded, or 0 if none
*/
int encodeASCII(char[] src, int srcOff, byte[] dst, int dstOff, int len);
/**
* Set the cause of Throwable
* @param cause set t's cause to new value

View file

@ -76,11 +76,11 @@ class CESU_8 extends Unicode
dst.position(dp - dst.arrayOffset());
}
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
private static class Decoder extends CharsetDecoder
implements ArrayDecoder {
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
private Decoder(Charset cs) {
super(cs, 1.0f, 1.0f);
}
@ -434,7 +434,6 @@ class CESU_8 extends Unicode
}
private Surrogate.Parser sgp;
private char[] c2;
private CoderResult encodeArrayLoop(CharBuffer src,
ByteBuffer dst)
{
@ -445,11 +444,12 @@ class CESU_8 extends Unicode
byte[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
int dlASCII = dp + Math.min(sl - sp, dl - dp);
// ASCII only loop
while (dp < dlASCII && sa[sp] < '\u0080')
da[dp++] = (byte) sa[sp++];
// Handle ASCII-only prefix
int n = JLA.encodeASCII(sa, sp, da, dp, Math.min(sl - sp, dl - dp));
sp += n;
dp += n;
while (sp < sl) {
char c = sa[sp];
if (c < 0x80) {
@ -549,11 +549,11 @@ class CESU_8 extends Unicode
public int encode(char[] sa, int sp, int len, byte[] da) {
int sl = sp + len;
int dp = 0;
int dlASCII = dp + Math.min(len, da.length);
// ASCII only optimized loop
while (dp < dlASCII && sa[sp] < '\u0080')
da[dp++] = (byte) sa[sp++];
// Handle ASCII-only prefix
int n = JLA.encodeASCII(sa, sp, da, dp, Math.min(len, da.length));
sp += n;
dp += n;
while (sp < sl) {
char c = sa[sp++];

View file

@ -49,11 +49,11 @@ public class SingleByte
return cr;
}
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
public static final class Decoder extends CharsetDecoder
implements ArrayDecoder {
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
private final char[] b2c;
private final boolean isASCIICompatible;
private final boolean isLatin1Decodable;
@ -214,8 +214,14 @@ public class SingleByte
byte[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
int len = Math.min(dl - dp, sl - sp);
int len = Math.min(dl - dp, sl - sp);
if (isASCIICompatible) {
int n = JLA.encodeASCII(sa, sp, da, dp, len);
sp += n;
dp += n;
len -= n;
}
while (len-- > 0) {
char c = sa[sp];
int b = encode(c);

View file

@ -61,9 +61,9 @@ public class US_ASCII
return new Encoder(this);
}
private static class Decoder extends CharsetDecoder {
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
private static class Decoder extends CharsetDecoder {
private Decoder(Charset cs) {
super(cs, 1.0f, 1.0f);
@ -159,6 +159,10 @@ public class US_ASCII
assert (dp <= dl);
dp = (dp <= dl ? dp : dl);
int n = JLA.encodeASCII(sa, sp, da, dp, Math.min(sl - sp, dl - dp));
sp += n;
dp += n;
try {
while (sp < sl) {
char c = sa[sp];

View file

@ -83,9 +83,9 @@ public final class UTF_8 extends Unicode {
dst.position(dp - dst.arrayOffset());
}
private static class Decoder extends CharsetDecoder {
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
private static class Decoder extends CharsetDecoder {
private Decoder(Charset cs) {
super(cs, 1.0f, 1.0f);
@ -443,8 +443,7 @@ public final class UTF_8 extends Unicode {
private Surrogate.Parser sgp;
private CoderResult encodeArrayLoop(CharBuffer src,
ByteBuffer dst)
{
ByteBuffer dst) {
char[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
@ -452,11 +451,22 @@ public final class UTF_8 extends Unicode {
byte[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
int dlASCII = dp + Math.min(sl - sp, dl - dp);
// ASCII only loop
while (dp < dlASCII && sa[sp] < '\u0080')
da[dp++] = (byte) sa[sp++];
// Handle ASCII-only prefix
int n = JLA.encodeASCII(sa, sp, da, dp, Math.min(sl - sp, dl - dp));
sp += n;
dp += n;
if (sp < sl) {
return encodeArrayLoopSlow(src, sa, sp, sl, dst, da, dp, dl);
} else {
updatePositions(src, sp, dst, dp);
return CoderResult.UNDERFLOW;
}
}
private CoderResult encodeArrayLoopSlow(CharBuffer src, char[] sa, int sp, int sl,
ByteBuffer dst, byte[] da, int dp, int dl) {
while (sp < sl) {
char c = sa[sp];
if (c < 0x80) {