23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package jdk.nashorn.internal.ir; |
26 package jdk.nashorn.internal.ir; |
27 |
27 |
|
28 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; |
|
29 |
|
30 import java.util.Arrays; |
|
31 import java.util.Collections; |
|
32 import java.util.List; |
28 import jdk.nashorn.internal.codegen.types.Type; |
33 import jdk.nashorn.internal.codegen.types.Type; |
|
34 import jdk.nashorn.internal.ir.annotations.Ignore; |
29 import jdk.nashorn.internal.ir.annotations.Immutable; |
35 import jdk.nashorn.internal.ir.annotations.Immutable; |
30 import jdk.nashorn.internal.ir.visitor.NodeVisitor; |
36 import jdk.nashorn.internal.ir.visitor.NodeVisitor; |
31 import jdk.nashorn.internal.parser.TokenType; |
37 import jdk.nashorn.internal.parser.TokenType; |
32 |
38 |
33 /** |
39 /** |
34 * BinaryNode nodes represent two operand operations. |
40 * BinaryNode nodes represent two operand operations. |
35 */ |
41 */ |
36 @Immutable |
42 @Immutable |
37 public final class BinaryNode extends Expression implements Assignment<Expression> { |
43 public final class BinaryNode extends Expression implements Assignment<Expression>, Optimistic { |
38 /** Left hand side argument. */ |
44 /** Left hand side argument. */ |
39 private final Expression lhs; |
45 private final Expression lhs; |
40 |
46 |
41 private final Expression rhs; |
47 private final Expression rhs; |
|
48 |
|
49 private final int programPoint; |
|
50 |
|
51 private final boolean isOptimistic; |
|
52 |
|
53 private final Type type; |
|
54 |
|
55 @Ignore |
|
56 private static final List<TokenType> CAN_OVERFLOW = |
|
57 Collections.unmodifiableList( |
|
58 Arrays.asList(new TokenType[] { |
|
59 TokenType.ADD, |
|
60 TokenType.DIV, |
|
61 TokenType.MOD, |
|
62 TokenType.MUL, |
|
63 TokenType.SUB, |
|
64 TokenType.ASSIGN_ADD, |
|
65 TokenType.ASSIGN_DIV, |
|
66 TokenType.ASSIGN_MOD, |
|
67 TokenType.ASSIGN_MUL, |
|
68 TokenType.ASSIGN_SUB |
|
69 })); |
42 |
70 |
43 /** |
71 /** |
44 * Constructor |
72 * Constructor |
45 * |
73 * |
46 * @param token token |
74 * @param token token |
49 */ |
77 */ |
50 public BinaryNode(final long token, final Expression lhs, final Expression rhs) { |
78 public BinaryNode(final long token, final Expression lhs, final Expression rhs) { |
51 super(token, lhs.getStart(), rhs.getFinish()); |
79 super(token, lhs.getStart(), rhs.getFinish()); |
52 this.lhs = lhs; |
80 this.lhs = lhs; |
53 this.rhs = rhs; |
81 this.rhs = rhs; |
54 } |
82 this.programPoint = INVALID_PROGRAM_POINT; |
55 |
83 this.isOptimistic = false; |
56 private BinaryNode(final BinaryNode binaryNode, final Expression lhs, final Expression rhs) { |
84 this.type = null; |
|
85 } |
|
86 |
|
87 private BinaryNode(final BinaryNode binaryNode, final Expression lhs, final Expression rhs, final Type type, final int programPoint, final boolean isOptimistic) { |
57 super(binaryNode); |
88 super(binaryNode); |
58 this.lhs = lhs; |
89 this.lhs = lhs; |
59 this.rhs = rhs; |
90 this.rhs = rhs; |
|
91 this.programPoint = programPoint; |
|
92 this.isOptimistic = isOptimistic; |
|
93 this.type = type; |
60 } |
94 } |
61 |
95 |
62 @Override |
96 @Override |
63 public boolean isComparison() { |
97 public boolean isComparison() { |
64 switch (tokenType()) { |
98 switch (tokenType()) { |
208 } |
245 } |
209 } |
246 } |
210 |
247 |
211 @Override |
248 @Override |
212 public void toString(final StringBuilder sb) { |
249 public void toString(final StringBuilder sb) { |
213 final TokenType type = tokenType(); |
250 final TokenType tokenType = tokenType(); |
214 |
251 |
215 final boolean lhsParen = type.needsParens(lhs().tokenType(), true); |
252 final boolean lhsParen = tokenType.needsParens(lhs().tokenType(), true); |
216 final boolean rhsParen = type.needsParens(rhs().tokenType(), false); |
253 final boolean rhsParen = tokenType.needsParens(rhs().tokenType(), false); |
217 |
254 |
218 if (lhsParen) { |
255 if (lhsParen) { |
219 sb.append('('); |
256 sb.append('('); |
220 } |
257 } |
221 |
258 |
277 */ |
318 */ |
278 public BinaryNode setLHS(final Expression lhs) { |
319 public BinaryNode setLHS(final Expression lhs) { |
279 if (this.lhs == lhs) { |
320 if (this.lhs == lhs) { |
280 return this; |
321 return this; |
281 } |
322 } |
282 return new BinaryNode(this, lhs, rhs); |
323 return new BinaryNode(this, lhs, rhs, type, programPoint, isOptimistic); |
283 } |
324 } |
284 |
325 |
285 /** |
326 /** |
286 * Set the right hand side expression for this node |
327 * Set the right hand side expression for this node |
287 * @param rhs new left hand side expression |
328 * @param rhs new left hand side expression |
289 */ |
330 */ |
290 public BinaryNode setRHS(final Expression rhs) { |
331 public BinaryNode setRHS(final Expression rhs) { |
291 if (this.rhs == rhs) { |
332 if (this.rhs == rhs) { |
292 return this; |
333 return this; |
293 } |
334 } |
294 return new BinaryNode(this, lhs, rhs); |
335 return new BinaryNode(this, lhs, rhs, type, programPoint, isOptimistic); |
295 } |
336 } |
296 |
337 |
|
338 @Override |
|
339 public int getProgramPoint() { |
|
340 return programPoint; |
|
341 } |
|
342 |
|
343 @Override |
|
344 public boolean canBeOptimistic() { |
|
345 return getMostOptimisticType() != getMostPessimisticType(); |
|
346 } |
|
347 |
|
348 @Override |
|
349 public BinaryNode setProgramPoint(final int programPoint) { |
|
350 if (this.programPoint == programPoint) { |
|
351 return this; |
|
352 } |
|
353 return new BinaryNode(this, lhs, rhs, type, programPoint, isOptimistic); |
|
354 } |
|
355 |
|
356 @Override |
|
357 public BinaryNode setIsOptimistic(final boolean isOptimistic) { |
|
358 if (this.isOptimistic == isOptimistic) { |
|
359 return this; |
|
360 } |
|
361 assert isOptimistic; |
|
362 return new BinaryNode(this, lhs, rhs, type, programPoint, isOptimistic); |
|
363 } |
|
364 |
|
365 @Override |
|
366 public Type getMostOptimisticType() { |
|
367 if (CAN_OVERFLOW.contains(tokenType())) { |
|
368 return Type.widest(Type.INT, Type.widest(lhs.getType(), rhs.getType())); |
|
369 } |
|
370 return getMostPessimisticType(); |
|
371 } |
|
372 |
|
373 @Override |
|
374 public Type getMostPessimisticType() { |
|
375 return getWidestOperationType(); |
|
376 } |
|
377 |
|
378 @Override |
|
379 public boolean isOptimistic() { |
|
380 return isOptimistic; |
|
381 } |
|
382 |
|
383 @Override |
|
384 public Type getType() { |
|
385 return type == null ? super.getType() : type; |
|
386 } |
|
387 |
|
388 @Override |
|
389 public BinaryNode setType(TemporarySymbols ts, Type type) { |
|
390 if (this.type == type) { |
|
391 return this; |
|
392 } |
|
393 return new BinaryNode(this, lhs, rhs, type, programPoint, isOptimistic); |
|
394 } |
297 } |
395 } |