privatestaticvoid assertSingleImplementation(Class<?> clazz, String method_name, boolean b) { if (hasSingleImplementation(clazz, method_name) != b) {
System.out.println(clazz + "." + method_name + " doesn't have single implementation value of " + b);
}
}
// sMain1.foo()/sMain2.foo() will be always be Base.foo() before Main3 is loaded/linked. // So sMain1.foo() can be devirtualized to Base.foo() and be inlined. // After Helper.createMain3() which links in Main3, live testImplement() on stack // should be deoptimized. staticvoid testImplement(boolean createMain3, boolean wait, boolean setHasJIT) { if (setHasJIT) { if (isInterpreted()) {
sHasJIT = false;
} return;
}
if (createMain3 && (sIsOptimizing || sHasJIT)) {
assertIsManaged();
}
if (sMain1.foo(getValue(sMain1.getClass())) != 11) {
System.out.println("11 expected.");
} if (sMain1.$noinline$bar() != -1) {
System.out.println("-1 expected.");
} if (sMain2.foo(getValue(sMain2.getClass())) != 11) {
System.out.println("11 expected.");
}
if (createMain3) { // Wait for the other thread to start. while (!sOtherThreadStarted); // Create an Main2 instance and assign it to sMain2. // sMain1 is kept the same.
sMain3 = Helper.createMain3(); // Wake up the other thread. synchronized(Main.class) {
Main.class.notify();
}
} elseif (wait) { // This is the other thread. synchronized(Main.class) {
sOtherThreadStarted = true; // Wait for Main2 to be linked and deoptimization is triggered. try {
Main.class.wait();
} catch (Exception e) {
}
}
}
// There should be a deoptimization here right after Main3 is linked by // calling Helper.createMain3(), even though sMain1 didn't change. // The behavior here would be different if inline-cache is used, which // doesn't deoptimize since sMain1 still hits the type cache. if (sMain1.foo(getValue(sMain1.getClass())) != 11) {
System.out.println("11 expected.");
} if ((createMain3 || wait) && sHasJIT && !sIsOptimizing) { // This method should be deoptimized right after Main3 is created.
assertIsInterpreted();
}
if (sMain3 != null) { if (sMain3.foo(getValue(sMain3.getClass())) != -13) {
System.out.println("-13 expected.");
}
}
}
// Test scenarios under which CHA-based devirtualization happens, // and class loading that implements a method can invalidate compiled code. publicstaticvoid main(String[] args) {
System.loadLibrary(args[0]);
if (isInterpreted()) {
sIsOptimizing = false;
}
// sMain1 is an instance of Main1. // sMain2 is an instance of Main2. // Neither Main1 nor Main2 override default method Base.foo(). // Main3 hasn't bee loaded yet.
sMain1 = new Main1();
sMain2 = new Main2();
if (sHasJIT && !sIsOptimizing) {
assertSingleImplementation(Base.class, "foo", true);
assertSingleImplementation(Main1.class, "foo", true);
} else { // Main3 is verified ahead-of-time so it's linked in already.
}
// Create another thread that also calls sMain1.foo(). // Try to test suspend and deopt another thread. newThread() { publicvoid run() {
testImplement(false, true, false);
}
}.start();
// This will create Main3 instance in the middle of testImplement().
testImplement(true, false, false);
assertSingleImplementation(Base.class, "foo", false);
assertSingleImplementation(Main1.class, "foo", true);
assertSingleImplementation(sMain3.getClass(), "foo", true);
}
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.