Skip to content

Instantly share code, notes, and snippets.

@rednaxelafx
Last active April 17, 2018 12:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save rednaxelafx/c5ab8a79fb3fc5ad7cbbc08154cfa92c to your computer and use it in GitHub Desktop.
Save rednaxelafx/c5ab8a79fb3fc5ad7cbbc08154cfa92c to your computer and use it in GitHub Desktop.
Demo JDK8 HotSpot C2's escape analysis + lock elision
$ java -XX:+UnlockDiagnosticVMOptions -XX:+TieredCompilation -XX:-BackgroundCompilation -XX:+PrintEscapeAnalysis -XX:+PrintEliminateLocks -XX:+PrintEliminateAllocations -XX:+PrintCompilation -XX:+PrintInlining TestSynchSB
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)
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);
}
}
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();
}
}
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;
}
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