1593
1594 //call nodes have program points.
1595
1596 final int flags = getCallSiteFlags() | (callNode.isApplyToCall() ? CALLSITE_APPLY_TO_CALL : 0);
1597
1598 new OptimisticOperation(callNode, resultBounds) {
1599 int argCount;
1600 @Override
1601 void loadStack() {
1602 loadExpressionAsObject(node.getBase());
1603 method.dup();
1604 // NOTE: not using a nested OptimisticOperation on this dynamicGet, as we expect to get back
1605 // a callable object. Nobody in their right mind would optimistically type this call site.
1606 assert !node.isOptimistic();
1607 method.dynamicGet(node.getType(), node.getProperty(), flags, true, node.isIndex());
1608 method.swap();
1609 argCount = loadArgs(args);
1610 }
1611 @Override
1612 void consumeStack() {
1613 dynamicCall(2 + argCount, flags, node.getProperty());
1614 }
1615 }.emit();
1616
1617 return false;
1618 }
1619
1620 @Override
1621 public boolean enterFunctionNode(final FunctionNode origCallee) {
1622 new OptimisticOperation(callNode, resultBounds) {
1623 FunctionNode callee;
1624 int argsCount;
1625 @Override
1626 void loadStack() {
1627 callee = (FunctionNode)origCallee.accept(CodeGenerator.this);
1628 if (callee.isStrict()) { // "this" is undefined
1629 method.loadUndefined(Type.OBJECT);
1630 } else { // get global from scope (which is the self)
1631 globalInstance();
1632 }
1633 argsCount = loadArgs(args);
1634 }
1635
1636 @Override
1637 void consumeStack() {
1638 final int flags = getCallSiteFlags();
1639 //assert callNodeType.equals(callee.getReturnType()) : callNodeType + " != " + callee.getReturnType();
1640 dynamicCall(2 + argsCount, flags, origCallee.getName());
1641 }
1642 }.emit();
1643 return false;
1644 }
1645
1646 @Override
1647 public boolean enterIndexNode(final IndexNode node) {
1648 new OptimisticOperation(callNode, resultBounds) {
1649 int argsCount;
1650 @Override
1651 void loadStack() {
1652 loadExpressionAsObject(node.getBase());
1653 method.dup();
1654 final Type indexType = node.getIndex().getType();
1655 if (indexType.isObject() || indexType.isBoolean()) {
1656 loadExpressionAsObject(node.getIndex()); //TODO boolean
1657 } else {
1658 loadExpressionUnbounded(node.getIndex());
1659 }
1660 // NOTE: not using a nested OptimisticOperation on this dynamicGetIndex, as we expect to get
1661 // back a callable object. Nobody in their right mind would optimistically type this call site.
1662 assert !node.isOptimistic();
1663 method.dynamicGetIndex(node.getType(), getCallSiteFlags(), true);
1664 method.swap();
1665 argsCount = loadArgs(args);
1666 }
1667 @Override
1668 void consumeStack() {
1669 final int flags = getCallSiteFlags();
1670 dynamicCall(2 + argsCount, flags, null);
1671 }
1672 }.emit();
1673 return false;
1674 }
1675
1676 @Override
1677 protected boolean enterDefault(final Node node) {
1678 new OptimisticOperation(callNode, resultBounds) {
1679 int argsCount;
1680 @Override
1681 void loadStack() {
1682 // Load up function.
1683 loadExpressionAsObject(function); //TODO, e.g. booleans can be used as functions
1684 method.loadUndefined(Type.OBJECT); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
1685 argsCount = loadArgs(args);
1686 }
1687 @Override
1688 void consumeStack() {
1689 final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
1690 dynamicCall(2 + argsCount, flags, null);
1691 }
1692 }.emit();
1693 return false;
1694 }
1695 });
1696
1697 return false;
1698 }
1699
1700 /**
1701 * Returns the flags with optimistic flag and program point removed.
1702 * @param flags the flags that need optimism stripped from them.
1703 * @return flags without optimism
1704 */
1705 static int nonOptimisticFlags(final int flags) {
1706 return flags & ~(CALLSITE_OPTIMISTIC | -1 << CALLSITE_PROGRAM_POINT_SHIFT);
1707 }
1708
1709 @Override
1710 public boolean enterContinueNode(final ContinueNode continueNode) {
3694 * @param discard if true, the expression is loaded and discarded
3695 * @param expr the expression that's either normally loaded or discard-loaded
3696 * @param resultBounds result bounds for when loading the expression normally
3697 */
3698 private void loadMaybeDiscard(final boolean discard, final Expression expr, final TypeBounds resultBounds) {
3699 if (discard) {
3700 loadAndDiscard(expr);
3701 } else {
3702 loadExpression(expr, resultBounds);
3703 }
3704 }
3705
3706 private void loadNEW(final UnaryNode unaryNode) {
3707 final CallNode callNode = (CallNode)unaryNode.getExpression();
3708 final List<Expression> args = callNode.getArgs();
3709
3710 final Expression func = callNode.getFunction();
3711 // Load function reference.
3712 loadExpressionAsObject(func); // must detect type error
3713
3714 method.dynamicNew(1 + loadArgs(args), getCallSiteFlags(),
3715 func instanceof IdentNode? ((IdentNode)func).getName() : null);
3716 }
3717
3718 private void loadNOT(final UnaryNode unaryNode) {
3719 final Expression expr = unaryNode.getExpression();
3720 if(expr instanceof UnaryNode && expr.isTokenType(TokenType.NOT)) {
3721 // !!x is idiomatic boolean cast in JavaScript
3722 loadExpressionAsBoolean(((UnaryNode)expr).getExpression());
3723 } else {
3724 final Label trueLabel = new Label("true");
3725 final Label afterLabel = new Label("after");
3726
3727 emitBranch(expr, trueLabel, true);
3728 method.load(true);
3729 method._goto(afterLabel);
3730 method.label(trueLabel);
3731 method.load(false);
3732 method.label(afterLabel);
3733 }
3734 }
3735
|
1593
1594 //call nodes have program points.
1595
1596 final int flags = getCallSiteFlags() | (callNode.isApplyToCall() ? CALLSITE_APPLY_TO_CALL : 0);
1597
1598 new OptimisticOperation(callNode, resultBounds) {
1599 int argCount;
1600 @Override
1601 void loadStack() {
1602 loadExpressionAsObject(node.getBase());
1603 method.dup();
1604 // NOTE: not using a nested OptimisticOperation on this dynamicGet, as we expect to get back
1605 // a callable object. Nobody in their right mind would optimistically type this call site.
1606 assert !node.isOptimistic();
1607 method.dynamicGet(node.getType(), node.getProperty(), flags, true, node.isIndex());
1608 method.swap();
1609 argCount = loadArgs(args);
1610 }
1611 @Override
1612 void consumeStack() {
1613 dynamicCall(2 + argCount, flags, node.toString(false));
1614 }
1615 }.emit();
1616
1617 return false;
1618 }
1619
1620 @Override
1621 public boolean enterFunctionNode(final FunctionNode origCallee) {
1622 new OptimisticOperation(callNode, resultBounds) {
1623 FunctionNode callee;
1624 int argsCount;
1625 @Override
1626 void loadStack() {
1627 callee = (FunctionNode)origCallee.accept(CodeGenerator.this);
1628 if (callee.isStrict()) { // "this" is undefined
1629 method.loadUndefined(Type.OBJECT);
1630 } else { // get global from scope (which is the self)
1631 globalInstance();
1632 }
1633 argsCount = loadArgs(args);
1634 }
1635
1636 @Override
1637 void consumeStack() {
1638 dynamicCall(2 + argsCount, getCallSiteFlags(), origCallee.getName());
1639 }
1640 }.emit();
1641 return false;
1642 }
1643
1644 @Override
1645 public boolean enterIndexNode(final IndexNode node) {
1646 new OptimisticOperation(callNode, resultBounds) {
1647 int argsCount;
1648 @Override
1649 void loadStack() {
1650 loadExpressionAsObject(node.getBase());
1651 method.dup();
1652 final Type indexType = node.getIndex().getType();
1653 if (indexType.isObject() || indexType.isBoolean()) {
1654 loadExpressionAsObject(node.getIndex()); //TODO boolean
1655 } else {
1656 loadExpressionUnbounded(node.getIndex());
1657 }
1658 // NOTE: not using a nested OptimisticOperation on this dynamicGetIndex, as we expect to get
1659 // back a callable object. Nobody in their right mind would optimistically type this call site.
1660 assert !node.isOptimistic();
1661 method.dynamicGetIndex(node.getType(), getCallSiteFlags(), true);
1662 method.swap();
1663 argsCount = loadArgs(args);
1664 }
1665 @Override
1666 void consumeStack() {
1667 dynamicCall(2 + argsCount, getCallSiteFlags(), node.toString(false));
1668 }
1669 }.emit();
1670 return false;
1671 }
1672
1673 @Override
1674 protected boolean enterDefault(final Node node) {
1675 new OptimisticOperation(callNode, resultBounds) {
1676 int argsCount;
1677 @Override
1678 void loadStack() {
1679 // Load up function.
1680 loadExpressionAsObject(function); //TODO, e.g. booleans can be used as functions
1681 method.loadUndefined(Type.OBJECT); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
1682 argsCount = loadArgs(args);
1683 }
1684 @Override
1685 void consumeStack() {
1686 final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
1687 dynamicCall(2 + argsCount, flags, node.toString(false));
1688 }
1689 }.emit();
1690 return false;
1691 }
1692 });
1693
1694 return false;
1695 }
1696
1697 /**
1698 * Returns the flags with optimistic flag and program point removed.
1699 * @param flags the flags that need optimism stripped from them.
1700 * @return flags without optimism
1701 */
1702 static int nonOptimisticFlags(final int flags) {
1703 return flags & ~(CALLSITE_OPTIMISTIC | -1 << CALLSITE_PROGRAM_POINT_SHIFT);
1704 }
1705
1706 @Override
1707 public boolean enterContinueNode(final ContinueNode continueNode) {
3691 * @param discard if true, the expression is loaded and discarded
3692 * @param expr the expression that's either normally loaded or discard-loaded
3693 * @param resultBounds result bounds for when loading the expression normally
3694 */
3695 private void loadMaybeDiscard(final boolean discard, final Expression expr, final TypeBounds resultBounds) {
3696 if (discard) {
3697 loadAndDiscard(expr);
3698 } else {
3699 loadExpression(expr, resultBounds);
3700 }
3701 }
3702
3703 private void loadNEW(final UnaryNode unaryNode) {
3704 final CallNode callNode = (CallNode)unaryNode.getExpression();
3705 final List<Expression> args = callNode.getArgs();
3706
3707 final Expression func = callNode.getFunction();
3708 // Load function reference.
3709 loadExpressionAsObject(func); // must detect type error
3710
3711 method.dynamicNew(1 + loadArgs(args), getCallSiteFlags(), func.toString(false));
3712 }
3713
3714 private void loadNOT(final UnaryNode unaryNode) {
3715 final Expression expr = unaryNode.getExpression();
3716 if(expr instanceof UnaryNode && expr.isTokenType(TokenType.NOT)) {
3717 // !!x is idiomatic boolean cast in JavaScript
3718 loadExpressionAsBoolean(((UnaryNode)expr).getExpression());
3719 } else {
3720 final Label trueLabel = new Label("true");
3721 final Label afterLabel = new Label("after");
3722
3723 emitBranch(expr, trueLabel, true);
3724 method.load(true);
3725 method._goto(afterLabel);
3726 method.label(trueLabel);
3727 method.load(false);
3728 method.label(afterLabel);
3729 }
3730 }
3731
|