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