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.java; 024 025import static com.oracle.graal.graph.iterators.NodePredicates.*; 026import jdk.internal.jvmci.meta.*; 027 028import com.oracle.graal.compiler.common.type.*; 029import com.oracle.graal.graph.*; 030import com.oracle.graal.graph.spi.*; 031import com.oracle.graal.nodeinfo.*; 032import com.oracle.graal.nodes.*; 033import com.oracle.graal.nodes.spi.*; 034import com.oracle.graal.nodes.type.*; 035import com.oracle.graal.nodes.virtual.*; 036 037/** 038 * The {@code LoadFieldNode} represents a read of a static or instance field. 039 */ 040@NodeInfo(nameTemplate = "LoadField#{p#field/s}") 041public final class LoadFieldNode extends AccessFieldNode implements Canonicalizable.Unary<ValueNode>, Virtualizable, UncheckedInterfaceProvider { 042 043 public static final NodeClass<LoadFieldNode> TYPE = NodeClass.create(LoadFieldNode.class); 044 045 public LoadFieldNode(ValueNode object, ResolvedJavaField field) { 046 super(TYPE, createStamp(field), object, field); 047 } 048 049 public ValueNode getValue() { 050 return object(); 051 } 052 053 private static Stamp createStamp(ResolvedJavaField field) { 054 Kind kind = field.getKind(); 055 if (kind == Kind.Object && field.getType() instanceof ResolvedJavaType) { 056 return StampFactory.declared((ResolvedJavaType) field.getType()); 057 } else { 058 return StampFactory.forKind(kind); 059 } 060 } 061 062 public ValueNode canonical(CanonicalizerTool tool, ValueNode forObject) { 063 if (tool.allUsagesAvailable() && hasNoUsages() && !isVolatile() && (isStatic() || StampTool.isPointerNonNull(forObject.stamp()))) { 064 return null; 065 } 066 MetaAccessProvider metaAccess = tool.getMetaAccess(); 067 ConstantReflectionProvider constantReflection = tool.getConstantReflection(); 068 if (tool.canonicalizeReads() && metaAccess != null) { 069 ConstantNode constant = asConstant(metaAccess, constantReflection, forObject); 070 if (constant != null) { 071 return constant; 072 } 073 if (tool.allUsagesAvailable()) { 074 PhiNode phi = asPhi(metaAccess, constantReflection, forObject); 075 if (phi != null) { 076 return phi; 077 } 078 } 079 } 080 if (!isStatic() && forObject.isNullConstant()) { 081 return new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException); 082 } 083 return this; 084 } 085 086 /** 087 * Gets a constant value for this load if possible. 088 */ 089 public ConstantNode asConstant(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ValueNode forObject) { 090 JavaConstant constant = null; 091 if (isStatic()) { 092 constant = constantReflection.readConstantFieldValue(field(), null); 093 } else if (forObject.isConstant() && !forObject.isNullConstant()) { 094 constant = constantReflection.readConstantFieldValue(field(), forObject.asJavaConstant()); 095 } 096 if (constant != null) { 097 return ConstantNode.forConstant(constant, metaAccess); 098 } 099 return null; 100 } 101 102 private PhiNode asPhi(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ValueNode forObject) { 103 if (!isStatic() && field.isFinal() && forObject instanceof ValuePhiNode && ((ValuePhiNode) forObject).values().filter(isNotA(ConstantNode.class)).isEmpty()) { 104 PhiNode phi = (PhiNode) forObject; 105 JavaConstant[] constants = new JavaConstant[phi.valueCount()]; 106 for (int i = 0; i < phi.valueCount(); i++) { 107 JavaConstant constantValue = constantReflection.readConstantFieldValue(field(), phi.valueAt(i).asJavaConstant()); 108 if (constantValue == null) { 109 return null; 110 } 111 constants[i] = constantValue; 112 } 113 ConstantNode[] constantNodes = new ConstantNode[phi.valueCount()]; 114 for (int i = 0; i < phi.valueCount(); i++) { 115 constantNodes[i] = ConstantNode.forConstant(constants[i], metaAccess); 116 } 117 return new ValuePhiNode(stamp(), phi.merge(), constantNodes); 118 } 119 return null; 120 } 121 122 @Override 123 public void virtualize(VirtualizerTool tool) { 124 ValueNode alias = tool.getAlias(object()); 125 if (alias instanceof VirtualObjectNode) { 126 int fieldIndex = ((VirtualInstanceNode) alias).fieldIndex(field()); 127 if (fieldIndex != -1) { 128 tool.replaceWith(tool.getEntry((VirtualObjectNode) alias, fieldIndex)); 129 } 130 } 131 } 132 133 public Stamp uncheckedStamp() { 134 return UncheckedInterfaceProvider.uncheckedOrNull(field().getType(), stamp()); 135 } 136}