Here is newString() of StringLatin1. StringUTF16.java has the similar pattern.
public static String newString(byte[] val, int index, int len) {
if (len == 0) {
return "";
}
return new String(Arrays.copyOfRange(val, index, index + len),
LATIN1);
}
If C2 can't determine len is a constant, it has to generate a PhiNode to merge the result_cast() of AllocateNode and ConP of "".
As a result, EA marks AllocateNode NSR and C2 rules it out as a candidate of scalar replacement.
here is an example:
//java -ea -XX:+PrintEscapeAnalysis -XX:+PrintEliminateAllocations SubstringNSR
import java.util.Arrays;
class SubstringNSR {
public static void foo(String s, int index, int len) {
String p = s.substring(index, index + len);
assert(p.length() == len);
assert(p.charAt(0) == 'h');
assert(p.charAt(1) == 'e');
}
public static void main(String[] args) {
String s = "the quick brown fox jumps";
for (int j=0; j<50_000; ++j) {
foo(s, 1, 2);
}
}
}
EA: 3 iterations to build connection graph with 1031 nodes and worklist size 53
======== Connection graph for SubstringNSR::foo
JavaObject NoEscape(NoEscape) NSR [ 479F 628F 666F 701F [ 255 260 225 30 ]] 243 Allocate === 235 6 7 8 1 ( 241 240 60 1 1 1 12 1 1 1 1 1 1 63 170 171 ) [[ 244 245 246 253 254 255 ]] rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top ) StringLatin1::newString @ bci:7 (line 769) String::substring @ bci:41 (line 1913) SubstringNSR::foo @ bci:5 (line 6) !jvms: StringLatin1::newString @ bci:7 (line 769) String::substring @ bci:41 (line 1913) SubstringNSR::foo @ bci:5 (line 6)
LocalVar [ 243P [ 260 ]] 255 Proj === 243 [[ 256 260 ]] #5 !jvms: StringLatin1::newString @ bci:7 (line 769) String::substring @ bci:41 (line 1913) SubstringNSR::foo @ bci:5 (line 6)
LocalVar [ 255 243P [ 479b 628b 225 ]] 260 CheckCastPP === 257 255 [[ 633 628 479 479 282 282 309 309 545 628 225 401 388 388 401 ]] #java/lang/String:NotNull:exact * Oop:java/lang/String:NotNull:exact * !jvms: StringLatin1::newString @ bci:7 (line 769) String::substring @ bci:41 (line 1913) SubstringNSR::foo @ bci:5 (line 6)
LocalVar [ 239P 260 243P [ 30 ]] 225 Phi === 221 239 260 [[ 30 ]] #java/lang/String:NotNull:exact * Oop:java/lang/String:NotNull:exact * !jvms: String::substring @ bci:41 (line 1913) SubstringNSR::foo @ bci:5 (line 6)
LocalVar [ 45 225 1P 239P 243P [ 666b 701b ]] 30 Phi === 26 45 225 [[ 904 834 817 714 762 762 666 666 856 701 701 ]] #java/lang/String:NotNull:exact * Oop:java/lang/String:NotNull:exact * !jvms: SubstringNSR::foo @ bci:5 (line 6)
It's also weird that EA marks "309 AllocateArray" GlobalEscape(only show that with -XX:+Verbose).
It's the internal buffer value of the String object.
public static String newString(byte[] val, int index, int len) {
if (len == 0) {
return "";
}
return new String(Arrays.copyOfRange(val, index, index + len),
LATIN1);
}
If C2 can't determine len is a constant, it has to generate a PhiNode to merge the result_cast() of AllocateNode and ConP of "".
As a result, EA marks AllocateNode NSR and C2 rules it out as a candidate of scalar replacement.
here is an example:
//java -ea -XX:+PrintEscapeAnalysis -XX:+PrintEliminateAllocations SubstringNSR
import java.util.Arrays;
class SubstringNSR {
public static void foo(String s, int index, int len) {
String p = s.substring(index, index + len);
assert(p.length() == len);
assert(p.charAt(0) == 'h');
assert(p.charAt(1) == 'e');
}
public static void main(String[] args) {
String s = "the quick brown fox jumps";
for (int j=0; j<50_000; ++j) {
foo(s, 1, 2);
}
}
}
EA: 3 iterations to build connection graph with 1031 nodes and worklist size 53
======== Connection graph for SubstringNSR::foo
JavaObject NoEscape(NoEscape) NSR [ 479F 628F 666F 701F [ 255 260 225 30 ]] 243 Allocate === 235 6 7 8 1 ( 241 240 60 1 1 1 12 1 1 1 1 1 1 63 170 171 ) [[ 244 245 246 253 254 255 ]] rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top ) StringLatin1::newString @ bci:7 (line 769) String::substring @ bci:41 (line 1913) SubstringNSR::foo @ bci:5 (line 6) !jvms: StringLatin1::newString @ bci:7 (line 769) String::substring @ bci:41 (line 1913) SubstringNSR::foo @ bci:5 (line 6)
LocalVar [ 243P [ 260 ]] 255 Proj === 243 [[ 256 260 ]] #5 !jvms: StringLatin1::newString @ bci:7 (line 769) String::substring @ bci:41 (line 1913) SubstringNSR::foo @ bci:5 (line 6)
LocalVar [ 255 243P [ 479b 628b 225 ]] 260 CheckCastPP === 257 255 [[ 633 628 479 479 282 282 309 309 545 628 225 401 388 388 401 ]] #java/lang/String:NotNull:exact * Oop:java/lang/String:NotNull:exact * !jvms: StringLatin1::newString @ bci:7 (line 769) String::substring @ bci:41 (line 1913) SubstringNSR::foo @ bci:5 (line 6)
LocalVar [ 239P 260 243P [ 30 ]] 225 Phi === 221 239 260 [[ 30 ]] #java/lang/String:NotNull:exact * Oop:java/lang/String:NotNull:exact * !jvms: String::substring @ bci:41 (line 1913) SubstringNSR::foo @ bci:5 (line 6)
LocalVar [ 45 225 1P 239P 243P [ 666b 701b ]] 30 Phi === 26 45 225 [[ 904 834 817 714 762 762 666 666 856 701 701 ]] #java/lang/String:NotNull:exact * Oop:java/lang/String:NotNull:exact * !jvms: SubstringNSR::foo @ bci:5 (line 6)
It's also weird that EA marks "309 AllocateArray" GlobalEscape(only show that with -XX:+Verbose).
It's the internal buffer value of the String object.
- relates to
-
JDK-6853701 Scalar replacement (escape analysis) fails for simple test case
- Open