1/*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package org.graalvm.compiler.hotspot.meta;
24
25import java.lang.reflect.Type;
26
27import org.graalvm.compiler.core.common.GraalOptions;
28import org.graalvm.compiler.graph.Node;
29import org.graalvm.compiler.graph.iterators.NodeIterable;
30import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
31import org.graalvm.compiler.hotspot.phases.AheadOfTimeVerificationPhase;
32import org.graalvm.compiler.nodes.ConstantNode;
33import org.graalvm.compiler.nodes.FrameState;
34import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
35import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
36import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
37import org.graalvm.compiler.nodes.type.StampTool;
38import org.graalvm.compiler.replacements.nodes.MacroNode;
39
40import jdk.vm.ci.meta.JavaKind;
41import jdk.vm.ci.meta.ResolvedJavaType;
42
43/**
44 * Extension of {@link InvocationPlugins} that disables plugins based on runtime configuration.
45 */
46final class HotSpotInvocationPlugins extends InvocationPlugins {
47    final GraalHotSpotVMConfig config;
48
49    HotSpotInvocationPlugins(GraalHotSpotVMConfig config) {
50        this.config = config;
51    }
52
53    @Override
54    public void register(InvocationPlugin plugin, Type declaringClass, String name, Type... argumentTypes) {
55        if (!config.usePopCountInstruction) {
56            if (name.equals("bitCount")) {
57                assert declaringClass.equals(Integer.class) || declaringClass.equals(Long.class);
58                return;
59            }
60        }
61        super.register(plugin, declaringClass, name, argumentTypes);
62    }
63
64    @Override
65    public void checkNewNodes(GraphBuilderContext b, InvocationPlugin plugin, NodeIterable<Node> newNodes) {
66        for (Node node : newNodes) {
67            if (node instanceof MacroNode) {
68                // MacroNode based plugins can only be used for inlining since they
69                // require a valid bci should they need to replace themselves with
70                // an InvokeNode during lowering.
71                assert plugin.inlineOnly() : String.format("plugin that creates a %s (%s) must return true for inlineOnly(): %s", MacroNode.class.getSimpleName(), node, plugin);
72            }
73        }
74        if (GraalOptions.ImmutableCode.getValue()) {
75            for (Node node : newNodes) {
76                if (node.hasUsages() && node instanceof ConstantNode) {
77                    ConstantNode c = (ConstantNode) node;
78                    if (c.getStackKind() == JavaKind.Object && AheadOfTimeVerificationPhase.isIllegalObjectConstant(c)) {
79                        if (isClass(c)) {
80                            // This will be handled later by LoadJavaMirrorWithKlassPhase
81                        } else {
82                            // Tolerate uses in unused FrameStates
83                            if (node.usages().filter((n) -> !(n instanceof FrameState) || n.hasUsages()).isNotEmpty()) {
84                                throw new AssertionError("illegal constant node in AOT: " + node);
85                            }
86                        }
87                    }
88                }
89            }
90        }
91        super.checkNewNodes(b, plugin, newNodes);
92    }
93
94    private static boolean isClass(ConstantNode node) {
95        ResolvedJavaType type = StampTool.typeOrNull(node);
96        return type != null && "Ljava/lang/Class;".equals(type.getName());
97    }
98}
99