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);
}
}
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;
}
Aggregations