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.calc;
26
27 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
28 import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
29 import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
30 import org.graalvm.compiler.core.common.type.ObjectStamp;
31 import org.graalvm.compiler.core.common.type.TypeReference;
32 import org.graalvm.compiler.debug.GraalError;
33 import org.graalvm.compiler.graph.NodeClass;
34 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
35 import org.graalvm.compiler.nodeinfo.NodeInfo;
36 import org.graalvm.compiler.nodes.ConstantNode;
37 import org.graalvm.compiler.nodes.LogicConstantNode;
38 import org.graalvm.compiler.nodes.LogicNode;
39 import org.graalvm.compiler.nodes.NodeView;
40 import org.graalvm.compiler.nodes.ValueNode;
41 import org.graalvm.compiler.nodes.extended.GetClassNode;
42 import org.graalvm.compiler.nodes.java.InstanceOfNode;
43 import org.graalvm.compiler.nodes.spi.Virtualizable;
44 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
45 import org.graalvm.compiler.nodes.virtual.VirtualBoxingNode;
46 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
47 import org.graalvm.compiler.options.OptionValues;
48
49 import jdk.vm.ci.meta.Constant;
50 import jdk.vm.ci.meta.ConstantReflectionProvider;
51 import jdk.vm.ci.meta.JavaConstant;
52 import jdk.vm.ci.meta.JavaKind;
53 import jdk.vm.ci.meta.MetaAccessProvider;
54 import jdk.vm.ci.meta.ResolvedJavaType;
55
56 @NodeInfo(shortName = "==")
57 public final class ObjectEqualsNode extends PointerEqualsNode implements Virtualizable {
58
59 public static final NodeClass<ObjectEqualsNode> TYPE = NodeClass.create(ObjectEqualsNode.class);
108 assert ((ObjectStamp) object.stamp(view)).nonNull();
109 if (!type.isPrimitive() && (type.isConcrete() || type.isArray())) {
110 return InstanceOfNode.create(TypeReference.createExactTrusted(type), object);
111 }
112 return LogicConstantNode.forBoolean(false);
113 }
114 return super.canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, constant, nonConstant, mirrored, unorderedIsTrue, view);
115 }
116
117 @Override
118 protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue, NodeView view) {
119 if (newX.stamp(view) instanceof ObjectStamp && newY.stamp(view) instanceof ObjectStamp) {
120 return new ObjectEqualsNode(newX, newY);
121 } else if (newX.stamp(view) instanceof AbstractPointerStamp && newY.stamp(view) instanceof AbstractPointerStamp) {
122 return new PointerEqualsNode(newX, newY);
123 }
124 throw GraalError.shouldNotReachHere();
125 }
126 }
127
128 private void virtualizeNonVirtualComparison(VirtualObjectNode virtual, ValueNode other, VirtualizerTool tool) {
129 if (virtual instanceof VirtualBoxingNode && other.isConstant()) {
130 VirtualBoxingNode virtualBoxingNode = (VirtualBoxingNode) virtual;
131 if (virtualBoxingNode.getBoxingKind() == JavaKind.Boolean) {
132 JavaConstant otherUnboxed = tool.getConstantReflectionProvider().unboxPrimitive(other.asJavaConstant());
133 if (otherUnboxed != null && otherUnboxed.getJavaKind() == JavaKind.Boolean) {
134 int expectedValue = otherUnboxed.asBoolean() ? 1 : 0;
135 IntegerEqualsNode equals = new IntegerEqualsNode(virtualBoxingNode.getBoxedValue(tool), ConstantNode.forInt(expectedValue, graph()));
136 tool.addNode(equals);
137 tool.replaceWithValue(equals);
138 } else {
139 tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
140 }
141 }
142 }
143 if (virtual.hasIdentity()) {
144 // one of them is virtual: they can never be the same objects
145 tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
146 }
147 }
148
149 @Override
150 public void virtualize(VirtualizerTool tool) {
151 ValueNode xAlias = tool.getAlias(getX());
152 ValueNode yAlias = tool.getAlias(getY());
153
154 VirtualObjectNode xVirtual = xAlias instanceof VirtualObjectNode ? (VirtualObjectNode) xAlias : null;
155 VirtualObjectNode yVirtual = yAlias instanceof VirtualObjectNode ? (VirtualObjectNode) yAlias : null;
156
157 if (xVirtual != null && yVirtual == null) {
158 virtualizeNonVirtualComparison(xVirtual, yAlias, tool);
159 } else if (xVirtual == null && yVirtual != null) {
160 virtualizeNonVirtualComparison(yVirtual, xAlias, tool);
161 } else if (xVirtual != null && yVirtual != null) {
162 if (xVirtual.hasIdentity() ^ yVirtual.hasIdentity()) {
163 /*
164 * One of the two objects has identity, the other doesn't. In code, this looks like
165 * "Integer.valueOf(a) == new Integer(b)", which is always false.
166 *
167 * In other words: an object created via valueOf can never be equal to one created
168 * by new in the same compilation unit.
169 */
170 tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
171 } else if (!xVirtual.hasIdentity() && !yVirtual.hasIdentity()) {
172 ResolvedJavaType type = xVirtual.type();
173 if (type.equals(yVirtual.type())) {
174 MetaAccessProvider metaAccess = tool.getMetaAccessProvider();
175 if (type.equals(metaAccess.lookupJavaType(Integer.class)) || type.equals(metaAccess.lookupJavaType(Long.class))) {
176 // both are virtual without identity: check contents
177 assert xVirtual.entryCount() == 1 && yVirtual.entryCount() == 1;
178 assert xVirtual.entryKind(0).getStackKind() == JavaKind.Int || xVirtual.entryKind(0) == JavaKind.Long;
179 IntegerEqualsNode equals = new IntegerEqualsNode(tool.getEntry(xVirtual, 0), tool.getEntry(yVirtual, 0));
180 tool.addNode(equals);
181 tool.replaceWithValue(equals);
182 }
183 }
184 } else {
185 // both are virtual with identity: check if they refer to the same object
186 tool.replaceWithValue(LogicConstantNode.forBoolean(xVirtual == yVirtual, graph()));
187 }
188 }
189 }
190 }
|
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.calc;
26
27 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
28 import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
29 import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
30 import org.graalvm.compiler.core.common.type.ObjectStamp;
31 import org.graalvm.compiler.core.common.type.TypeReference;
32 import org.graalvm.compiler.debug.GraalError;
33 import org.graalvm.compiler.graph.NodeClass;
34 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
35 import org.graalvm.compiler.nodeinfo.NodeInfo;
36 import org.graalvm.compiler.nodes.ConstantNode;
37 import org.graalvm.compiler.nodes.LogicConstantNode;
38 import org.graalvm.compiler.nodes.LogicNode;
39 import org.graalvm.compiler.nodes.NodeView;
40 import org.graalvm.compiler.nodes.StructuredGraph;
41 import org.graalvm.compiler.nodes.ValueNode;
42 import org.graalvm.compiler.nodes.extended.GetClassNode;
43 import org.graalvm.compiler.nodes.java.InstanceOfNode;
44 import org.graalvm.compiler.nodes.spi.Virtualizable;
45 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
46 import org.graalvm.compiler.nodes.virtual.VirtualBoxingNode;
47 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
48 import org.graalvm.compiler.options.OptionValues;
49
50 import jdk.vm.ci.meta.Constant;
51 import jdk.vm.ci.meta.ConstantReflectionProvider;
52 import jdk.vm.ci.meta.JavaConstant;
53 import jdk.vm.ci.meta.JavaKind;
54 import jdk.vm.ci.meta.MetaAccessProvider;
55 import jdk.vm.ci.meta.ResolvedJavaType;
56
57 @NodeInfo(shortName = "==")
58 public final class ObjectEqualsNode extends PointerEqualsNode implements Virtualizable {
59
60 public static final NodeClass<ObjectEqualsNode> TYPE = NodeClass.create(ObjectEqualsNode.class);
109 assert ((ObjectStamp) object.stamp(view)).nonNull();
110 if (!type.isPrimitive() && (type.isConcrete() || type.isArray())) {
111 return InstanceOfNode.create(TypeReference.createExactTrusted(type), object);
112 }
113 return LogicConstantNode.forBoolean(false);
114 }
115 return super.canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, constant, nonConstant, mirrored, unorderedIsTrue, view);
116 }
117
118 @Override
119 protected CompareNode duplicateModified(ValueNode newX, ValueNode newY, boolean unorderedIsTrue, NodeView view) {
120 if (newX.stamp(view) instanceof ObjectStamp && newY.stamp(view) instanceof ObjectStamp) {
121 return new ObjectEqualsNode(newX, newY);
122 } else if (newX.stamp(view) instanceof AbstractPointerStamp && newY.stamp(view) instanceof AbstractPointerStamp) {
123 return new PointerEqualsNode(newX, newY);
124 }
125 throw GraalError.shouldNotReachHere();
126 }
127 }
128
129 private static LogicNode virtualizeNonVirtualComparison(VirtualObjectNode virtual, ValueNode other, StructuredGraph graph, VirtualizerTool tool) {
130 if (virtual instanceof VirtualBoxingNode && other.isConstant()) {
131 VirtualBoxingNode virtualBoxingNode = (VirtualBoxingNode) virtual;
132 if (virtualBoxingNode.getBoxingKind() == JavaKind.Boolean) {
133 JavaConstant otherUnboxed = tool.getConstantReflection().unboxPrimitive(other.asJavaConstant());
134 if (otherUnboxed != null && otherUnboxed.getJavaKind() == JavaKind.Boolean) {
135 int expectedValue = otherUnboxed.asBoolean() ? 1 : 0;
136 return new IntegerEqualsNode(virtualBoxingNode.getBoxedValue(tool), ConstantNode.forInt(expectedValue, graph));
137 } else {
138 return LogicConstantNode.contradiction(graph);
139 }
140 }
141 }
142 if (virtual.hasIdentity()) {
143 // one of them is virtual: they can never be the same objects
144 return LogicConstantNode.contradiction(graph);
145 }
146 return null;
147 }
148
149 public static LogicNode virtualizeComparison(ValueNode x, ValueNode y, StructuredGraph graph, VirtualizerTool tool) {
150 ValueNode xAlias = tool.getAlias(x);
151 ValueNode yAlias = tool.getAlias(y);
152
153 VirtualObjectNode xVirtual = xAlias instanceof VirtualObjectNode ? (VirtualObjectNode) xAlias : null;
154 VirtualObjectNode yVirtual = yAlias instanceof VirtualObjectNode ? (VirtualObjectNode) yAlias : null;
155
156 if (xVirtual != null && yVirtual == null) {
157 return virtualizeNonVirtualComparison(xVirtual, yAlias, graph, tool);
158 } else if (xVirtual == null && yVirtual != null) {
159 return virtualizeNonVirtualComparison(yVirtual, xAlias, graph, tool);
160 } else if (xVirtual != null && yVirtual != null) {
161 if (xVirtual.hasIdentity() ^ yVirtual.hasIdentity()) {
162 /*
163 * One of the two objects has identity, the other doesn't. In code, this looks like
164 * "Integer.valueOf(a) == new Integer(b)", which is always false.
165 *
166 * In other words: an object created via valueOf can never be equal to one created
167 * by new in the same compilation unit.
168 */
169 return LogicConstantNode.contradiction(graph);
170 } else if (!xVirtual.hasIdentity() && !yVirtual.hasIdentity()) {
171 ResolvedJavaType type = xVirtual.type();
172 if (type.equals(yVirtual.type())) {
173 MetaAccessProvider metaAccess = tool.getMetaAccess();
174 if (type.equals(metaAccess.lookupJavaType(Integer.class)) || type.equals(metaAccess.lookupJavaType(Long.class))) {
175 // both are virtual without identity: check contents
176 assert xVirtual.entryCount() == 1 && yVirtual.entryCount() == 1;
177 assert xVirtual.entryKind(0).getStackKind() == JavaKind.Int || xVirtual.entryKind(0) == JavaKind.Long;
178 return new IntegerEqualsNode(tool.getEntry(xVirtual, 0), tool.getEntry(yVirtual, 0));
179 }
180 }
181 } else {
182 // both are virtual with identity: check if they refer to the same object
183 return LogicConstantNode.forBoolean(xVirtual == yVirtual, graph);
184 }
185 }
186 return null;
187 }
188
189 @Override
190 public void virtualize(VirtualizerTool tool) {
191 ValueNode node = virtualizeComparison(getX(), getY(), graph(), tool);
192 if (node == null) {
193 return;
194 }
195 if (!node.isAlive()) {
196 tool.addNode(node);
197 }
198 tool.replaceWithValue(node);
199 }
200 }
|