Ignore:
Timestamp:
Jul 5, 2011, 12:01:41 PM (14 years ago)
Author:
[email protected]
Message:

https://bugs.webkit.org/show_bug.cgi?id=63880
Evaluation order of conversions of operands to >, >= incorrect.

Reviewed by Sam Weinig.

Source/JavaScriptCore:

Add 'leftFirst' parameter to jsLess, jsLessEq matching that described in the ES5
spec. This allows these methods to be reused to perform >, >= relational compares
with correct ordering of type conversions.

  • dfg/DFGOperations.cpp:
  • interpreter/Interpreter.cpp:

(JSC::Interpreter::privateExecute):

  • jit/JITStubs.cpp:

(JSC::DEFINE_STUB_FUNCTION):

  • runtime/Operations.h:

(JSC::jsLess):
(JSC::jsLessEq):

LayoutTests:

Updated layout test results. Two of these tests now pass, however for
the third we now need to check in failing results, since the test is
incorrect!

The problem if that the test author has made the mistake of thinking
that the evaluation order for the operands to '>' is RHS then LHS.
This is due to a quirk in the way the spec is written. The greater
than opeator is defined to call the abstract relational comparison
algorithm with 'leftFirst' set to false, and as such conversion is
performed on the second operand ('y') first (see 11.8.5). However
the abstract relational comparison algorith is performing a less
than comaprison, and the greater than operator calls this algorithm
with the operands to the greater than operator reversed (see 11.8.2).
As such, the second operand to the abstract comaparison is the LHS
of the greater than. This bug also affects the corresponding less
than or equals test, where we already we have failing results checked
in, and again it is the test that is wrong (for the same reason).

  • fast/js/exception-sequencing-binops2-expected.txt:
  • sputnik/Conformance/11_Expressions/11.8_Relational_Operators/11.8.2_The_Greater_than_Operator/S11.8.2_A2.3_T1-expected.txt:
  • sputnik/Conformance/11_Expressions/11.8_Relational_Operators/11.8.4_The_Grater_than_or_equal_Operator/S11.8.4_A2.3_T1-expected.txt:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/runtime/Operations.h

    r83751 r90401  
    335335    }
    336336
     337    // See ES5 11.8.1/11.8.2/11.8.5 for definition of leftFirst, this value ensures correct
     338    // evaluation ordering for argument conversions for '<' and '>'. For '<' pass the value
     339    // true, for leftFirst, for '>' pass the value false (and reverse operand order).
     340    template<bool leftFirst>
    337341    ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2)
    338342    {
     
    351355        JSValue p1;
    352356        JSValue p2;
    353         bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
    354         bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
     357        bool wasNotString1;
     358        bool wasNotString2;
     359        if (leftFirst) {
     360            wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
     361            wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
     362        } else {
     363            wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
     364            wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
     365        }
    355366
    356367        if (wasNotString1 | wasNotString2)
    357368            return n1 < n2;
    358 
    359369        return asString(p1)->value(callFrame) < asString(p2)->value(callFrame);
    360370    }
    361371
    362     inline bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2)
     372    // See ES5 11.8.3/11.8.4/11.8.5 for definition of leftFirst, this value ensures correct
     373    // evaluation ordering for argument conversions for '<=' and '=>'. For '<=' pass the
     374    // value true, for leftFirst, for '=>' pass the value false (and reverse operand order).
     375    template<bool leftFirst>
     376    ALWAYS_INLINE bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2)
    363377    {
    364378        if (v1.isInt32() && v2.isInt32())
     
    376390        JSValue p1;
    377391        JSValue p2;
    378         bool wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
    379         bool wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
     392        bool wasNotString1;
     393        bool wasNotString2;
     394        if (leftFirst) {
     395            wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
     396            wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
     397        } else {
     398            wasNotString2 = v2.getPrimitiveNumber(callFrame, n2, p2);
     399            wasNotString1 = v1.getPrimitiveNumber(callFrame, n1, p1);
     400        }
    380401
    381402        if (wasNotString1 | wasNotString2)
    382403            return n1 <= n2;
    383 
    384404        return !(asString(p2)->value(callFrame) < asString(p1)->value(callFrame));
    385405    }
Note: See TracChangeset for help on using the changeset viewer.