Skip to content

Instantly share code, notes, and snippets.

@rednaxelafx
Created June 26, 2012 07:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rednaxelafx/2994161 to your computer and use it in GitHub Desktop.
Save rednaxelafx/2994161 to your computer and use it in GitHub Desktop.
OptimizeStringConcat in HS24 won't optimize a StringBuilder with append() calls after toString()
public class AppendAfterToString {
public static void foo(Pair p) {
String s = "testing";
StringBuilder sb = new StringBuilder();
sb.append(s).append(s);
p.first = sb.toString();
sb.append(s);
p.second = sb.toString();
}
public static void main(String[] args) throws Exception {
Pair p = new Pair();
for (int i = 0; i < 20000; i++) {
foo(p);
}
System.in.read();
}
}
class Pair {
Object first;
Object second;
}
$ javap -verbose -private AppendAfterToString
Compiled from "AppendAfterToString.java"
public class AppendAfterToString extends java.lang.Object
SourceFile: "AppendAfterToString.java"
minor version: 0
major version: 50
Constant pool:
const #1 = Method #15.#43; // java/lang/Object."<init>":()V
const #2 = String #44; // testing
const #3 = class #45; // java/lang/StringBuilder
const #4 = Method #3.#43; // java/lang/StringBuilder."<init>":()V
const #5 = Method #3.#46; // java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
const #6 = Method #3.#47; // java/lang/StringBuilder.toString:()Ljava/lang/String;
const #7 = Field #9.#48; // Pair.first:Ljava/lang/Object;
const #8 = Field #9.#49; // Pair.second:Ljava/lang/Object;
const #9 = class #50; // Pair
const #10 = Method #9.#43; // Pair."<init>":()V
const #11 = Method #14.#51; // AppendAfterToString.foo:(LPair;)V
const #12 = Field #52.#53; // java/lang/System.in:Ljava/io/InputStream;
const #13 = Method #54.#55; // java/io/InputStream.read:()I
const #14 = class #56; // AppendAfterToString
const #15 = class #57; // java/lang/Object
const #16 = Asciz <init>;
const #17 = Asciz ()V;
const #18 = Asciz Code;
const #19 = Asciz LineNumberTable;
const #20 = Asciz LocalVariableTable;
const #21 = Asciz this;
const #22 = Asciz LAppendAfterToString;;
const #23 = Asciz foo;
const #24 = Asciz (LPair;)V;
const #25 = Asciz p;
const #26 = Asciz LPair;;
const #27 = Asciz s;
const #28 = Asciz Ljava/lang/String;;
const #29 = Asciz sb;
const #30 = Asciz Ljava/lang/StringBuilder;;
const #31 = Asciz main;
const #32 = Asciz ([Ljava/lang/String;)V;
const #33 = Asciz i;
const #34 = Asciz I;
const #35 = Asciz args;
const #36 = Asciz [Ljava/lang/String;;
const #37 = Asciz StackMapTable;
const #38 = class #50; // Pair
const #39 = Asciz Exceptions;
const #40 = class #58; // java/lang/Exception
const #41 = Asciz SourceFile;
const #42 = Asciz AppendAfterToString.java;
const #43 = NameAndType #16:#17;// "<init>":()V
const #44 = Asciz testing;
const #45 = Asciz java/lang/StringBuilder;
const #46 = NameAndType #59:#60;// append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
const #47 = NameAndType #61:#62;// toString:()Ljava/lang/String;
const #48 = NameAndType #63:#64;// first:Ljava/lang/Object;
const #49 = NameAndType #65:#64;// second:Ljava/lang/Object;
const #50 = Asciz Pair;
const #51 = NameAndType #23:#24;// foo:(LPair;)V
const #52 = class #66; // java/lang/System
const #53 = NameAndType #67:#68;// in:Ljava/io/InputStream;
const #54 = class #69; // java/io/InputStream
const #55 = NameAndType #70:#71;// read:()I
const #56 = Asciz AppendAfterToString;
const #57 = Asciz java/lang/Object;
const #58 = Asciz java/lang/Exception;
const #59 = Asciz append;
const #60 = Asciz (Ljava/lang/String;)Ljava/lang/StringBuilder;;
const #61 = Asciz toString;
const #62 = Asciz ()Ljava/lang/String;;
const #63 = Asciz first;
const #64 = Asciz Ljava/lang/Object;;
const #65 = Asciz second;
const #66 = Asciz java/lang/System;
const #67 = Asciz in;
const #68 = Asciz Ljava/io/InputStream;;
const #69 = Asciz java/io/InputStream;
const #70 = Asciz read;
const #71 = Asciz ()I;
{
public AppendAfterToString();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LAppendAfterToString;
public static void foo(Pair);
Code:
Stack=2, Locals=3, Args_size=1
0: ldc #2; //String testing
2: astore_1
3: new #3; //class java/lang/StringBuilder
6: dup
7: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
10: astore_2
11: aload_2
12: aload_1
13: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
16: aload_1
17: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: pop
21: aload_0
22: aload_2
23: invokevirtual #6; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
26: putfield #7; //Field Pair.first:Ljava/lang/Object;
29: aload_2
30: aload_1
31: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
34: pop
35: aload_0
36: aload_2
37: invokevirtual #6; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
40: putfield #8; //Field Pair.second:Ljava/lang/Object;
43: return
LineNumberTable:
line 3: 0
line 4: 3
line 5: 11
line 6: 21
line 7: 29
line 8: 35
line 9: 43
LocalVariableTable:
Start Length Slot Name Signature
0 44 0 p LPair;
3 41 1 s Ljava/lang/String;
11 33 2 sb Ljava/lang/StringBuilder;
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
Stack=2, Locals=3, Args_size=1
0: new #9; //class Pair
3: dup
4: invokespecial #10; //Method Pair."<init>":()V
7: astore_1
8: iconst_0
9: istore_2
10: iload_2
11: sipush 20000
14: if_icmpge 27
17: aload_1
18: invokestatic #11; //Method foo:(LPair;)V
21: iinc 2, 1
24: goto 10
27: getstatic #12; //Field java/lang/System.in:Ljava/io/InputStream;
30: invokevirtual #13; //Method java/io/InputStream.read:()I
33: pop
34: return
LineNumberTable:
line 12: 0
line 13: 8
line 14: 17
line 13: 21
line 16: 27
line 17: 34
LocalVariableTable:
Start Length Slot Name Signature
10 17 2 i I
0 35 0 args [Ljava/lang/String;
8 27 1 p LPair;
StackMapTable: number_of_entries = 2
frame_type = 253 /* append */
offset_delta = 10
locals = [ class Pair, int ]
frame_type = 250 /* chop */
offset_delta = 16
Exceptions:
throws java.lang.Exception
}
$
$ java -version
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b43)
OpenJDK 64-Bit Server VM (build 24.0-b14-internal-fastdebug, mixed mode)
$ java -XX:-TieredCompilation -XX:+PrintCompilation -XX:+PrintOptimizeStringConcat -XX:CompileCommand='exclude,AppendAfterToString,main' AppendAfterToString
CompilerOracle: exclude AppendAfterToString.main
285 1 n java.lang.System::arraycopy (0 bytes) (static)
298 2 java.lang.Object::<init> (1 bytes)
313 3 java.lang.Math::min (11 bytes)
314 4 java.lang.String::length (6 bytes)
314 5 java.lang.AbstractStringBuilder::ensureCapacityInternal (16 bytes)
314 6 java.lang.AbstractStringBuilder::append (48 bytes)
324 7 java.lang.String::getChars (62 bytes)
328 8 java.lang.StringBuilder::append (8 bytes)
333 9 java.lang.String::<init> (67 bytes)
342 10 java.util.Arrays::copyOfRange (63 bytes)
343 11 java.lang.StringBuilder::toString (17 bytes)
358 12 java.lang.AbstractStringBuilder::<init> (12 bytes)
358 13 java.lang.StringBuilder::<init> (7 bytes)
360 14 AppendAfterToString::foo (44 bytes)
considering toString call in AppendAfterToString::foo @ bci:23
fusion would fail for
26 Allocate === 5 6 7 8 1 ( 24 22 23 1 10 21 1 ) [[ 27 28 29 36 37 38 ]] rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, int ) AppendAfterToString::foo @ bci:3 !jvms: AppendAfterToString::foo @ bci:3
108 CatchProj === 107 [[ 118 ]] #0@bci -1 !jvms: AppendAfterToString::foo @ bci:17
107 Catch === 101 102 [[ 108 109 ]] !jvms: AppendAfterToString::foo @ bci:17
101 Proj === 85 [[ 107 ]] #0 !jvms: AppendAfterToString::foo @ bci:17
85 CallStaticJava === 92 76 77 8 1 ( 100 21 10 21 43 ) [[ 101 102 103 114 113 ]] # Static java.lang.StringBuilder::append java/lang/StringBuilder:exact * ( java/lang/StringBuilder:NotNull:exact *, java/lang/String:exact * ) AppendAfterToString::foo @ bci:17 !jvms: AppendAfterToString::foo @ bci:17
71 CatchProj === 70 [[ 91 ]] #0@bci -1 !jvms: AppendAfterToString::foo @ bci:13
70 Catch === 64 65 [[ 71 72 ]] !jvms: AppendAfterToString::foo @ bci:13
64 Proj === 63 [[ 70 ]] #0 !jvms: AppendAfterToString::foo @ bci:13
63 CallStaticJava === 53 58 59 8 1 ( 43 21 10 21 43 ) [[ 64 65 66 68 77 76 ]] # Static java.lang.StringBuilder::append java/lang/StringBuilder:exact * ( java/lang/StringBuilder:NotNull:exact *, java/lang/String:exact * ) AppendAfterToString::foo @ bci:13 !jvms: AppendAfterToString::foo @ bci:13
considering toString call in AppendAfterToString::foo @ bci:37
fusion would fail for
26 Allocate === 5 6 7 8 1 ( 24 22 23 1 10 21 1 ) [[ 27 28 29 36 37 38 ]] rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, int ) AppendAfterToString::foo @ bci:3 !jvms: AppendAfterToString::foo @ bci:3
169 CatchProj === 168 [[ 179 ]] #0@bci -1 !jvms: AppendAfterToString::foo @ bci:31
168 Catch === 162 163 [[ 169 170 ]] !jvms: AppendAfterToString::foo @ bci:31
162 Proj === 161 [[ 168 ]] #0 !jvms: AppendAfterToString::foo @ bci:31
161 CallStaticJava === 141 131 160 8 1 ( 43 21 148 1 43 ) [[ 162 163 164 175 174 ]] # Static java.lang.StringBuilder::append java/lang/StringBuilder:exact * ( java/lang/StringBuilder:NotNull:exact *, java/lang/String:exact * ) AppendAfterToString::foo @ bci:31 !jvms: AppendAfterToString::foo @ bci:31
126 CatchProj === 125 [[ 140 ]] #0@bci -1 !jvms: AppendAfterToString::foo @ bci:23
125 Catch === 119 120 [[ 126 127 ]] !jvms: AppendAfterToString::foo @ bci:23
119 Proj === 118 [[ 125 ]] #0 !jvms: AppendAfterToString::foo @ bci:23
118 CallStaticJava === 108 113 114 8 1 ( 43 10 21 43 10 ) [[ 119 120 121 123 132 131 ]] # Static java.lang.StringBuilder::toString java/lang/String:exact * ( java/lang/StringBuilder:NotNull:exact * ) AppendAfterToString::foo @ bci:23 !jvms: AppendAfterToString::foo @ bci:23
108 CatchProj === 107 [[ 118 ]] #0@bci -1 !jvms: AppendAfterToString::foo @ bci:17
107 Catch === 101 102 [[ 108 109 ]] !jvms: AppendAfterToString::foo @ bci:17
101 Proj === 85 [[ 107 ]] #0 !jvms: AppendAfterToString::foo @ bci:17
85 CallStaticJava === 92 76 77 8 1 ( 100 21 10 21 43 ) [[ 101 102 103 114 113 ]] # Static java.lang.StringBuilder::append java/lang/StringBuilder:exact * ( java/lang/StringBuilder:NotNull:exact *, java/lang/String:exact * ) AppendAfterToString::foo @ bci:17 !jvms: AppendAfterToString::foo @ bci:17
71 CatchProj === 70 [[ 91 ]] #0@bci -1 !jvms: AppendAfterToString::foo @ bci:13
70 Catch === 64 65 [[ 71 72 ]] !jvms: AppendAfterToString::foo @ bci:13
64 Proj === 63 [[ 70 ]] #0 !jvms: AppendAfterToString::foo @ bci:13
63 CallStaticJava === 53 58 59 8 1 ( 43 21 10 21 43 ) [[ 64 65 66 68 77 76 ]] # Static java.lang.StringBuilder::append java/lang/StringBuilder:exact * ( java/lang/StringBuilder:NotNull:exact *, java/lang/String:exact * ) AppendAfterToString::foo @ bci:13 !jvms: AppendAfterToString::foo @ bci:13
### Excluding compile: static AppendAfterToString::main
$
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment