hg: nashorn/jdk8/nashorn: 8026137: Fix Issues with Binary Evaluation Order
André Bargull
andrebargull at googlemail.com
Mon Oct 14 23:29:09 PDT 2013
Yeah, sure strings need to be handled explicitly here.
On 10/14/2013 10:32 PM, Hannes Wallnoefer wrote:
> Looks good. One thing I'm noting is that String is currently handled
> as ObjectType (i.e. getType().isObject() will return true), which is
> true in Java terms, but in this context we should treat String as
> primitive, right?
>
> Hannes
>
> Am 2013-10-14 21:59, schrieb André Bargull:
>> "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