64 assert x.stamp() instanceof AbstractPointerStamp;
65 assert y.stamp() instanceof AbstractPointerStamp;
66 }
67
68 /**
69 * Determines if this is a comparison used to determine whether dispatching on a receiver could
70 * select a certain method and if so, returns {@code true} if the answer is guaranteed to be
71 * false. Otherwise, returns {@code false}.
72 */
73 private boolean isAlwaysFailingVirtualDispatchTest(ValueNode forX, ValueNode forY) {
74 if (forY.isConstant()) {
75 if (forX instanceof LoadMethodNode && condition == Condition.EQ) {
76 LoadMethodNode lm = ((LoadMethodNode) forX);
77 if (lm.getMethod().getEncoding().equals(forY.asConstant())) {
78 if (lm.getHub() instanceof LoadHubNode) {
79 ValueNode object = ((LoadHubNode) lm.getHub()).getValue();
80 ResolvedJavaType type = StampTool.typeOrNull(object);
81 ResolvedJavaType declaringClass = lm.getMethod().getDeclaringClass();
82 if (type != null && !type.equals(declaringClass) && declaringClass.isAssignableFrom(type)) {
83 ResolvedJavaMethod override = type.resolveMethod(lm.getMethod(), lm.getCallerType());
84 if (override != null && override != lm.getMethod()) {
85 assert declaringClass.isAssignableFrom(override.getDeclaringClass());
86 return true;
87 }
88 }
89 }
90 }
91 }
92 }
93 return false;
94 }
95
96 @Override
97 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
98 LogicNode result = findSynonym(forX, forY);
99 if (result != null) {
100 return result;
101 }
102 if (isAlwaysFailingVirtualDispatchTest(forX, forY)) {
103 return LogicConstantNode.contradiction();
104 }
108 public static LogicNode findSynonym(ValueNode forX, ValueNode forY) {
109 if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
110 return LogicConstantNode.tautology();
111 } else if (forX.stamp().alwaysDistinct(forY.stamp())) {
112 return LogicConstantNode.contradiction();
113 } else if (((AbstractPointerStamp) forX.stamp()).alwaysNull()) {
114 return IsNullNode.create(forY);
115 } else if (((AbstractPointerStamp) forY.stamp()).alwaysNull()) {
116 return IsNullNode.create(forX);
117 } else {
118 return null;
119 }
120 }
121
122 @Override
123 protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) {
124 return new PointerEqualsNode(newX, newY);
125 }
126
127 @Override
128 public Stamp getSucceedingStampForX(boolean negated) {
129 if (!negated) {
130 Stamp xStamp = getX().stamp();
131 Stamp newStamp = xStamp.join(getY().stamp());
132 if (!newStamp.equals(xStamp)) {
133 return newStamp;
134 }
135 }
136 return null;
137 }
138
139 @Override
140 public Stamp getSucceedingStampForY(boolean negated) {
141 if (!negated) {
142 Stamp yStamp = getY().stamp();
143 Stamp newStamp = yStamp.join(getX().stamp());
144 if (!newStamp.equals(yStamp)) {
145 return newStamp;
146 }
147 }
148 return null;
149 }
150
151 @Override
152 public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) {
153 if (xStampGeneric instanceof ObjectStamp && yStampGeneric instanceof ObjectStamp) {
154 ObjectStamp xStamp = (ObjectStamp) xStampGeneric;
155 ObjectStamp yStamp = (ObjectStamp) yStampGeneric;
156 if (xStamp.alwaysDistinct(yStamp)) {
157 return TriState.FALSE;
158 } else if (xStamp.neverDistinct(yStamp)) {
159 return TriState.TRUE;
160 }
161 }
162 return TriState.UNKNOWN;
163 }
|
64 assert x.stamp() instanceof AbstractPointerStamp;
65 assert y.stamp() instanceof AbstractPointerStamp;
66 }
67
68 /**
69 * Determines if this is a comparison used to determine whether dispatching on a receiver could
70 * select a certain method and if so, returns {@code true} if the answer is guaranteed to be
71 * false. Otherwise, returns {@code false}.
72 */
73 private boolean isAlwaysFailingVirtualDispatchTest(ValueNode forX, ValueNode forY) {
74 if (forY.isConstant()) {
75 if (forX instanceof LoadMethodNode && condition == Condition.EQ) {
76 LoadMethodNode lm = ((LoadMethodNode) forX);
77 if (lm.getMethod().getEncoding().equals(forY.asConstant())) {
78 if (lm.getHub() instanceof LoadHubNode) {
79 ValueNode object = ((LoadHubNode) lm.getHub()).getValue();
80 ResolvedJavaType type = StampTool.typeOrNull(object);
81 ResolvedJavaType declaringClass = lm.getMethod().getDeclaringClass();
82 if (type != null && !type.equals(declaringClass) && declaringClass.isAssignableFrom(type)) {
83 ResolvedJavaMethod override = type.resolveMethod(lm.getMethod(), lm.getCallerType());
84 if (override != null && !override.equals(lm.getMethod())) {
85 assert declaringClass.isAssignableFrom(override.getDeclaringClass());
86 return true;
87 }
88 }
89 }
90 }
91 }
92 }
93 return false;
94 }
95
96 @Override
97 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
98 LogicNode result = findSynonym(forX, forY);
99 if (result != null) {
100 return result;
101 }
102 if (isAlwaysFailingVirtualDispatchTest(forX, forY)) {
103 return LogicConstantNode.contradiction();
104 }
108 public static LogicNode findSynonym(ValueNode forX, ValueNode forY) {
109 if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) {
110 return LogicConstantNode.tautology();
111 } else if (forX.stamp().alwaysDistinct(forY.stamp())) {
112 return LogicConstantNode.contradiction();
113 } else if (((AbstractPointerStamp) forX.stamp()).alwaysNull()) {
114 return IsNullNode.create(forY);
115 } else if (((AbstractPointerStamp) forY.stamp()).alwaysNull()) {
116 return IsNullNode.create(forX);
117 } else {
118 return null;
119 }
120 }
121
122 @Override
123 protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) {
124 return new PointerEqualsNode(newX, newY);
125 }
126
127 @Override
128 public Stamp getSucceedingStampForX(boolean negated, Stamp xStamp, Stamp yStamp) {
129 if (!negated) {
130 Stamp newStamp = xStamp.join(yStamp);
131 if (!newStamp.equals(xStamp)) {
132 return newStamp;
133 }
134 }
135 return null;
136 }
137
138 @Override
139 public Stamp getSucceedingStampForY(boolean negated, Stamp xStamp, Stamp yStamp) {
140 if (!negated) {
141 Stamp newStamp = yStamp.join(xStamp);
142 if (!newStamp.equals(yStamp)) {
143 return newStamp;
144 }
145 }
146 return null;
147 }
148
149 @Override
150 public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) {
151 if (xStampGeneric instanceof ObjectStamp && yStampGeneric instanceof ObjectStamp) {
152 ObjectStamp xStamp = (ObjectStamp) xStampGeneric;
153 ObjectStamp yStamp = (ObjectStamp) yStampGeneric;
154 if (xStamp.alwaysDistinct(yStamp)) {
155 return TriState.FALSE;
156 } else if (xStamp.neverDistinct(yStamp)) {
157 return TriState.TRUE;
158 }
159 }
160 return TriState.UNKNOWN;
161 }
|