Last active
April 17, 2018 12:44
-
-
Save rednaxelafx/c5ab8a79fb3fc5ad7cbbc08154cfa92c to your computer and use it in GitHub Desktop.
Demo JDK8 HotSpot C2's escape analysis + lock elision
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ java -XX:+UnlockDiagnosticVMOptions -XX:+TieredCompilation -XX:-BackgroundCompilation -XX:+PrintEscapeAnalysis -XX:+PrintEliminateLocks -XX:+PrintEliminateAllocations -XX:+PrintCompilation -XX:+PrintInlining TestSynchSB |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
389 48 b 4 TestSynchSB::doTest (45 bytes) | |
***Eliminated 1 unlocks and 1 locks | |
***Eliminated 1 unlocks and 1 locks | |
======== Connection graph for TestSynchSB::doTest | |
JavaObject NoEscape(NoEscape) [ 129F [ 37 42 ]] 25 Allocate === 5 6 7 8 1 ( 23 21 22 1 1 1 ) [[ 26 27 28 35 36 37 ]] rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool, top ) TestSynchSB::doTest @ bci:0 !jvms: TestSynchSB::doTest @ bci:0 | |
LocalVar [ 25P [ 42 ]] 37 Proj === 25 [[ 38 42 ]] #5 !jvms: TestSynchSB::doTest @ bci:0 | |
LocalVar [ 37 25P [ 129b ]] 42 CheckCastPP === 39 37 [[ 664 572 525 525 466 433 133 433 383 561 85 85 356 356 356 896 896 356 355 316 129 129 341 174 187 289 289 289 289 211 289 212 212 212 212 262 288 273 235 798 798 759 683 683 ]] #SynchSB:NotNull:exact * Oop:SynchSB:NotNull:exact * !jvms: TestSynchSB::doTest @ bci:0 | |
++++ Eliminated: 572 Unlock | |
++++ Eliminated: 561 Unlock | |
++++ Eliminated: 356 Lock | |
++++ Eliminated: 341 Unlock | |
++++ Eliminated: 289 Lock | |
++++ Eliminated: 273 Unlock | |
++++ Eliminated: 262 Unlock | |
++++ Eliminated: 212 Lock | |
@ 4 SynchSB::<init> (16 bytes) inline (hot) | |
@ 1 java.lang.Object::<init> (1 bytes) inline (hot) | |
@ 9 java.lang.StringBuilder::<init> (7 bytes) inline (hot) | |
@ 3 java.lang.AbstractStringBuilder::<init> (12 bytes) inline (hot) | |
@ 1 java.lang.Object::<init> (1 bytes) inline (hot) | |
s @ 20 SynchSB::append (9 bytes) inline (hot) | |
@ 5 java.lang.StringBuilder::append (8 bytes) inline (hot) | |
@ 2 java.lang.AbstractStringBuilder::append (50 bytes) inline (hot) | |
@ 10 java.lang.String::length (6 bytes) inline (hot) | |
@ 21 java.lang.AbstractStringBuilder::ensureCapacityInternal (16 bytes) inline (hot) | |
@ 12 java.lang.AbstractStringBuilder::expandCapacity (50 bytes) too big | |
@ 35 java.lang.String::getChars (62 bytes) inline (hot) | |
@ 58 java.lang.System::arraycopy (0 bytes) (intrinsic) | |
s @ 27 SynchSB::length (8 bytes) inline (hot) | |
@ 4 java.lang.StringBuilder::length (5 bytes) inline (hot) | |
@ 1 java.lang.AbstractStringBuilder::length (5 bytes) accessor | |
s @ 30 SynchSB::delete (10 bytes) inline (hot) | |
@ 6 java.lang.StringBuilder::delete (9 bytes) inline (hot) | |
@ 3 java.lang.AbstractStringBuilder::delete (80 bytes) inline (hot) | |
@ 65 java.lang.System::arraycopy (0 bytes) (intrinsic) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class SynchSB { | |
StringBuilder sb = new StringBuilder(); | |
public synchronized int length() { | |
return sb.length(); | |
} | |
public synchronized StringBuilder append(String str) { | |
return sb.append(str); | |
} | |
public synchronized StringBuilder delete(int start, int end) { | |
return sb.delete(start, end); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class TestSynchSB { | |
public static StringBuilder doTest() { | |
SynchSB thesb = new SynchSB(); | |
for (int i = 0; i < 10000; i++) { | |
thesb.append("abc"); | |
thesb.delete(0, thesb.length()); | |
} | |
return thesb.sb; | |
} | |
public static void main(String[] args) throws Exception { | |
for (int i = 0; i < 200; i++) { | |
doTest(); | |
} | |
System.out.println("done."); | |
System.in.read(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static StringBuilder doTest() { | |
SynchSB thesb = allocate(SynchSB.class); | |
{ | |
StringBuilder sb = allocate(StringBuilder.class); | |
sb.value = new char[16]; | |
thesb.sb = sb; | |
} | |
for (int i = 0; i < 10000; i++) { | |
synchronized (thesb) { | |
StringBuilder sb = thesb.sb; | |
String str = "abc"; | |
int len = 3; // str.value.length; | |
int minimalCapacity = sb.count + len; | |
if (minimalCapacity - sb.value.length > 0) { | |
{ | |
int newCapacity = sb.value.length * 2 + 2; | |
if (newCapacity - minimumCapacity < 0) | |
newCapacity = minimumCapacity; | |
if (newCapacity < 0) { | |
if (minimumCapacity < 0) // overflow | |
throw new OutOfMemoryError(); | |
newCapacity = Integer.MAX_VALUE; | |
} | |
{ | |
char[] original = sb.value; | |
char[] copy = new char[newCapacity]; | |
System.arraycopy(original, 0, copy, 0, | |
Math.min(original.length, newCapacity)); | |
sb.value = copy; | |
} | |
} | |
} | |
System.arraycopy(str.value, 0, sb.value, sb.count, len); | |
sb.count += len; | |
} | |
int sblen; | |
synchronized (thesb) { | |
sblen = thesb.sb.length; | |
} | |
synchronized (thesb) { | |
StringBuilder sb = thesb.sb; | |
System.arraycopy(sb.value, sblen, sb.value, 0, 0); | |
sb.count = 0; | |
} | |
} | |
return thesb.sb; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class TestSynchSB { | |
public static StringBuilder doTest() { | |
SynchSB thesb = allocate(SynchSB.class); | |
{ | |
// inlined SynchSB::<init>()V | |
{ | |
// inlined java.lang.Object::<init>()V | |
// no-op | |
} | |
StringBuilder sb = allocate(StringBuilder.class); | |
{ | |
// inlined java.lang.StringBuilder::<init>()V | |
{ | |
// inlined java.lang.Object::<init>()V | |
// no-op | |
} | |
sb.value = new char[16]; | |
} | |
thesb.sb = sb; | |
} | |
for (int i = 0; i < 10000; i++) { | |
// thesb.append("abc"); | |
// inlined SynchSB::append(Ljava/lang/String;)Ljava/lang/StringBuilder; | |
synchronized (thesb) { | |
StringBuilder sb = thesb.sb; | |
// sb.append("abc"); | |
// inlined java.lang.StringBuilder::append | |
// inlined java.lang.AbstractStringBuilder::append | |
String str = "abc"; | |
// inlined java.lang.String::length()I | |
int len = str.value.length; | |
// ensureCapacityInternal | |
int minimalCapacity = sb.count + len; | |
if (minimalCapacity - sb.value.length > 0){ | |
// expandCapacity(minimalCapacity); | |
{ | |
int newCapacity = sb.value.length * 2 + 2; | |
if (newCapacity - minimumCapacity < 0) | |
newCapacity = minimumCapacity; | |
if (newCapacity < 0) { | |
if (minimumCapacity < 0) // overflow | |
throw new OutOfMemoryError(); | |
newCapacity = Integer.MAX_VALUE; | |
} | |
// sb.value = Arrays.copyOf(sb.value, newCapacity); | |
{ | |
char[] original = sb.value; | |
char[] copy = new char[newCapacity]; | |
System.arraycopy(original, 0, copy, 0, | |
Math.min(original.length, newCapacity)); | |
sb.value = copy; | |
} | |
} | |
} | |
// str.getChars() | |
{ | |
// inlined java.lang.String::getChars([CI)[C | |
System.arraycopy(str.value, 0, sb.value, sb.count, str.value.length); | |
} | |
sb.count += len; | |
} | |
// thesb.delete(0, thesb.length()); | |
// inlined SynchSB::length()I | |
int sblen; | |
synchronized (thesb) { | |
// inlined java.lang.StringBuilder::length()I | |
// inlined java.lang.AbstractStringBuilder::length()I | |
sblen = thesb.sb.count; | |
} | |
// inlined SynchSB::delete(II)Ljava/lang/StringBuilder; | |
synchronized (thesb) { | |
// inlined java.lang.StringBuilder::delete(II)Ljava/lang/StringBuilder; | |
// inlined java.lang.AbstractStringBuilder::delete(II)Ljava/lang/AbstractStringBuilder; | |
StringBuilder sb = thesb.sb; | |
System.arraycopy(sb.value, sblen, sb.value, 0, 0); | |
sb.count -= sb.count; | |
} | |
} | |
return thesb.sb; | |
} | |
public static void main(String[] args) throws Exception { | |
for (int i = 0; i < 200; i++) { | |
doTest(); | |
} | |
System.out.println("done."); | |
System.in.read(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment