"primitive type" was a bad choice of words, I rather meant "side-effect-free".

When all operands are primitives, most operations won't trigger side-effects. Only most operations because in `0 - (0 instanceof 1)` all operands are primitives, but `(0 instanceof 1)` still needs to be executed before the subtraction. So I was thinking of the following change for Codegen (incomplete -> `instanceof` etc. not handled!):


    private static boolean isSideEffectFree(final Expression rhs) {
        if (rhs instanceof LiteralNode.PrimitiveLiteralNode) {
            return true;
        } else if (rhs instanceof IdentNode) {
            return !rhs.getSymbol().isScope() && !rhs.getType().isObject();
        } else if (rhs instanceof UnaryNode) {
            UnaryNode unary = (UnaryNode) rhs;
            return isSideEffectFree(unary.rhs());
        } else if (rhs instanceof BinaryNode) {
            BinaryNode binary = (BinaryNode) rhs;
            return isSideEffectFree(binary.lhs())
                    && isSideEffectFree(binary.rhs());
        } else if (rhs instanceof TernaryNode) {
            TernaryNode ternary = (TernaryNode) rhs;
            return isSideEffectFree(ternary.getTest())
                    && isSideEffectFree(ternary.getTrueExpression())
                    && isSideEffectFree(ternary.getFalseExpression());
        }
        return false;
    }

    private static boolean safeLiteral(final Expression rhs) {
//        return isSideEffectFree(rhs);
return rhs instanceof LiteralNode && !(rhs instanceof ArrayLiteralNode);
    }


- André


Side effects can still occur with primitive types. As an example, this
script from the test case as a numeric right hand side:

({valueOf: function(){throw 0}}) - ({valueOf: function(){throw 1}} - 1)

But maybe something like this (pseudo-code) could work in
CodeGenerator#safeLiteral:

    isPrimitiveLiteralNode || (isIdentNode && isPrimitiveType)

An IdentNode can have side effects if it is a global with a getter, but
if we know it's type that shouldn't be the case.

Hannes

Am 2013-10-09 18:44, schrieb André Bargull:
>/  Quick question for this change set:
/>/
/>/  Why does CodeGenerator#safeLiteral(...) need to test for literal nodes
/>/  instead of using type information? When the right-hand-side is a
/>/  primitive type, side effects cannot occur, so the additional
/>/  swap/dup/pop instructions can be omitted safely.
/>/
/>/  For example `function f(a){var c = 1; return a - c }` now emits:
/>/      ALOAD 1
/>/      ILOAD 4
/>/      SWAP
/>/      INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber
/>/  (Ljava/lang/Object;)D
/>/      DUP2_X1
/>/      POP2
/>/      I2D
/>/      DSUB
/>/
/>/  Using type info it's possible to change the bytecode to:
/>/      ALOAD 1
/>/      INVOKESTATIC jdk/nashorn/internal/runtime/JSType.toNumber
/>/  (Ljava/lang/Object;)D
/>/      ILOAD 4
/>/      I2D
/>/      DSUB
/>/
/>/
/>/  (Also: That was one of the bug reports which worried me a bit, because
/>/  I expected the changes to be non-trivial. :-(
/>/
/>/
/>/  - André/

Reply via email to