001/* 002 * Copyright (c) 2009, 2015, 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.nodes; 024 025import java.util.*; 026 027import jdk.internal.jvmci.meta.*; 028 029import com.oracle.graal.compiler.common.type.*; 030import com.oracle.graal.graph.*; 031import com.oracle.graal.nodeinfo.*; 032import com.oracle.graal.nodes.extended.*; 033import com.oracle.graal.nodes.java.*; 034import com.oracle.graal.nodes.memory.*; 035import com.oracle.graal.nodes.spi.*; 036import com.oracle.graal.nodes.util.*; 037 038/** 039 * The {@code InvokeNode} represents all kinds of method calls. 040 */ 041@NodeInfo(nameTemplate = "Invoke#{p#targetMethod/s}", allowedUsageTypes = {InputType.Memory}) 042public final class InvokeNode extends AbstractMemoryCheckpoint implements Invoke, LIRLowerable, MemoryCheckpoint.Single { 043 public static final NodeClass<InvokeNode> TYPE = NodeClass.create(InvokeNode.class); 044 045 @Input(InputType.Extension) CallTargetNode callTarget; 046 @OptionalInput(InputType.State) FrameState stateDuring; 047 @OptionalInput(InputType.Guard) GuardingNode guard; 048 protected final int bci; 049 protected boolean polymorphic; 050 protected boolean useForInlining; 051 052 public InvokeNode(CallTargetNode callTarget, int bci) { 053 this(callTarget, bci, callTarget.returnStamp()); 054 } 055 056 public InvokeNode(CallTargetNode callTarget, int bci, Stamp stamp) { 057 super(TYPE, stamp); 058 this.callTarget = callTarget; 059 this.bci = bci; 060 this.polymorphic = false; 061 this.useForInlining = true; 062 } 063 064 @Override 065 public CallTargetNode callTarget() { 066 return callTarget; 067 } 068 069 void setCallTarget(CallTargetNode callTarget) { 070 updateUsages(this.callTarget, callTarget); 071 this.callTarget = callTarget; 072 } 073 074 @Override 075 public boolean isPolymorphic() { 076 return polymorphic; 077 } 078 079 @Override 080 public void setPolymorphic(boolean value) { 081 this.polymorphic = value; 082 } 083 084 public boolean useForInlining() { 085 return useForInlining; 086 } 087 088 @Override 089 public void setUseForInlining(boolean value) { 090 this.useForInlining = value; 091 } 092 093 @Override 094 public boolean isAllowedUsageType(InputType type) { 095 if (!super.isAllowedUsageType(type)) { 096 if (getKind() != Kind.Void) { 097 if (callTarget instanceof MethodCallTargetNode && ((MethodCallTargetNode) callTarget).targetMethod().getAnnotation(NodeIntrinsic.class) != null) { 098 return true; 099 } 100 } 101 return false; 102 } 103 return true; 104 } 105 106 @Override 107 public Map<Object, Object> getDebugProperties(Map<Object, Object> map) { 108 Map<Object, Object> debugProperties = super.getDebugProperties(map); 109 if (callTarget != null) { 110 debugProperties.put("targetMethod", callTarget.targetName()); 111 } 112 return debugProperties; 113 } 114 115 @Override 116 public LocationIdentity getLocationIdentity() { 117 return LocationIdentity.any(); 118 } 119 120 @Override 121 public void lower(LoweringTool tool) { 122 tool.getLowerer().lower(this, tool); 123 } 124 125 @Override 126 public void generate(NodeLIRBuilderTool gen) { 127 gen.emitInvoke(this); 128 } 129 130 @Override 131 public String toString(Verbosity verbosity) { 132 if (verbosity == Verbosity.Long) { 133 return super.toString(Verbosity.Short) + "(bci=" + bci() + ")"; 134 } else if (verbosity == Verbosity.Name) { 135 return "Invoke#" + (callTarget == null ? "null" : callTarget().targetName()); 136 } else { 137 return super.toString(verbosity); 138 } 139 } 140 141 public int bci() { 142 return bci; 143 } 144 145 @Override 146 public void intrinsify(Node node) { 147 assert !(node instanceof ValueNode) || node.isAllowedUsageType(InputType.Value) == isAllowedUsageType(InputType.Value) : "replacing " + this + " with " + node; 148 CallTargetNode call = callTarget; 149 FrameState currentStateAfter = stateAfter(); 150 if (node instanceof StateSplit) { 151 StateSplit stateSplit = (StateSplit) node; 152 stateSplit.setStateAfter(currentStateAfter); 153 } 154 if (node instanceof ForeignCallNode) { 155 ForeignCallNode foreign = (ForeignCallNode) node; 156 foreign.setBci(bci()); 157 } 158 if (node instanceof FixedWithNextNode) { 159 graph().replaceFixedWithFixed(this, (FixedWithNextNode) node); 160 } else if (node instanceof ControlSinkNode) { 161 this.replaceAtPredecessor(node); 162 this.replaceAtUsages(null); 163 GraphUtil.killCFG(this); 164 return; 165 } else { 166 graph().replaceFixed(this, node); 167 } 168 GraphUtil.killWithUnusedFloatingInputs(call); 169 if (currentStateAfter.hasNoUsages()) { 170 GraphUtil.killWithUnusedFloatingInputs(currentStateAfter); 171 } 172 } 173 174 @Override 175 public boolean canDeoptimize() { 176 return true; 177 } 178 179 @Override 180 public FrameState stateDuring() { 181 return stateDuring; 182 } 183 184 @Override 185 public void setStateDuring(FrameState stateDuring) { 186 updateUsages(this.stateDuring, stateDuring); 187 this.stateDuring = stateDuring; 188 } 189 190 @Override 191 public GuardingNode getGuard() { 192 return guard; 193 } 194 195 @Override 196 public void setGuard(GuardingNode guard) { 197 updateUsagesInterface(this.guard, guard); 198 this.guard = guard; 199 } 200}