32 import org.graalvm.compiler.core.common.type.TypeReference;
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.LogicConstantNode;
37 import org.graalvm.compiler.nodes.LogicNegationNode;
38 import org.graalvm.compiler.nodes.LogicNode;
39 import org.graalvm.compiler.nodes.UnaryOpLogicNode;
40 import org.graalvm.compiler.nodes.ValueNode;
41 import org.graalvm.compiler.nodes.calc.IsNullNode;
42 import org.graalvm.compiler.nodes.extended.AnchoringNode;
43 import org.graalvm.compiler.nodes.spi.Lowerable;
44 import org.graalvm.compiler.nodes.spi.LoweringTool;
45 import org.graalvm.compiler.nodes.spi.Virtualizable;
46 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
47 import org.graalvm.compiler.nodes.type.StampTool;
48
49 import jdk.vm.ci.meta.JavaTypeProfile;
50 import jdk.vm.ci.meta.TriState;
51
52 /**
53 * The {@code InstanceOfNode} represents an instanceof test.
54 */
55 @NodeInfo(cycles = CYCLES_8, size = SIZE_8)
56 public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtualizable {
57 public static final NodeClass<InstanceOfNode> TYPE = NodeClass.create(InstanceOfNode.class);
58
59 protected final ObjectStamp checkedStamp;
60
61 private JavaTypeProfile profile;
62 @OptionalInput(Anchor) protected AnchoringNode anchor;
63
64 private InstanceOfNode(ObjectStamp checkedStamp, ValueNode object, JavaTypeProfile profile, AnchoringNode anchor) {
65 this(TYPE, checkedStamp, object, profile, anchor);
66 }
67
68 protected InstanceOfNode(NodeClass<? extends InstanceOfNode> c, ObjectStamp checkedStamp, ValueNode object, JavaTypeProfile profile, AnchoringNode anchor) {
69 super(c, object);
70 this.checkedStamp = checkedStamp;
71 this.profile = profile;
72 this.anchor = anchor;
73 assert (profile == null) || (anchor != null) : "profiles must be anchored";
74 assert checkedStamp != null;
75 }
76
77 public static LogicNode createAllowNull(TypeReference type, ValueNode object, JavaTypeProfile profile, AnchoringNode anchor) {
78 if (StampTool.isPointerNonNull(object)) {
79 return create(type, object, profile, anchor);
109 if (synonym != null) {
110 return synonym;
111 } else {
112 return this;
113 }
114 }
115
116 public static LogicNode findSynonym(ObjectStamp checkedStamp, ValueNode object) {
117 ObjectStamp inputStamp = (ObjectStamp) object.stamp();
118 ObjectStamp joinedStamp = (ObjectStamp) checkedStamp.join(inputStamp);
119
120 if (joinedStamp.isEmpty()) {
121 // The check can never succeed, the intersection of the two stamps is empty.
122 return LogicConstantNode.contradiction();
123 } else {
124 ObjectStamp meetStamp = (ObjectStamp) checkedStamp.meet(inputStamp);
125 if (checkedStamp.equals(meetStamp)) {
126 // The check will always succeed, the union of the two stamps is equal to the
127 // checked stamp.
128 return LogicConstantNode.tautology();
129 } else if (checkedStamp.type().equals(meetStamp.type()) && checkedStamp.isExactType() == meetStamp.isExactType() && checkedStamp.alwaysNull() == meetStamp.alwaysNull()) {
130 assert checkedStamp.nonNull() != inputStamp.nonNull();
131 // The only difference makes the null-ness of the value => simplify the check.
132 if (checkedStamp.nonNull()) {
133 return LogicNegationNode.create(IsNullNode.create(object));
134 } else {
135 return IsNullNode.create(object);
136 }
137 }
138 }
139
140 return null;
141 }
142
143 /**
144 * Gets the type being tested.
145 */
146 public TypeReference type() {
147 return StampTool.typeReferenceOrNull(checkedStamp);
148 }
149
150 public JavaTypeProfile profile() {
151 return profile;
152 }
153
154 @Override
155 public void virtualize(VirtualizerTool tool) {
156 ValueNode alias = tool.getAlias(getValue());
157 TriState fold = tryFold(alias.stamp());
158 if (fold != TriState.UNKNOWN) {
159 tool.replaceWithValue(LogicConstantNode.forBoolean(fold.isTrue(), graph()));
186 return TriState.TRUE;
187 }
188 }
189 }
190 return TriState.UNKNOWN;
191 }
192
193 public boolean allowsNull() {
194 return !checkedStamp.nonNull();
195 }
196
197 public void setProfile(JavaTypeProfile typeProfile, AnchoringNode anchor) {
198 this.profile = typeProfile;
199 updateUsagesInterface(this.anchor, anchor);
200 this.anchor = anchor;
201 assert (profile == null) || (anchor != null) : "profiles must be anchored";
202 }
203
204 public AnchoringNode getAnchor() {
205 return anchor;
206 }
207 }
|
32 import org.graalvm.compiler.core.common.type.TypeReference;
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.LogicConstantNode;
37 import org.graalvm.compiler.nodes.LogicNegationNode;
38 import org.graalvm.compiler.nodes.LogicNode;
39 import org.graalvm.compiler.nodes.UnaryOpLogicNode;
40 import org.graalvm.compiler.nodes.ValueNode;
41 import org.graalvm.compiler.nodes.calc.IsNullNode;
42 import org.graalvm.compiler.nodes.extended.AnchoringNode;
43 import org.graalvm.compiler.nodes.spi.Lowerable;
44 import org.graalvm.compiler.nodes.spi.LoweringTool;
45 import org.graalvm.compiler.nodes.spi.Virtualizable;
46 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
47 import org.graalvm.compiler.nodes.type.StampTool;
48
49 import jdk.vm.ci.meta.JavaTypeProfile;
50 import jdk.vm.ci.meta.TriState;
51
52 import java.util.Objects;
53
54 /**
55 * The {@code InstanceOfNode} represents an instanceof test.
56 */
57 @NodeInfo(cycles = CYCLES_8, size = SIZE_8)
58 public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtualizable {
59 public static final NodeClass<InstanceOfNode> TYPE = NodeClass.create(InstanceOfNode.class);
60
61 private ObjectStamp checkedStamp;
62
63 private JavaTypeProfile profile;
64 @OptionalInput(Anchor) protected AnchoringNode anchor;
65
66 private InstanceOfNode(ObjectStamp checkedStamp, ValueNode object, JavaTypeProfile profile, AnchoringNode anchor) {
67 this(TYPE, checkedStamp, object, profile, anchor);
68 }
69
70 protected InstanceOfNode(NodeClass<? extends InstanceOfNode> c, ObjectStamp checkedStamp, ValueNode object, JavaTypeProfile profile, AnchoringNode anchor) {
71 super(c, object);
72 this.checkedStamp = checkedStamp;
73 this.profile = profile;
74 this.anchor = anchor;
75 assert (profile == null) || (anchor != null) : "profiles must be anchored";
76 assert checkedStamp != null;
77 }
78
79 public static LogicNode createAllowNull(TypeReference type, ValueNode object, JavaTypeProfile profile, AnchoringNode anchor) {
80 if (StampTool.isPointerNonNull(object)) {
81 return create(type, object, profile, anchor);
111 if (synonym != null) {
112 return synonym;
113 } else {
114 return this;
115 }
116 }
117
118 public static LogicNode findSynonym(ObjectStamp checkedStamp, ValueNode object) {
119 ObjectStamp inputStamp = (ObjectStamp) object.stamp();
120 ObjectStamp joinedStamp = (ObjectStamp) checkedStamp.join(inputStamp);
121
122 if (joinedStamp.isEmpty()) {
123 // The check can never succeed, the intersection of the two stamps is empty.
124 return LogicConstantNode.contradiction();
125 } else {
126 ObjectStamp meetStamp = (ObjectStamp) checkedStamp.meet(inputStamp);
127 if (checkedStamp.equals(meetStamp)) {
128 // The check will always succeed, the union of the two stamps is equal to the
129 // checked stamp.
130 return LogicConstantNode.tautology();
131 } else if (checkedStamp.alwaysNull()) {
132 return IsNullNode.create(object);
133 } else if (Objects.equals(checkedStamp.type(), meetStamp.type()) && checkedStamp.isExactType() == meetStamp.isExactType() && checkedStamp.alwaysNull() == meetStamp.alwaysNull()) {
134 assert checkedStamp.nonNull() != inputStamp.nonNull();
135 // The only difference makes the null-ness of the value => simplify the check.
136 if (checkedStamp.nonNull()) {
137 return LogicNegationNode.create(IsNullNode.create(object));
138 } else {
139 return IsNullNode.create(object);
140 }
141 }
142 assert checkedStamp.type() != null;
143 }
144 return null;
145 }
146
147 /**
148 * Gets the type being tested.
149 */
150 public TypeReference type() {
151 return StampTool.typeReferenceOrNull(checkedStamp);
152 }
153
154 public JavaTypeProfile profile() {
155 return profile;
156 }
157
158 @Override
159 public void virtualize(VirtualizerTool tool) {
160 ValueNode alias = tool.getAlias(getValue());
161 TriState fold = tryFold(alias.stamp());
162 if (fold != TriState.UNKNOWN) {
163 tool.replaceWithValue(LogicConstantNode.forBoolean(fold.isTrue(), graph()));
190 return TriState.TRUE;
191 }
192 }
193 }
194 return TriState.UNKNOWN;
195 }
196
197 public boolean allowsNull() {
198 return !checkedStamp.nonNull();
199 }
200
201 public void setProfile(JavaTypeProfile typeProfile, AnchoringNode anchor) {
202 this.profile = typeProfile;
203 updateUsagesInterface(this.anchor, anchor);
204 this.anchor = anchor;
205 assert (profile == null) || (anchor != null) : "profiles must be anchored";
206 }
207
208 public AnchoringNode getAnchor() {
209 return anchor;
210 }
211
212 public ObjectStamp getCheckedStamp() {
213 return checkedStamp;
214 }
215
216 public void strengthenCheckedStamp(ObjectStamp newCheckedStamp) {
217 assert this.checkedStamp.join(newCheckedStamp).equals(newCheckedStamp) : "stamp can only improve";
218 this.checkedStamp = newCheckedStamp;
219 }
220 }
|