// // Variant intrinsics remain in the loop, but invariant references are hoisted out of the loop. // /// CHECK-START: int Main.liveIndexOf() licm (before) /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOf loop:{{B\d+}} outer_loop:none /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOfAfter loop:{{B\d+}} outer_loop:none /// CHECK-DAG: InvokeStaticOrDirect intrinsic:StringStringIndexOf loop:{{B\d+}} outer_loop:none /// CHECK-DAG: InvokeStaticOrDirect intrinsic:StringStringIndexOfAfter loop:{{B\d+}} outer_loop:none // /// CHECK-START: int Main.liveIndexOf() licm (after) /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOf loop:{{B\d+}} outer_loop:none /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOfAfter loop:{{B\d+}} outer_loop:none /// CHECK-DAG: InvokeStaticOrDirect intrinsic:StringStringIndexOf loop:none /// CHECK-DAG: InvokeStaticOrDirect intrinsic:StringStringIndexOfAfter loop:none staticint liveIndexOf() { int k = ABC.length() + XYZ.length(); // does LoadString before loops for (char c = 'A'; c <= 'Z'; c++) {
k += ABC.indexOf(c);
} for (char c = 'A'; c <= 'Z'; c++) {
k += ABC.indexOf(c, 4);
} for (char c = 'A'; c <= 'Z'; c++) {
k += ABC.indexOf(XYZ);
} for (char c = 'A'; c <= 'Z'; c++) {
k += ABC.indexOf(XYZ, 2);
} return k;
}
// // All dead intrinsics can be removed completely. // /// CHECK-START: int Main.deadIndexOf() dead_code_elimination$initial (before) /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOf loop:{{B\d+}} outer_loop:none /// CHECK-DAG: InvokeVirtual intrinsic:StringIndexOfAfter loop:{{B\d+}} outer_loop:none /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOf loop:{{B\d+}} outer_loop:none /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOfAfter loop:{{B\d+}} outer_loop:none // /// CHECK-START: int Main.deadIndexOf() dead_code_elimination$initial (after) /// CHECK-NOT: InvokeVirtual intrinsic:StringIndexOf /// CHECK-NOT: InvokeVirtual intrinsic:StringIndexOfAfter /// CHECK-NOT: InvokeVirtual intrinsic:StringStringIndexOf /// CHECK-NOT: InvokeVirtual intrinsic:StringStringIndexOfAfter staticint deadIndexOf() { int k = ABC.length() + XYZ.length(); // does LoadString before loops for (char c = 'A'; c <= 'Z'; c++) { int d = ABC.indexOf(c);
} for (char c = 'A'; c <= 'Z'; c++) { int d = ABC.indexOf(c, 4);
} for (char c = 'A'; c <= 'Z'; c++) { int d = ABC.indexOf(XYZ);
} for (char c = 'A'; c <= 'Z'; c++) { int d = ABC.indexOf(XYZ, 2);
} return k;
}
// // Explicit null check on receiver, implicit null check on argument prevents hoisting. // /// CHECK-START: int Main.indexOfExceptions(java.lang.String, java.lang.String) licm (after) /// CHECK-DAG: <<String:l\d+>> NullCheck loop:<<Loop:B\d+>> outer_loop:none /// CHECK-DAG: InvokeStaticOrDirect [<<String>>,{{l\d+}}] intrinsic:StringStringIndexOf loop:<<Loop>> outer_loop:none staticint indexOfExceptions(String s, String t) { int k = 0; for (char c = 'A'; c <= 'Z'; c++) {
k += s.indexOf(t);
} return k;
}
// // Allows combining of returned "this". Also ensures that similar looking append() calls // are not combined somehow through returned result. // /// CHECK-START: int Main.bufferLen2() instruction_simplifier (before) /// CHECK-DAG: <<New:l\d+>> NewInstance /// CHECK-DAG: <<String1:l\d+>> LoadString /// CHECK-DAG: <<Append1:l\d+>> InvokeVirtual [<<New>>,<<String1>>] intrinsic:StringBufferAppend /// CHECK-DAG: <<String2:l\d+>> LoadString /// CHECK-DAG: <<Append2:l\d+>> InvokeVirtual [{{l\d+}},<<String2>>] intrinsic:StringBufferAppend /// CHECK-DAG: InvokeVirtual [{{l\d+}}] intrinsic:StringBufferLength // /// CHECK-START: int Main.bufferLen2() instruction_simplifier (after) /// CHECK-DAG: <<New:l\d+>> NewInstance /// CHECK-DAG: <<String1:l\d+>> LoadString /// CHECK-DAG: <<Append1:l\d+>> InvokeVirtual [<<New>>,<<String1>>] intrinsic:StringBufferAppend /// CHECK-DAG: <<String2:l\d+>> LoadString /// CHECK-DAG: <<Append2:l\d+>> InvokeVirtual [<<New>>,<<String2>>] intrinsic:StringBufferAppend /// CHECK-DAG: InvokeVirtual [<<New>>] intrinsic:StringBufferLength staticint bufferLen2() {
StringBuffer s = new StringBuffer(); return s.append("x").append("y").length();
}
staticint bufferLen2Smali() throws Exception { Class<?> c = Class.forName("Smali");
Method m = c.getMethod("bufferLen2"); return (Integer) m.invoke(null);
}
// // Allows combining of returned "this". Also ensures that similar looking append() calls // are not combined somehow through returned result. // /// CHECK-START: int Main.builderLen2() instruction_simplifier (before) /// CHECK-DAG: <<New:l\d+>> NewInstance /// CHECK-DAG: <<String1:l\d+>> LoadString /// CHECK-DAG: <<Append1:l\d+>> InvokeVirtual [<<New>>,<<String1>>] intrinsic:StringBuilderAppendString /// CHECK-DAG: <<String2:l\d+>> LoadString /// CHECK-DAG: <<Append2:l\d+>> InvokeVirtual [{{l\d+}},<<String2>>] intrinsic:StringBuilderAppendString /// CHECK-DAG: InvokeVirtual [{{l\d+}}] intrinsic:StringBuilderLength // /// CHECK-START: int Main.builderLen2() instruction_simplifier (after) /// CHECK-DAG: <<New:l\d+>> NewInstance /// CHECK-DAG: <<String1:l\d+>> LoadString /// CHECK-DAG: <<Append1:l\d+>> InvokeVirtual [<<New>>,<<String1>>] intrinsic:StringBuilderAppendString /// CHECK-DAG: <<String2:l\d+>> LoadString /// CHECK-DAG: <<Append2:l\d+>> InvokeVirtual [<<New>>,<<String2>>] intrinsic:StringBuilderAppendString /// CHECK-DAG: InvokeVirtual [<<New>>] intrinsic:StringBuilderLength staticint builderLen2() {
StringBuilder s = new StringBuilder(); return s.append("x").append("y").length();
}
staticint builderLen2Smali() throws Exception { Class<?> c = Class.forName("Smali");
Method m = c.getMethod("builderLen2"); return (Integer) m.invoke(null);
}
staticint builderLoopAppenderSmali() throws Exception { Class<?> c = Class.forName("Smali");
Method m = c.getMethod("bufferLoopAppender"); return (Integer) m.invoke(null);
}
// // All calls in the loop-body are dead and thus loop can be eliminated. // /// CHECK-START: int Main.bufferDeadLoop() dead_code_elimination$initial (before) /// CHECK-DAG: Phi loop:<<Loop:B\d+>> /// CHECK-DAG: InvokeVirtual intrinsic:StringBufferToString loop:<<Loop>> /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOfAfter loop:<<Loop>> // /// CHECK-START: int Main.bufferDeadLoop() dead_code_elimination$initial (after) /// CHECK-NOT: InvokeVirtual intrinsic:StringStringIndexOfAfter // /// CHECK-START: int Main.bufferDeadLoop() instruction_simplifier$after_inlining (before) /// CHECK: InvokeStaticOrDirect intrinsic:StringBufferToString // /// CHECK-START: int Main.bufferDeadLoop() instruction_simplifier$after_inlining (after) /// CHECK-NOT: InvokeStaticOrDirect intrinsic:StringBufferToString // /// CHECK-START: int Main.bufferDeadLoop() loop_optimization (before) /// CHECK: Phi // /// CHECK-START: int Main.bufferDeadLoop() loop_optimization (after) /// CHECK-NOT: Phi staticint bufferDeadLoop() {
StringBuffer b = new StringBuffer();
String x = "x"; for (int i = 0; i < 10; i++) { int d = b.toString().indexOf(x, 1);
} return b.length();
}
// // All calls in the loop-body are dead and thus loop can be eliminated. // /// CHECK-START: int Main.builderDeadLoop() instruction_simplifier (before) /// CHECK-DAG: Phi loop:<<Loop:B\d+>> /// CHECK-DAG: InvokeVirtual intrinsic:StringBuilderToString loop:<<Loop>> /// CHECK-DAG: InvokeVirtual intrinsic:StringStringIndexOfAfter loop:<<Loop>> // /// CHECK-START: int Main.builderDeadLoop() loop_optimization (after) /// CHECK-NOT: Phi /// CHECK-NOT: InvokeVirtual intrinsic:StringBuilderToString /// CHECK-NOT: InvokeVirtual intrinsic:StringStringIndexOfAfter staticint builderDeadLoop() {
StringBuilder b = new StringBuilder();
String x = "x"; for (int i = 0; i < 10; i++) { int d = b.toString().indexOf(x, 1);
} return b.length();
}
// Regression b/33656359: StringBuffer x is passed to constructor of String // (this caused old code to crash due to missing nullptr check). // /// CHECK-START: void Main.doesNothing() instruction_simplifier (before) /// CHECK-DAG: InvokeVirtual intrinsic:StringBufferToString // /// CHECK-START: void Main.doesNothing() instruction_simplifier (after) /// CHECK-DAG: InvokeVirtual intrinsic:StringBufferToString staticvoid doesNothing() {
StringBuffer x = new StringBuffer();
String y = new String(x);
x.toString();
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.