author | attila |
Thu, 05 Mar 2015 15:43:43 +0100 | |
changeset 29283 | fb47e4d25a9f |
parent 28130 | 433d6755c5f8 |
child 30392 | dc4a419b2982 |
permissions | -rw-r--r-- |
16147 | 1 |
/* |
16151 | 2 |
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. |
16147 | 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. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
package jdk.nashorn.internal.ir; |
|
27 |
||
24719 | 28 |
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; |
29 |
||
30 |
import java.util.Arrays; |
|
31 |
import java.util.Collections; |
|
24751 | 32 |
import java.util.HashSet; |
33 |
import java.util.Set; |
|
16147 | 34 |
import jdk.nashorn.internal.codegen.types.Type; |
24719 | 35 |
import jdk.nashorn.internal.ir.annotations.Ignore; |
17233 | 36 |
import jdk.nashorn.internal.ir.annotations.Immutable; |
16147 | 37 |
import jdk.nashorn.internal.ir.visitor.NodeVisitor; |
38 |
import jdk.nashorn.internal.parser.TokenType; |
|
39 |
||
40 |
/** |
|
41 |
* BinaryNode nodes represent two operand operations. |
|
42 |
*/ |
|
17233 | 43 |
@Immutable |
24719 | 44 |
public final class BinaryNode extends Expression implements Assignment<Expression>, Optimistic { |
27204 | 45 |
private static final long serialVersionUID = 1L; |
46 |
||
24751 | 47 |
// Placeholder for "undecided optimistic ADD type". Unfortunately, we can't decide the type of ADD during optimistic |
48 |
// type calculation as it can have local variables as its operands that will decide its ultimate type. |
|
24993
b707d46bae40
8046898: Make sure that lazy compilation is the default, remove redundant "enable lazy compilation" flags, added warning message if compile logging is enabled and lazy is switched off. Verified existing test suite code coverage equivalence between lazy and eager.
lagergren
parents:
24769
diff
changeset
|
49 |
private static final Type OPTIMISTIC_UNDECIDED_TYPE = Type.typeFor(new Object(){/*empty*/}.getClass()); |
24751 | 50 |
|
16147 | 51 |
/** Left hand side argument. */ |
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
17769
diff
changeset
|
52 |
private final Expression lhs; |
17233 | 53 |
|
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
17769
diff
changeset
|
54 |
private final Expression rhs; |
16147 | 55 |
|
24719 | 56 |
private final int programPoint; |
57 |
||
58 |
private final Type type; |
|
27204 | 59 |
private transient Type cachedType; |
24751 | 60 |
|
24719 | 61 |
@Ignore |
24751 | 62 |
private static final Set<TokenType> CAN_OVERFLOW = |
63 |
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(new TokenType[] { |
|
24719 | 64 |
TokenType.ADD, |
65 |
TokenType.DIV, |
|
66 |
TokenType.MOD, |
|
67 |
TokenType.MUL, |
|
68 |
TokenType.SUB, |
|
69 |
TokenType.ASSIGN_ADD, |
|
70 |
TokenType.ASSIGN_DIV, |
|
71 |
TokenType.ASSIGN_MOD, |
|
72 |
TokenType.ASSIGN_MUL, |
|
73 |
TokenType.ASSIGN_SUB |
|
24751 | 74 |
}))); |
24719 | 75 |
|
16147 | 76 |
/** |
77 |
* Constructor |
|
78 |
* |
|
79 |
* @param token token |
|
80 |
* @param lhs left hand side |
|
81 |
* @param rhs right hand side |
|
82 |
*/ |
|
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
17769
diff
changeset
|
83 |
public BinaryNode(final long token, final Expression lhs, final Expression rhs) { |
17523
cb4a7c901e0d
8013913: Removed Source field from all nodes except FunctionNode in order to save footprint
lagergren
parents:
17233
diff
changeset
|
84 |
super(token, lhs.getStart(), rhs.getFinish()); |
24751 | 85 |
assert !(isTokenType(TokenType.AND) || isTokenType(TokenType.OR)) || lhs instanceof JoinPredecessorExpression; |
17233 | 86 |
this.lhs = lhs; |
87 |
this.rhs = rhs; |
|
24719 | 88 |
this.programPoint = INVALID_PROGRAM_POINT; |
89 |
this.type = null; |
|
16147 | 90 |
} |
91 |
||
24751 | 92 |
private BinaryNode(final BinaryNode binaryNode, final Expression lhs, final Expression rhs, final Type type, final int programPoint) { |
17233 | 93 |
super(binaryNode); |
94 |
this.lhs = lhs; |
|
95 |
this.rhs = rhs; |
|
24719 | 96 |
this.programPoint = programPoint; |
97 |
this.type = type; |
|
16147 | 98 |
} |
99 |
||
24751 | 100 |
/** |
29283
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
101 |
* Returns true if the node is a comparison operation (either equality, inequality, or relational). |
24751 | 102 |
* @return true if the node is a comparison operation. |
103 |
*/ |
|
17756
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
104 |
public boolean isComparison() { |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
105 |
switch (tokenType()) { |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
106 |
case EQ: |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
107 |
case EQ_STRICT: |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
108 |
case NE: |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
109 |
case NE_STRICT: |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
110 |
case LE: |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
111 |
case LT: |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
112 |
case GE: |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
113 |
case GT: |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
114 |
return true; |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
115 |
default: |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
116 |
return false; |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
117 |
} |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
118 |
} |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17523
diff
changeset
|
119 |
|
16147 | 120 |
/** |
29283
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
121 |
* Returns true if the node is a relational operation (less than (or equals), greater than (or equals)). |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
122 |
* @return true if the node is a relational operation. |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
123 |
*/ |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
124 |
public boolean isRelational() { |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
125 |
switch (tokenType()) { |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
126 |
case LT: |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
127 |
case GT: |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
128 |
case LE: |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
129 |
case GE: |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
130 |
return true; |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
131 |
default: |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
132 |
return false; |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
133 |
} |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
134 |
} |
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
135 |
|
fb47e4d25a9f
8035712: Restore some of the RuntimeCallSite specializations
attila
parents:
28130
diff
changeset
|
136 |
/** |
24751 | 137 |
* Returns true if the node is a logical operation. |
138 |
* @return true if the node is a logical operation. |
|
139 |
*/ |
|
140 |
public boolean isLogical() { |
|
141 |
return isLogical(tokenType()); |
|
142 |
} |
|
143 |
||
144 |
/** |
|
145 |
* Returns true if the token type represents a logical operation. |
|
146 |
* @param tokenType the token type |
|
147 |
* @return true if the token type represents a logical operation. |
|
148 |
*/ |
|
149 |
public static boolean isLogical(final TokenType tokenType) { |
|
150 |
switch (tokenType) { |
|
151 |
case AND: |
|
152 |
case OR: |
|
153 |
return true; |
|
154 |
default: |
|
155 |
return false; |
|
156 |
} |
|
157 |
} |
|
158 |
||
159 |
/** |
|
160 |
* Return the widest possible operand type for this operation. |
|
161 |
* |
|
162 |
* @return Type |
|
163 |
*/ |
|
164 |
public Type getWidestOperandType() { |
|
16147 | 165 |
switch (tokenType()) { |
166 |
case SHR: |
|
167 |
case ASSIGN_SHR: |
|
24751 | 168 |
return Type.INT; |
169 |
case INSTANCEOF: |
|
170 |
return Type.OBJECT; |
|
171 |
default: |
|
172 |
if (isComparison()) { |
|
173 |
return Type.OBJECT; |
|
174 |
} |
|
175 |
return getWidestOperationType(); |
|
176 |
} |
|
177 |
} |
|
178 |
||
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
179 |
@Override |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
180 |
public Type getWidestOperationType() { |
24751 | 181 |
switch (tokenType()) { |
182 |
case ADD: |
|
183 |
case ASSIGN_ADD: { |
|
25829
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
184 |
// Compare this logic to decideType(Type, Type); it's similar, but it handles the optimistic type |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
185 |
// calculation case while this handles the conservative case. |
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
186 |
final Type lhsType = lhs.getType(); |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
187 |
final Type rhsType = rhs.getType(); |
24751 | 188 |
if(lhsType == Type.BOOLEAN && rhsType == Type.BOOLEAN) { |
25829
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
189 |
// Will always fit in an int, as the value range is [0, 1, 2]. If we didn't treat them specially here, |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
190 |
// they'd end up being treated as generic INT operands and their sum would be conservatively considered |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
191 |
// to be a LONG in the generic case below; we can do better here. |
24751 | 192 |
return Type.INT; |
25829
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
193 |
} else if(isString(lhsType) || isString(rhsType)) { |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
194 |
// We can statically figure out that this is a string if either operand is a string. In this case, use |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
195 |
// CHARSEQUENCE to prevent it from being proactively flattened. |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
196 |
return Type.CHARSEQUENCE; |
24751 | 197 |
} |
25829
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
198 |
final Type widestOperandType = Type.widest(undefinedToNumber(booleanToInt(lhsType)), undefinedToNumber(booleanToInt(rhsType))); |
24751 | 199 |
if(widestOperandType == Type.INT) { |
200 |
return Type.LONG; |
|
201 |
} else if (widestOperandType.isNumeric()) { |
|
202 |
return Type.NUMBER; |
|
203 |
} |
|
25829
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
204 |
// We pretty much can't know what it will be statically. Must presume OBJECT conservatively, as we can end |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
205 |
// up getting either a string or an object when adding something + object, e.g.: |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
206 |
// 1 + {} == "1[object Object]", but |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
207 |
// 1 + {valueOf: function() { return 2 }} == 3. Also: |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
208 |
// 1 + {valueOf: function() { return "2" }} == "12". |
24751 | 209 |
return Type.OBJECT; |
210 |
} |
|
211 |
case SHR: |
|
212 |
case ASSIGN_SHR: |
|
16147 | 213 |
return Type.LONG; |
214 |
case ASSIGN_SAR: |
|
215 |
case ASSIGN_SHL: |
|
21457
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
216 |
case BIT_AND: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
217 |
case BIT_OR: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
218 |
case BIT_XOR: |
16147 | 219 |
case ASSIGN_BIT_AND: |
220 |
case ASSIGN_BIT_OR: |
|
221 |
case ASSIGN_BIT_XOR: |
|
222 |
case SAR: |
|
223 |
case SHL: |
|
224 |
return Type.INT; |
|
225 |
case DIV: |
|
226 |
case MOD: |
|
24751 | 227 |
case ASSIGN_DIV: |
228 |
case ASSIGN_MOD: { |
|
229 |
// Naively, one might think MOD has the same type as the widest of its operands, this is unfortunately not |
|
230 |
// true when denominator is zero, so even type(int % int) == double. |
|
231 |
return Type.NUMBER; |
|
232 |
} |
|
16147 | 233 |
case MUL: |
19472
9476460521b3
8023017: SUB missing for widest op == number for BinaryNode
lagergren
parents:
18867
diff
changeset
|
234 |
case SUB: |
16147 | 235 |
case ASSIGN_MUL: |
24751 | 236 |
case ASSIGN_SUB: { |
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
237 |
final Type lhsType = lhs.getType(); |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
238 |
final Type rhsType = rhs.getType(); |
24751 | 239 |
if(lhsType == Type.BOOLEAN && rhsType == Type.BOOLEAN) { |
240 |
return Type.INT; |
|
241 |
} |
|
242 |
final Type widestOperandType = Type.widest(booleanToInt(lhsType), booleanToInt(rhsType)); |
|
243 |
if(widestOperandType == Type.INT) { |
|
244 |
return Type.LONG; |
|
245 |
} |
|
16147 | 246 |
return Type.NUMBER; |
24751 | 247 |
} |
248 |
case VOID: { |
|
249 |
return Type.UNDEFINED; |
|
250 |
} |
|
251 |
case ASSIGN: { |
|
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
252 |
return rhs.getType(); |
24751 | 253 |
} |
254 |
case INSTANCEOF: { |
|
255 |
return Type.BOOLEAN; |
|
256 |
} |
|
24769 | 257 |
case COMMALEFT: { |
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
258 |
return lhs.getType(); |
24769 | 259 |
} |
260 |
case COMMARIGHT: { |
|
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
261 |
return rhs.getType(); |
24769 | 262 |
} |
27524
f34b84c9f880
8062799: Binary logical expressions can have numeric types
attila
parents:
27204
diff
changeset
|
263 |
case AND: |
f34b84c9f880
8062799: Binary logical expressions can have numeric types
attila
parents:
27204
diff
changeset
|
264 |
case OR:{ |
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
265 |
return Type.widestReturnType(lhs.getType(), rhs.getType()); |
27524
f34b84c9f880
8062799: Binary logical expressions can have numeric types
attila
parents:
27204
diff
changeset
|
266 |
} |
16147 | 267 |
default: |
24719 | 268 |
if (isComparison()) { |
269 |
return Type.BOOLEAN; |
|
270 |
} |
|
16147 | 271 |
return Type.OBJECT; |
272 |
} |
|
273 |
} |
|
274 |
||
25829
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
275 |
private static boolean isString(final Type type) { |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
276 |
return type == Type.STRING || type == Type.CHARSEQUENCE; |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
277 |
} |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
278 |
|
24759
31aed7d9c02a
8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents:
24751
diff
changeset
|
279 |
private static Type booleanToInt(final Type type) { |
24751 | 280 |
return type == Type.BOOLEAN ? Type.INT : type; |
281 |
} |
|
282 |
||
25829
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
283 |
private static Type undefinedToNumber(final Type type) { |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
284 |
return type == Type.UNDEFINED ? Type.NUMBER : type; |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
285 |
} |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
286 |
|
16147 | 287 |
/** |
24751 | 288 |
* Check if this node is an assignment |
16147 | 289 |
* |
290 |
* @return true if this node assigns a value |
|
291 |
*/ |
|
292 |
@Override |
|
293 |
public boolean isAssignment() { |
|
294 |
switch (tokenType()) { |
|
295 |
case ASSIGN: |
|
296 |
case ASSIGN_ADD: |
|
297 |
case ASSIGN_BIT_AND: |
|
298 |
case ASSIGN_BIT_OR: |
|
299 |
case ASSIGN_BIT_XOR: |
|
300 |
case ASSIGN_DIV: |
|
301 |
case ASSIGN_MOD: |
|
302 |
case ASSIGN_MUL: |
|
303 |
case ASSIGN_SAR: |
|
304 |
case ASSIGN_SHL: |
|
305 |
case ASSIGN_SHR: |
|
306 |
case ASSIGN_SUB: |
|
307 |
return true; |
|
308 |
default: |
|
309 |
return false; |
|
310 |
} |
|
311 |
} |
|
312 |
||
313 |
@Override |
|
314 |
public boolean isSelfModifying() { |
|
315 |
return isAssignment() && tokenType() != TokenType.ASSIGN; |
|
316 |
} |
|
317 |
||
318 |
@Override |
|
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
17769
diff
changeset
|
319 |
public Expression getAssignmentDest() { |
16147 | 320 |
return isAssignment() ? lhs() : null; |
321 |
} |
|
322 |
||
323 |
@Override |
|
24759
31aed7d9c02a
8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents:
24751
diff
changeset
|
324 |
public BinaryNode setAssignmentDest(final Expression n) { |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16269
diff
changeset
|
325 |
return setLHS(n); |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16269
diff
changeset
|
326 |
} |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16269
diff
changeset
|
327 |
|
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16269
diff
changeset
|
328 |
@Override |
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
17769
diff
changeset
|
329 |
public Expression getAssignmentSource() { |
16147 | 330 |
return rhs(); |
331 |
} |
|
332 |
||
333 |
/** |
|
334 |
* Assist in IR navigation. |
|
335 |
* @param visitor IR navigating visitor. |
|
336 |
*/ |
|
337 |
@Override |
|
17769
14ea7feaf658
8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents:
17756
diff
changeset
|
338 |
public Node accept(final NodeVisitor<? extends LexicalContext> visitor) { |
17233 | 339 |
if (visitor.enterBinaryNode(this)) { |
27969 | 340 |
return visitor.leaveBinaryNode(setLHS((Expression)lhs.accept(visitor)).setRHS((Expression)rhs.accept(visitor))); |
16147 | 341 |
} |
342 |
||
343 |
return this; |
|
344 |
} |
|
345 |
||
346 |
@Override |
|
21457
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
347 |
public boolean isLocal() { |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
348 |
switch (tokenType()) { |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
349 |
case SAR: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
350 |
case SHL: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
351 |
case SHR: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
352 |
case BIT_AND: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
353 |
case BIT_OR: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
354 |
case BIT_XOR: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
355 |
case ADD: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
356 |
case DIV: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
357 |
case MOD: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
358 |
case MUL: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
359 |
case SUB: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
360 |
return lhs.isLocal() && lhs.getType().isJSPrimitive() |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
361 |
&& rhs.isLocal() && rhs.getType().isJSPrimitive(); |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
362 |
case ASSIGN_ADD: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
363 |
case ASSIGN_BIT_AND: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
364 |
case ASSIGN_BIT_OR: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
365 |
case ASSIGN_BIT_XOR: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
366 |
case ASSIGN_DIV: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
367 |
case ASSIGN_MOD: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
368 |
case ASSIGN_MUL: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
369 |
case ASSIGN_SAR: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
370 |
case ASSIGN_SHL: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
371 |
case ASSIGN_SHR: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
372 |
case ASSIGN_SUB: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
373 |
return lhs instanceof IdentNode && lhs.isLocal() && lhs.getType().isJSPrimitive() |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
374 |
&& rhs.isLocal() && rhs.getType().isJSPrimitive(); |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
375 |
case ASSIGN: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
376 |
return lhs instanceof IdentNode && lhs.isLocal() && rhs.isLocal(); |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
377 |
default: |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
378 |
return false; |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
379 |
} |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
380 |
} |
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
381 |
|
381acbd07fe5
8027042: Evaluation order for binary operators can be improved
hannesw
parents:
19472
diff
changeset
|
382 |
@Override |
24751 | 383 |
public boolean isAlwaysFalse() { |
384 |
switch (tokenType()) { |
|
385 |
case COMMALEFT: |
|
386 |
return lhs.isAlwaysFalse(); |
|
387 |
case COMMARIGHT: |
|
388 |
return rhs.isAlwaysFalse(); |
|
389 |
default: |
|
390 |
return false; |
|
391 |
} |
|
392 |
} |
|
393 |
||
394 |
@Override |
|
395 |
public boolean isAlwaysTrue() { |
|
396 |
switch (tokenType()) { |
|
397 |
case COMMALEFT: |
|
398 |
return lhs.isAlwaysTrue(); |
|
399 |
case COMMARIGHT: |
|
400 |
return rhs.isAlwaysTrue(); |
|
401 |
default: |
|
402 |
return false; |
|
403 |
} |
|
404 |
} |
|
405 |
||
406 |
@Override |
|
24759
31aed7d9c02a
8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents:
24751
diff
changeset
|
407 |
public void toString(final StringBuilder sb, final boolean printType) { |
24719 | 408 |
final TokenType tokenType = tokenType(); |
16147 | 409 |
|
24719 | 410 |
final boolean lhsParen = tokenType.needsParens(lhs().tokenType(), true); |
411 |
final boolean rhsParen = tokenType.needsParens(rhs().tokenType(), false); |
|
16147 | 412 |
|
413 |
if (lhsParen) { |
|
414 |
sb.append('('); |
|
415 |
} |
|
416 |
||
24759
31aed7d9c02a
8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents:
24751
diff
changeset
|
417 |
lhs().toString(sb, printType); |
16147 | 418 |
|
419 |
if (lhsParen) { |
|
420 |
sb.append(')'); |
|
421 |
} |
|
422 |
||
423 |
sb.append(' '); |
|
424 |
||
24719 | 425 |
switch (tokenType) { |
16147 | 426 |
case COMMALEFT: |
427 |
sb.append(",<"); |
|
428 |
break; |
|
429 |
case COMMARIGHT: |
|
430 |
sb.append(",>"); |
|
431 |
break; |
|
432 |
case INCPREFIX: |
|
433 |
case DECPREFIX: |
|
434 |
sb.append("++"); |
|
435 |
break; |
|
436 |
default: |
|
24719 | 437 |
sb.append(tokenType.getName()); |
16147 | 438 |
break; |
439 |
} |
|
440 |
||
24719 | 441 |
if (isOptimistic()) { |
24751 | 442 |
sb.append(Expression.OPT_IDENTIFIER); |
24719 | 443 |
} |
444 |
||
16147 | 445 |
sb.append(' '); |
446 |
||
447 |
if (rhsParen) { |
|
448 |
sb.append('('); |
|
449 |
} |
|
24759
31aed7d9c02a
8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents:
24751
diff
changeset
|
450 |
rhs().toString(sb, printType); |
16147 | 451 |
if (rhsParen) { |
452 |
sb.append(')'); |
|
453 |
} |
|
454 |
} |
|
455 |
||
456 |
/** |
|
457 |
* Get the left hand side expression for this node |
|
458 |
* @return the left hand side expression |
|
459 |
*/ |
|
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
17769
diff
changeset
|
460 |
public Expression lhs() { |
16147 | 461 |
return lhs; |
462 |
} |
|
463 |
||
464 |
/** |
|
17233 | 465 |
* Get the right hand side expression for this node |
466 |
* @return the left hand side expression |
|
467 |
*/ |
|
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
17769
diff
changeset
|
468 |
public Expression rhs() { |
17233 | 469 |
return rhs; |
470 |
} |
|
471 |
||
472 |
/** |
|
16147 | 473 |
* Set the left hand side expression for this node |
474 |
* @param lhs new left hand side expression |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16269
diff
changeset
|
475 |
* @return a node equivalent to this one except for the requested change. |
16147 | 476 |
*/ |
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
17769
diff
changeset
|
477 |
public BinaryNode setLHS(final Expression lhs) { |
17233 | 478 |
if (this.lhs == lhs) { |
479 |
return this; |
|
480 |
} |
|
24751 | 481 |
return new BinaryNode(this, lhs, rhs, type, programPoint); |
16147 | 482 |
} |
17233 | 483 |
|
484 |
/** |
|
485 |
* Set the right hand side expression for this node |
|
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
486 |
* @param rhs new right hand side expression |
17233 | 487 |
* @return a node equivalent to this one except for the requested change. |
488 |
*/ |
|
18867
bc91e3fcc5ba
8013925: Remove symbol fields from nodes that don't need them
attila
parents:
17769
diff
changeset
|
489 |
public BinaryNode setRHS(final Expression rhs) { |
17233 | 490 |
if (this.rhs == rhs) { |
491 |
return this; |
|
492 |
} |
|
24751 | 493 |
return new BinaryNode(this, lhs, rhs, type, programPoint); |
24719 | 494 |
} |
495 |
||
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
496 |
/** |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
497 |
* Set both the left and the right hand side expression for this node |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
498 |
* @param lhs new left hand side expression |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
499 |
* @param rhs new left hand side expression |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
500 |
* @return a node equivalent to this one except for the requested change. |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
501 |
*/ |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
502 |
public BinaryNode setOperands(final Expression lhs, final Expression rhs) { |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
503 |
if (this.lhs == lhs && this.rhs == rhs) { |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
504 |
return this; |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
505 |
} |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
506 |
return new BinaryNode(this, lhs, rhs, type, programPoint); |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
507 |
} |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
508 |
|
24719 | 509 |
@Override |
510 |
public int getProgramPoint() { |
|
511 |
return programPoint; |
|
512 |
} |
|
513 |
||
514 |
@Override |
|
515 |
public boolean canBeOptimistic() { |
|
24751 | 516 |
return isTokenType(TokenType.ADD) || (getMostOptimisticType() != getMostPessimisticType()); |
24719 | 517 |
} |
518 |
||
519 |
@Override |
|
520 |
public BinaryNode setProgramPoint(final int programPoint) { |
|
521 |
if (this.programPoint == programPoint) { |
|
522 |
return this; |
|
523 |
} |
|
24751 | 524 |
return new BinaryNode(this, lhs, rhs, type, programPoint); |
17233 | 525 |
} |
526 |
||
24719 | 527 |
@Override |
528 |
public Type getMostOptimisticType() { |
|
24751 | 529 |
final TokenType tokenType = tokenType(); |
530 |
if(tokenType == TokenType.ADD || tokenType == TokenType.ASSIGN_ADD) { |
|
531 |
return OPTIMISTIC_UNDECIDED_TYPE; |
|
532 |
} else if (CAN_OVERFLOW.contains(tokenType())) { |
|
533 |
return Type.INT; |
|
24719 | 534 |
} |
535 |
return getMostPessimisticType(); |
|
536 |
} |
|
537 |
||
538 |
@Override |
|
539 |
public Type getMostPessimisticType() { |
|
540 |
return getWidestOperationType(); |
|
541 |
} |
|
542 |
||
24751 | 543 |
/** |
544 |
* Returns true if the node has the optimistic type of the node is not yet decided. Optimistic ADD nodes start out |
|
545 |
* as undecided until we can figure out if they're numeric or not. |
|
546 |
* @return true if the node has the optimistic type of the node is not yet decided. |
|
547 |
*/ |
|
548 |
public boolean isOptimisticUndecidedType() { |
|
549 |
return type == OPTIMISTIC_UNDECIDED_TYPE; |
|
24719 | 550 |
} |
551 |
||
552 |
@Override |
|
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
553 |
public Type getType() { |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
554 |
if (cachedType == null) { |
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
555 |
cachedType = getTypeUncached(); |
24751 | 556 |
} |
557 |
return cachedType; |
|
558 |
} |
|
559 |
||
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
560 |
private Type getTypeUncached() { |
24751 | 561 |
if(type == OPTIMISTIC_UNDECIDED_TYPE) { |
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
562 |
return decideType(lhs.getType(), rhs.getType()); |
24751 | 563 |
} |
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
564 |
final Type widest = getWidestOperationType(); |
24751 | 565 |
if(type == null) { |
566 |
return widest; |
|
567 |
} |
|
28130
433d6755c5f8
8067774: Use a stack of types when calculating local variable types
attila
parents:
27969
diff
changeset
|
568 |
return Type.narrowest(widest, Type.widest(type, Type.widest(lhs.getType(), rhs.getType()))); |
24719 | 569 |
} |
570 |
||
25829
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
571 |
private static Type decideType(final Type lhsType, final Type rhsType) { |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
572 |
// Compare this to getWidestOperationType() for ADD and ASSIGN_ADD cases. There's some similar logic, but these |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
573 |
// are optimistic decisions, meaning that we don't have to treat boolean addition separately (as it'll become |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
574 |
// int addition in the general case anyway), and that we also don't conservatively widen sums of ints to |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
575 |
// longs, or sums of longs to doubles. |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
576 |
if(isString(lhsType) || isString(rhsType)) { |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
577 |
return Type.CHARSEQUENCE; |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
578 |
} |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
579 |
// NOTE: We don't have optimistic object-to-(int, long) conversions. Therefore, if any operand is an Object, we |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
580 |
// bail out of optimism here and presume a conservative Object return value, as the object's ToPrimitive() can |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
581 |
// end up returning either a number or a string, and their common supertype is Object, for better or worse. |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
582 |
final Type widest = Type.widest(undefinedToNumber(booleanToInt(lhsType)), undefinedToNumber(booleanToInt(rhsType))); |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
583 |
return widest.isObject() ? Type.OBJECT : widest; |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
584 |
} |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
585 |
|
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
586 |
/** |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
587 |
* If the node is a node representing an add operation and has {@link #isOptimisticUndecidedType() optimistic |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
588 |
* undecided type}, decides its type. Should be invoked after its operands types have been finalized. |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
589 |
* @return returns a new node similar to this node, but with its type set to the type decided from the type of its |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
590 |
* operands. |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
591 |
*/ |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
592 |
public BinaryNode decideType() { |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
593 |
assert type == OPTIMISTIC_UNDECIDED_TYPE; |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
594 |
return setType(decideType(lhs.getType(), rhs.getType())); |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
595 |
} |
1a5e1de71e57
8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents:
24993
diff
changeset
|
596 |
|
24719 | 597 |
@Override |
24759
31aed7d9c02a
8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents:
24751
diff
changeset
|
598 |
public BinaryNode setType(final Type type) { |
24719 | 599 |
if (this.type == type) { |
600 |
return this; |
|
601 |
} |
|
24751 | 602 |
return new BinaryNode(this, lhs, rhs, type, programPoint); |
24719 | 603 |
} |
16147 | 604 |
} |