001/* 002 * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.phases.common.inlining.info; 024 025import java.util.*; 026 027import jdk.internal.jvmci.meta.*; 028 029import com.oracle.graal.compiler.common.calc.*; 030import com.oracle.graal.graph.*; 031import com.oracle.graal.nodes.CallTargetNode.InvokeKind; 032import com.oracle.graal.nodes.*; 033import com.oracle.graal.nodes.calc.*; 034import com.oracle.graal.nodes.extended.*; 035import com.oracle.graal.phases.common.inlining.*; 036import com.oracle.graal.phases.common.inlining.info.elem.*; 037import com.oracle.graal.phases.util.*; 038 039/** 040 * Represents an inlining opportunity for which profiling information suggests a monomorphic 041 * receiver, but for which the receiver type cannot be proven. A type check guard will be generated 042 * if this inlining is performed. 043 */ 044public class TypeGuardInlineInfo extends AbstractInlineInfo { 045 046 private final ResolvedJavaMethod concrete; 047 private final ResolvedJavaType type; 048 private Inlineable inlineableElement; 049 050 public TypeGuardInlineInfo(Invoke invoke, ResolvedJavaMethod concrete, ResolvedJavaType type) { 051 super(invoke); 052 this.concrete = concrete; 053 this.type = type; 054 assert type.isArray() || type.isConcrete() : type; 055 } 056 057 @Override 058 public int numberOfMethods() { 059 return 1; 060 } 061 062 @Override 063 public ResolvedJavaMethod methodAt(int index) { 064 assert index == 0; 065 return concrete; 066 } 067 068 @Override 069 public Inlineable inlineableElementAt(int index) { 070 assert index == 0; 071 return inlineableElement; 072 } 073 074 @Override 075 public double probabilityAt(int index) { 076 assert index == 0; 077 return 1.0; 078 } 079 080 @Override 081 public double relevanceAt(int index) { 082 assert index == 0; 083 return 1.0; 084 } 085 086 @Override 087 public void setInlinableElement(int index, Inlineable inlineableElement) { 088 assert index == 0; 089 this.inlineableElement = inlineableElement; 090 } 091 092 @Override 093 public Collection<Node> inline(Providers providers) { 094 createGuard(graph(), providers); 095 return inline(invoke, concrete, inlineableElement, false); 096 } 097 098 @Override 099 public void tryToDevirtualizeInvoke(Providers providers) { 100 createGuard(graph(), providers); 101 InliningUtil.replaceInvokeCallTarget(invoke, graph(), InvokeKind.Special, concrete); 102 } 103 104 private void createGuard(StructuredGraph graph, Providers providers) { 105 ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke); 106 LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver)); 107 ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(), type.getObjectHub(), providers.getMetaAccess(), graph); 108 109 LogicNode typeCheck = CompareNode.createCompareNode(graph, Condition.EQ, receiverHub, typeHub, providers.getConstantReflection()); 110 FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile)); 111 assert invoke.predecessor() != null; 112 113 ValueNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, guard, type, nonNullReceiver, true); 114 invoke.callTarget().replaceFirstInput(nonNullReceiver, anchoredReceiver); 115 116 graph.addBeforeFixed(invoke.asNode(), guard); 117 } 118 119 @Override 120 public String toString() { 121 return "type-checked with type " + type.getName() + " and method " + concrete.format("%H.%n(%p):%r"); 122 } 123 124 public boolean shouldInline() { 125 return concrete.shouldBeInlined(); 126 } 127}