$noinline$objectReturned(new Main());
ensureJitCompiled(Main.class, "$noinline$objectReturned");
Object o = $noinline$objectReturned(new SubMain()); // We used to get 0xebadde09 in 'o' here and therefore crash // both interpreter and compiled code. if (o instanceof Cloneable) {
System.out.println("Unexpected object type " + o.getClass());
}
}
publicboolean doCheck() { returnfalse;
}
publicstaticvoid $noinline$intUpdate(Main m) { int a = 0; // We used to kill 'a' when the inline cache of 'doCheck' only // contains 'Main' (which makes the only branch using 'a' dead). // So the deoptimization at the inline cache was incorrectly assuming // 'a' was dead. for (int i = 0; i < 5000; i++) { if (m.doCheck()) {
a++; // We make this branch the only true user of the 'a' phi. All other uses // of 'a' are phi updates.
myIntStatic = a;
} elseif (myIntStatic == 42) {
a = 1;
}
}
}
publicstaticvoid $noinline$objectUpdate(Main m) {
Object o = new Object(); // We used to kill 'o' when the inline cache of 'doCheck' only // contains 'Main' (which makes the only branch using 'o' dead). // So the deoptimization at the inline cache was incorrectly assuming // 'o' was dead. // This lead to a NPE on the 'toString' call just after deoptimizing. for (int i = 0; i < 5000; i++) { if (m.doCheck()) { // We make this branch the only true user of the 'o' phi. All other uses // of 'o' are phi updates.
o.toString();
} elseif (myIntStatic == 42) {
o = m;
}
}
}
publicstaticvoid $noinline$loopIncrement(Main m) { int k = 0; // We used to kill 'k' and replace it with 5000 when the inline cache // of 'doCheck' only contains 'Main'. // So the deoptimization at the inline cache was incorrectly assuming // 'k' was 5000. for (int i = 0; i < 5000; i++, k++) { if (m.doCheck()) { // We make this branch the only true user of the 'k' phi. All other uses // of 'k' are phi updates.
myIntStatic = k;
}
} if (k != 5000) { thrownew Error("Expected 5000, got " + k);
}
}
publicstatic Object $noinline$objectReturned(Main m) {
Object o = new Object(); // We used to kill 'o' when the inline cache of 'doCheck' only // contains 'Main' (which makes the only branch using 'o' dead). // So the deoptimization at the inline cache was incorrectly assuming // 'o' was dead. // We also need to make 'o' escape through a return instruction, as mterp // executes the same code for return and return-object, and the 0xebadde09 // sentinel for dead value is only pushed to non-object dex registers.
Object myReturnValue = null; for (int i = 0; i < 5000; i++) { if (m.doCheck()) { // We make this branch the only true user of the 'o' phi. All other uses // of 'o' are phi updates.
myReturnValue = o;
} elseif (myIntStatic == 42) {
o = m;
}
} return myReturnValue;
}
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.