nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LiteralNode.java
changeset 32781 d8f34ffbbc7a
parent 32534 b3ec7f3b3c2a
child 34732 6605efbe8447
equal deleted inserted replaced
32712:f61a63b7d1e5 32781:d8f34ffbbc7a
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package jdk.nashorn.internal.ir;
    26 package jdk.nashorn.internal.ir;
    27 
    27 
    28 import java.io.Serializable;
       
    29 import java.util.Arrays;
    28 import java.util.Arrays;
    30 import java.util.Collections;
    29 import java.util.Collections;
    31 import java.util.List;
    30 import java.util.List;
    32 import jdk.nashorn.internal.codegen.CompileUnit;
       
    33 import jdk.nashorn.internal.codegen.types.ArrayType;
    31 import jdk.nashorn.internal.codegen.types.ArrayType;
    34 import jdk.nashorn.internal.codegen.types.Type;
    32 import jdk.nashorn.internal.codegen.types.Type;
    35 import jdk.nashorn.internal.ir.annotations.Immutable;
    33 import jdk.nashorn.internal.ir.annotations.Immutable;
    36 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    34 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
    37 import jdk.nashorn.internal.objects.NativeArray;
    35 import jdk.nashorn.internal.objects.NativeArray;
   581         }
   579         }
   582 
   580 
   583         return POSTSET_MARKER;
   581         return POSTSET_MARKER;
   584     }
   582     }
   585 
   583 
       
   584     /**
       
   585      * Test whether {@code object} represents a constant value.
       
   586      * @param object a node or value object
       
   587      * @return true if object is a constant value
       
   588      */
       
   589     public static boolean isConstant(final Object object) {
       
   590         return objectAsConstant(object) != POSTSET_MARKER;
       
   591     }
       
   592 
   586     private static final class NullLiteralNode extends PrimitiveLiteralNode<Object> {
   593     private static final class NullLiteralNode extends PrimitiveLiteralNode<Object> {
   587         private static final long serialVersionUID = 1L;
   594         private static final long serialVersionUID = 1L;
   588 
   595 
   589         private NullLiteralNode(final long token, final int finish) {
   596         private NullLiteralNode(final long token, final int finish) {
   590             super(Token.recast(token, TokenType.OBJECT), finish, null);
   597             super(Token.recast(token, TokenType.OBJECT), finish, null);
   612 
   619 
   613     /**
   620     /**
   614      * Array literal node class.
   621      * Array literal node class.
   615      */
   622      */
   616     @Immutable
   623     @Immutable
   617     public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode {
   624     public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode, Splittable {
   618         private static final long serialVersionUID = 1L;
   625         private static final long serialVersionUID = 1L;
   619 
   626 
   620         /** Array element type. */
   627         /** Array element type. */
   621         private final Type elementType;
   628         private final Type elementType;
   622 
   629 
   624         private final Object presets;
   631         private final Object presets;
   625 
   632 
   626         /** Indices of array elements requiring computed post sets. */
   633         /** Indices of array elements requiring computed post sets. */
   627         private final int[] postsets;
   634         private final int[] postsets;
   628 
   635 
   629         /** Sub units with indexes ranges, in which to split up code generation, for large literals */
   636         /** Ranges for splitting up large literals in code generation */
   630         private final List<ArrayUnit> units;
   637         private final List<Splittable.SplitRange> splitRanges;
   631 
   638 
   632         @Override
   639         @Override
   633         public boolean isArray() {
   640         public boolean isArray() {
   634             return true;
   641             return true;
   635         }
   642         }
   636 
   643 
   637 
       
   638         /**
       
   639          * An ArrayUnit is a range in an ArrayLiteral. ArrayLiterals can
       
   640          * be split if they are too large, for bytecode generation reasons
       
   641          */
       
   642         public static final class ArrayUnit implements CompileUnitHolder, Serializable {
       
   643             private static final long serialVersionUID = 1L;
       
   644 
       
   645             /** Compile unit associated with the postsets range. */
       
   646             private final CompileUnit compileUnit;
       
   647 
       
   648             /** postsets range associated with the unit (hi not inclusive). */
       
   649             private final int lo, hi;
       
   650 
       
   651             /**
       
   652              * Constructor
       
   653              * @param compileUnit compile unit
       
   654              * @param lo lowest array index in unit
       
   655              * @param hi highest array index in unit + 1
       
   656              */
       
   657             public ArrayUnit(final CompileUnit compileUnit, final int lo, final int hi) {
       
   658                 this.compileUnit = compileUnit;
       
   659                 this.lo   = lo;
       
   660                 this.hi   = hi;
       
   661             }
       
   662 
       
   663             /**
       
   664              * Get the high index position of the ArrayUnit (non inclusive)
       
   665              * @return high index position
       
   666              */
       
   667             public int getHi() {
       
   668                 return hi;
       
   669             }
       
   670 
       
   671             /**
       
   672              * Get the low index position of the ArrayUnit (inclusive)
       
   673              * @return low index position
       
   674              */
       
   675             public int getLo() {
       
   676                 return lo;
       
   677             }
       
   678 
       
   679             /**
       
   680              * The array compile unit
       
   681              * @return array compile unit
       
   682              */
       
   683             @Override
       
   684             public CompileUnit getCompileUnit() {
       
   685                 return compileUnit;
       
   686             }
       
   687         }
       
   688 
   644 
   689         private static final class ArrayLiteralInitializer {
   645         private static final class ArrayLiteralInitializer {
   690 
   646 
   691             static ArrayLiteralNode initialize(final ArrayLiteralNode node) {
   647             static ArrayLiteralNode initialize(final ArrayLiteralNode node) {
   692                 final Type elementType = computeElementType(node.value);
   648                 final Type elementType = computeElementType(node.value);
   693                 final int[] postsets = computePostsets(node.value);
   649                 final int[] postsets = computePostsets(node.value);
   694                 final Object presets = computePresets(node.value, elementType, postsets);
   650                 final Object presets = computePresets(node.value, elementType, postsets);
   695                 return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.units);
   651                 return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.splitRanges);
   696             }
   652             }
   697 
   653 
   698             private static Type computeElementType(final Expression[] value) {
   654             private static Type computeElementType(final Expression[] value) {
   699                 Type widestElementType = Type.INT;
   655                 Type widestElementType = Type.INT;
   700 
   656 
   723                 final int[] computed = new int[value.length];
   679                 final int[] computed = new int[value.length];
   724                 int nComputed = 0;
   680                 int nComputed = 0;
   725 
   681 
   726                 for (int i = 0; i < value.length; i++) {
   682                 for (int i = 0; i < value.length; i++) {
   727                     final Expression element = value[i];
   683                     final Expression element = value[i];
   728                     if (element == null || objectAsConstant(element) == POSTSET_MARKER) {
   684                     if (element == null || !isConstant(element)) {
   729                         computed[nComputed++] = i;
   685                         computed[nComputed++] = i;
   730                     }
   686                     }
   731                 }
   687                 }
   732                 return Arrays.copyOf(computed, nComputed);
   688                 return Arrays.copyOf(computed, nComputed);
   733             }
   689             }
   840         protected ArrayLiteralNode(final long token, final int finish, final Expression[] value) {
   796         protected ArrayLiteralNode(final long token, final int finish, final Expression[] value) {
   841             super(Token.recast(token, TokenType.ARRAY), finish, value);
   797             super(Token.recast(token, TokenType.ARRAY), finish, value);
   842             this.elementType = Type.UNKNOWN;
   798             this.elementType = Type.UNKNOWN;
   843             this.presets     = null;
   799             this.presets     = null;
   844             this.postsets    = null;
   800             this.postsets    = null;
   845             this.units       = null;
   801             this.splitRanges = null;
   846         }
   802         }
   847 
   803 
   848         /**
   804         /**
   849          * Copy constructor
   805          * Copy constructor
   850          * @param node source array literal node
   806          * @param node source array literal node
   851          */
   807          */
   852         private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<ArrayUnit> units) {
   808         private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<Splittable.SplitRange> splitRanges) {
   853             super(node, value);
   809             super(node, value);
   854             this.elementType = elementType;
   810             this.elementType = elementType;
   855             this.postsets    = postsets;
   811             this.postsets    = postsets;
   856             this.presets     = presets;
   812             this.presets     = presets;
   857             this.units       = units;
   813             this.splitRanges = splitRanges;
   858         }
   814         }
   859 
   815 
   860         /**
   816         /**
   861          * Returns a list of array element expressions. Note that empty array elements manifest themselves as
   817          * Returns a list of array element expressions. Note that empty array elements manifest themselves as
   862          * null.
   818          * null.
   944             assert presets != null && presetsMatchElementType() : this + " doesn't have presets, or invalid preset type: " + presets;
   900             assert presets != null && presetsMatchElementType() : this + " doesn't have presets, or invalid preset type: " + presets;
   945             return presets;
   901             return presets;
   946         }
   902         }
   947 
   903 
   948         /**
   904         /**
   949          * Get the array units that make up this ArrayLiteral
   905          * Get the split ranges for this ArrayLiteral, or null if this array does not have to be split.
   950          * @see ArrayUnit
   906          * @see Splittable.SplitRange
   951          * @return list of array units
   907          * @return list of split ranges
   952          */
   908          */
   953         public List<ArrayUnit> getUnits() {
   909         @Override
   954             return units == null ? null : Collections.unmodifiableList(units);
   910         public List<Splittable.SplitRange> getSplitRanges() {
       
   911             return splitRanges == null ? null : Collections.unmodifiableList(splitRanges);
   955         }
   912         }
   956 
   913 
   957         /**
   914         /**
   958          * Set the ArrayUnits that make up this ArrayLiteral
   915          * Set the SplitRanges that make up this ArrayLiteral
   959          * @param lc lexical context
   916          * @param lc lexical context
   960          * @see ArrayUnit
   917          * @see Splittable.SplitRange
   961          * @param units list of array units
   918          * @param splitRanges list of split ranges
   962          * @return new or changed arrayliteralnode
   919          * @return new or changed node
   963          */
   920          */
   964         public ArrayLiteralNode setUnits(final LexicalContext lc, final List<ArrayUnit> units) {
   921         public ArrayLiteralNode setSplitRanges(final LexicalContext lc, final List<Splittable.SplitRange> splitRanges) {
   965             if (this.units == units) {
   922             if (this.splitRanges == splitRanges) {
   966                 return this;
   923                 return this;
   967             }
   924             }
   968             return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
   925             return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, splitRanges));
   969         }
   926         }
   970 
   927 
   971         @Override
   928         @Override
   972         public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
   929         public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
   973             return Acceptor.accept(this, visitor);
   930             return Acceptor.accept(this, visitor);
   985 
   942 
   986         private ArrayLiteralNode setValue(final LexicalContext lc, final Expression[] value) {
   943         private ArrayLiteralNode setValue(final LexicalContext lc, final Expression[] value) {
   987             if (this.value == value) {
   944             if (this.value == value) {
   988                 return this;
   945                 return this;
   989             }
   946             }
   990             return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
   947             return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, splitRanges));
   991         }
   948         }
   992 
   949 
   993         private ArrayLiteralNode setValue(final LexicalContext lc, final List<Expression> value) {
   950         private ArrayLiteralNode setValue(final LexicalContext lc, final List<Expression> value) {
   994             return setValue(lc, value.toArray(new Expression[value.size()]));
   951             return setValue(lc, value.toArray(new Expression[value.size()]));
   995         }
   952         }