blob: 97851bf052aa6c8a65a6765b9c135b576187e562 [file] [log] [blame]
/*
* Copyright (c) 2014, 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.
*/
package org.graalvm.compiler.core.test;
import jdk.vm.ci.meta.Assumptions.AssumptionResult;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaType;
import org.junit.Ignore;
import org.junit.Test;
import org.graalvm.compiler.debug.Debug;
import org.graalvm.compiler.debug.Debug.Scope;
import org.graalvm.compiler.nodes.ReturnNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
/**
* This test illustrates problems and limitations with class hierarchy analysis when default methods
* are involved.
*/
public class FindUniqueDefaultMethodTest extends GraalCompilerTest {
interface Interface1 {
default int v1() {
return 1;
}
}
static class Implementor1 implements Interface1 {
int callV1() {
return v1();
}
}
static class Subclass1 extends Implementor1 {
}
/**
* HotSpot has an internal mismatch with CHA and default methods. The initial query says that
* it's a unique method but the verification code that ensures that a dependence of this kind
* would pass will fail an assert in debug mode.
*/
@Test
public void testFindUnique() {
ResolvedJavaType cType = getMetaAccess().lookupJavaType(Implementor1.class);
cType.initialize();
ResolvedJavaMethod v1Method = getMetaAccess().lookupJavaMethod(this.getMethod(Interface1.class, "v1"));
AssumptionResult<ResolvedJavaMethod> method = cType.findUniqueConcreteMethod(v1Method);
assertDeepEquals(null, method);
}
interface Interface2 {
default int v1() {
return 1;
}
}
static class Base2 {
public int v2() {
return 1;
}
}
static class Implementor2 extends Base2 implements Interface2 {
int callV1() {
return v1();
}
int callV2() {
return v2();
}
}
static class Subclass2 extends Implementor2 {
}
/**
* This test illustrates a common pattern where a method at the root of a hierarchy is the only
* implementation and can be statically inlined.
*/
@SuppressWarnings("unused")
@Test
public void testInherited() {
Subclass2 s = new Subclass2();
testConstantReturn("runInherited", 1);
}
/**
* Test same pattern as above but using default methods instead. HotSpot doesn't allow this
* version to be optimized.
*/
@SuppressWarnings("unused")
@Test
@Ignore("HotSpot CHA doesn't treat default methods like regular methods")
public void testDefault() {
Subclass2 s = new Subclass2();
testConstantReturn("runDefault", 1);
}
public int runDefault(Implementor2 i) {
return i.callV1();
}
public int runInherited(Implementor2 i) {
return i.callV2();
}
private void testConstantReturn(String name, Object value) {
StructuredGraph result = buildGraph(name);
ReturnNode ret = result.getNodes(ReturnNode.TYPE).first();
assertDeepEquals(1, result.getNodes(ReturnNode.TYPE).count());
assertDeepEquals(true, ret.result().isConstant());
assertDeepEquals(value, ret.result().asJavaConstant().asBoxedPrimitive());
}
@SuppressWarnings("try")
protected StructuredGraph buildGraph(final String snippet) {
try (Scope s = Debug.scope("InstanceOfTest", getMetaAccess().lookupJavaMethod(getMethod(snippet)))) {
StructuredGraph graph = parseEager(snippet, AllowAssumptions.YES);
compile(graph.method(), graph);
Debug.dump(Debug.BASIC_LOG_LEVEL, graph, snippet);
return graph;
} catch (Throwable e) {
throw Debug.handle(e);
}
}
}