1/*
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package org.graalvm.compiler.core.test;
24
25import org.junit.Test;
26
27import org.graalvm.compiler.common.RetryableBailoutException;
28import org.graalvm.compiler.core.common.util.CompilationAlarm;
29import org.graalvm.compiler.debug.GraalError;
30import org.graalvm.compiler.nodes.StructuredGraph;
31import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
32import org.graalvm.compiler.options.OptionValue;
33import org.graalvm.compiler.options.OptionValue.OverrideScope;
34import org.graalvm.compiler.phases.Phase;
35
36public class CooperativePhaseTest extends GraalCompilerTest {
37
38    public static void snippet() {
39        // dummy snippet
40    }
41
42    private static class CooperativePhase extends Phase {
43
44        @Override
45        protected void run(StructuredGraph graph) {
46            while (true) {
47                sleep(200);
48                if (CompilationAlarm.hasExpired()) {
49                    return;
50                }
51            }
52        }
53
54    }
55
56    private static class UnCooperativePhase extends Phase {
57
58        @Override
59        protected void run(StructuredGraph graph) {
60            while (true) {
61                sleep(200);
62                if (CompilationAlarm.hasExpired()) {
63                    throw new RetryableBailoutException("Expiring...");
64                }
65            }
66        }
67
68    }
69
70    private static class ParlyCooperativePhase extends Phase {
71
72        @Override
73        protected void run(StructuredGraph graph) {
74            for (int i = 0; i < 10; i++) {
75                sleep(200);
76                if (CompilationAlarm.hasExpired()) {
77                    throw new RuntimeException("Phase must not exit in the timeout path");
78                }
79            }
80        }
81    }
82
83    private static class CooperativePhaseWithoutAlarm extends Phase {
84
85        @Override
86        protected void run(StructuredGraph graph) {
87            if (CompilationAlarm.hasExpired()) {
88                throw new RuntimeException("Phase must not exit in the timeout path");
89            }
90        }
91    }
92
93    private static void sleep(long millis) {
94        try {
95            Thread.sleep(millis);
96        } catch (InterruptedException e) {
97            GraalError.shouldNotReachHere(e.getCause());
98        }
99    }
100
101    @Test(timeout = 60_000)
102    @SuppressWarnings("try")
103    public void test01() {
104        StructuredGraph g = parseEager("snippet", AllowAssumptions.NO);
105        try (OverrideScope o = OptionValue.override(CompilationAlarm.Options.CompilationExpirationPeriod, 1/* sec */);
106                        CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod()) {
107            new CooperativePhase().apply(g);
108        }
109    }
110
111    @Test(expected = RetryableBailoutException.class, timeout = 60_000)
112    @SuppressWarnings("try")
113    public void test02() {
114        StructuredGraph g = parseEager("snippet", AllowAssumptions.NO);
115        try (OverrideScope o = OptionValue.override(CompilationAlarm.Options.CompilationExpirationPeriod, 1/* sec */);
116                        CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod()) {
117            new UnCooperativePhase().apply(g);
118        }
119    }
120
121    @Test(timeout = 60_000)
122    @SuppressWarnings("try")
123    public void test03() {
124        StructuredGraph g = parseEager("snippet", AllowAssumptions.NO);
125        // 0 disables alarm utility
126        try (OverrideScope o = OptionValue.override(CompilationAlarm.Options.CompilationExpirationPeriod, 0);
127                        CompilationAlarm c1 = CompilationAlarm.trackCompilationPeriod()) {
128            new ParlyCooperativePhase().apply(g);
129        }
130    }
131
132    @Test(timeout = 60_000)
133    @SuppressWarnings("try")
134    public void test04() {
135        StructuredGraph g = parseEager("snippet", AllowAssumptions.NO);
136        new CooperativePhaseWithoutAlarm().apply(g);
137    }
138}
139