RFR: JDK-8237528: Inefficient compilation of Pattern Matching for instanceof
Jan Lahoda
jan.lahoda at oracle.com
Thu Jan 23 17:10:36 UTC 2020
Hi,
When javac compiles:
o instanceof String s
it desugars this to:
(let /*synthetic*/ final Object s$temp = o in s$temp instanceof String
&& (s = (String)s$temp) == (String)s$temp)
The "(s = (String)s$temp) == (String)s$temp)" is there to set the
variable "s" to the correct, and still return/have a boolean value. But
this produces several unnecessary instructions for the comparison -
second cast and unnecessary test/jump. This can be changed to:
(let /*synthetic*/ final Object s$temp = o in s$temp instanceof String
&& (let s = (String)s$temp; in true))
I.e. the (s = (String)s$temp) == (String)s$temp) is replaced with
(let s = (String)s$temp; in true)
This is a let expression that will execute the assignment as a statement
and then return true without any tests. This eliminates the unnecessary
cast and test/jump, producing a smaller code (see bytecode before and
after below).
Proposed patch:
http://cr.openjdk.java.net/~jlahoda/8237528/webrev.00/index.html
JBS:
https://bugs.openjdk.java.net/browse/JDK-8237528
How does this look?
Jan
The bytecode for:
if (o instanceof String s) {
nop(s);
}
current state:
0: aload_0
1: astore_2
2: aload_2
3: instanceof #7 // class java/lang/String
6: ifeq 26
9: aload_2
10: checkcast #7 // class java/lang/String
13: dup
14: astore_1
15: aload_2
16: checkcast #7 // class java/lang/String
19: if_acmpne 26
22: aload_1
23: invokestatic #9 // Method
nop:(Ljava/lang/String;)V
26: return
after the proposed patch:
0: aload_0
1: astore_2
2: aload_2
3: instanceof #7 // class java/lang/String
6: ifeq 18
9: aload_2
10: checkcast #7 // class java/lang/String
13: astore_1
14: aload_1
15: invokestatic #9 // Method
nop:(Ljava/lang/String;)V
18: return
I.e. the instructions at original bytecode indexes 13, 15, 16 and 19
disappear.
More information about the compiler-dev
mailing list