Search in sources :

Example 1 with SpreadElementMethod

use of com.github.anba.es6draft.ast.synthetic.SpreadElementMethod in project es6draft by anba.

the class ExpressionGenerator method spreadArray.

/**
 * 12.2.4.1.3 Runtime Semantics: Evaluation<br>
 * 12.2.4.1.2 Runtime Semantics: Array Accumulation
 *
 * @param elements
 *            the array elements
 * @param array
 *            the array object
 * @param nextIndex
 *            the next array index
 * @param mv
 *            the code visitor
 */
private void spreadArray(List<Expression> elements, Variable<ArrayObject> array, Variable<Integer> nextIndex, CodeVisitor mv) {
    int elisionWidth = 0;
    for (Expression element : elements) {
        if (element instanceof Elision) {
            // Elision
            elisionWidth += 1;
            continue;
        }
        if (elisionWidth != 0) {
            iadd(nextIndex, elisionWidth, mv);
            elisionWidth = 0;
        }
        if (element instanceof SpreadElementMethod) {
            SpreadElementMethod spread = (SpreadElementMethod) element;
            OutlinedCall call = mv.compile(spread, this::spreadElement);
            mv.enterVariableScope();
            Variable<int[]> nextIndexRef = mv.newVariable("nextIndexRef", int[].class);
            mv.newarray(1, Type.INT_TYPE);
            mv.store(nextIndexRef);
            mv.invoke(call, false, array, nextIndex, nextIndexRef);
            mv.store(nextIndex, mv.iarrayElement(nextIndexRef, 0));
            mv.exitVariableScope();
        } else if (element instanceof SpreadElement) {
            SpreadElement spread = (SpreadElement) element;
            // stack: [] -> []
            mv.load(array);
            mv.load(nextIndex);
            ArrayAccumulationSpreadElement(spread, mv);
            mv.store(nextIndex);
        } else {
            // stack: [] -> [array, nextIndex, value]
            mv.load(array);
            mv.load(nextIndex);
            ArrayAccumulationElement(element, mv);
            elisionWidth += 1;
        }
    }
    if (elisionWidth != 0) {
        iadd(nextIndex, elisionWidth, mv);
    }
}
Also used : OutlinedCall(com.github.anba.es6draft.compiler.CodeVisitor.OutlinedCall) SpreadElementMethod(com.github.anba.es6draft.ast.synthetic.SpreadElementMethod)

Example 2 with SpreadElementMethod

use of com.github.anba.es6draft.ast.synthetic.SpreadElementMethod in project es6draft by anba.

the class ExpressionGenerator method visit.

/**
 * 12.2.5 Array Initializer
 * <p>
 * 12.2.5.3 Runtime Semantics: Evaluation<br>
 * 12.2.5.2 Runtime Semantics: ArrayAccumulation
 */
@Override
public ValType visit(ArrayLiteral node, CodeVisitor mv) {
    int elision = 0, spread = 0;
    boolean hasSpreadMethod = false;
    for (Expression element : node.getElements()) {
        if (element instanceof SpreadElementMethod) {
            hasSpreadMethod = true;
            break;
        } else if (element instanceof Elision) {
            elision += 1;
        } else if (element instanceof SpreadElement) {
            spread += 1;
        }
    }
    if (hasSpreadMethod) {
        arrayLiteralWithSpread(node, mv);
    } else if (spread > 0 && hasTrailingSpread(node, spread)) {
        arrayLiteralTrailingSpread(node, mv);
    } else if (spread > 0) {
        arrayLiteralWithSpread(node, mv);
    } else {
        // Try to initialize array with faster {Dense, Sparse}ArrayCreate methods
        int length = node.getElements().size();
        float density = (float) (length - elision) / length;
        if ((density >= 0.25f && length < 0x10) || (density >= 0.75f && length < 0x1000)) {
            mv.loadExecutionContext();
            mv.anewarray(length, Types.Object);
            int nextIndex = 0;
            for (Expression element : node.getElements()) {
                if (element instanceof Elision) {
                // Elision
                } else {
                    mv.dup();
                    mv.iconst(nextIndex);
                    ValType elementType = element.accept(this, mv);
                    mv.toBoxed(elementType);
                    mv.astore(Types.Object);
                }
                nextIndex += 1;
            }
            if (elision == 0) {
                mv.invoke(Methods.ArrayObject_DenseArrayCreate);
            } else {
                mv.invoke(Methods.ArrayObject_SparseArrayCreate);
            }
        } else {
            // initialize with correct "length"
            ArrayCreate(length, mv);
            int nextIndex = 0;
            for (Expression element : node.getElements()) {
                if (element instanceof Elision) {
                // Elision
                } else {
                    mv.dup();
                    mv.iconst(nextIndex);
                    ArrayAccumulationElement(element, mv);
                }
                nextIndex += 1;
            }
            assert nextIndex == length;
        // Skip Put(array, "length", nextIndex, false), array is initialized with fixed length.
        }
    }
    return ValType.Object;
}
Also used : SpreadElementMethod(com.github.anba.es6draft.ast.synthetic.SpreadElementMethod) ValType(com.github.anba.es6draft.compiler.DefaultCodeGenerator.ValType)

Aggregations

SpreadElementMethod (com.github.anba.es6draft.ast.synthetic.SpreadElementMethod)2 OutlinedCall (com.github.anba.es6draft.compiler.CodeVisitor.OutlinedCall)1 ValType (com.github.anba.es6draft.compiler.DefaultCodeGenerator.ValType)1