diff options
author | 2017-06-22 11:56:01 +0100 | |
---|---|---|
committer | 2017-06-22 12:09:16 +0100 | |
commit | 1a0a519c82044ec3e6d3910ff0602b11292de47a (patch) | |
tree | 342691a82a58ddb0660b9111622b2ff67d92f898 /test/656-loop-deopt/src/Main.java | |
parent | 8979f71079ec18fa8d3c0915549ec03ee1fbadf5 (diff) |
Fix loop optimization in the presence of environment uses.
We should not remove instructions that have deoptimize as
users, or that have environment uses in a debuggable setup.
bug: 62536525
bug: 33775412
Test: 656-loop-deopt
Change-Id: Iaec1a0b6e90c6a0169f18c6985f00fd8baf2dece
Diffstat (limited to 'test/656-loop-deopt/src/Main.java')
-rw-r--r-- | test/656-loop-deopt/src/Main.java | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/test/656-loop-deopt/src/Main.java b/test/656-loop-deopt/src/Main.java new file mode 100644 index 0000000000..c99cccf4f1 --- /dev/null +++ b/test/656-loop-deopt/src/Main.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +public class Main { + public static void main(String[] args) throws Exception { + System.loadLibrary(args[0]); + + $noinline$intUpdate(new Main()); + ensureJitCompiled(Main.class, "$noinline$intUpdate"); + $noinline$intUpdate(new SubMain()); + if (myIntStatic != 5000) { + throw new Error("Expected 5000, got " + myIntStatic); + } + + $noinline$objectUpdate(new Main()); + ensureJitCompiled(Main.class, "$noinline$objectUpdate"); + $noinline$objectUpdate(new SubMain()); + + $noinline$loopIncrement(new Main()); + ensureJitCompiled(Main.class, "$noinline$loopIncrement"); + $noinline$loopIncrement(new SubMain()); + } + + public boolean doCheck() { + return false; + } + + public static void $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; + } else if (myIntStatic == 42) { + a = 1; + } + } + } + + public static void $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 'a' 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(); + } else if (myIntStatic == 42) { + o = m; + } + } + } + + public static void $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 'a' phi. All other uses + // of 'a' are phi updates. + myIntStatic = k; + } + } + if (k != 5000) { + throw new Error("Expected 5000, got " + k); + } + } + + public static int myIntStatic = 0; + + public static native void ensureJitCompiled(Class<?> itf, String name); +} + +class SubMain extends Main { + public boolean doCheck() { + return true; + } +} |