mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8172733: [JVMCI] add ResolvedJavaMethod.hasNeverInlineDirective
Reviewed-by: kvn
This commit is contained in:
parent
f3fcb0ec76
commit
1cd0ad5c34
10 changed files with 158 additions and 53 deletions
|
@ -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:
|
||||||
|
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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)},
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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() {
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -466,6 +466,7 @@ public class TestResolvedJavaMethod extends MethodUniverse {
|
||||||
"getProfilingInfo",
|
"getProfilingInfo",
|
||||||
"reprofile",
|
"reprofile",
|
||||||
"getCompilerStorage",
|
"getCompilerStorage",
|
||||||
|
"hasNeverInlineDirective",
|
||||||
"canBeInlined",
|
"canBeInlined",
|
||||||
"shouldBeInlined",
|
"shouldBeInlined",
|
||||||
"getLineNumberTable",
|
"getLineNumberTable",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue