Changeset 260805 in webkit


Ignore:
Timestamp:
Apr 27, 2020 6:33:22 PM (4 years ago)
Author:
ysuzuki@apple.com
Message:

[JSC] >>> should call ToNumeric
https://bugs.webkit.org/show_bug.cgi?id=211065

Reviewed by Ross Kirsling.

JSTests:

  • stress/bigint-urshift.js: Added.

(shouldBe):
(shouldThrow):

  • test262/expectations.yaml:

Source/JavaScriptCore:

While BigInt does not support >>> operator, >>> operator should call ToNumeric (in this case, toBigIntOrInt32) for both before throwing an error.
We call toBigIntOrInt32 for both operands, and throw an error. And after that, casting int32_t to uint32_t to perform >>> operator. This is correct
since the only difference between toUint32 and toInt32 is casting int32_t result to uint32_t.

  • dfg/DFGOperations.cpp:
  • runtime/CommonSlowPaths.cpp:

(JSC::SLOW_PATH_DECL):

  • runtime/Operations.h:

(JSC::shift):
(JSC::jsURShift):

Location:
trunk
Files:
1 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r260784 r260805  
     12020-04-27  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] >>> should call ToNumeric
     4        https://bugs.webkit.org/show_bug.cgi?id=211065
     5
     6        Reviewed by Ross Kirsling.
     7
     8        * stress/bigint-urshift.js: Added.
     9        (shouldBe):
     10        (shouldThrow):
     11        * test262/expectations.yaml:
     12
    1132020-04-27  Yusuke Suzuki  <ysuzuki@apple.com>
    214
  • trunk/JSTests/test262/expectations.yaml

    r260733 r260805  
    30933093  default: 'Test262Error: should not be called'
    30943094  strict mode: 'Test262Error: should not be called'
    3095 test/language/expressions/unsigned-right-shift/bigint-toprimitive.js:
    3096   default: 'Test262Error: 0n >>> {[Symbol.toPrimitive]: function() {throw new MyError();}} throws MyError Expected a MyError but got a TypeError'
    3097   strict mode: 'Test262Error: 0n >>> {[Symbol.toPrimitive]: function() {throw new MyError();}} throws MyError Expected a MyError but got a TypeError'
    30983095test/language/expressions/yield/star-iterable.js:
    30993096  default: 'Test262Error: First result `done` flag Expected SameValue(«false», «undefined») to be true'
  • trunk/Source/JavaScriptCore/ChangeLog

    r260803 r260805  
     12020-04-27  Yusuke Suzuki  <ysuzuki@apple.com>
     2
     3        [JSC] >>> should call ToNumeric
     4        https://bugs.webkit.org/show_bug.cgi?id=211065
     5
     6        Reviewed by Ross Kirsling.
     7
     8        While BigInt does not support >>> operator, >>> operator should call ToNumeric (in this case, toBigIntOrInt32) for both before throwing an error.
     9        We call toBigIntOrInt32 for both operands, and throw an error. And after that, casting int32_t to uint32_t to perform >>> operator. This is correct
     10        since the only difference between toUint32 and toInt32 is casting int32_t result to uint32_t.
     11
     12        * dfg/DFGOperations.cpp:
     13        * runtime/CommonSlowPaths.cpp:
     14        (JSC::SLOW_PATH_DECL):
     15        * runtime/Operations.h:
     16        (JSC::shift):
     17        (JSC::jsURShift):
     18
    1192020-04-27  Keith Miller  <keith_miller@apple.com>
    220
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r260744 r260805  
    507507    CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
    508508    JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
    509     auto scope = DECLARE_THROW_SCOPE(vm);
    510 
    511     JSValue op1 = JSValue::decode(encodedOp1);
    512     JSValue op2 = JSValue::decode(encodedOp2);
    513 
    514     uint32_t a = op1.toUInt32(globalObject);
    515     RETURN_IF_EXCEPTION(scope, encodedJSValue());
    516     scope.release();
    517     uint32_t b = op2.toUInt32(globalObject);
    518     return JSValue::encode(jsNumber(static_cast<int32_t>(a >> (b & 0x1f))));
     509
     510    return JSValue::encode(jsURShift(globalObject, JSValue::decode(encodedOp1), JSValue::decode(encodedOp2)));
    519511}
    520512
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r260744 r260805  
    756756    BEGIN();
    757757    auto bytecode = pc->as<OpUrshift>();
    758     uint32_t a = GET_C(bytecode.m_lhs).jsValue().toUInt32(globalObject);
    759     if (UNLIKELY(throwScope.exception()))
    760         RETURN(JSValue());
    761     uint32_t b = GET_C(bytecode.m_rhs).jsValue().toUInt32(globalObject);
    762     RETURN(jsNumber(static_cast<int32_t>(a >> (b & 31))));
     758    JSValue left = GET_C(bytecode.m_lhs).jsValue();
     759    JSValue right = GET_C(bytecode.m_rhs).jsValue();
     760
     761    JSValue result = jsURShift(globalObject, left, right);
     762    CHECK_EXCEPTION();
     763    RETURN(result);
    763764}
    764765
  • trunk/Source/JavaScriptCore/runtime/JSCJSValue.h

    r260744 r260805  
    295295    double toLength(JSGlobalObject*) const;
    296296
     297    Optional<uint32_t> toUInt32AfterToNumeric(JSGlobalObject*) const;
     298
    297299    // Floating point conversions (this is a convenience function for WebCore;
    298300    // single precision float is not a representation used in JS or JSC).
  • trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h

    r260735 r260805  
    5454inline uint32_t JSValue::toUInt32(JSGlobalObject* globalObject) const
    5555{
    56     // See comment on JSC::toUInt32, in JSCJSValue.h.
     56    // The only difference between toInt32 and toUint32 is that toUint32 reinterprets resulted int32_t value as uint32_t.
     57    // https://tc39.es/ecma262/#sec-touint32
    5758    return toInt32(globalObject);
    5859}
     
    848849
    849850    return jsNumber(value);
     851}
     852
     853ALWAYS_INLINE Optional<uint32_t> JSValue::toUInt32AfterToNumeric(JSGlobalObject* globalObject) const
     854{
     855    VM& vm = getVM(globalObject);
     856    auto scope = DECLARE_THROW_SCOPE(vm);
     857    JSValue result = toBigIntOrInt32(globalObject);
     858    RETURN_IF_EXCEPTION(scope, { });
     859    if (LIKELY(result.isInt32()))
     860        return static_cast<uint32_t>(result.asInt32());
     861    return WTF::nullopt;
    850862}
    851863
  • trunk/Source/JavaScriptCore/runtime/Operations.h

    r260720 r260805  
    793793#endif
    794794
    795     if (!(leftNumeric.isBigInt() && rightNumeric.isBigInt())) {
     795    if (UNLIKELY(!(leftNumeric.isBigInt() && rightNumeric.isBigInt()))) {
    796796        auto errorMessage = isLeft ? "Invalid mix of BigInt and other type in left shift operation." : "Invalid mix of BigInt and other type in signed right shift operation.";
    797797        return throwTypeError(globalObject, scope, errorMessage);
     
    824824}
    825825
     826ALWAYS_INLINE JSValue jsURShift(JSGlobalObject* globalObject, JSValue left, JSValue right)
     827{
     828    VM& vm = globalObject->vm();
     829    auto scope = DECLARE_THROW_SCOPE(vm);
     830
     831    Optional<uint32_t> leftUint32 = left.toUInt32AfterToNumeric(globalObject);
     832    RETURN_IF_EXCEPTION(scope, { });
     833    Optional<uint32_t> rightUint32 = right.toUInt32AfterToNumeric(globalObject);
     834    RETURN_IF_EXCEPTION(scope, { });
     835
     836    if (UNLIKELY(!leftUint32 || !rightUint32)) {
     837        throwTypeError(globalObject, scope, "BigInt does not support >>> operator"_s);
     838        return { };
     839    }
     840
     841    return jsNumber(static_cast<int32_t>(leftUint32.value() >> (rightUint32.value() & 31)));
     842}
     843
    826844template<typename HeapBigIntOperation, typename Int32Operation>
    827845ALWAYS_INLINE JSValue bitwiseBinaryOp(JSGlobalObject* globalObject, JSValue v1, JSValue v2, HeapBigIntOperation&& bigIntOp, Int32Operation&& int32Op, const char* errorMessage)
Note: See TracChangeset for help on using the changeset viewer.