1 /*
   2  * Copyright (c) 2013, 2015, 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  */
  23 
  24 import compiler.whitebox.CompilerWhiteBoxTest;
  25 
  26 /*
  27  * @test MakeMethodNotCompilableTest
  28  * @bug 8012322 8006683 8007288 8022832
  29  * @library /testlibrary /test/lib /
  30  * @modules java.base/jdk.internal.misc
  31  * @modules java.management
  32  * @build MakeMethodNotCompilableTest
  33  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  34  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
  35  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmixed -XX:-UseCounterDecay MakeMethodNotCompilableTest
  36  * @summary testing of WB::makeMethodNotCompilable()
  37  * @author igor.ignatyev@oracle.com
  38  */
  39 public class MakeMethodNotCompilableTest extends CompilerWhiteBoxTest {
  40     private int bci;
  41     public static void main(String[] args) throws Exception {
  42         String directive =
  43                 "[{ match:\"*SimpleTestCaseHelper.*\", BackgroundCompilation: false }, " +
  44                 " { match:\"*.*\", inline:\"-*SimpleTestCaseHelper.*\"}]";
  45         if (WHITE_BOX.addCompilerDirective(directive) != 2) {
  46             throw new RuntimeException("Could not add directive");
  47         }
  48         try {
  49             CompilerWhiteBoxTest.main(MakeMethodNotCompilableTest::new, args);
  50         } finally {
  51             WHITE_BOX.removeCompilerDirective(2);
  52         }
  53     }
  54 
  55     private MakeMethodNotCompilableTest(TestCase testCase) {
  56         super(testCase);
  57         // to prevent inlining of #method
  58         WHITE_BOX.testSetDontInlineMethod(method, true);
  59     }
  60 
  61     /**
  62      * Tests {@code WB::makeMethodNotCompilable()} by calling it before
  63      * compilation and checking that method isn't compiled. Also
  64      * checks that WB::clearMethodState() clears no-compilable flags. For
  65      * tiered, additional checks for all available levels are conducted.
  66      *
  67      * @throws Exception if one of the checks fails.
  68      */
  69     @Override
  70     protected void test() throws Exception {
  71         if (skipXcompOSR()) {
  72             return;
  73         }
  74         checkNotCompiled();
  75         if (!isCompilable()) {
  76             throw new RuntimeException(method + " must be compilable");
  77         }
  78 
  79         bci = getBci();
  80 
  81         if (TIERED_COMPILATION) {
  82             final int tierLimit = TIERED_STOP_AT_LEVEL + 1;
  83             for (int testedTier = 1; testedTier < tierLimit; ++testedTier) {
  84                 testTier(testedTier);
  85             }
  86             for (int testedTier = 1; testedTier < tierLimit; ++testedTier) {
  87                 makeNotCompilable(testedTier);
  88                 if (isCompilable(testedTier)) {
  89                     throw new RuntimeException(method
  90                             + " must be not compilable at level" + testedTier);
  91                 }
  92                 WHITE_BOX.enqueueMethodForCompilation(method, testedTier, bci);
  93                 checkNotCompiled();
  94 
  95                 if (!isCompilable()) {
  96                     System.out.println(method
  97                             + " is not compilable after level " + testedTier);
  98                 }
  99             }
 100         } else {
 101             compile();
 102             checkCompiled();
 103             int compLevel = getCompLevel();
 104             deoptimize();
 105             makeNotCompilable(compLevel);
 106             if (isCompilable(COMP_LEVEL_ANY)) {
 107                 throw new RuntimeException(method
 108                         + " must be not compilable at CompLevel::CompLevel_any,"
 109                         + " after it is not compilable at " + compLevel);
 110             }
 111 
 112             WHITE_BOX.clearMethodState(method);
 113             if (!isCompilable()) {
 114                 throw new RuntimeException(method
 115                         + " is not compilable after clearMethodState()");
 116             }
 117 
 118             // nocompilable at opposite level must make no sense
 119             int oppositeLevel;
 120             if (isC1Compile(compLevel)) {
 121               oppositeLevel = COMP_LEVEL_FULL_OPTIMIZATION;
 122             } else {
 123               oppositeLevel = COMP_LEVEL_SIMPLE;
 124             }
 125             makeNotCompilable(oppositeLevel);
 126 
 127             if (!isCompilable(COMP_LEVEL_ANY)) {
 128                   throw new RuntimeException(method
 129                         + " must be compilable at CompLevel::CompLevel_any,"
 130                         + " even it is not compilable at opposite level ["
 131                         + compLevel + "]");
 132             }
 133 
 134             if (!isCompilable(compLevel)) {
 135                   throw new RuntimeException(method
 136                         + " must be compilable at level " + compLevel
 137                         + ", even it is not compilable at opposite level ["
 138                         + compLevel + "]");
 139             }
 140         }
 141 
 142         // clearing after tiered/non-tiered tests
 143         // WB.clearMethodState() must reset no-compilable flags
 144         WHITE_BOX.clearMethodState(method);
 145         if (!isCompilable()) {
 146             throw new RuntimeException(method
 147                     + " is not compilable after clearMethodState()");
 148         }
 149         // Make method not (OSR-)compilable (depending on testCase.isOsr())
 150         makeNotCompilable();
 151         if (isCompilable()) {
 152             throw new RuntimeException(method + " must be not compilable");
 153         }
 154         // Try to (OSR-)compile method
 155         compile();
 156         // Method should not be (OSR-)compiled
 157         checkNotCompiled(testCase.isOsr());
 158         if (isCompilable()) {
 159             throw new RuntimeException(method + " must be not compilable");
 160         }
 161         // WB.clearMethodState() must reset no-compilable flags
 162         WHITE_BOX.clearMethodState(method);
 163         if (!isCompilable()) {
 164             throw new RuntimeException(method
 165                     + " is not compilable after clearMethodState()");
 166         }
 167         compile();
 168         checkCompiled();
 169     }
 170 
 171     // separately tests each tier
 172     private void testTier(int testedTier) {
 173         if (!isCompilable(testedTier)) {
 174             throw new RuntimeException(method
 175                     + " is not compilable on start");
 176         }
 177         makeNotCompilable(testedTier);
 178 
 179         // tests for all other tiers
 180         for (int anotherTier = 1, tierLimit = TIERED_STOP_AT_LEVEL + 1;
 181                     anotherTier < tierLimit; ++anotherTier) {
 182             boolean isCompilable = isCompilable(anotherTier);
 183             if (sameCompile(testedTier, anotherTier)) {
 184                 if (isCompilable) {
 185                     throw new RuntimeException(method
 186                             + " must be not compilable at level " + anotherTier
 187                             + ", if it is not compilable at " + testedTier);
 188                 }
 189                 WHITE_BOX.enqueueMethodForCompilation(method, anotherTier, bci);
 190                 checkNotCompiled();
 191             } else {
 192                 if (!isCompilable) {
 193                     throw new RuntimeException(method
 194                             + " must be compilable at level " + anotherTier
 195                             + ", even if it is not compilable at "
 196                             + testedTier);
 197                 }
 198                 WHITE_BOX.enqueueMethodForCompilation(method, anotherTier, bci);
 199                 checkCompiled();
 200                 deoptimize();
 201             }
 202 
 203             if (!isCompilable(COMP_LEVEL_ANY)) {
 204                 throw new RuntimeException(method
 205                         + " must be compilable at 'CompLevel::CompLevel_any'"
 206                         + ", if it is not compilable only at " + testedTier);
 207             }
 208         }
 209 
 210         // clear state after test
 211         WHITE_BOX.clearMethodState(method);
 212         if (!isCompilable(testedTier)) {
 213             throw new RuntimeException(method
 214                     + " is not compilable after clearMethodState()");
 215         }
 216     }
 217 
 218     private boolean sameCompile(int level1, int level2) {
 219         if (level1 == level2) {
 220             return true;
 221         }
 222         if (isC1Compile(level1) && isC1Compile(level2)) {
 223             return true;
 224         }
 225         if (isC2Compile(level1) && isC2Compile(level2)) {
 226             return true;
 227         }
 228         return false;
 229     }
 230 
 231     private int getBci() throws Exception {
 232         compile();
 233         checkCompiled();
 234         int result = WHITE_BOX.getMethodEntryBci(method);
 235         deoptimize();
 236         WHITE_BOX.clearMethodState(method);
 237         return result;
 238     }
 239 }