Skip to content

Commit

Permalink
jdk11 always create compact Strings when possible
Browse files Browse the repository at this point in the history
Issue eclipse-openj9#19543

Signed-off-by: Peter Shipton <Peter_Shipton@ca.ibm.com>
2

Signed-off-by: Peter Shipton <Peter_Shipton@ca.ibm.com>
  • Loading branch information
pshipton committed May 28, 2024
1 parent e61548b commit f5c2ed1
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 27 deletions.
13 changes: 13 additions & 0 deletions jcl/src/java.base/share/classes/com/ibm/jit/JITHelpers.java
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,19 @@ public char getCharFromArrayByIndex(Object obj, int index) {
}
}

public boolean canEncodeAsLatin1(byte[] array, int start, int length) {
int index = start << 1;
if (!IS_BIG_ENDIAN) {
index += 1;
}
for (int end = index + (length << 1); index < end; index += 2) {
if (array[index] != 0) {
return false;
}
}
return true;
}

/**
* Returns the first index of the target character array within the source character array starting from the specified
* offset.
Expand Down
72 changes: 45 additions & 27 deletions jcl/src/java.base/share/classes/java/lang/String.java
Original file line number Diff line number Diff line change
Expand Up @@ -824,19 +824,25 @@ public String(char[] data, int start, int length) {
} else {
char theChar = helpers.getCharFromArrayByIndex(data, start);

if (theChar <= 255) {
value = decompressedAsciiTable[theChar];
if (COMPACT_STRINGS && (theChar <= 255)) {
value = compressedAsciiTable[theChar];
coder = LATIN1;
hash = theChar;
} else {
value = new byte[2];
if (theChar <= 255) {
value = decompressedAsciiTable[theChar];
} else {
value = new byte[2];

helpers.putCharInArrayByIndex(value, 0, theChar);
}
helpers.putCharInArrayByIndex(value, 0, theChar);
}

coder = UTF16;
hash = theChar;
coder = UTF16;
hash = theChar;

if (COMPACT_STRINGS) {
initCompressionFlag();
if (COMPACT_STRINGS) {
initCompressionFlag();
}
}
}
} else {
Expand All @@ -850,6 +856,11 @@ public String(char[] data, int start, int length) {
}

coder = LATIN1;
} else if (COMPACT_STRINGS && helpers.canEncodeAsLatin1(data, start, length)) {
value = new byte[length];
coder = LATIN1;

compress(data, start, value, 0, length);
} else {
if (start == 0 && data.length == length * 2) {
value = data;
Expand Down Expand Up @@ -887,19 +898,25 @@ public String(char[] data, int start, int length) {
} else {
char theChar = helpers.getCharFromArrayByIndex(data, start);

if (theChar <= 255) {
value = decompressedAsciiTable[theChar];
if (COMPACT_STRINGS && (theChar <= 255)) {
value = compressedAsciiTable[theChar];
coder = LATIN1;
hash = theChar;
} else {
value = new byte[2];
if (theChar <= 255) {
value = decompressedAsciiTable[theChar];
} else {
value = new byte[2];

helpers.putCharInArrayByIndex(value, 0, theChar);
}
helpers.putCharInArrayByIndex(value, 0, theChar);
}

coder = UTF16;
hash = theChar;
coder = UTF16;
hash = theChar;

if (COMPACT_STRINGS) {
initCompressionFlag();
if (COMPACT_STRINGS) {
initCompressionFlag();
}
}
}
} else {
Expand All @@ -913,14 +930,15 @@ public String(char[] data, int start, int length) {
}

coder = LATIN1;
} else if (COMPACT_STRINGS && helpers.canEncodeAsLatin1(data, start, length)) {
value = new byte[length];
coder = LATIN1;

compress(data, start, value, 0, length);
} else {
if (sharingIsAllowed && start == 0 && data.length == length * 2) {
value = data;
} else {
value = StringUTF16.newBytesFor(length);
value = StringUTF16.newBytesFor(length);

decompressedArrayCopy(data, start, value, 0, length);
}
decompressedArrayCopy(data, start, value, 0, length);

coder = UTF16;

Expand Down Expand Up @@ -2581,7 +2599,7 @@ public String replace(char oldChar, char newChar) {
helpers.putCharInArrayByIndex(buffer, index++, (char) newChar);
} while ((index = indexOf(oldChar, index)) != -1);

return new String(buffer, UTF16);
return new String(buffer, 0, len, false);
}
}

Expand Down Expand Up @@ -3194,7 +3212,7 @@ public String replaceAll(String regex, String substitute) {
if (COMPACT_STRINGS && isCompressed() && (substituteLength == 0 || substitute.isCompressed())) {
byte[] newChars = new byte[length];
byte toReplace = helpers.getByteFromArrayByIndex(regex.value, 0);
byte replacement = (byte)-1; // assign dummy value that will never be used
byte replacement = (byte)0; // assign dummy value that isn't used
if (substituteLength == 1) {
replacement = helpers.getByteFromArrayByIndex(substitute.value, 0);
checkLastChar((char)replacement);
Expand All @@ -3212,7 +3230,7 @@ public String replaceAll(String regex, String substitute) {
} else if (!COMPACT_STRINGS || !isCompressed()) {
byte[] newChars = StringUTF16.newBytesFor(length);
char toReplace = regex.charAtInternal(0);
char replacement = (char)-1; // assign dummy value that will never be used
char replacement = (char)0; // assign dummy value that isn't used
if (substituteLength == 1) {
replacement = substitute.charAtInternal(0);
checkLastChar(replacement);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,18 @@ public void test_indexOf3() {
String needle = "\u00b0\u00b1";
String hay = new StringBuilder("a").append(needle).toString();
AssertJUnit.assertEquals("Failed to find string 3", 1, hay.indexOf(needle));

String multi = "\u0100:abc";
String[] splits = multi.split(":");
AssertJUnit.assertEquals("Failed to find string 4", 3, "123abc".indexOf(splits[1]));
String sub = multi.substring(2);
AssertJUnit.assertEquals("Failed to find string 5", 3, "123abc".indexOf(sub));
String r1 = multi.replace('\u0100', '1');
AssertJUnit.assertEquals("Failed to find string 6", 0, "1:abc".indexOf(r1));
String r2 = multi.replaceAll("\u0100", "1");
AssertJUnit.assertEquals("Failed to find string 7", 0, "1:abc".indexOf(r2));
String r3 = multi.replaceAll("\u0100", "");
AssertJUnit.assertEquals("Failed to find string 8", 0, ":abc".indexOf(r3));
}

/**
Expand Down

0 comments on commit f5c2ed1

Please sign in to comment.