Skip to content

Commit 8d8f4f7

Browse files
authored
Merge pull request #19909 from pshipton/replaceall0.47
(0.47) String.replaceAll() fast path must check regex is compressed
2 parents 2e60903 + f8fff6e commit 8d8f4f7

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

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

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,6 +3202,9 @@ public String replaceAll(String regex, String substitute) {
32023202
int length = lengthInternal();
32033203
if (substituteLength < 2) {
32043204
if (COMPACT_STRINGS && isCompressed() && (substituteLength == 0 || substitute.isCompressed())) {
3205+
if (!regex.isCompressed()) {
3206+
return this;
3207+
}
32053208
byte[] newChars = new byte[length];
32063209
byte toReplace = helpers.getByteFromArrayByIndex(regex.value, 0);
32073210
byte replacement = (byte)0; // assign dummy value that isn't used
@@ -3210,14 +3213,21 @@ public String replaceAll(String regex, String substitute) {
32103213
checkLastChar((char)replacement);
32113214
}
32123215
int newCharIndex = 0;
3216+
boolean replaced = false;
32133217
for (int i = 0; i < length; ++i) {
32143218
byte current = helpers.getByteFromArrayByIndex(value, i);
32153219
if (current != toReplace) {
32163220
helpers.putByteInArrayByIndex(newChars, newCharIndex++, current);
3217-
} else if (substituteLength == 1) {
3218-
helpers.putByteInArrayByIndex(newChars, newCharIndex++, replacement);
3221+
} else {
3222+
replaced = true;
3223+
if (substituteLength == 1) {
3224+
helpers.putByteInArrayByIndex(newChars, newCharIndex++, replacement);
3225+
}
32193226
}
32203227
}
3228+
if (!replaced) {
3229+
return this;
3230+
}
32213231
return new String(newChars, 0, newCharIndex, true);
32223232
} else if (!COMPACT_STRINGS || !isCompressed()) {
32233233
byte[] newChars = StringUTF16.newBytesFor(length);
@@ -3228,14 +3238,21 @@ public String replaceAll(String regex, String substitute) {
32283238
checkLastChar(replacement);
32293239
}
32303240
int newCharIndex = 0;
3241+
boolean replaced = false;
32313242
for (int i = 0; i < length; ++i) {
32323243
char current = helpers.getCharFromArrayByIndex(value, i);
32333244
if (current != toReplace) {
32343245
helpers.putCharInArrayByIndex(newChars, newCharIndex++, current);
3235-
} else if (substituteLength == 1) {
3236-
helpers.putCharInArrayByIndex(newChars, newCharIndex++, replacement);
3246+
} else {
3247+
replaced = true;
3248+
if (substituteLength == 1) {
3249+
helpers.putCharInArrayByIndex(newChars, newCharIndex++, replacement);
3250+
}
32373251
}
32383252
}
3253+
if (!replaced) {
3254+
return this;
3255+
}
32393256
if (replacement > 255) {
32403257
// If the original String isn't compressed and the replacement character isn't Latin1, the result is uncompressed.
32413258
return new String(newChars, UTF16);
@@ -7601,6 +7618,9 @@ public String replaceAll(String regex, String substitute) {
76017618
int length = lengthInternal();
76027619
if (substituteLength < 2) {
76037620
if (COMPACT_STRINGS && isCompressed() && (substituteLength == 0 || substitute.isCompressed())) {
7621+
if (!regex.isCompressed()) {
7622+
return this;
7623+
}
76047624
char[] newChars = new char[(length + 1) >>> 1];
76057625
byte toReplace = helpers.getByteFromArrayByIndex(regex.value, 0);
76067626
byte replacement = (byte)-1; // assign dummy value that will never be used
@@ -7609,14 +7629,21 @@ public String replaceAll(String regex, String substitute) {
76097629
checkLastChar((char)replacement);
76107630
}
76117631
int newCharIndex = 0;
7632+
boolean replaced = false;
76127633
for (int i = 0; i < length; ++i) {
76137634
byte current = helpers.getByteFromArrayByIndex(value, i);
76147635
if (current != toReplace) {
76157636
helpers.putByteInArrayByIndex(newChars, newCharIndex++, current);
7616-
} else if (substituteLength == 1) {
7617-
helpers.putByteInArrayByIndex(newChars, newCharIndex++, replacement);
7637+
} else {
7638+
replaced = true;
7639+
if (substituteLength == 1) {
7640+
helpers.putByteInArrayByIndex(newChars, newCharIndex++, replacement);
7641+
}
76187642
}
76197643
}
7644+
if (!replaced) {
7645+
return this;
7646+
}
76207647
return new String(newChars, 0, newCharIndex, true);
76217648
} else if (!COMPACT_STRINGS || !isCompressed()) {
76227649
char[] newChars = new char[length];
@@ -7627,14 +7654,21 @@ public String replaceAll(String regex, String substitute) {
76277654
checkLastChar(replacement);
76287655
}
76297656
int newCharIndex = 0;
7657+
boolean replaced = false;
76307658
for (int i = 0; i < length; ++i) {
76317659
char current = helpers.getCharFromArrayByIndex(value, i);
76327660
if (current != toReplace) {
76337661
helpers.putCharInArrayByIndex(newChars, newCharIndex++, current);
7634-
} else if (substituteLength == 1) {
7635-
helpers.putCharInArrayByIndex(newChars, newCharIndex++, replacement);
7662+
} else {
7663+
replaced = true;
7664+
if (substituteLength == 1) {
7665+
helpers.putCharInArrayByIndex(newChars, newCharIndex++, replacement);
7666+
}
76367667
}
76377668
}
7669+
if (!replaced) {
7670+
return this;
7671+
}
76387672
return new String(newChars, 0, newCharIndex, false);
76397673
}
76407674
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1860,6 +1860,19 @@ public void test_join2() {
18601860
}
18611861
}
18621862

1863+
/**
1864+
* @tests java.lang.String#replaceAll(String, String)
1865+
*/
1866+
@Test
1867+
public void test_replaceAll() {
1868+
String replace1 = "1a2a3a\u0011";
1869+
String result1 = replace1.replaceAll("\u1161", "[");
1870+
AssertJUnit.assertSame("replaceAll() compact result should be identical", replace1, result1);
1871+
String replace2 = "1a2b3c\u1161";
1872+
String result2 = replace2.replaceAll("\u1162", "\u1234");
1873+
AssertJUnit.assertSame("replaceAll() non-compact result should be identical", replace2, result2);
1874+
}
1875+
18631876
/**
18641877
* @tests java.lang.String#replaceAll(String, String)
18651878
*/
@@ -1872,6 +1885,7 @@ public void test_replaceAll_last_char_dollarsign() {
18721885
// expected
18731886
}
18741887
}
1888+
18751889
/**
18761890
* @tests java.lang.String#replaceAll(String, String)
18771891
*/

0 commit comments

Comments
 (0)