1 /* 2 * Copyright (c) 2009, 2016, 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 */ 23 24 25 package org.graalvm.compiler.nodes.java; 26 27 import static org.graalvm.compiler.graph.iterators.NodePredicates.isNotA; 28 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2; 29 30 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; 31 import org.graalvm.compiler.core.common.type.Stamp; 32 import org.graalvm.compiler.core.common.type.StampFactory; 33 import org.graalvm.compiler.core.common.type.StampPair; 34 import org.graalvm.compiler.graph.NodeClass; 35 import org.graalvm.compiler.graph.spi.Canonicalizable; 36 import org.graalvm.compiler.graph.spi.CanonicalizerTool; 37 import org.graalvm.compiler.nodeinfo.NodeCycles; 38 import org.graalvm.compiler.nodeinfo.NodeInfo; 39 import org.graalvm.compiler.nodes.ConstantNode; 40 import org.graalvm.compiler.nodes.DeoptimizeNode; 41 import org.graalvm.compiler.nodes.NodeView; 42 import org.graalvm.compiler.nodes.PhiNode; 43 import org.graalvm.compiler.nodes.ValueNode; 44 import org.graalvm.compiler.nodes.ValuePhiNode; 45 import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider; 46 import org.graalvm.compiler.nodes.spi.Virtualizable; 47 import org.graalvm.compiler.nodes.spi.VirtualizerTool; 48 import org.graalvm.compiler.nodes.type.StampTool; 49 import org.graalvm.compiler.nodes.util.ConstantFoldUtil; 50 import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode; 51 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; 52 import org.graalvm.compiler.options.OptionValues; 53 54 import jdk.vm.ci.meta.Assumptions; 55 import jdk.vm.ci.meta.ConstantReflectionProvider; 56 import jdk.vm.ci.meta.DeoptimizationAction; 57 import jdk.vm.ci.meta.DeoptimizationReason; 58 import jdk.vm.ci.meta.JavaConstant; 59 import jdk.vm.ci.meta.JavaKind; 60 import jdk.vm.ci.meta.MetaAccessProvider; 61 import jdk.vm.ci.meta.ResolvedJavaField; 62 63 /** 64 * The {@code LoadFieldNode} represents a read of a static or instance field. 65 */ 66 @NodeInfo(nameTemplate = "LoadField#{p#field/s}") 67 public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable.Unary<ValueNode>, Virtualizable, UncheckedInterfaceProvider { 68 69 public static final NodeClass<LoadFieldNode> TYPE = NodeClass.create(LoadFieldNode.class); 70 71 private final Stamp uncheckedStamp; 72 LoadFieldNode(StampPair stamp, ValueNode object, ResolvedJavaField field)73 protected LoadFieldNode(StampPair stamp, ValueNode object, ResolvedJavaField field) { 74 this(stamp, object, field, field.isVolatile()); 75 } 76 LoadFieldNode(StampPair stamp, ValueNode object, ResolvedJavaField field, boolean volatileAccess)77 protected LoadFieldNode(StampPair stamp, ValueNode object, ResolvedJavaField field, boolean volatileAccess) { 78 super(TYPE, stamp.getTrustedStamp(), object, field, volatileAccess); 79 this.uncheckedStamp = stamp.getUncheckedStamp(); 80 } 81 create(Assumptions assumptions, ValueNode object, ResolvedJavaField field)82 public static LoadFieldNode create(Assumptions assumptions, ValueNode object, ResolvedJavaField field) { 83 return create(assumptions, object, field, field.isVolatile()); 84 } 85 create(Assumptions assumptions, ValueNode object, ResolvedJavaField field, boolean volatileAccess)86 public static LoadFieldNode create(Assumptions assumptions, ValueNode object, ResolvedJavaField field, boolean volatileAccess) { 87 return new LoadFieldNode(StampFactory.forDeclaredType(assumptions, field.getType(), false), object, field, volatileAccess); 88 } 89 create(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Assumptions assumptions, ValueNode object, ResolvedJavaField field, boolean canonicalizeReads, boolean allUsagesAvailable)90 public static ValueNode create(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, 91 OptionValues options, Assumptions assumptions, ValueNode object, ResolvedJavaField field, boolean canonicalizeReads, boolean allUsagesAvailable) { 92 return canonical(null, StampFactory.forDeclaredType(assumptions, field.getType(), false), object, 93 field, constantFields, constantReflection, options, metaAccess, canonicalizeReads, allUsagesAvailable); 94 } 95 createOverrideStamp(StampPair stamp, ValueNode object, ResolvedJavaField field)96 public static LoadFieldNode createOverrideStamp(StampPair stamp, ValueNode object, ResolvedJavaField field) { 97 return new LoadFieldNode(stamp, object, field); 98 } 99 createOverrideStamp(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, StampPair stamp, ValueNode object, ResolvedJavaField field, boolean canonicalizeReads, boolean allUsagesAvailable)100 public static ValueNode createOverrideStamp(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, 101 OptionValues options, StampPair stamp, ValueNode object, ResolvedJavaField field, boolean canonicalizeReads, boolean allUsagesAvailable) { 102 return canonical(null, stamp, object, field, constantFields, constantReflection, options, metaAccess, canonicalizeReads, allUsagesAvailable); 103 } 104 105 @Override getValue()106 public ValueNode getValue() { 107 return object(); 108 } 109 110 @Override canonical(CanonicalizerTool tool, ValueNode forObject)111 public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject) { 112 NodeView view = NodeView.from(tool); 113 if (tool.allUsagesAvailable() && hasNoUsages() && !isVolatile() && (isStatic() || StampTool.isPointerNonNull(forObject.stamp(view)))) { 114 return null; 115 } 116 return canonical(this, StampPair.create(stamp, uncheckedStamp), forObject, field, tool.getConstantFieldProvider(), 117 tool.getConstantReflection(), tool.getOptions(), tool.getMetaAccess(), tool.canonicalizeReads(), tool.allUsagesAvailable()); 118 } 119 canonical(LoadFieldNode loadFieldNode, StampPair stamp, ValueNode forObject, ResolvedJavaField field, ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection, OptionValues options, MetaAccessProvider metaAccess, boolean canonicalizeReads, boolean allUsagesAvailable)120 private static ValueNode canonical(LoadFieldNode loadFieldNode, StampPair stamp, ValueNode forObject, ResolvedJavaField field, 121 ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection, 122 OptionValues options, MetaAccessProvider metaAccess, boolean canonicalizeReads, boolean allUsagesAvailable) { 123 LoadFieldNode self = loadFieldNode; 124 if (canonicalizeReads && metaAccess != null) { 125 ConstantNode constant = asConstant(constantFields, constantReflection, metaAccess, options, forObject, field); 126 if (constant != null) { 127 return constant; 128 } 129 if (allUsagesAvailable) { 130 PhiNode phi = asPhi(constantFields, constantReflection, metaAccess, options, forObject, 131 field, stamp.getTrustedStamp()); 132 if (phi != null) { 133 return phi; 134 } 135 } 136 } 137 if (self != null && !field.isStatic() && forObject.isNullConstant()) { 138 return new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); 139 } 140 if (self == null) { 141 self = new LoadFieldNode(stamp, forObject, field); 142 } 143 return self; 144 } 145 146 /** 147 * Gets a constant value for this load if possible. 148 */ asConstant(CanonicalizerTool tool, ValueNode forObject)149 public ConstantNode asConstant(CanonicalizerTool tool, ValueNode forObject) { 150 return asConstant(tool.getConstantFieldProvider(), tool.getConstantReflection(), 151 tool.getMetaAccess(), tool.getOptions(), forObject, field); 152 } 153 asConstant(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, ValueNode forObject, ResolvedJavaField field)154 private static ConstantNode asConstant(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection, 155 MetaAccessProvider metaAccess, OptionValues options, ValueNode forObject, ResolvedJavaField field) { 156 if (field.isStatic()) { 157 return ConstantFoldUtil.tryConstantFold(constantFields, constantReflection, metaAccess, field, null, options); 158 } else if (forObject.isConstant() && !forObject.isNullConstant()) { 159 return ConstantFoldUtil.tryConstantFold(constantFields, constantReflection, metaAccess, field, forObject.asJavaConstant(), options); 160 } 161 return null; 162 } 163 asConstant(CanonicalizerTool tool, JavaConstant constant)164 public ConstantNode asConstant(CanonicalizerTool tool, JavaConstant constant) { 165 return ConstantFoldUtil.tryConstantFold(tool.getConstantFieldProvider(), tool.getConstantReflection(), tool.getMetaAccess(), field(), constant, tool.getOptions()); 166 } 167 asPhi(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAcccess, OptionValues options, ValueNode forObject, ResolvedJavaField field, Stamp stamp)168 private static PhiNode asPhi(ConstantFieldProvider constantFields, ConstantReflectionProvider constantReflection, 169 MetaAccessProvider metaAcccess, OptionValues options, ValueNode forObject, ResolvedJavaField field, Stamp stamp) { 170 if (!field.isStatic() && field.isFinal() && forObject instanceof ValuePhiNode && ((ValuePhiNode) forObject).values().filter(isNotA(ConstantNode.class)).isEmpty()) { 171 PhiNode phi = (PhiNode) forObject; 172 ConstantNode[] constantNodes = new ConstantNode[phi.valueCount()]; 173 for (int i = 0; i < phi.valueCount(); i++) { 174 ConstantNode constant = ConstantFoldUtil.tryConstantFold(constantFields, constantReflection, metaAcccess, field, phi.valueAt(i).asJavaConstant(), 175 options); 176 if (constant == null) { 177 return null; 178 } 179 constantNodes[i] = constant; 180 } 181 return new ValuePhiNode(stamp, phi.merge(), constantNodes); 182 } 183 return null; 184 } 185 186 @Override virtualize(VirtualizerTool tool)187 public void virtualize(VirtualizerTool tool) { 188 ValueNode alias = tool.getAlias(object()); 189 if (alias instanceof VirtualObjectNode) { 190 int fieldIndex = ((VirtualInstanceNode) alias).fieldIndex(field()); 191 if (fieldIndex != -1) { 192 ValueNode entry = tool.getEntry((VirtualObjectNode) alias, fieldIndex); 193 if (stamp.isCompatible(entry.stamp(NodeView.DEFAULT))) { 194 tool.replaceWith(entry); 195 } else { 196 assert stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Int && (entry.stamp(NodeView.DEFAULT).getStackKind() == JavaKind.Long || entry.getStackKind() == JavaKind.Double || 197 entry.getStackKind() == JavaKind.Illegal) : "Can only allow different stack kind two slot marker writes on one stot fields."; 198 } 199 } 200 } 201 } 202 203 @Override uncheckedStamp()204 public Stamp uncheckedStamp() { 205 return uncheckedStamp; 206 } 207 setObject(ValueNode newObject)208 public void setObject(ValueNode newObject) { 209 this.updateUsages(object, newObject); 210 this.object = newObject; 211 } 212 213 @Override estimatedNodeCycles()214 public NodeCycles estimatedNodeCycles() { 215 if (isVolatile()) { 216 return CYCLES_2; 217 } 218 return super.estimatedNodeCycles(); 219 } 220 } 221