From 01dbff5e4c3144cf939802868718491a8d7b7328 Mon Sep 17 00:00:00 2001 From: Dean Long Date: Fri, 7 Jun 2019 18:11:33 -0400 Subject: [PATCH] Backport c18ffd6a79fc6cd634b410a2dd37d0026ebb2664 --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 3 ++ .../HotSpotResolvedJavaMethodImpl.java | 5 ++- .../FindUniqueConcreteMethodTest.java | 43 ++++++++++++++----- .../runtime/test/TestResolvedJavaMethod.java | 3 +- 4 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index f102b79fee4..16de33f113f 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -370,6 +370,9 @@ C2V_VMENTRY(jobject, findUniqueConcreteMethod, (JNIEnv *, jobject, jobject jvmci if (method->is_abstract()) { return NULL; } + if (method->can_be_statically_bound()) { + THROW_MSG_0(vmSymbols::java_lang_InternalError(), err_msg("Effectively static method %s.%s should be handled in Java code", method->method_holder()->external_name(), method->external_name())); + } methodHandle ucm; { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index da3227653e7..d5594466e2d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -228,7 +228,7 @@ public int getModifiers() { @Override public boolean canBeStaticallyBound() { - return (isFinal() || isPrivate() || isStatic() || holder.isLeaf()) && isConcrete(); + return (isFinal() || isPrivate() || isStatic() || holder.isLeaf() || isConstructor()) && isConcrete(); } @Override @@ -392,6 +392,8 @@ public StackTraceElement asStackTraceElement(int bci) { @Override public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receiver) { + assert !canBeStaticallyBound() : this; + if (receiver.isInterface()) { // Cannot trust interfaces. Because of: // interface I { void foo(); } @@ -403,6 +405,7 @@ public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receive // seeing A.foo(). return null; } + assert !receiver.isLinked() || isInVirtualMethodTable(receiver); if (this.isDefault()) { // CHA for default methods doesn't work and may crash the VM return null; diff --git a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java index 200b292d735..8918257ab58 100644 --- a/test/hotspot/jtreg/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java @@ -79,7 +79,7 @@ private static Set createTestCases() { // overriden method result.add(new TestCase(true, SingleSubclass.class, "overridenMethod")); // private method - result.add(new TestCase(true, SingleSubclass.class, "privateMethod")); + result.add(new TestCase(InternalError.class, SingleSubclass.class, "privateMethod")); // protected method result.add(new TestCase(true, SingleSubclass.class, "protectedMethod")); // default(package-private) method @@ -92,7 +92,7 @@ private static Set createTestCases() { // result.add(new TestCase(true, SingleImplementer.class, // SingleImplementerInterface.class, "defaultMethod")); // static method - result.add(new TestCase(false, SingleSubclass.class, "staticMethod")); + result.add(new TestCase(InternalError.class, SingleSubclass.class, "staticMethod")); // interface method result.add(new TestCase(false, MultipleSuperImplementers.class, DuplicateSimpleSingleImplementerInterface.class, "interfaceMethod")); @@ -109,10 +109,21 @@ private void runTest(TestCase tcase) throws NoSuchMethodException { HotSpotResolvedObjectType resolvedType = CompilerToVMHelper .lookupTypeHelper(Utils.toJVMTypeSignature(tcase.receiver), getClass(), /* resolve = */ true); - HotSpotResolvedJavaMethod concreteMethod = CompilerToVMHelper - .findUniqueConcreteMethod(resolvedType, testMethod); - Asserts.assertEQ(concreteMethod, tcase.isPositive ? testMethod : null, - "Unexpected concrete method for " + tcase.methodName); + if (tcase.exception != null) { + try { + HotSpotResolvedJavaMethod concreteMethod = CompilerToVMHelper + .findUniqueConcreteMethod(resolvedType, testMethod); + + Asserts.fail("Exception " + tcase.exception.getName() + " not thrown for " + tcase.methodName); + } catch (Throwable t) { + Asserts.assertEQ(t.getClass(), tcase.exception, "Wrong exception thrown for " + tcase.methodName); + } + } else { + HotSpotResolvedJavaMethod concreteMethod = CompilerToVMHelper + .findUniqueConcreteMethod(resolvedType, testMethod); + Asserts.assertEQ(concreteMethod, tcase.isPositive ? testMethod : null, + "Unexpected concrete method for " + tcase.methodName); + } } private static class TestCase { @@ -120,23 +131,35 @@ private static class TestCase { public final Class holder; public final String methodName; public final boolean isPositive; + public final Class exception; public TestCase(boolean isPositive, Class clazz, Class holder, - String methodName) { + String methodName, Class exception) { this.receiver = clazz; this.methodName = methodName; this.isPositive = isPositive; this.holder = holder; + this.exception = exception; + } + + public TestCase(boolean isPositive, Class clazz, Class holder, + String methodName) { + this(isPositive, clazz, holder, methodName, null); } public TestCase(boolean isPositive, Class clazz, String methodName) { - this(isPositive, clazz, clazz, methodName); + this(isPositive, clazz, clazz, methodName, null); + } + + public TestCase(Class exception, Class clazz, String methodName) { + this(false, clazz, clazz, methodName, exception); } @Override public String toString() { - return String.format("CASE: receiver=%s, holder=%s, method=%s, isPositive=%s", - receiver.getName(), holder.getName(), methodName, isPositive); + return String.format("CASE: receiver=%s, holder=%s, method=%s, isPositive=%s, exception=%s", + receiver.getName(), holder.getName(), methodName, isPositive, + exception == null ? "" : exception.getName()); } } } diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java index e94ed85eb1d..cc5777074e2 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java @@ -214,7 +214,8 @@ public void canBeStaticallyBoundTest() { private static boolean canBeStaticallyBound(Member method) { int modifiers = method.getModifiers(); - return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(method.getDeclaringClass().getModifiers())) && + boolean isConstructor = method instanceof Constructor; + return (Modifier.isFinal(modifiers) || Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(method.getDeclaringClass().getModifiers()) || isConstructor) && !Modifier.isAbstract(modifiers); }