Details
-
Bug
-
Status: Resolved
-
P4
-
Resolution: Fixed
-
11, 13, 15, 17, 18, 19
-
b05
Description
The invokedynamic string concatenation strategies don't preserve the order of operations when evaluating subexpressions and converting them to strings.
With the inline strategy, each subexpression is evaluated and converted to a string in order. With indy each subexpression is evaluated in order *but not converted to a string*, and later each subexpression is converted to a string in order.
Originally reported on compiler-dev@ [1]. briangoetz confirmed the original behaviour of the inline strategy [2] is correct, and sketched one possible fix [3]:
> The nature of indy leads to the structure we ended up with. The natural
> way to do this is to have the various arguments passed as real stack
> arguments, causing them to all be evaluated before being pushed through
> the MH nest (which is where the string conversion happens, using
> MethodHandle::filterArguments.) We'd essentially have to write a new
> bootstrap (but leave the old one in place), and have the compiler
> generate bytecode to do the string conversion as the values are being
> pushed on the stack. This requires a different bootstrap and a
> different calling convention. So old bytecode will stay around, and the
> old bootstrap would have to be kept around ... pretty disruptive.
[1] https://mail.openjdk.java.net/pipermail/compiler-dev/2021-September/017911.html
[2] https://mail.openjdk.java.net/pipermail/compiler-dev/2021-September/017912.html
[3] https://mail.openjdk.java.net/pipermail/compiler-dev/2021-September/017929.html
Repro:
class T {
static String test() {
StringBuilder builder = new StringBuilder("foo");
return "" + builder + builder.append("bar");
}
public static void main(String[] args) {
System.err.println(test());
}
}
$ javac -XDstringConcat=inline T.java ; java T
foofoobar
$ javac -XDstringConcat=indy T.java ; java T
foobarfoobar
With the inline strategy, each subexpression is evaluated and converted to a string in order. With indy each subexpression is evaluated in order *but not converted to a string*, and later each subexpression is converted to a string in order.
Originally reported on compiler-dev@ [1]. briangoetz confirmed the original behaviour of the inline strategy [2] is correct, and sketched one possible fix [3]:
> The nature of indy leads to the structure we ended up with. The natural
> way to do this is to have the various arguments passed as real stack
> arguments, causing them to all be evaluated before being pushed through
> the MH nest (which is where the string conversion happens, using
> MethodHandle::filterArguments.) We'd essentially have to write a new
> bootstrap (but leave the old one in place), and have the compiler
> generate bytecode to do the string conversion as the values are being
> pushed on the stack. This requires a different bootstrap and a
> different calling convention. So old bytecode will stay around, and the
> old bootstrap would have to be kept around ... pretty disruptive.
[1] https://mail.openjdk.java.net/pipermail/compiler-dev/2021-September/017911.html
[2] https://mail.openjdk.java.net/pipermail/compiler-dev/2021-September/017912.html
[3] https://mail.openjdk.java.net/pipermail/compiler-dev/2021-September/017929.html
Repro:
class T {
static String test() {
StringBuilder builder = new StringBuilder("foo");
return "" + builder + builder.append("bar");
}
public static void main(String[] args) {
System.err.println(test());
}
}
$ javac -XDstringConcat=inline T.java ; java T
foofoobar
$ javac -XDstringConcat=indy T.java ; java T
foobarfoobar
Attachments
Issue Links
- csr for
-
JDK-8274863 Indy string concat changes order of operations
-
- Closed
-
- duplicates
-
JDK-8282627 JDK 11 invokedynamic-based string concatenation produces different result than JDK 8
-
- Closed
-
- relates to
-
JDK-8085796 JEP 280: Indify String Concatenation
-
- Closed
-