hg: nashorn/jdk8/nashorn: 8026137: Fix Issues with Binary Evaluation Order

André Bargull andrebargull at googlemail.com
Mon Oct 14 12:59:31 PDT 2013


"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é/


More information about the nashorn-dev mailing list