TypeGuardInlineInfo.java revision 12651:6ef01bd40ce2
1/*
2 * Copyright (c) 2013, 2014, 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.phases.common.inlining.info;
24
25import java.util.Collection;
26
27import org.graalvm.compiler.core.common.calc.Condition;
28import org.graalvm.compiler.graph.Node;
29import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
30import org.graalvm.compiler.nodes.ConstantNode;
31import org.graalvm.compiler.nodes.FixedGuardNode;
32import org.graalvm.compiler.nodes.Invoke;
33import org.graalvm.compiler.nodes.LogicNode;
34import org.graalvm.compiler.nodes.StructuredGraph;
35import org.graalvm.compiler.nodes.ValueNode;
36import org.graalvm.compiler.nodes.calc.CompareNode;
37import org.graalvm.compiler.nodes.extended.LoadHubNode;
38import org.graalvm.compiler.phases.common.inlining.InliningUtil;
39import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
40import org.graalvm.compiler.phases.util.Providers;
41
42import jdk.vm.ci.meta.DeoptimizationAction;
43import jdk.vm.ci.meta.DeoptimizationReason;
44import jdk.vm.ci.meta.ResolvedJavaMethod;
45import jdk.vm.ci.meta.ResolvedJavaType;
46
47/**
48 * Represents an inlining opportunity for which profiling information suggests a monomorphic
49 * receiver, but for which the receiver type cannot be proven. A type check guard will be generated
50 * if this inlining is performed.
51 */
52public class TypeGuardInlineInfo extends AbstractInlineInfo {
53
54    private final ResolvedJavaMethod concrete;
55    private final ResolvedJavaType type;
56    private Inlineable inlineableElement;
57
58    public TypeGuardInlineInfo(Invoke invoke, ResolvedJavaMethod concrete, ResolvedJavaType type) {
59        super(invoke);
60        this.concrete = concrete;
61        this.type = type;
62        assert type.isArray() || type.isConcrete() : type;
63    }
64
65    @Override
66    public int numberOfMethods() {
67        return 1;
68    }
69
70    @Override
71    public ResolvedJavaMethod methodAt(int index) {
72        assert index == 0;
73        return concrete;
74    }
75
76    @Override
77    public Inlineable inlineableElementAt(int index) {
78        assert index == 0;
79        return inlineableElement;
80    }
81
82    @Override
83    public double probabilityAt(int index) {
84        assert index == 0;
85        return 1.0;
86    }
87
88    @Override
89    public double relevanceAt(int index) {
90        assert index == 0;
91        return 1.0;
92    }
93
94    @Override
95    public void setInlinableElement(int index, Inlineable inlineableElement) {
96        assert index == 0;
97        this.inlineableElement = inlineableElement;
98    }
99
100    @Override
101    public Collection<Node> inline(Providers providers) {
102        createGuard(graph(), providers);
103        return inline(invoke, concrete, inlineableElement, false);
104    }
105
106    @Override
107    public void tryToDevirtualizeInvoke(Providers providers) {
108        createGuard(graph(), providers);
109        InliningUtil.replaceInvokeCallTarget(invoke, graph(), InvokeKind.Special, concrete);
110    }
111
112    private void createGuard(StructuredGraph graph, Providers providers) {
113        ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke);
114        LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver));
115        ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(), providers.getConstantReflection().asObjectHub(type), providers.getMetaAccess(), graph);
116
117        LogicNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub, providers.getConstantReflection());
118        FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
119        assert invoke.predecessor() != null;
120
121        ValueNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, guard, type, nonNullReceiver, true);
122        invoke.callTarget().replaceFirstInput(nonNullReceiver, anchoredReceiver);
123
124        graph.addBeforeFixed(invoke.asNode(), guard);
125    }
126
127    @Override
128    public String toString() {
129        return "type-checked with type " + type.getName() + " and method " + concrete.format("%H.%n(%p):%r");
130    }
131
132    @Override
133    public boolean shouldInline() {
134        return concrete.shouldBeInlined();
135    }
136}
137