/* * Copyright (c) 2019, 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.replacements.test; import java.util.ArrayList; import java.util.List; import jdk.internal.vm.compiler.collections.MapCursor; import org.graalvm.compiler.api.test.Graal; import org.graalvm.compiler.core.common.CompilationIdentifier; import org.graalvm.compiler.core.common.GraalOptions; import org.graalvm.compiler.core.target.Backend; import org.graalvm.compiler.core.test.GraalCompilerTest; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin; import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins; import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.runtime.RuntimeProvider; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; /** * Exercise * {@link org.graalvm.compiler.nodes.spi.Replacements#getIntrinsicGraph(ResolvedJavaMethod, CompilationIdentifier, DebugContext)} * with regular method substitutions and encoded graphs. */ @RunWith(Parameterized.class) public class RootMethodSubstitutionTest extends GraalCompilerTest { public RootMethodSubstitutionTest(ResolvedJavaMethod method) { this.method = method; } @Parameterized.Parameters(name = "{0}") public static List data() { ArrayList ret = new ArrayList<>(); Backend backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend(); Providers providers = backend.getProviders(); MapCursor> cursor = providers.getReplacements().getGraphBuilderPlugins().getInvocationPlugins().getBindings(true).getEntries(); MetaAccessProvider metaAccess = providers.getMetaAccess(); while (cursor.advance()) { String className = cursor.getKey(); ResolvedJavaType type = null; try { String typeName = className.substring(1, className.length() - 1).replace('/', '.'); ClassLoader cl = ClassLoader.getSystemClassLoader(); Class clazz = Class.forName(typeName, true, cl); type = metaAccess.lookupJavaType(clazz); } catch (ClassNotFoundException e) { continue; } for (InvocationPlugins.Binding binding : cursor.getValue()) { if (binding.plugin instanceof MethodSubstitutionPlugin) { ResolvedJavaMethod original = null; for (ResolvedJavaMethod declared : type.getDeclaredMethods()) { if (declared.getName().equals(binding.name)) { if (declared.isStatic() == binding.isStatic) { if (declared.getSignature().toMethodDescriptor().startsWith(binding.argumentsDescriptor)) { original = declared; break; } } } } if (!original.isNative()) { // Make sure the plugin we found hasn't been overridden. InvocationPlugin plugin = providers.getReplacements().getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(original); if (plugin instanceof MethodSubstitutionPlugin) { ret.add(new Object[]{original}); } } } } } return ret; } private final ResolvedJavaMethod method; private StructuredGraph getIntrinsicGraph(boolean useEncodedGraphs) { OptionValues options = new OptionValues(getDebugContext().getOptions(), GraalOptions.UseEncodedGraphs, useEncodedGraphs); DebugContext debugContext = DebugContext.create(options, getDebugContext().getDescription(), getDebugHandlersFactories()); return getReplacements().getIntrinsicGraph(method, CompilationIdentifier.INVALID_COMPILATION_ID, debugContext); } StructuredGraph expectedGraph; StructuredGraph actualGraph; @Override protected boolean checkHighTierGraph(StructuredGraph graph) { // Capture the graphs after high tier if (expectedGraph == null) { expectedGraph = (StructuredGraph) graph.copy(graph.getDebug()); } else { assert actualGraph == null; actualGraph = (StructuredGraph) graph.copy(graph.getDebug()); } return super.checkHighTierGraph(graph); } @Test public void test() { StructuredGraph regularGraph = getIntrinsicGraph(false); assertTrue(regularGraph != null, "must produce a graph"); getCode(method, regularGraph); StructuredGraph encodedGraph = getIntrinsicGraph(true); assertTrue(encodedGraph != null, "must produce a graph"); getCode(method, encodedGraph); // Compare the high tier graphs since the final graph might have scheduler // differences because of different usage ordering. assertEquals(expectedGraph, actualGraph, true, false); } }