[ESNext][BigInt] Implement support for "^"
authorticaiolima@gmail.com <ticaiolima@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Oct 2018 19:31:37 +0000 (19:31 +0000)
committerticaiolima@gmail.com <ticaiolima@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Oct 2018 19:31:37 +0000 (19:31 +0000)
https://bugs.webkit.org/show_bug.cgi?id=186235

Reviewed by Yusuke Suzuki.

JSTests:

* stress/big-int-bitwise-xor-general.js: Added.
* stress/big-int-bitwise-xor-to-primitive-precedence.js: Added.
* stress/big-int-bitwise-xor-type-error.js: Added.
* stress/big-int-bitwise-xor-wrapped-value.js: Added.

Source/JavaScriptCore:

This patch is introducing support for BigInt into bitwise xor
operation. We are including only support into LLInt and Baseline.

* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/JSBigInt.cpp:
(JSC::JSBigInt::bitwiseXor):
(JSC::JSBigInt::absoluteXor):
* runtime/JSBigInt.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@237296 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JSTests/ChangeLog
JSTests/stress/big-int-bitwise-xor-general.js [new file with mode: 0644]
JSTests/stress/big-int-bitwise-xor-to-primitive-precedence.js [new file with mode: 0644]
JSTests/stress/big-int-bitwise-xor-type-error.js [new file with mode: 0644]
JSTests/stress/big-int-bitwise-xor-wrapped-value.js [new file with mode: 0644]
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/JSBigInt.cpp
Source/JavaScriptCore/runtime/JSBigInt.h

index 0ee3965..33dec6b 100644 (file)
@@ -1,5 +1,17 @@
 2018-10-19  Caio Lima  <ticaiolima@gmail.com>
 
+        [ESNext][BigInt] Implement support for "^"
+        https://bugs.webkit.org/show_bug.cgi?id=186235
+
+        Reviewed by Yusuke Suzuki.
+
+        * stress/big-int-bitwise-xor-general.js: Added.
+        * stress/big-int-bitwise-xor-to-primitive-precedence.js: Added.
+        * stress/big-int-bitwise-xor-type-error.js: Added.
+        * stress/big-int-bitwise-xor-wrapped-value.js: Added.
+
+2018-10-19  Caio Lima  <ticaiolima@gmail.com>
+
         [BigInt] Add ValueSub into DFG
         https://bugs.webkit.org/show_bug.cgi?id=186176
 
diff --git a/JSTests/stress/big-int-bitwise-xor-general.js b/JSTests/stress/big-int-bitwise-xor-general.js
new file mode 100644 (file)
index 0000000..282d4f4
--- /dev/null
@@ -0,0 +1,97 @@
+//@ runBigIntEnabled
+
+// Copyright (C) 2017 Josh Wolfe. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+function assert(a) {
+    if (!a)
+        throw new Error("Bad assertion");
+}
+
+assert.sameValue = function (input, expected, message) {
+    if (input !== expected)
+        throw new Error(message);
+}
+
+assert.sameValue(0b00n ^ 0b00n, 0b00n, "0b00n ^ 0b00n === 0b00n");
+assert.sameValue(0b00n ^ 0b01n, 0b01n, "0b00n ^ 0b01n === 0b01n");
+assert.sameValue(0b01n ^ 0b00n, 0b01n, "0b01n ^ 0b00n === 0b01n");
+assert.sameValue(0b00n ^ 0b10n, 0b10n, "0b00n ^ 0b10n === 0b10n");
+assert.sameValue(0b10n ^ 0b00n, 0b10n, "0b10n ^ 0b00n === 0b10n");
+assert.sameValue(0b00n ^ 0b11n, 0b11n, "0b00n ^ 0b11n === 0b11n");
+assert.sameValue(0b11n ^ 0b00n, 0b11n, "0b11n ^ 0b00n === 0b11n");
+assert.sameValue(0b01n ^ 0b01n, 0b00n, "0b01n ^ 0b01n === 0b00n");
+assert.sameValue(0b01n ^ 0b10n, 0b11n, "0b01n ^ 0b10n === 0b11n");
+assert.sameValue(0b10n ^ 0b01n, 0b11n, "0b10n ^ 0b01n === 0b11n");
+assert.sameValue(0b01n ^ 0b11n, 0b10n, "0b01n ^ 0b11n === 0b10n");
+assert.sameValue(0b11n ^ 0b01n, 0b10n, "0b11n ^ 0b01n === 0b10n");
+assert.sameValue(0b10n ^ 0b10n, 0b00n, "0b10n ^ 0b10n === 0b00n");
+assert.sameValue(0b10n ^ 0b11n, 0b01n, "0b10n ^ 0b11n === 0b01n");
+assert.sameValue(0b11n ^ 0b10n, 0b01n, "0b11n ^ 0b10n === 0b01n");
+assert.sameValue(0xffffffffn ^ 0n, 0xffffffffn, "0xffffffffn ^ 0n === 0xffffffffn");
+assert.sameValue(0n ^ 0xffffffffn, 0xffffffffn, "0n ^ 0xffffffffn === 0xffffffffn");
+assert.sameValue(0xffffffffn ^ 0xffffffffn, 0n, "0xffffffffn ^ 0xffffffffn === 0n");
+assert.sameValue(0xffffffffffffffffn ^ 0n, 0xffffffffffffffffn, "0xffffffffffffffffn ^ 0n === 0xffffffffffffffffn");
+assert.sameValue(0n ^ 0xffffffffffffffffn, 0xffffffffffffffffn, "0n ^ 0xffffffffffffffffn === 0xffffffffffffffffn");
+assert.sameValue(0xffffffffffffffffn ^ 0xffffffffn, 0xffffffff00000000n, "0xffffffffffffffffn ^ 0xffffffffn === 0xffffffff00000000n");
+assert.sameValue(0xffffffffn ^ 0xffffffffffffffffn, 0xffffffff00000000n, "0xffffffffn ^ 0xffffffffffffffffn === 0xffffffff00000000n");
+assert.sameValue(
+  0xffffffffffffffffn ^ 0xffffffffffffffffn, 0n,
+  "0xffffffffffffffffn ^ 0xffffffffffffffffn === 0n");
+assert.sameValue(
+  0xbf2ed51ff75d380fd3be813ec6185780n ^ 0x4aabef2324cedff5387f1f65n, 0xbf2ed51fbdf6d72cf7705ecbfe6748e5n,
+  "0xbf2ed51ff75d380fd3be813ec6185780n ^ 0x4aabef2324cedff5387f1f65n === 0xbf2ed51fbdf6d72cf7705ecbfe6748e5n");
+assert.sameValue(
+  0x4aabef2324cedff5387f1f65n ^ 0xbf2ed51ff75d380fd3be813ec6185780n, 0xbf2ed51fbdf6d72cf7705ecbfe6748e5n,
+  "0x4aabef2324cedff5387f1f65n ^ 0xbf2ed51ff75d380fd3be813ec6185780n === 0xbf2ed51fbdf6d72cf7705ecbfe6748e5n");
+assert.sameValue(0n ^ -1n, -1n, "0n ^ -1n === -1n");
+assert.sameValue(-1n ^ 0n, -1n, "-1n ^ 0n === -1n");
+assert.sameValue(0n ^ -2n, -2n, "0n ^ -2n === -2n");
+assert.sameValue(-2n ^ 0n, -2n, "-2n ^ 0n === -2n");
+assert.sameValue(1n ^ -2n, -1n, "1n ^ -2n === -1n");
+assert.sameValue(-2n ^ 1n, -1n, "-2n ^ 1n === -1n");
+assert.sameValue(2n ^ -2n, -4n, "2n ^ -2n === -4n");
+assert.sameValue(-2n ^ 2n, -4n, "-2n ^ 2n === -4n");
+assert.sameValue(2n ^ -3n, -1n, "2n ^ -3n === -1n");
+assert.sameValue(-3n ^ 2n, -1n, "-3n ^ 2n === -1n");
+assert.sameValue(-1n ^ -2n, 1n, "-1n ^ -2n === 1n");
+assert.sameValue(-2n ^ -1n, 1n, "-2n ^ -1n === 1n");
+assert.sameValue(-2n ^ -2n, 0n, "-2n ^ -2n === 0n");
+assert.sameValue(-2n ^ -3n, 3n, "-2n ^ -3n === 3n");
+assert.sameValue(-3n ^ -2n, 3n, "-3n ^ -2n === 3n");
+assert.sameValue(0xffffffffn ^ -1n, -0x100000000n, "0xffffffffn ^ -1n === -0x100000000n");
+assert.sameValue(-1n ^ 0xffffffffn, -0x100000000n, "-1n ^ 0xffffffffn === -0x100000000n");
+assert.sameValue(0xffffffffffffffffn ^ -1n, -0x10000000000000000n, "0xffffffffffffffffn ^ -1n === -0x10000000000000000n");
+assert.sameValue(-1n ^ 0xffffffffffffffffn, -0x10000000000000000n, "-1n ^ 0xffffffffffffffffn === -0x10000000000000000n");
+assert.sameValue(
+  0xbf2ed51ff75d380fd3be813ec6185780n ^ -0x4aabef2324cedff5387f1f65n, -0xbf2ed51fbdf6d72cf7705ecbfe6748e5n,
+  "0xbf2ed51ff75d380fd3be813ec6185780n ^ -0x4aabef2324cedff5387f1f65n === -0xbf2ed51fbdf6d72cf7705ecbfe6748e5n");
+assert.sameValue(
+  -0x4aabef2324cedff5387f1f65n ^ 0xbf2ed51ff75d380fd3be813ec6185780n, -0xbf2ed51fbdf6d72cf7705ecbfe6748e5n,
+  "-0x4aabef2324cedff5387f1f65n ^ 0xbf2ed51ff75d380fd3be813ec6185780n === -0xbf2ed51fbdf6d72cf7705ecbfe6748e5n");
+assert.sameValue(
+  -0xbf2ed51ff75d380fd3be813ec6185780n ^ 0x4aabef2324cedff5387f1f65n, -0xbf2ed51fbdf6d72cf7705ecbfe67481bn,
+  "-0xbf2ed51ff75d380fd3be813ec6185780n ^ 0x4aabef2324cedff5387f1f65n === -0xbf2ed51fbdf6d72cf7705ecbfe67481bn");
+assert.sameValue(
+  0x4aabef2324cedff5387f1f65n ^ -0xbf2ed51ff75d380fd3be813ec6185780n, -0xbf2ed51fbdf6d72cf7705ecbfe67481bn,
+  "0x4aabef2324cedff5387f1f65n ^ -0xbf2ed51ff75d380fd3be813ec6185780n === -0xbf2ed51fbdf6d72cf7705ecbfe67481bn");
+assert.sameValue(
+  -0xbf2ed51ff75d380fd3be813ec6185780n ^ -0x4aabef2324cedff5387f1f65n, 0xbf2ed51fbdf6d72cf7705ecbfe67481bn,
+  "-0xbf2ed51ff75d380fd3be813ec6185780n ^ -0x4aabef2324cedff5387f1f65n === 0xbf2ed51fbdf6d72cf7705ecbfe67481bn");
+assert.sameValue(
+  -0x4aabef2324cedff5387f1f65n ^ -0xbf2ed51ff75d380fd3be813ec6185780n, 0xbf2ed51fbdf6d72cf7705ecbfe67481bn,
+  "-0x4aabef2324cedff5387f1f65n ^ -0xbf2ed51ff75d380fd3be813ec6185780n === 0xbf2ed51fbdf6d72cf7705ecbfe67481bn");
+assert.sameValue(-0xffffffffn ^ 0n, -0xffffffffn, "-0xffffffffn ^ 0n === -0xffffffffn");
+assert.sameValue(0n ^ -0xffffffffn, -0xffffffffn, "0n ^ -0xffffffffn === -0xffffffffn");
+assert.sameValue(
+  -0xffffffffffffffffn ^ 0x10000000000000000n, -0x1ffffffffffffffffn,
+  "-0xffffffffffffffffn ^ 0x10000000000000000n === -0x1ffffffffffffffffn");
+assert.sameValue(
+  0x10000000000000000n ^ -0xffffffffffffffffn, -0x1ffffffffffffffffn,
+  "0x10000000000000000n ^ -0xffffffffffffffffn === -0x1ffffffffffffffffn");
+assert.sameValue(
+  -0xffffffffffffffffffffffffn ^ 0x10000000000000000n, -0xfffffffeffffffffffffffffn,
+  "-0xffffffffffffffffffffffffn ^ 0x10000000000000000n === -0xfffffffeffffffffffffffffn");
+assert.sameValue(
+  0x10000000000000000n ^ -0xffffffffffffffffffffffffn, -0xfffffffeffffffffffffffffn,
+  "0x10000000000000000n ^ -0xffffffffffffffffffffffffn === -0xfffffffeffffffffffffffffn");
diff --git a/JSTests/stress/big-int-bitwise-xor-to-primitive-precedence.js b/JSTests/stress/big-int-bitwise-xor-to-primitive-precedence.js
new file mode 100644 (file)
index 0000000..8f90dbf
--- /dev/null
@@ -0,0 +1,29 @@
+//@ runBigIntEnabled
+
+assert = {
+    sameValue: function (input, expected, message) {
+        if (input !== expected)
+            throw new Error(message);
+    }
+};
+
+let o = {
+    [Symbol.toPrimitive]: function() {
+        throw new Error("Bad");
+    }
+};
+
+try{
+    o ^ Symbol("2");
+    assert.sameValue(true, false, "Exception expected to be throwed, but executed without error");
+} catch (e) {
+    assert.sameValue(e.message, "Bad", "Expected to throw Error('Bad'), but got: " + e);
+}
+
+try{
+    Symbol("2") ^ o;
+    assert.sameValue(true, false, "Exception expected to be throwed, but executed without error");
+} catch (e) {
+    assert.sameValue(e instanceof TypeError, true, "Expected to throw TypeError, but got: " + e)
+}
+
diff --git a/JSTests/stress/big-int-bitwise-xor-type-error.js b/JSTests/stress/big-int-bitwise-xor-type-error.js
new file mode 100644 (file)
index 0000000..2fc57d2
--- /dev/null
@@ -0,0 +1,104 @@
+//@ runBigIntEnabled
+
+function assert(a, message) {
+    if (!a)
+        throw new Error(message);
+}
+
+function assertThrowTypeError(a, b, message) {
+    try {
+        let n = a ^ b;
+        assert(false, message + ": Should throw TypeError, but executed without exception");
+    } catch (e) {
+        assert(e instanceof TypeError, message + ": expected TypeError, got: " + e);
+    }
+}
+
+assertThrowTypeError(30n, "foo", "BigInt ^ String");
+assertThrowTypeError("bar", 18757382984821n, "String ^ BigInt");
+assertThrowTypeError(30n, Symbol("foo"), "BigInt ^ Symbol");
+assertThrowTypeError(Symbol("bar"), 18757382984821n, "Symbol ^ BigInt");
+assertThrowTypeError(30n, 3320, "BigInt ^ Int32");
+assertThrowTypeError(33256, 18757382984821n, "Int32 ^ BigInt");
+assertThrowTypeError(30n, 0.543, "BigInt ^ Double");
+assertThrowTypeError(230.19293, 18757382984821n, "Double ^ BigInt");
+assertThrowTypeError(30n, NaN, "BigInt ^ NaN");
+assertThrowTypeError(NaN, 18757382984821n, "NaN ^ BigInt");
+assertThrowTypeError(30n, +Infinity, "BigInt ^ +Infinity");
+assertThrowTypeError(+Infinity, 18757382984821n, "+Infinity ^ BigInt");
+assertThrowTypeError(30n, -Infinity, "BigInt ^ -Infinity");
+assertThrowTypeError(-Infinity, 18757382984821n, "-Infinity ^ BigInt");
+assertThrowTypeError(30n, null, "BigInt ^ null");
+assertThrowTypeError(null, 18757382984821n, "null ^ BigInt");
+assertThrowTypeError(30n, undefined, "BigInt ^ undefined");
+assertThrowTypeError(undefined, 18757382984821n, "undefined ^ BigInt");
+assertThrowTypeError(30n, true, "BigInt ^ true");
+assertThrowTypeError(true, 18757382984821n, "true ^ BigInt");
+assertThrowTypeError(30n, false, "BigInt ^ false");
+assertThrowTypeError(false, 18757382984821n, "false ^ BigInt");
+
+// Error when returning from object
+
+let o = {
+    valueOf: function () { return Symbol("Foo"); }
+};
+
+assertThrowTypeError(30n, o, "BigInt ^ Object.valueOf returning Symbol");
+assertThrowTypeError(o, 18757382984821n, "Object.valueOf returning Symbol ^ BigInt");
+
+o = {
+    valueOf: function () { return 33256; }
+};
+
+assertThrowTypeError(30n, o, "BigInt ^ Object.valueOf returning Int32");
+assertThrowTypeError(o, 18757382984821n, "Object.valueOf returning Int32 ^ BigInt");
+
+o = {
+    valueOf: function () { return 0.453; }
+};
+
+assertThrowTypeError(30n, o, "BigInt ^ Object.valueOf returning Double");
+assertThrowTypeError(o, 18757382984821n, "Object.valueOf returning Double ^ BigInt");
+
+o = {
+    toString: function () { return Symbol("Foo"); }
+};
+
+assertThrowTypeError(30n, o, "BigInt ^ Object.toString returning Symbol");
+assertThrowTypeError(o, 18757382984821n, "Object.toString returning Symbol ^ BigInt");
+
+o = {
+    toString: function () { return 33256; }
+};
+
+assertThrowTypeError(30n, o, "BigInt ^ Object.toString returning Int32");
+assertThrowTypeError(o, 18757382984821n, "Object.toString returning Int32 ^ BigInt");
+
+o = {
+    toString: function () { return 0.453; }
+};
+
+assertThrowTypeError(30n, o, "BigInt ^ Object.toString returning Double");
+assertThrowTypeError(o, 18757382984821n, "Object.toString returning Double ^ BigInt");
+
+o = {
+    [Symbol.toPrimitive]: function () { return Symbol("Foo"); }
+};
+
+assertThrowTypeError(30n, o, "BigInt ^ Object.@@toPrimitive returning Symbol");
+assertThrowTypeError(o, 18757382984821n, "Object.@@toPrimitive returning Symbol ^ BigInt");
+
+o = {
+    [Symbol.toPrimitive]: function () { return 33256; }
+};
+
+assertThrowTypeError(30n, o, "BigInt ^ Object.@@toPrimitive returning Int32");
+assertThrowTypeError(o, 18757382984821n, "Object.@@toPrimitive returning Int32 ^ BigInt");
+
+o = {
+    [Symbol.toPrimitive]: function () { return 0.453; }
+};
+
+assertThrowTypeError(30n, o, "BigInt ^ Object.@@toPrimitive returning Double");
+assertThrowTypeError(o, 18757382984821n, "Object.@@toPrimitive returning Double ^ BigInt");
+
diff --git a/JSTests/stress/big-int-bitwise-xor-wrapped-value.js b/JSTests/stress/big-int-bitwise-xor-wrapped-value.js
new file mode 100644 (file)
index 0000000..97008ef
--- /dev/null
@@ -0,0 +1,37 @@
+//@ runBigIntEnabled
+
+assert = {
+    sameValue: function (input, expected, message) {
+        if (input !== expected)
+            throw new Error(message);
+    }
+};
+
+function testBitXor(x, y, z, message) {
+    assert.sameValue(x ^ y, z, message);
+    assert.sameValue(y ^ x, z, message);
+}
+
+testBitXor(Object(0b10n), 0b01n, 0b11n, "ToPrimitive: unbox object with internal slot");
+
+let o = {
+    [Symbol.toPrimitive]: function() {
+        return 0b10n;
+    }
+};
+testBitXor(o, 0b01n, 0b11n, "ToPrimitive: @@toPrimitive");
+
+o = {
+    valueOf: function() {
+        return 0b10n;
+    }
+};
+testBitXor(o, 0b01n, 0b11n, "ToPrimitive: valueOf");
+
+o = {
+    toString: function() {
+        return 0b10n;
+    }
+}
+testBitXor(o, 0b01n, 0b11n, "ToPrimitive: toString");
+
index b166c2e..8ad9aaa 100644 (file)
@@ -1,5 +1,22 @@
 2018-10-19  Caio Lima  <ticaiolima@gmail.com>
 
+        [ESNext][BigInt] Implement support for "^"
+        https://bugs.webkit.org/show_bug.cgi?id=186235
+
+        Reviewed by Yusuke Suzuki.
+
+        This patch is introducing support for BigInt into bitwise xor
+        operation. We are including only support into LLInt and Baseline.
+
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/JSBigInt.cpp:
+        (JSC::JSBigInt::bitwiseXor):
+        (JSC::JSBigInt::absoluteXor):
+        * runtime/JSBigInt.h:
+
+2018-10-19  Caio Lima  <ticaiolima@gmail.com>
+
         [BigInt] Add ValueSub into DFG
         https://bugs.webkit.org/show_bug.cgi?id=186176
 
index c26f31b..0a1327a 100644 (file)
@@ -696,11 +696,21 @@ SLOW_PATH_DECL(slow_path_bitor)
 SLOW_PATH_DECL(slow_path_bitxor)
 {
     BEGIN();
-    int32_t a = OP_C(2).jsValue().toInt32(exec);
-    if (UNLIKELY(throwScope.exception()))
-        RETURN(JSValue());
-    int32_t b = OP_C(3).jsValue().toInt32(exec);
-    RETURN(jsNumber(a ^ b));
+    auto leftNumeric = OP_C(2).jsValue().toBigIntOrInt32(exec);
+    CHECK_EXCEPTION();
+    auto rightNumeric = OP_C(3).jsValue().toBigIntOrInt32(exec);
+    CHECK_EXCEPTION();
+    if (WTF::holds_alternative<JSBigInt*>(leftNumeric) || WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
+        if (WTF::holds_alternative<JSBigInt*>(leftNumeric) && WTF::holds_alternative<JSBigInt*>(rightNumeric)) {
+            JSBigInt* result = JSBigInt::bitwiseXor(vm, WTF::get<JSBigInt*>(leftNumeric), WTF::get<JSBigInt*>(rightNumeric));
+            CHECK_EXCEPTION();
+            RETURN(result);
+        }
+
+        THROW(createTypeError(exec, "Invalid mix of BigInt and other type in bitwise 'xor' operation."));
+    }
+
+    RETURN(jsNumber(WTF::get<int32_t>(leftNumeric) ^ WTF::get<int32_t>(rightNumeric)));
 }
 
 SLOW_PATH_DECL(slow_path_typeof)
index 0f9a4f4..4ab5a52 100644 (file)
@@ -428,6 +428,32 @@ JSBigInt* JSBigInt::bitwiseOr(VM& vm, JSBigInt* x, JSBigInt* y)
     return absoluteAddOne(vm, result, SignOption::Signed);
 }
 
+JSBigInt* JSBigInt::bitwiseXor(VM& vm, JSBigInt* x, JSBigInt* y)
+{
+    if (!x->sign() && !y->sign())
+        return absoluteXor(vm, x, y);
+    
+    if (x->sign() && y->sign()) {
+        int resultLength = std::max(x->length(), y->length());
+        
+        // (-x) ^ (-y) == ~(x-1) ^ ~(y-1) == (x-1) ^ (y-1)
+        JSBigInt* result = absoluteSubOne(vm, x, resultLength);
+        JSBigInt* y1 = absoluteSubOne(vm, y, y->length());
+        return absoluteXor(vm, result, y1);
+    }
+    ASSERT(x->sign() != y->sign());
+    int resultLength = std::max(x->length(), y->length()) + 1;
+    
+    // Assume that x is the positive BigInt.
+    if (x->sign())
+        std::swap(x, y);
+    
+    // x ^ (-y) == x ^ ~(y-1) == ~(x ^ (y-1)) == -((x ^ (y-1)) + 1)
+    JSBigInt* result = absoluteSubOne(vm, y, resultLength);
+    result = absoluteXor(vm, result, x);
+    return absoluteAddOne(vm, result, SignOption::Signed);
+}
+
 #if USE(JSVALUE32_64)
 #define HAVE_TWO_DIGIT 1
 typedef uint64_t TwoDigit;
@@ -1110,6 +1136,14 @@ JSBigInt* JSBigInt::absoluteAndNot(VM& vm, JSBigInt* x, JSBigInt* y)
     return absoluteBitwiseOp(vm, x, y, ExtraDigitsHandling::Copy, SymmetricOp::NotSymmetric, digitOperation);
 }
 
+JSBigInt* JSBigInt::absoluteXor(VM& vm, JSBigInt* x, JSBigInt* y)
+{
+    auto digitOperation = [](Digit a, Digit b) {
+        return a ^ b;
+    };
+    return absoluteBitwiseOp(vm, x, y, ExtraDigitsHandling::Copy, SymmetricOp::Symmetric, digitOperation);
+}
+    
 JSBigInt* JSBigInt::absoluteAddOne(VM& vm, JSBigInt* x, SignOption signOption)
 {
     unsigned inputLength = x->length();
index 805a115..a62e138 100644 (file)
@@ -116,6 +116,7 @@ public:
 
     static JSBigInt* bitwiseAnd(VM&, JSBigInt* x, JSBigInt* y);
     static JSBigInt* bitwiseOr(VM&, JSBigInt* x, JSBigInt* y);
+    static JSBigInt* bitwiseXor(VM&, JSBigInt* x, JSBigInt* y);
 
 private:
 
@@ -168,6 +169,7 @@ private:
     static JSBigInt* absoluteAnd(VM&, JSBigInt* x, JSBigInt* y);
     static JSBigInt* absoluteOr(VM&, JSBigInt* x, JSBigInt* y);
     static JSBigInt* absoluteAndNot(VM&, JSBigInt* x, JSBigInt* y);
+    static JSBigInt* absoluteXor(VM&, JSBigInt* x, JSBigInt* y);
 
     enum class SignOption {
         Signed,