8172733: [JVMCI] add ResolvedJavaMethod.hasNeverInlineDirective

Reviewed-by: kvn
This commit is contained in:
Doug Simon 2017-01-22 21:40:59 +01:00
parent f3fcb0ec76
commit 1cd0ad5c34
10 changed files with 158 additions and 53 deletions

View file

@ -100,15 +100,19 @@ final class CompilerToVM {
native long getExceptionTableStart(HotSpotResolvedJavaMethodImpl method); native long getExceptionTableStart(HotSpotResolvedJavaMethodImpl method);
/** /**
* Determines if {@code method} can be inlined. A method may not be inlinable for a number of * Determines whether {@code method} is currently compilable by the JVMCI compiler being used by
* reasons such as: * the VM. This can return false if JVMCI compilation failed earlier for {@code method}, a
* <ul> * breakpoint is currently set in {@code method} or {@code method} contains other bytecode
* <li>a CompileOracle directive may prevent inlining or compilation of methods</li> * features that require special handling by the VM.
* <li>the method may have a bytecode breakpoint set</li>
* <li>the method may have other bytecode features that require special handling by the VM</li>
* </ul>
*/ */
native boolean canInlineMethod(HotSpotResolvedJavaMethodImpl method); native boolean isCompilable(HotSpotResolvedJavaMethodImpl method);
/**
* Determines if {@code method} is targeted by a VM directive (e.g.,
* {@code -XX:CompileCommand=dontinline,<pattern>}) or annotation (e.g.,
* {@code jdk.internal.vm.annotation.DontInline}) that specifies it should not be inlined.
*/
native boolean hasNeverInlineDirective(HotSpotResolvedJavaMethodImpl method);
/** /**
* Determines if {@code method} should be inlined at any cost. This could be because: * Determines if {@code method} should be inlined at any cost. This could be because:

View file

@ -49,13 +49,6 @@ public interface HotSpotResolvedJavaMethod extends ResolvedJavaMethod {
*/ */
boolean isForceInline(); boolean isForceInline();
/**
* Returns true if this method has a {@code DontInline} annotation.
*
* @return true if DontInline annotation present, false otherwise
*/
boolean isDontInline();
/** /**
* Returns true if this method has a {@code ReservedStackAccess} annotation. * Returns true if this method has a {@code ReservedStackAccess} annotation.
* *

View file

@ -298,15 +298,6 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
return (getFlags() & config().methodFlagsForceInline) != 0; return (getFlags() & config().methodFlagsForceInline) != 0;
} }
/**
* Returns true if this method has a {@code DontInline} annotation.
*
* @return true if DontInline annotation present, false otherwise
*/
public boolean isDontInline() {
return (getFlags() & config().methodFlagsDontInline) != 0;
}
/** /**
* Returns true if this method has a {@code ReservedStackAccess} annotation. * Returns true if this method has a {@code ReservedStackAccess} annotation.
* *
@ -582,10 +573,15 @@ final class HotSpotResolvedJavaMethodImpl extends HotSpotMethod implements HotSp
@Override @Override
public boolean canBeInlined() { public boolean canBeInlined() {
if (isDontInline()) { if (hasNeverInlineDirective()) {
return false; return false;
} }
return compilerToVM().canInlineMethod(this); return compilerToVM().isCompilable(this);
}
@Override
public boolean hasNeverInlineDirective() {
return compilerToVM().hasNeverInlineDirective(this);
} }
@Override @Override

View file

@ -346,6 +346,13 @@ public interface ResolvedJavaMethod extends JavaMethod, InvokeTarget, ModifiersP
*/ */
boolean canBeInlined(); boolean canBeInlined();
/**
* Determines if this method is targeted by a VM directive (e.g.,
* {@code -XX:CompileCommand=dontinline,<pattern>}) or VM recognized annotation (e.g.,
* {@code jdk.internal.vm.annotation.DontInline}) that specifies it should not be inlined.
*/
boolean hasNeverInlineDirective();
/** /**
* Returns {@code true} if the inlining of this method should be forced. * Returns {@code true} if the inlining of this method should be forced.
*/ */

View file

@ -591,12 +591,16 @@ C2V_VMENTRY(jboolean, methodIsIgnoredBySecurityStackWalk,(JNIEnv *, jobject, job
return method->is_ignored_by_security_stack_walk(); return method->is_ignored_by_security_stack_walk();
C2V_END C2V_END
C2V_VMENTRY(jboolean, canInlineMethod,(JNIEnv *, jobject, jobject jvmci_method)) C2V_VMENTRY(jboolean, isCompilable,(JNIEnv *, jobject, jobject jvmci_method))
methodHandle method = CompilerToVM::asMethod(jvmci_method); methodHandle method = CompilerToVM::asMethod(jvmci_method);
// In hosted mode ignore the not_compilable flags since they are never set by // Ignore the not_compilable flags in hosted mode since they are never set by
// the JVMCI compiler. // the JVMCI compiler.
bool is_compilable = UseJVMCICompiler ? !method->is_not_compilable(CompLevel_full_optimization) : true; return UseJVMCICompiler || !method->is_not_compilable(CompLevel_full_optimization);
return is_compilable && !CompilerOracle::should_not_inline(method) && !method->dont_inline(); C2V_END
C2V_VMENTRY(jboolean, hasNeverInlineDirective,(JNIEnv *, jobject, jobject jvmci_method))
methodHandle method = CompilerToVM::asMethod(jvmci_method);
return CompilerOracle::should_not_inline(method) || method->dont_inline();
C2V_END C2V_END
C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jobject jvmci_method)) C2V_VMENTRY(jboolean, shouldInlineMethod,(JNIEnv *, jobject, jobject jvmci_method))
@ -1591,7 +1595,8 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "getStackTraceElement", CC "(" HS_RESOLVED_METHOD "I)" STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)}, {CC "getStackTraceElement", CC "(" HS_RESOLVED_METHOD "I)" STACK_TRACE_ELEMENT, FN_PTR(getStackTraceElement)},
{CC "methodIsIgnoredBySecurityStackWalk", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)}, {CC "methodIsIgnoredBySecurityStackWalk", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(methodIsIgnoredBySecurityStackWalk)},
{CC "doNotInlineOrCompile", CC "(" HS_RESOLVED_METHOD ")V", FN_PTR(doNotInlineOrCompile)}, {CC "doNotInlineOrCompile", CC "(" HS_RESOLVED_METHOD ")V", FN_PTR(doNotInlineOrCompile)},
{CC "canInlineMethod", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(canInlineMethod)}, {CC "isCompilable", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(isCompilable)},
{CC "hasNeverInlineDirective", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(hasNeverInlineDirective)},
{CC "shouldInlineMethod", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(shouldInlineMethod)}, {CC "shouldInlineMethod", CC "(" HS_RESOLVED_METHOD ")Z", FN_PTR(shouldInlineMethod)},
{CC "lookupType", CC "(" STRING CLASS "Z)" HS_RESOLVED_KLASS, FN_PTR(lookupType)}, {CC "lookupType", CC "(" STRING CLASS "Z)" HS_RESOLVED_KLASS, FN_PTR(lookupType)},
{CC "lookupNameInPool", CC "(" HS_CONSTANT_POOL "I)" STRING, FN_PTR(lookupNameInPool)}, {CC "lookupNameInPool", CC "(" HS_CONSTANT_POOL "I)" STRING, FN_PTR(lookupNameInPool)},

View file

@ -48,8 +48,12 @@ public class CompilerToVMHelper {
return CTVM.getExceptionTableStart((HotSpotResolvedJavaMethodImpl)method); return CTVM.getExceptionTableStart((HotSpotResolvedJavaMethodImpl)method);
} }
public static boolean canInlineMethod(HotSpotResolvedJavaMethod method) { public static boolean isCompilable(HotSpotResolvedJavaMethod method) {
return CTVM.canInlineMethod((HotSpotResolvedJavaMethodImpl)method); return CTVM.isCompilable((HotSpotResolvedJavaMethodImpl)method);
}
public static boolean hasNeverInlineDirective(HotSpotResolvedJavaMethod method) {
return CTVM.hasNeverInlineDirective((HotSpotResolvedJavaMethodImpl)method);
} }
public static boolean shouldInlineMethod(HotSpotResolvedJavaMethod method) { public static boolean shouldInlineMethod(HotSpotResolvedJavaMethod method) {

View file

@ -67,13 +67,13 @@ public class DoNotInlineOrCompileTest {
private static void runSanityTest(Executable aMethod) { private static void runSanityTest(Executable aMethod) {
HotSpotResolvedJavaMethod method = CTVMUtilities HotSpotResolvedJavaMethod method = CTVMUtilities
.getResolvedMethod(aMethod); .getResolvedMethod(aMethod);
boolean canInline = CompilerToVMHelper.canInlineMethod(method); boolean hasNeverInlineDirective = CompilerToVMHelper.hasNeverInlineDirective(method);
Asserts.assertTrue(canInline, "Unexpected initial " + Asserts.assertFalse(hasNeverInlineDirective, "Unexpected initial " +
"value of property 'can inline'"); "value of property 'hasNeverInlineDirective'");
CompilerToVMHelper.doNotInlineOrCompile(method); CompilerToVMHelper.doNotInlineOrCompile(method);
canInline = CompilerToVMHelper.canInlineMethod(method); hasNeverInlineDirective = CompilerToVMHelper.hasNeverInlineDirective(method);
Asserts.assertFalse(canInline, aMethod Asserts.assertTrue(hasNeverInlineDirective, aMethod
+ " : can be inlined even after doNotInlineOrCompile'"); + " : hasNeverInlineDirective is false even after doNotInlineOrCompile'");
} }
private static List<Executable> createTestCases() { private static List<Executable> createTestCases() {

View file

@ -39,7 +39,7 @@
* @run main/othervm -Xbootclasspath/a:. * @run main/othervm -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
* compiler.jvmci.compilerToVM.CanInlineMethodTest * compiler.jvmci.compilerToVM.HasNeverInlineDirectiveTest
*/ */
package compiler.jvmci.compilerToVM; package compiler.jvmci.compilerToVM;
@ -55,31 +55,30 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
public class CanInlineMethodTest { public class HasNeverInlineDirectiveTest {
private static final WhiteBox WB = WhiteBox.getWhiteBox(); private static final WhiteBox WB = WhiteBox.getWhiteBox();
public static void main(String[] args) { public static void main(String[] args) {
List<Executable> testCases = createTestCases(); List<Executable> testCases = createTestCases();
testCases.forEach(CanInlineMethodTest::runSanityTest); testCases.forEach(HasNeverInlineDirectiveTest::runSanityTest);
} }
private static void runSanityTest(Executable aMethod) { private static void runSanityTest(Executable aMethod) {
HotSpotResolvedJavaMethod method = CTVMUtilities HotSpotResolvedJavaMethod method = CTVMUtilities
.getResolvedMethod(aMethod); .getResolvedMethod(aMethod);
boolean canInline = CompilerToVMHelper.canInlineMethod(method); boolean hasNeverInlineDirective = CompilerToVMHelper.hasNeverInlineDirective(method);
boolean expectedCanInline = !WB.testSetDontInlineMethod(aMethod, boolean expected = WB.testSetDontInlineMethod(aMethod, true);
true); Asserts.assertEQ(hasNeverInlineDirective, expected, "Unexpected initial " +
Asserts.assertEQ(canInline, expectedCanInline, "Unexpected initial " + "value of property 'hasNeverInlineDirective'");
"value of property 'can inline'");
canInline = CompilerToVMHelper.canInlineMethod(method); hasNeverInlineDirective = CompilerToVMHelper.hasNeverInlineDirective(method);
Asserts.assertFalse(canInline, aMethod + "Unexpected value of " + Asserts.assertTrue(hasNeverInlineDirective, aMethod + "Unexpected value of " +
"property 'can inline' after setting 'do not inline' to true"); "property 'hasNeverInlineDirective' after setting 'do not inline' to true");
WB.testSetDontInlineMethod(aMethod, false); WB.testSetDontInlineMethod(aMethod, false);
canInline = CompilerToVMHelper.canInlineMethod(method); hasNeverInlineDirective = CompilerToVMHelper.hasNeverInlineDirective(method);
Asserts.assertTrue(canInline, "Unexpected value of " + Asserts.assertFalse(hasNeverInlineDirective, "Unexpected value of " +
"property 'can inline' after setting 'do not inline' to false"); "property 'hasNeverInlineDirective' after setting 'do not inline' to false");
} }
private static List<Executable> createTestCases() { private static List<Executable> createTestCases() {

View file

@ -0,0 +1,96 @@
/*
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8136421
* @requires vm.jvmci
* @library /test/lib /
* @library ../common/patches
* @modules java.base/jdk.internal.misc
* @modules java.base/jdk.internal.org.objectweb.asm
* java.base/jdk.internal.org.objectweb.asm.tree
* jdk.vm.ci/jdk.vm.ci.hotspot
* jdk.vm.ci/jdk.vm.ci.code
*
* @build jdk.vm.ci/jdk.vm.ci.hotspot.CompilerToVMHelper sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:+UseJVMCICompiler
* compiler.jvmci.compilerToVM.IsCompilableTest
* @run main/othervm -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
* -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI
* compiler.jvmci.compilerToVM.IsCompilableTest
*/
package compiler.jvmci.compilerToVM;
import compiler.jvmci.common.CTVMUtilities;
import jdk.test.lib.Asserts;
import jdk.vm.ci.hotspot.CompilerToVMHelper;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import sun.hotspot.WhiteBox;
import java.lang.reflect.Executable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class IsCompilableTest {
private static final WhiteBox WB = WhiteBox.getWhiteBox();
public static void main(String[] args) {
List<Executable> testCases = createTestCases();
testCases.forEach(IsCompilableTest::runSanityTest);
}
private static void runSanityTest(Executable aMethod) {
boolean UseJVMCICompiler = (Boolean) WB.getVMFlag("UseJVMCICompiler");
HotSpotResolvedJavaMethod method = CTVMUtilities
.getResolvedMethod(aMethod);
boolean isCompilable = CompilerToVMHelper.isCompilable(method);
boolean expected = UseJVMCICompiler || WB.isMethodCompilable(aMethod);
Asserts.assertEQ(isCompilable, expected, "Unexpected initial " +
"value of property 'compilable'");
if (!UseJVMCICompiler) {
WB.makeMethodNotCompilable(aMethod);
isCompilable = CompilerToVMHelper.isCompilable(method);
Asserts.assertFalse(isCompilable, aMethod + "Unexpected value of " +
"property 'isCompilable' after setting 'compilable' to false");
}
}
private static List<Executable> createTestCases() {
List<Executable> testCases = new ArrayList<>();
Class<?> aClass = DummyClass.class;
testCases.addAll(Arrays.asList(aClass.getDeclaredMethods()));
testCases.addAll(Arrays.asList(aClass.getDeclaredConstructors()));
return testCases;
}
}

View file

@ -466,6 +466,7 @@ public class TestResolvedJavaMethod extends MethodUniverse {
"getProfilingInfo", "getProfilingInfo",
"reprofile", "reprofile",
"getCompilerStorage", "getCompilerStorage",
"hasNeverInlineDirective",
"canBeInlined", "canBeInlined",
"shouldBeInlined", "shouldBeInlined",
"getLineNumberTable", "getLineNumberTable",