Skip to content

Commit 0f7645c

Browse files
authored
Merge pull request #19607 from pshipton/split0.46
(0.46) jdk11 always create compact Strings when possible
2 parents d22a436 + 9bd7fc5 commit 0f7645c

File tree

3 files changed

+81
-42
lines changed

3 files changed

+81
-42
lines changed

jcl/src/java.base/share/classes/com/ibm/jit/JITHelpers.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,19 @@ public char getCharFromArrayByIndex(Object obj, int index) {
566566
}
567567
}
568568

569+
public boolean canEncodeAsLatin1(byte[] array, int start, int length) {
570+
int index = start << 1;
571+
if (!IS_BIG_ENDIAN) {
572+
index += 1;
573+
}
574+
for (int end = index + (length << 1); index < end; index += 2) {
575+
if (array[index] != 0) {
576+
return false;
577+
}
578+
}
579+
return true;
580+
}
581+
569582
/**
570583
* Returns the first index of the target character array within the source character array starting from the specified
571584
* offset.

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

Lines changed: 56 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -805,7 +805,7 @@ public String(char[] data, int start, int length) {
805805
}
806806
}
807807

808-
String(byte[] data, int start, int length, boolean compressed) {
808+
private String(byte[] data, int start, int length, boolean compressed) {
809809
if (length == 0) {
810810
value = emptyValue;
811811

@@ -824,19 +824,25 @@ public String(char[] data, int start, int length) {
824824
} else {
825825
char theChar = helpers.getCharFromArrayByIndex(data, start);
826826

827-
if (theChar <= 255) {
828-
value = decompressedAsciiTable[theChar];
827+
if (COMPACT_STRINGS && (theChar <= 255)) {
828+
value = compressedAsciiTable[theChar];
829+
coder = LATIN1;
830+
hash = theChar;
829831
} else {
830-
value = new byte[2];
832+
if (theChar <= 255) {
833+
value = decompressedAsciiTable[theChar];
834+
} else {
835+
value = new byte[2];
831836

832-
helpers.putCharInArrayByIndex(value, 0, theChar);
833-
}
837+
helpers.putCharInArrayByIndex(value, 0, theChar);
838+
}
834839

835-
coder = UTF16;
836-
hash = theChar;
840+
coder = UTF16;
841+
hash = theChar;
837842

838-
if (COMPACT_STRINGS) {
839-
initCompressionFlag();
843+
if (COMPACT_STRINGS) {
844+
initCompressionFlag();
845+
}
840846
}
841847
}
842848
} else {
@@ -845,17 +851,19 @@ public String(char[] data, int start, int length) {
845851
value = data;
846852
} else {
847853
value = new byte[length];
848-
849854
compressedArrayCopy(data, start, value, 0, length);
850855
}
851856

857+
coder = LATIN1;
858+
} else if (COMPACT_STRINGS && helpers.canEncodeAsLatin1(data, start, length)) {
859+
value = new byte[length];
860+
compress(data, start, value, 0, length);
852861
coder = LATIN1;
853862
} else {
854863
if (start == 0 && data.length == length * 2) {
855864
value = data;
856865
} else {
857866
value = StringUTF16.newBytesFor(length);
858-
859867
decompressedArrayCopy(data, start, value, 0, length);
860868
}
861869

@@ -868,7 +876,7 @@ public String(char[] data, int start, int length) {
868876
}
869877
}
870878

871-
String(byte[] data, int start, int length, boolean compressed, boolean sharingIsAllowed) {
879+
private String(byte[] data, int start, int length, boolean compressed, boolean sharingIsAllowed) {
872880
if (length == 0) {
873881
value = emptyValue;
874882

@@ -887,41 +895,38 @@ public String(char[] data, int start, int length) {
887895
} else {
888896
char theChar = helpers.getCharFromArrayByIndex(data, start);
889897

890-
if (theChar <= 255) {
891-
value = decompressedAsciiTable[theChar];
898+
if (COMPACT_STRINGS && (theChar <= 255)) {
899+
value = compressedAsciiTable[theChar];
900+
coder = LATIN1;
901+
hash = theChar;
892902
} else {
893-
value = new byte[2];
894-
895-
helpers.putCharInArrayByIndex(value, 0, theChar);
896-
}
903+
if (theChar <= 255) {
904+
value = decompressedAsciiTable[theChar];
905+
} else {
906+
value = new byte[2];
907+
helpers.putCharInArrayByIndex(value, 0, theChar);
908+
}
897909

898-
coder = UTF16;
899-
hash = theChar;
910+
coder = UTF16;
911+
hash = theChar;
900912

901-
if (COMPACT_STRINGS) {
902-
initCompressionFlag();
913+
if (COMPACT_STRINGS) {
914+
initCompressionFlag();
915+
}
903916
}
904917
}
905918
} else {
906919
if (COMPACT_STRINGS && compressed) {
907-
if (sharingIsAllowed && start == 0 && data.length == length) {
908-
value = data;
909-
} else {
910-
value = new byte[length];
911-
912-
compressedArrayCopy(data, start, value, 0, length);
913-
}
914-
920+
value = new byte[length];
921+
compressedArrayCopy(data, start, value, 0, length);
922+
coder = LATIN1;
923+
} else if (COMPACT_STRINGS && helpers.canEncodeAsLatin1(data, start, length)) {
924+
value = new byte[length];
925+
compress(data, start, value, 0, length);
915926
coder = LATIN1;
916927
} else {
917-
if (sharingIsAllowed && start == 0 && data.length == length * 2) {
918-
value = data;
919-
} else {
920-
value = StringUTF16.newBytesFor(length);
921-
922-
decompressedArrayCopy(data, start, value, 0, length);
923-
}
924-
928+
value = StringUTF16.newBytesFor(length);
929+
decompressedArrayCopy(data, start, value, 0, length);
925930
coder = UTF16;
926931

927932
if (COMPACT_STRINGS) {
@@ -2581,7 +2586,12 @@ public String replace(char oldChar, char newChar) {
25812586
helpers.putCharInArrayByIndex(buffer, index++, (char) newChar);
25822587
} while ((index = indexOf(oldChar, index)) != -1);
25832588

2584-
return new String(buffer, UTF16);
2589+
if (newChar > 255) {
2590+
// If the original String isn't compressed and the replacement character isn't Latin1, the result is uncompressed.
2591+
return new String(buffer, UTF16);
2592+
}
2593+
2594+
return new String(buffer, 0, len, false);
25852595
}
25862596
}
25872597

@@ -3194,7 +3204,7 @@ public String replaceAll(String regex, String substitute) {
31943204
if (COMPACT_STRINGS && isCompressed() && (substituteLength == 0 || substitute.isCompressed())) {
31953205
byte[] newChars = new byte[length];
31963206
byte toReplace = helpers.getByteFromArrayByIndex(regex.value, 0);
3197-
byte replacement = (byte)-1; // assign dummy value that will never be used
3207+
byte replacement = (byte)0; // assign dummy value that isn't used
31983208
if (substituteLength == 1) {
31993209
replacement = helpers.getByteFromArrayByIndex(substitute.value, 0);
32003210
checkLastChar((char)replacement);
@@ -3212,7 +3222,7 @@ public String replaceAll(String regex, String substitute) {
32123222
} else if (!COMPACT_STRINGS || !isCompressed()) {
32133223
byte[] newChars = StringUTF16.newBytesFor(length);
32143224
char toReplace = regex.charAtInternal(0);
3215-
char replacement = (char)-1; // assign dummy value that will never be used
3225+
char replacement = (char)0; // assign dummy value that must be Latin1 (0 - 255)
32163226
if (substituteLength == 1) {
32173227
replacement = substitute.charAtInternal(0);
32183228
checkLastChar(replacement);
@@ -3226,6 +3236,10 @@ public String replaceAll(String regex, String substitute) {
32263236
helpers.putCharInArrayByIndex(newChars, newCharIndex++, replacement);
32273237
}
32283238
}
3239+
if (replacement > 255) {
3240+
// If the original String isn't compressed and the replacement character isn't Latin1, the result is uncompressed.
3241+
return new String(newChars, UTF16);
3242+
}
32293243
return new String(newChars, 0, newCharIndex, false);
32303244
}
32313245
}

test/functional/Java8andUp/src/org/openj9/test/java/lang/Test_String.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,18 @@ public void test_indexOf3() {
937937
String needle = "\u00b0\u00b1";
938938
String hay = new StringBuilder("a").append(needle).toString();
939939
AssertJUnit.assertEquals("Failed to find string 3", 1, hay.indexOf(needle));
940+
941+
String multi = "\u0100:abc";
942+
String[] splits = multi.split(":");
943+
AssertJUnit.assertEquals("Failed to find string 4", 3, "123abc".indexOf(splits[1]));
944+
String sub = multi.substring(2);
945+
AssertJUnit.assertEquals("Failed to find string 5", 3, "123abc".indexOf(sub));
946+
String r1 = multi.replace('\u0100', '1');
947+
AssertJUnit.assertEquals("Failed to find string 6", 0, "1:abc".indexOf(r1));
948+
String r2 = multi.replaceAll("\u0100", "1");
949+
AssertJUnit.assertEquals("Failed to find string 7", 0, "1:abc".indexOf(r2));
950+
String r3 = multi.replaceAll("\u0100", "");
951+
AssertJUnit.assertEquals("Failed to find string 8", 0, ":abc".indexOf(r3));
940952
}
941953

942954
/**

0 commit comments

Comments
 (0)