-
Bug
-
Resolution: Fixed
-
P3
-
7
-
b43
-
generic
-
generic
-
Not verified
Here's the critical decoder loop for ASCII
private CoderResult decodeArrayLoop(ByteBuffer src,
CharBuffer dst)
{
byte[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
assert (sp <= sl);
sp = (sp <= sl ? sp : sl);
char[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
assert (dp <= dl);
dp = (dp <= dl ? dp : dl);
try {
while (sp < sl) {
byte b = sa[sp];
if (b >= 0) {
if (dp >= dl)
return CoderResult.OVERFLOW;
da[dp++] = (char)b;
sp++;
continue;
}
return CoderResult.malformedForLength(1);
}
return CoderResult.UNDERFLOW;
} finally {
src.position(sp - src.arrayOffset());
dst.position(dp - dst.arrayOffset());
}
}
We can optimize the inner loop by checking for overflow and underflow at the same time.
private static CoderResult normalResult(ByteBuffer src, int sp,
CharBuffer dst, int dp) {
updateBufferPositions(src, sp, dst, dp);
return src.hasRemaining() ?
CoderResult.OVERFLOW :
CoderResult.UNDERFLOW;
}
private CoderResult decodeArrayLoop(ByteBuffer src,
CharBuffer dst)
{
byte[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
char[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dp + Math.min(src.remaining(),
dst.remaining());
while (dp < dl) {
byte b = sa[sp];
if (b >= 0) {
da[dp++] = (char)b;
sp++;
} else
return coderResult(CoderResult.malformedForLength(1),
src, sp, dst, dp);
}
return normalResult(src, sp, dst, dp);
}
Similarly, for ISO-8859-1, we can optimize thus:
int dl = dp + Math.min(src.remaining(),
dst.remaining());
while (dp < dl) {
da[dp++] = (char)(sa[sp++] & 0xff);
}
return normalResult(src, sp, dst, dp);
For other table-driven single byte decoders,
we can index into a char array instead of adding
a degree of indirection by indexing into a String.
If all bytes are valid, we can eliminate a check for unmappable
characters. For e.g. ISO-8859-15, we are left with the tight inner loop
while (dp < dl) {
da[dp++] = byteToChar[sa[sp++] & 0xff];
}
Simple benchmarking shows approximately a factor of two speedup
of decoding of long random byte sequences.
private CoderResult decodeArrayLoop(ByteBuffer src,
CharBuffer dst)
{
byte[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
assert (sp <= sl);
sp = (sp <= sl ? sp : sl);
char[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dst.arrayOffset() + dst.limit();
assert (dp <= dl);
dp = (dp <= dl ? dp : dl);
try {
while (sp < sl) {
byte b = sa[sp];
if (b >= 0) {
if (dp >= dl)
return CoderResult.OVERFLOW;
da[dp++] = (char)b;
sp++;
continue;
}
return CoderResult.malformedForLength(1);
}
return CoderResult.UNDERFLOW;
} finally {
src.position(sp - src.arrayOffset());
dst.position(dp - dst.arrayOffset());
}
}
We can optimize the inner loop by checking for overflow and underflow at the same time.
private static CoderResult normalResult(ByteBuffer src, int sp,
CharBuffer dst, int dp) {
updateBufferPositions(src, sp, dst, dp);
return src.hasRemaining() ?
CoderResult.OVERFLOW :
CoderResult.UNDERFLOW;
}
private CoderResult decodeArrayLoop(ByteBuffer src,
CharBuffer dst)
{
byte[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sl = src.arrayOffset() + src.limit();
char[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dl = dp + Math.min(src.remaining(),
dst.remaining());
while (dp < dl) {
byte b = sa[sp];
if (b >= 0) {
da[dp++] = (char)b;
sp++;
} else
return coderResult(CoderResult.malformedForLength(1),
src, sp, dst, dp);
}
return normalResult(src, sp, dst, dp);
}
Similarly, for ISO-8859-1, we can optimize thus:
int dl = dp + Math.min(src.remaining(),
dst.remaining());
while (dp < dl) {
da[dp++] = (char)(sa[sp++] & 0xff);
}
return normalResult(src, sp, dst, dp);
For other table-driven single byte decoders,
we can index into a char array instead of adding
a degree of indirection by indexing into a String.
If all bytes are valid, we can eliminate a check for unmappable
characters. For e.g. ISO-8859-15, we are left with the tight inner loop
while (dp < dl) {
da[dp++] = byteToChar[sa[sp++] & 0xff];
}
Simple benchmarking shows approximately a factor of two speedup
of decoding of long random byte sequences.
- relates to
-
JDK-6798572 (cs) test/closed/java/nio/charset/Charset/Contains.java failing since jdk7-b43
-
- Closed
-