Skip to content
This repository was archived by the owner on Aug 27, 2022. It is now read-only.
/ lanai Public archive

Commit 433096a

Browse files
committedFeb 19, 2021
8261744: Implement CharsetDecoder ASCII and latin-1 fast-paths
Reviewed-by: naoto, alanb
1 parent efbaede commit 433096a

File tree

13 files changed

+452
-262
lines changed

13 files changed

+452
-262
lines changed
 

‎src/java.base/share/classes/java/lang/String.java

+21
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,27 @@ private static byte[] encode8859_1(byte coder, byte[] val, boolean doReplace) {
10081008

10091009
//////////////////////////////// utf8 ////////////////////////////////////
10101010

1011+
/**
1012+
* Decodes ASCII from the source byte array into the destination
1013+
* char array. Used via JavaLangAccess from UTF_8 and other charset
1014+
* decoders.
1015+
*
1016+
* @return the number of bytes successfully decoded, at most len
1017+
*/
1018+
/* package-private */
1019+
static int decodeASCII(byte[] sa, int sp, char[] da, int dp, int len) {
1020+
if (!StringCoding.hasNegatives(sa, sp, len)) {
1021+
StringLatin1.inflate(sa, sp, da, dp, len);
1022+
return len;
1023+
} else {
1024+
int start = sp;
1025+
int end = sp + len;
1026+
while (sp < end && sa[sp] >= 0) {
1027+
da[dp++] = (char) sa[sp++];
1028+
}
1029+
return sp - start;
1030+
}
1031+
}
10111032

10121033
private static boolean isNotContinuation(int b) {
10131034
return (b & 0xc0) != 0x80;

‎src/java.base/share/classes/java/lang/System.java

+13-2
Original file line numberDiff line numberDiff line change
@@ -1981,6 +1981,11 @@ private static Properties createProperties(Map<String, String> initialProps) {
19811981
* Initialize the system class. Called after thread initialization.
19821982
*/
19831983
private static void initPhase1() {
1984+
1985+
// register the shared secrets - do this first, since SystemProps.initProperties
1986+
// might initialize CharsetDecoders that rely on it
1987+
setJavaLangAccess();
1988+
19841989
// VM might invoke JNU_NewStringPlatform() to set those encoding
19851990
// sensitive properties (user.home, user.name, boot.class.path, etc.)
19861991
// during "props" initialization.
@@ -2026,8 +2031,6 @@ private static void initPhase1() {
20262031
Thread current = Thread.currentThread();
20272032
current.getThreadGroup().add(current);
20282033

2029-
// register shared secrets
2030-
setJavaLangAccess();
20312034

20322035
// Subsystems that are invoked during initialization can invoke
20332036
// VM.isBooted() in order to avoid doing things that should
@@ -2277,6 +2280,14 @@ public byte[] getBytesUTF8NoRepl(String s) {
22772280
return String.getBytesUTF8NoRepl(s);
22782281
}
22792282

2283+
public void inflateBytesToChars(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
2284+
StringLatin1.inflate(src, srcOff, dst, dstOff, len);
2285+
}
2286+
2287+
public int decodeASCII(byte[] src, int srcOff, char[] dst, int dstOff, int len) {
2288+
return String.decodeASCII(src, srcOff, dst, dstOff, len);
2289+
}
2290+
22802291
public void setCause(Throwable t, Throwable cause) {
22812292
t.setCause(cause);
22822293
}

‎src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -328,6 +328,19 @@ public interface JavaLangAccess {
328328
*/
329329
byte[] getBytesUTF8NoRepl(String s);
330330

331+
/**
332+
* Inflated copy from byte[] to char[], as defined by StringLatin1.inflate
333+
*/
334+
void inflateBytesToChars(byte[] src, int srcOff, char[] dst, int dstOff, int len);
335+
336+
/**
337+
* Decodes ASCII from the source byte array into the destination
338+
* char array.
339+
*
340+
* @return the number of bytes successfully decoded, at most len
341+
*/
342+
int decodeASCII(byte[] src, int srcOff, char[] dst, int dstOff, int len);
343+
331344
/**
332345
* Set the cause of Throwable
333346
* @param cause set t's cause to new value

‎src/java.base/share/classes/jdk/internal/access/SharedSecrets.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -88,7 +88,7 @@ public static JavaUtilCollectionAccess getJavaUtilCollectionAccess() {
8888
try {
8989
Class.forName("java.util.ImmutableCollections$Access", true, null);
9090
access = javaUtilCollectionAccess;
91-
} catch (ClassNotFoundException e) {};
91+
} catch (ClassNotFoundException e) {}
9292
}
9393
return access;
9494
}
@@ -126,7 +126,7 @@ public static JavaLangInvokeAccess getJavaLangInvokeAccess() {
126126
try {
127127
Class.forName("java.lang.invoke.MethodHandleImpl", true, null);
128128
access = javaLangInvokeAccess;
129-
} catch (ClassNotFoundException e) {};
129+
} catch (ClassNotFoundException e) {}
130130
}
131131
return access;
132132
}

‎src/java.base/share/classes/sun/nio/cs/CESU_8.java

+17-30
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,9 @@
2525

2626
package sun.nio.cs;
2727

28+
import jdk.internal.access.JavaLangAccess;
29+
import jdk.internal.access.SharedSecrets;
30+
2831
import java.nio.Buffer;
2932
import java.nio.ByteBuffer;
3033
import java.nio.CharBuffer;
@@ -75,6 +78,9 @@ private static final void updatePositions(Buffer src, int sp,
7578

7679
private static class Decoder extends CharsetDecoder
7780
implements ArrayDecoder {
81+
82+
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
83+
7884
private Decoder(Charset cs) {
7985
super(cs, 1.0f, 1.0f);
8086
}
@@ -96,27 +102,6 @@ private static boolean isMalformed3_2(int b1, int b2) {
96102
(b2 & 0xc0) != 0x80;
97103
}
98104

99-
100-
// [F0] [90..BF] [80..BF] [80..BF]
101-
// [F1..F3] [80..BF] [80..BF] [80..BF]
102-
// [F4] [80..8F] [80..BF] [80..BF]
103-
// only check 80-be range here, the [0xf0,0x80...] and [0xf4,0x90-...]
104-
// will be checked by Character.isSupplementaryCodePoint(uc)
105-
private static boolean isMalformed4(int b2, int b3, int b4) {
106-
return (b2 & 0xc0) != 0x80 || (b3 & 0xc0) != 0x80 ||
107-
(b4 & 0xc0) != 0x80;
108-
}
109-
110-
// only used when there is less than 4 bytes left in src buffer
111-
private static boolean isMalformed4_2(int b1, int b2) {
112-
return (b1 == 0xf0 && b2 == 0x90) ||
113-
(b2 & 0xc0) != 0x80;
114-
}
115-
116-
private static boolean isMalformed4_3(int b3) {
117-
return (b3 & 0xc0) != 0x80;
118-
}
119-
120105
private static CoderResult malformedN(ByteBuffer src, int nb) {
121106
switch (nb) {
122107
case 1:
@@ -202,17 +187,19 @@ private CoderResult decodeArrayLoop(ByteBuffer src,
202187
{
203188
// This method is optimized for ASCII input.
204189
byte[] sa = src.array();
205-
int sp = src.arrayOffset() + src.position();
206-
int sl = src.arrayOffset() + src.limit();
190+
int soff = src.arrayOffset();
191+
int sp = soff + src.position();
192+
int sl = soff + src.limit();
207193

208194
char[] da = dst.array();
209-
int dp = dst.arrayOffset() + dst.position();
210-
int dl = dst.arrayOffset() + dst.limit();
211-
int dlASCII = dp + Math.min(sl - sp, dl - dp);
195+
int doff = dst.arrayOffset();
196+
int dp = doff + dst.position();
197+
int dl = doff + dst.limit();
198+
199+
int n = JLA.decodeASCII(sa, sp, da, dp, Math.min(sl - sp, dl - dp));
200+
sp += n;
201+
dp += n;
212202

213-
// ASCII only loop
214-
while (dp < dlASCII && sa[sp] >= 0)
215-
da[dp++] = (char) sa[sp++];
216203
while (sp < sl) {
217204
int b1 = sa[sp];
218205
if (b1 >= 0) {

‎src/java.base/share/classes/sun/nio/cs/DoubleByte.java

+20-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2009, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,9 @@
3232
import java.nio.charset.CharsetEncoder;
3333
import java.nio.charset.CoderResult;
3434
import java.util.Arrays;
35+
36+
import jdk.internal.access.JavaLangAccess;
37+
import jdk.internal.access.SharedSecrets;
3538
import sun.nio.cs.Surrogate;
3639
import sun.nio.cs.ArrayDecoder;
3740
import sun.nio.cs.ArrayEncoder;
@@ -111,6 +114,8 @@ public class DoubleByte {
111114
public static class Decoder extends CharsetDecoder
112115
implements DelegatableDecoder, ArrayDecoder
113116
{
117+
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
118+
114119
final char[][] b2c;
115120
final char[] b2cSB;
116121
final int b2Min;
@@ -154,14 +159,21 @@ public Decoder(Charset cs, char[][] b2c, char[] b2cSB, int b2Min, int b2Max) {
154159

155160
protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
156161
byte[] sa = src.array();
157-
int sp = src.arrayOffset() + src.position();
158-
int sl = src.arrayOffset() + src.limit();
162+
int soff = src.arrayOffset();
163+
int sp = soff + src.position();
164+
int sl = soff + src.limit();
159165

160166
char[] da = dst.array();
161-
int dp = dst.arrayOffset() + dst.position();
162-
int dl = dst.arrayOffset() + dst.limit();
167+
int doff = dst.arrayOffset();
168+
int dp = doff + dst.position();
169+
int dl = doff + dst.limit();
163170

164171
try {
172+
if (isASCIICompatible) {
173+
int n = JLA.decodeASCII(sa, sp, da, dp, Math.min(dl - dp, sl - sp));
174+
dp += n;
175+
sp += n;
176+
}
165177
while (sp < sl && dp < dl) {
166178
// inline the decodeSingle/Double() for better performance
167179
int inSize = 1;
@@ -183,8 +195,8 @@ protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
183195
return (sp >= sl) ? CoderResult.UNDERFLOW
184196
: CoderResult.OVERFLOW;
185197
} finally {
186-
src.position(sp - src.arrayOffset());
187-
dst.position(dp - dst.arrayOffset());
198+
src.position(sp - soff);
199+
dst.position(dp - doff);
188200
}
189201
}
190202

@@ -342,7 +354,7 @@ protected CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
342354
else
343355
currentState = SBCS;
344356
} else {
345-
char c = UNMAPPABLE_DECODING;
357+
char c;
346358
if (currentState == SBCS) {
347359
c = b2cSB[b1];
348360
if (c == UNMAPPABLE_DECODING)

‎src/java.base/share/classes/sun/nio/cs/ISO_8859_1.java

+21-21
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,8 @@
3333
import java.nio.charset.CoderResult;
3434
import java.util.Objects;
3535

36+
import jdk.internal.access.JavaLangAccess;
37+
import jdk.internal.access.SharedSecrets;
3638
import jdk.internal.vm.annotation.IntrinsicCandidate;
3739

3840
public class ISO_8859_1
@@ -64,6 +66,8 @@ public CharsetEncoder newEncoder() {
6466

6567
private static class Decoder extends CharsetDecoder {
6668

69+
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
70+
6771
private Decoder(Charset cs) {
6872
super(cs, 1.0f, 1.0f);
6973
}
@@ -72,29 +76,25 @@ private CoderResult decodeArrayLoop(ByteBuffer src,
7276
CharBuffer dst)
7377
{
7478
byte[] sa = src.array();
75-
int sp = src.arrayOffset() + src.position();
76-
int sl = src.arrayOffset() + src.limit();
77-
assert (sp <= sl);
78-
sp = (sp <= sl ? sp : sl);
79+
int soff = src.arrayOffset();
80+
int sp = soff + src.position();
81+
int sl = soff + src.limit();
82+
7983
char[] da = dst.array();
80-
int dp = dst.arrayOffset() + dst.position();
81-
int dl = dst.arrayOffset() + dst.limit();
82-
assert (dp <= dl);
83-
dp = (dp <= dl ? dp : dl);
84+
int doff = dst.arrayOffset();
85+
int dp = doff + dst.position();
86+
int dl = doff + dst.limit();
8487

85-
try {
86-
while (sp < sl) {
87-
byte b = sa[sp];
88-
if (dp >= dl)
89-
return CoderResult.OVERFLOW;
90-
da[dp++] = (char)(b & 0xff);
91-
sp++;
92-
}
93-
return CoderResult.UNDERFLOW;
94-
} finally {
95-
src.position(sp - src.arrayOffset());
96-
dst.position(dp - dst.arrayOffset());
88+
int decodeLen = Math.min(sl - sp, dl - dp);
89+
JLA.inflateBytesToChars(sa, sp, da, dp, decodeLen);
90+
sp += decodeLen;
91+
dp += decodeLen;
92+
src.position(sp - soff);
93+
dst.position(dp - doff);
94+
if (sl - sp > dl - dp) {
95+
return CoderResult.OVERFLOW;
9796
}
97+
return CoderResult.UNDERFLOW;
9898
}
9999

100100
private CoderResult decodeBufferLoop(ByteBuffer src,

‎src/java.base/share/classes/sun/nio/cs/SingleByte.java

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,9 @@
2525

2626
package sun.nio.cs;
2727

28+
import jdk.internal.access.JavaLangAccess;
29+
import jdk.internal.access.SharedSecrets;
30+
2831
import java.nio.Buffer;
2932
import java.nio.ByteBuffer;
3033
import java.nio.CharBuffer;
@@ -48,6 +51,9 @@ private static final CoderResult withResult(CoderResult cr,
4851

4952
public static final class Decoder extends CharsetDecoder
5053
implements ArrayDecoder {
54+
55+
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
56+
5157
private final char[] b2c;
5258
private final boolean isASCIICompatible;
5359
private final boolean isLatin1Decodable;
@@ -88,6 +94,11 @@ private CoderResult decodeArrayLoop(ByteBuffer src, CharBuffer dst) {
8894
cr = CoderResult.OVERFLOW;
8995
}
9096

97+
if (isASCIICompatible) {
98+
int n = JLA.decodeASCII(sa, sp, da, dp, Math.min(dl - dp, sl - sp));
99+
sp += n;
100+
dp += n;
101+
}
91102
while (sp < sl) {
92103
char c = decode(sa[sp]);
93104
if (c == UNMAPPABLE_DECODING) {

0 commit comments

Comments
 (0)
This repository has been archived.