nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java
changeset 24719 f726e9d67629
parent 21457 381acbd07fe5
child 24751 ccbd9cd3f720
equal deleted inserted replaced
23083:8c74590d5df1 24719:f726e9d67629
    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()) {
   107         case ASSIGN_MOD:
   141         case ASSIGN_MOD:
   108         case ASSIGN_MUL:
   142         case ASSIGN_MUL:
   109         case ASSIGN_SUB:
   143         case ASSIGN_SUB:
   110             return Type.NUMBER;
   144             return Type.NUMBER;
   111         default:
   145         default:
       
   146             if (isComparison()) {
       
   147                 return Type.BOOLEAN;
       
   148             }
   112             return Type.OBJECT;
   149             return Type.OBJECT;
   113         }
   150         }
   114     }
   151     }
   115 
   152 
   116     /**
   153     /**
   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 
   225             sb.append(')');
   262             sb.append(')');
   226         }
   263         }
   227 
   264 
   228         sb.append(' ');
   265         sb.append(' ');
   229 
   266 
   230         switch (type) {
   267         switch (tokenType) {
   231         case COMMALEFT:
   268         case COMMALEFT:
   232             sb.append(",<");
   269             sb.append(",<");
   233             break;
   270             break;
   234         case COMMARIGHT:
   271         case COMMARIGHT:
   235             sb.append(",>");
   272             sb.append(",>");
   237         case INCPREFIX:
   274         case INCPREFIX:
   238         case DECPREFIX:
   275         case DECPREFIX:
   239             sb.append("++");
   276             sb.append("++");
   240             break;
   277             break;
   241         default:
   278         default:
   242             sb.append(type.getName());
   279             sb.append(tokenType.getName());
   243             break;
   280             break;
       
   281         }
       
   282 
       
   283         if (isOptimistic()) {
       
   284             sb.append(Node.OPT_IDENTIFIER);
   244         }
   285         }
   245 
   286 
   246         sb.append(' ');
   287         sb.append(' ');
   247 
   288 
   248         if (rhsParen) {
   289         if (rhsParen) {
   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 }