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