diff --git a/jerry-core/ecma/operations/ecma-big-uint.c b/jerry-core/ecma/operations/ecma-big-uint.c
index a6023a07c..e33fac983 100644
--- a/jerry-core/ecma/operations/ecma-big-uint.c
+++ b/jerry-core/ecma/operations/ecma-big-uint.c
@@ -26,6 +26,9 @@ JERRY_STATIC_ASSERT (sizeof (ecma_bigint_two_digits_t) == 2 * sizeof (ecma_bigin
JERRY_STATIC_ASSERT ((1 << ECMA_BIGINT_DIGIT_SHIFT) == (8 * sizeof (ecma_bigint_digit_t)),
ecma_bigint_digit_shift_is_incorrect);
+JERRY_STATIC_ASSERT ((ECMA_BIG_UINT_BITWISE_DECREASE_LEFT << 1) == ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT,
+ ecma_big_uint_bitwise_left_and_right_sub_option_bits_must_follow_each_other);
+
/**
* Create a new BigInt value
*
@@ -64,12 +67,12 @@ ecma_bigint_create (uint32_t size) /**< size of the new BigInt value */
} /* ecma_bigint_create */
/**
- * Extend a BigInt value with a new data prefix value
+ * Extend a BigUInt value with a new data prefix value
*
- * @return new BigInt value, NULL on error
+ * @return new BigUInt value, NULL on error
*/
ecma_extended_primitive_t *
-ecma_big_uint_extend (ecma_extended_primitive_t *value_p, /**< BigInt value */
+ecma_big_uint_extend (ecma_extended_primitive_t *value_p, /**< BigUInt value */
ecma_bigint_digit_t digit) /**< new digit */
{
uint32_t old_size = ECMA_BIGINT_GET_SIZE (value_p);
@@ -96,6 +99,39 @@ ecma_big_uint_extend (ecma_extended_primitive_t *value_p, /**< BigInt value */
return result_p;
} /* ecma_big_uint_extend */
+/**
+ * Discard the high-order digits of a BigUInt
+ *
+ * @return BigUInt value, NULL on error
+ */
+static ecma_extended_primitive_t *
+ecma_big_uint_shrink_value (ecma_extended_primitive_t *value_p, /**< BigUInt value */
+ uint32_t new_size) /**< new size, which is smaller than the original size */
+{
+ JERRY_ASSERT (value_p != NULL);
+ JERRY_ASSERT (ECMA_BIGINT_GET_SIZE (value_p) > new_size);
+
+ if (ECMA_BIGINT_SIZE_IS_ODD (new_size)
+ && ((new_size + sizeof (ecma_bigint_digit_t)) == ECMA_BIGINT_GET_SIZE (value_p)))
+ {
+ value_p->u.bigint_sign_and_size -= (uint32_t) sizeof (ecma_bigint_digit_t);
+ return value_p;
+ }
+
+ ecma_extended_primitive_t *result_p = ecma_bigint_create (new_size);
+
+ if (JERRY_UNLIKELY (result_p == NULL))
+ {
+ ecma_deref_bigint (value_p);
+ return NULL;
+ }
+
+ memcpy (ECMA_BIGINT_GET_DIGITS (result_p, 0), ECMA_BIGINT_GET_DIGITS (value_p, 0), new_size);
+ ecma_deref_bigint (value_p);
+
+ return result_p;
+} /* ecma_big_uint_shrink_value */
+
/**
* Compare two BigUInt numbers
*
@@ -530,28 +566,8 @@ ecma_big_uint_sub (ecma_extended_primitive_t *left_value_p, /**< left BigUInt va
}
while (new_end_p[-1] == 0);
- ecma_bigint_digit_t *result_data_p = ECMA_BIGINT_GET_DIGITS (result_p, 0);
- uint32_t old_size = ECMA_BIGINT_GET_SIZE (result_p);
- uint32_t new_size = (uint32_t) ((uint8_t *) new_end_p - (uint8_t *) result_data_p);
-
- if (ECMA_BIGINT_SIZE_IS_ODD (new_size) && ((new_size + sizeof (ecma_bigint_digit_t)) == old_size))
- {
- result_p->u.bigint_sign_and_size -= (uint32_t) sizeof (ecma_bigint_digit_t);
- return result_p;
- }
-
- ecma_extended_primitive_t *new_result_p = ecma_bigint_create (new_size);
-
- if (JERRY_UNLIKELY (new_result_p == NULL))
- {
- ecma_deref_bigint (result_p);
- return NULL;
- }
-
- memcpy (ECMA_BIGINT_GET_DIGITS (new_result_p, 0), result_data_p, new_size);
- ecma_deref_bigint (result_p);
-
- return new_result_p;
+ ecma_bigint_digit_t *first_digit_p = ECMA_BIGINT_GET_DIGITS (result_p, 0);
+ return ecma_big_uint_shrink_value (result_p, (uint32_t) ((uint8_t *) new_end_p - (uint8_t *) first_digit_p));
} /* ecma_big_uint_sub */
/**
@@ -1156,6 +1172,12 @@ ecma_big_uint_shift_left (ecma_extended_primitive_t *left_value_p, /**< left Big
}
ecma_extended_primitive_t *result_value_p = ecma_bigint_create (result_size);
+
+ if (JERRY_UNLIKELY (result_value_p == NULL))
+ {
+ return NULL;
+ }
+
ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0);
ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0);
@@ -1195,7 +1217,7 @@ ecma_big_uint_shift_left (ecma_extended_primitive_t *left_value_p, /**< left Big
/**
* Shift right BigInt values by an uint32 value
*
- * return new BigInt value, NULL on error
+ * @return new BigInt value, NULL on error
*/
ecma_extended_primitive_t *
ecma_big_uint_shift_right (ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */
@@ -1227,6 +1249,11 @@ ecma_big_uint_shift_right (ecma_extended_primitive_t *left_value_p, /**< left B
uint32_t size = left_size - crop_size;
ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size);
+ if (JERRY_UNLIKELY (result_value_p == NULL))
+ {
+ return NULL;
+ }
+
if (shift_right == 0)
{
memcpy (ECMA_BIGINT_GET_DIGITS (result_value_p, 0), ECMA_BIGINT_GET_DIGITS (left_value_p, crop_size), size);
@@ -1249,4 +1276,293 @@ ecma_big_uint_shift_right (ecma_extended_primitive_t *left_value_p, /**< left B
return result_value_p;
} /* ecma_big_uint_shift_right */
+/**
+ * Helper function for bitwise operations which drops leading zeroes
+ *
+ * @return ecma BigInt value or ECMA_VALUE_ERROR
+ * Returned value must be freed with ecma_free_value.
+ */
+static ecma_extended_primitive_t *
+ecma_big_uint_normalize_result (ecma_extended_primitive_t *value_p, /**< BigUInt value */
+ ecma_bigint_digit_t *last_digit_p) /**< points to the end of BigUInt */
+{
+ JERRY_ASSERT (last_digit_p[-1] == 0);
+
+ ecma_bigint_digit_t *first_digit_p = ECMA_BIGINT_GET_DIGITS (value_p, 0);
+
+ do
+ {
+ --last_digit_p;
+ }
+ while (last_digit_p > first_digit_p && last_digit_p[-1] == 0);
+
+ return ecma_big_uint_shrink_value (value_p, (uint32_t) ((uint8_t *) last_digit_p - (uint8_t *) first_digit_p));
+} /* ecma_big_uint_normalize_result */
+
+/**
+ * Helper function for bitwise operations which increases the result by 1
+ *
+ * @return new BigInt value, NULL on error
+ */
+static ecma_extended_primitive_t *
+ecma_big_uint_increase_result (ecma_extended_primitive_t *value_p) /**< BigUInt value */
+{
+ uint32_t size = ECMA_BIGINT_GET_SIZE (value_p);
+
+ JERRY_ASSERT (size > 0);
+
+ ecma_bigint_digit_t *first_digit_p = ECMA_BIGINT_GET_DIGITS (value_p, 0);
+ ecma_bigint_digit_t *last_digit_p = ECMA_BIGINT_GET_DIGITS (value_p, size);
+
+ while (*first_digit_p == ~((ecma_bigint_digit_t) 0))
+ {
+ *first_digit_p++ = 0;
+
+ if (first_digit_p == last_digit_p)
+ {
+ return ecma_big_uint_extend (value_p, 1);
+ }
+ }
+
+ (*first_digit_p)++;
+
+ if (last_digit_p[-1] != 0)
+ {
+ return value_p;
+ }
+
+ return ecma_big_uint_normalize_result (value_p, last_digit_p);
+} /* ecma_big_uint_increase_result */
+
+/**
+ * Perform bitwise operations on two BigUInt numbers
+ *
+ * return new BigInt value, NULL on error
+ */
+ecma_extended_primitive_t *
+ecma_big_uint_bitwise_op (uint32_t operation_and_options, /**< bitwise operation type and options */
+ ecma_extended_primitive_t *left_value_p, /**< left BigUInt value */
+ ecma_extended_primitive_t *right_value_p) /**< right BigUInt value */
+{
+ uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_value_p);
+ uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_value_p);
+
+ JERRY_ASSERT (left_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (left_value_p, left_size) != 0);
+ JERRY_ASSERT (right_size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (right_value_p, right_size) != 0);
+
+ uint32_t operation_type = ECMA_BIGINT_BITWISE_GET_OPERATION_TYPE (operation_and_options);
+
+ switch (operation_type)
+ {
+ case ECMA_BIG_UINT_BITWISE_AND:
+ {
+ if (left_size > right_size)
+ {
+ left_size = right_size;
+ break;
+ }
+ /* FALLTHRU */
+ }
+ case ECMA_BIG_UINT_BITWISE_AND_NOT:
+ {
+ if (right_size > left_size)
+ {
+ right_size = left_size;
+ }
+ break;
+ }
+ default:
+ {
+ JERRY_ASSERT (operation_type == ECMA_BIG_UINT_BITWISE_OR
+ || operation_type == ECMA_BIG_UINT_BITWISE_XOR);
+
+ if (right_size <= left_size)
+ {
+ break;
+ }
+
+ /* Swap values. */
+ ecma_extended_primitive_t *tmp_value_p = left_value_p;
+ left_value_p = right_value_p;
+ right_value_p = tmp_value_p;
+
+ uint32_t tmp_size = left_size;
+ left_size = right_size;
+ right_size = tmp_size;
+
+ uint32_t decrease_opts = (operation_and_options & ECMA_BIG_UINT_BITWISE_DECREASE_BOTH);
+
+ /* When exactly one bit is set, invert both bits. */
+ if (decrease_opts >= ECMA_BIG_UINT_BITWISE_DECREASE_LEFT
+ && decrease_opts <= ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT)
+ {
+ operation_and_options ^= ECMA_BIG_UINT_BITWISE_DECREASE_BOTH;
+ }
+ break;
+ }
+ }
+
+ ecma_extended_primitive_t *result_value_p = ecma_bigint_create (left_size);
+
+ if (JERRY_UNLIKELY (result_value_p == NULL))
+ {
+ return NULL;
+ }
+
+ ecma_bigint_digit_t *left_p = ECMA_BIGINT_GET_DIGITS (left_value_p, 0);
+ ecma_bigint_digit_t *right_p = ECMA_BIGINT_GET_DIGITS (right_value_p, 0);
+ ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0);
+ ecma_bigint_digit_t *result_end_p = ECMA_BIGINT_GET_DIGITS (result_value_p, right_size);
+
+ if (!(operation_and_options & ECMA_BIG_UINT_BITWISE_DECREASE_BOTH))
+ {
+ JERRY_ASSERT (!(operation_and_options & ECMA_BIG_UINT_BITWISE_INCREASE_RESULT));
+
+ if (operation_type == ECMA_BIG_UINT_BITWISE_AND)
+ {
+ do
+ {
+ *result_p++ = *left_p++ & *right_p++;
+ }
+ while (result_p < result_end_p);
+
+ if (result_p[-1] == 0)
+ {
+ return ecma_big_uint_normalize_result (result_value_p, result_p);
+ }
+ return result_value_p;
+ }
+
+ if (operation_type == ECMA_BIG_UINT_BITWISE_OR)
+ {
+ do
+ {
+ *result_p++ = *left_p++ | *right_p++;
+ }
+ while (result_p < result_end_p);
+
+ if (left_size > right_size)
+ {
+ memcpy (result_p, left_p, left_size - right_size);
+ }
+ return result_value_p;
+ }
+
+ JERRY_ASSERT (operation_type == ECMA_BIG_UINT_BITWISE_XOR);
+
+ do
+ {
+ *result_p++ = *left_p++ ^ *right_p++;
+ }
+ while (result_p < result_end_p);
+
+ if (left_size > right_size)
+ {
+ memcpy (result_p, left_p, left_size - right_size);
+ return result_value_p;
+ }
+
+ if (result_p[-1] == 0)
+ {
+ return ecma_big_uint_normalize_result (result_value_p, result_p);
+ }
+ return result_value_p;
+ }
+
+ uint32_t left_carry = 0, right_carry = 0;
+
+ if (operation_and_options & ECMA_BIG_UINT_BITWISE_DECREASE_LEFT)
+ {
+ left_carry = 1;
+ }
+
+ if (operation_and_options & ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT)
+ {
+ right_carry = 1;
+ }
+
+ do
+ {
+ ecma_bigint_digit_t left = (*left_p++) - left_carry;
+
+ if (left != ~((ecma_bigint_digit_t) 0))
+ {
+ left_carry = 0;
+ }
+
+ ecma_bigint_digit_t right = (*right_p++) - right_carry;
+
+ if (right != ~((ecma_bigint_digit_t) 0))
+ {
+ right_carry = 0;
+ }
+
+ switch (operation_type)
+ {
+ case ECMA_BIG_UINT_BITWISE_AND:
+ {
+ *result_p++ = left & right;
+ break;
+ }
+ case ECMA_BIG_UINT_BITWISE_OR:
+ {
+ *result_p++ = left | right;
+ break;
+ }
+ case ECMA_BIG_UINT_BITWISE_XOR:
+ {
+ *result_p++ = left ^ right;
+ break;
+ }
+ default:
+ {
+ JERRY_ASSERT (operation_type == ECMA_BIG_UINT_BITWISE_AND_NOT);
+ *result_p++ = left & ~right;
+ break;
+ }
+ }
+ }
+ while (result_p < result_end_p);
+
+ if (operation_type != ECMA_BIG_UINT_BITWISE_AND)
+ {
+ result_end_p = ECMA_BIGINT_GET_DIGITS (result_value_p, left_size);
+
+ if (left_carry > 0)
+ {
+ while (*left_p == 0)
+ {
+ *result_p++ = ~((ecma_bigint_digit_t) 0);
+ left_p++;
+
+ JERRY_ASSERT (result_p < result_end_p);
+ }
+
+ *result_p++ = *left_p++ - 1;
+ }
+
+ if (result_p < result_end_p)
+ {
+ memcpy (result_p, left_p, (size_t) ((uint8_t *) result_end_p - (uint8_t *) result_p));
+
+ if (operation_and_options & ECMA_BIG_UINT_BITWISE_INCREASE_RESULT)
+ {
+ return ecma_big_uint_increase_result (result_value_p);
+ }
+ return result_value_p;
+ }
+ }
+
+ if (operation_and_options & ECMA_BIG_UINT_BITWISE_INCREASE_RESULT)
+ {
+ return ecma_big_uint_increase_result (result_value_p);
+ }
+
+ if (result_p[-1] == 0)
+ {
+ return ecma_big_uint_normalize_result (result_value_p, result_p);
+ }
+ return result_value_p;
+} /* ecma_big_uint_bitwise_op */
+
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
diff --git a/jerry-core/ecma/operations/ecma-big-uint.h b/jerry-core/ecma/operations/ecma-big-uint.h
index a8e16af8b..de4434d38 100644
--- a/jerry-core/ecma/operations/ecma-big-uint.h
+++ b/jerry-core/ecma/operations/ecma-big-uint.h
@@ -59,6 +59,39 @@ typedef uint64_t ecma_bigint_two_digits_t;
#define ECMA_BIGINT_HIGH_DIGIT(digit) \
(((ecma_bigint_two_digits_t) digit) << (8 * sizeof (ecma_bigint_digit_t)))
+/**
+ * Bitwise operation types.
+ */
+typedef enum
+{
+ ECMA_BIG_UINT_BITWISE_AND, /**< bitwise 'and' operation */
+ ECMA_BIG_UINT_BITWISE_OR, /**< bitwise 'or' operation */
+ ECMA_BIG_UINT_BITWISE_XOR, /**< bitwise 'xor' operation */
+ ECMA_BIG_UINT_BITWISE_AND_NOT, /**< bitwise 'and not' operation */
+} ecma_big_uint_bitwise_operation_types_t;
+
+/**
+ * Returns with the type of the operation.
+ */
+#define ECMA_BIGINT_BITWISE_GET_OPERATION_TYPE(operation_and_options) \
+ ((operation_and_options) & 0xf)
+
+/**
+ * Options for bitwise operations.
+ */
+typedef enum
+{
+ ECMA_BIG_UINT_BITWISE_DECREASE_LEFT = (1 << 4), /**< subtract 1 from left value */
+ ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT = (1 << 5), /**< subtract 1 from right value */
+ ECMA_BIG_UINT_BITWISE_INCREASE_RESULT = (1 << 6), /**< add 1 to the result */
+} ecma_big_uint_bitwise_options_t;
+
+/**
+ * Subtract 1 from both left and right values.
+ */
+#define ECMA_BIG_UINT_BITWISE_DECREASE_BOTH \
+ (ECMA_BIG_UINT_BITWISE_DECREASE_LEFT | ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT)
+
ecma_extended_primitive_t *ecma_bigint_create (uint32_t size);
ecma_extended_primitive_t *ecma_big_uint_extend (ecma_extended_primitive_t *value_p, ecma_bigint_digit_t digit);
@@ -83,6 +116,10 @@ ecma_extended_primitive_t *ecma_big_uint_div_mod (ecma_extended_primitive_t *div
ecma_extended_primitive_t *ecma_big_uint_shift_left (ecma_extended_primitive_t *left_value_p, uint32_t right_value);
ecma_extended_primitive_t *ecma_big_uint_shift_right (ecma_extended_primitive_t *left_value_p, uint32_t right_value);
+ecma_extended_primitive_t *ecma_big_uint_bitwise_op (uint32_t operation_and_options,
+ ecma_extended_primitive_t *left_value_p,
+ ecma_extended_primitive_t *right_value_p);
+
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
#endif /* ECMA_BIG_UINT_H */
diff --git a/jerry-core/ecma/operations/ecma-bigint.c b/jerry-core/ecma/operations/ecma-bigint.c
index f9590b050..8da8be0a6 100644
--- a/jerry-core/ecma/operations/ecma-bigint.c
+++ b/jerry-core/ecma/operations/ecma-bigint.c
@@ -970,4 +970,198 @@ ecma_bigint_shift (ecma_value_t left_value, /**< left BigInt value */
result_p->u.bigint_sign_and_size |= left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN;
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
} /* ecma_bigint_shift */
+
+/**
+ * Convert the result to an ecma value
+ *
+ * @return ecma BigInt value or ECMA_VALUE_ERROR
+ * Returned value must be freed with ecma_free_value.
+ */
+static ecma_value_t
+ecma_bigint_bitwise_op (uint32_t operation_and_options, /**< bitwise operation type and options */
+ ecma_extended_primitive_t *left_value_p, /**< left BigInt value */
+ ecma_extended_primitive_t *right_value_p) /**< right BigInt value */
+{
+ ecma_extended_primitive_t *result_p;
+ result_p = ecma_big_uint_bitwise_op (operation_and_options, left_value_p, right_value_p);
+
+ if (JERRY_UNLIKELY (result_p == NULL))
+ {
+ return ecma_bigint_raise_memory_error ();
+ }
+
+ if ((operation_and_options & ECMA_BIG_UINT_BITWISE_INCREASE_RESULT)
+ && ECMA_BIGINT_GET_SIZE (result_p) > 0)
+ {
+ result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN;
+ }
+
+ return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
+} /* ecma_bigint_bitwise_op */
+
+/**
+ * Perform bitwise 'and' operations on two BigUInt numbers
+ *
+ * @return ecma BigInt value or ECMA_VALUE_ERROR
+ * Returned value must be freed with ecma_free_value.
+ */
+ecma_value_t
+ecma_bigint_and (ecma_value_t left_value, /**< left BigInt value */
+ ecma_value_t right_value) /**< right BigInt value */
+{
+ ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value);
+ ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value);
+ uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_p);
+ uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_p);
+
+ if (left_size == 0)
+ {
+ ecma_ref_extended_primitive (left_p);
+ return left_value;
+ }
+
+ if (right_size == 0)
+ {
+ ecma_ref_extended_primitive (right_p);
+ return right_value;
+ }
+
+ if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN))
+ {
+ if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN))
+ {
+ return ecma_bigint_bitwise_op (ECMA_BIG_UINT_BITWISE_AND, left_p, right_p);
+ }
+
+ /* x & (-y) == x & ~(y-1) == x &~ (y-1) */
+ uint32_t operation_and_options = ECMA_BIG_UINT_BITWISE_AND_NOT | ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT;
+ return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p);
+ }
+
+ if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN))
+ {
+ /* (-x) & y == ~(x-1) & y == y &~ (x-1) */
+ uint32_t operation_and_options = ECMA_BIG_UINT_BITWISE_AND_NOT | ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT;
+ return ecma_bigint_bitwise_op (operation_and_options, right_p, left_p);
+ }
+
+ /* (-x) & (-y) == ~(x-1) & ~(y-1) == ~((x-1) | (y-1)) == -(((x-1) | (y-1)) + 1) */
+ uint32_t operation_and_options = (ECMA_BIG_UINT_BITWISE_OR
+ | ECMA_BIG_UINT_BITWISE_DECREASE_BOTH
+ | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT);
+ return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p);
+} /* ecma_bigint_and */
+
+/**
+ * Perform bitwise 'or' operations on two BigUInt numbers
+ *
+ * @return ecma BigInt value or ECMA_VALUE_ERROR
+ * Returned value must be freed with ecma_free_value.
+ */
+ecma_value_t
+ecma_bigint_or (ecma_value_t left_value, /**< left BigInt value */
+ ecma_value_t right_value) /**< right BigInt value */
+{
+ ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value);
+ ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value);
+ uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_p);
+ uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_p);
+
+ if (left_size == 0)
+ {
+ ecma_ref_extended_primitive (right_p);
+ return right_value;
+ }
+
+ if (right_size == 0)
+ {
+ ecma_ref_extended_primitive (left_p);
+ return left_value;
+ }
+
+ if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN))
+ {
+ if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN))
+ {
+ return ecma_bigint_bitwise_op (ECMA_BIG_UINT_BITWISE_OR, left_p, right_p);
+ }
+
+ /* x | (-y) == x | ~(y-1) == ~((y-1) &~ x) == -(((y-1) &~ x) + 1) */
+ uint32_t operation_and_options = (ECMA_BIG_UINT_BITWISE_AND_NOT
+ | ECMA_BIG_UINT_BITWISE_DECREASE_LEFT
+ | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT);
+ return ecma_bigint_bitwise_op (operation_and_options, right_p, left_p);
+ }
+
+ if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN))
+ {
+ /* (-x) | y == ~(x-1) | y == ~((x-1) &~ y) == -(((x-1) &~ y) + 1) */
+ uint32_t operation_and_options = (ECMA_BIG_UINT_BITWISE_AND_NOT
+ | ECMA_BIG_UINT_BITWISE_DECREASE_LEFT
+ | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT);
+ return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p);
+ }
+
+ /* (-x) | (-y) == ~(x-1) | ~(y-1) == ~((x-1) & (y-1)) = -(((x-1) & (y-1)) + 1) */
+ uint32_t operation_and_options = (ECMA_BIG_UINT_BITWISE_AND
+ | ECMA_BIG_UINT_BITWISE_DECREASE_BOTH
+ | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT);
+ return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p);
+} /* ecma_bigint_or */
+
+/**
+ * Perform bitwise 'xor' operations on two BigUInt numbers
+ *
+ * @return ecma BigInt value or ECMA_VALUE_ERROR
+ * Returned value must be freed with ecma_free_value.
+ */
+ecma_value_t
+ecma_bigint_xor (ecma_value_t left_value, /**< left BigInt value */
+ ecma_value_t right_value) /**< right BigInt value */
+{
+ ecma_extended_primitive_t *left_p = ecma_get_extended_primitive_from_value (left_value);
+ ecma_extended_primitive_t *right_p = ecma_get_extended_primitive_from_value (right_value);
+ uint32_t left_size = ECMA_BIGINT_GET_SIZE (left_p);
+ uint32_t right_size = ECMA_BIGINT_GET_SIZE (right_p);
+
+ if (left_size == 0)
+ {
+ ecma_ref_extended_primitive (right_p);
+ return right_value;
+ }
+
+ if (right_size == 0)
+ {
+ ecma_ref_extended_primitive (left_p);
+ return left_value;
+ }
+
+ if (!(left_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN))
+ {
+ if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN))
+ {
+ return ecma_bigint_bitwise_op (ECMA_BIG_UINT_BITWISE_XOR, left_p, right_p);
+ }
+
+ /* x ^ (-y) == x ^ ~(y-1) == ~(x ^ (y-1)) == -((x ^ (y-1)) + 1) */
+ uint32_t operation_and_options = (ECMA_BIG_UINT_BITWISE_XOR
+ | ECMA_BIG_UINT_BITWISE_DECREASE_RIGHT
+ | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT);
+ return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p);
+ }
+
+ if (!(right_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN))
+ {
+ /* (-x) | y == ~(x-1) ^ y == ~((x-1) ^ y) == -(((x-1) ^ y) + 1) */
+ uint32_t operation_and_options = (ECMA_BIG_UINT_BITWISE_XOR
+ | ECMA_BIG_UINT_BITWISE_DECREASE_LEFT
+ | ECMA_BIG_UINT_BITWISE_INCREASE_RESULT);
+ return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p);
+ }
+
+ /* (-x) ^ (-y) == ~(x-1) ^ ~(y-1) == (x-1) ^ (y-1) */
+ uint32_t operation_and_options = ECMA_BIG_UINT_BITWISE_XOR | ECMA_BIG_UINT_BITWISE_DECREASE_BOTH;
+ return ecma_bigint_bitwise_op (operation_and_options, left_p, right_p);
+} /* ecma_bigint_xor */
+
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
diff --git a/jerry-core/ecma/operations/ecma-bigint.h b/jerry-core/ecma/operations/ecma-bigint.h
index f75f51380..d617f16a3 100644
--- a/jerry-core/ecma/operations/ecma-bigint.h
+++ b/jerry-core/ecma/operations/ecma-bigint.h
@@ -56,6 +56,10 @@ ecma_value_t ecma_bigint_mul (ecma_value_t left_value, ecma_value_t right_value)
ecma_value_t ecma_bigint_div_mod (ecma_value_t left_value, ecma_value_t right_value, bool is_mod);
ecma_value_t ecma_bigint_shift (ecma_value_t left_value, ecma_value_t right_value, bool is_left);
+ecma_value_t ecma_bigint_and (ecma_value_t left_value, ecma_value_t right_value);
+ecma_value_t ecma_bigint_or (ecma_value_t left_value, ecma_value_t right_value);
+ecma_value_t ecma_bigint_xor (ecma_value_t left_value, ecma_value_t right_value);
+
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
#endif /* ECMA_BIG_INT_H */
diff --git a/jerry-core/vm/opcodes-ecma-bitwise.c b/jerry-core/vm/opcodes-ecma-bitwise.c
index 233f306c6..138b2008f 100644
--- a/jerry-core/vm/opcodes-ecma-bitwise.c
+++ b/jerry-core/vm/opcodes-ecma-bitwise.c
@@ -145,6 +145,21 @@ do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic o
{
switch (op)
{
+ case NUMBER_BITWISE_LOGIC_AND:
+ {
+ ret_value = ecma_bigint_and (left_value, right_value);
+ break;
+ }
+ case NUMBER_BITWISE_LOGIC_OR:
+ {
+ ret_value = ecma_bigint_or (left_value, right_value);
+ break;
+ }
+ case NUMBER_BITWISE_LOGIC_XOR:
+ {
+ ret_value = ecma_bigint_xor (left_value, right_value);
+ break;
+ }
case NUMBER_BITWISE_SHIFT_LEFT:
{
ret_value = ecma_bigint_shift (left_value, right_value, true);
@@ -157,7 +172,7 @@ do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic o
}
default:
{
- ret_value = ecma_raise_common_error (ECMA_ERR_MSG ("Not supported BigInt operation"));
+ ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Not supported BigInt operation"));
break;
}
}
diff --git a/tests/jerry/es.next/bigint6.js b/tests/jerry/es.next/bigint6.js
new file mode 100644
index 000000000..3270c2abe
--- /dev/null
+++ b/tests/jerry/es.next/bigint6.js
@@ -0,0 +1,54 @@
+/* Copyright JS Foundation and other contributors, http://js.foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Test bitwise 'and' operation
+
+assert((0n & 0n) === 0n)
+assert((0x12345678n & 0n) === 0n)
+assert((0n & 0x12345678n) === 0n)
+assert((0xff00ff00ff00ff00ff00n & 0xff00ff00ff00ff00ffn) === 0n)
+assert((0x12345678ffffffff12345678ffffffffn & 0xffff87654321n) === 0x567887654321n)
+assert((0xf56cd2479efcdn & 0x56cdf23bc02134e3bdc56f43297be4c27n) === 0x6540004384c05n)
+assert((0x45c308bd83cf279n & -0x100000000n) === 0x45c308b00000000n)
+assert((-0x10000000000000000n & 0xffffffffffffffffn) === 0n)
+assert((-0x11234567890abcdefn & 0xffffffffffffffffffffn) === 0xfffeedcba9876f543211n)
+assert((-0x10000000000000n & -0x10000000000000n) === -0x10000000000000n)
+assert((-0x100000000000000001n & -0x1n) === -0x100000000000000001n)
+
+// Test bitwise 'or' operation
+
+assert((0n | 0n) === 0n)
+assert((0x123456789abcdefn | 0n) === 0x123456789abcdefn)
+assert((0n | 0x123456789abcdefn) === 0x123456789abcdefn)
+assert((0xaa00bb00cc00dd00ee00n | 0xff00ee00dd00cc00bbn) === 0xaaffbbeeccddddcceebbn);
+assert((0xfedcba09876543210fedcba09876543210n | 0x7n) === 0xfedcba09876543210fedcba09876543217n)
+assert((0x8n | 0xfedcba09876543210fedcba09876543210n) === 0xfedcba09876543210fedcba09876543218n)
+assert((-0xc34bd5f946c7a92b69b3a96cd7c2a12n | 0xfcbacfbn) === -0xc34bd5f946c7a92b69b3a96c0340201n)
+assert((-0xb314c297ba3n | 0xfeacb00000000n) === -0x1304c297ba3n)
+assert((-0x74b186cd308b377cb23n | -0x5cba7935b213cd657d937c42975de63802a7b92cd49an) === -0x74900280200b124c001n)
+assert((-0x10000000000000000n | -0x100000000000000000000000000000000n) === -0x10000000000000000n)
+
+// Test bitwise 'xor' operation
+
+assert((0n ^ 0n) === 0n)
+assert((0x123456789abcdefn ^ 0n) === 0x123456789abcdefn)
+assert((0n ^ 0x123456789abcdefn) === 0x123456789abcdefn)
+assert((0x74b186cd308b355cb23cd28cd75n ^ 0x74b186cd308b355cb23cd28cd75n) === 0n)
+assert((0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ffn ^ 0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0fn) === 0xff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff0n)
+assert((0x31988644a57e18n ^ 0xb2303b6f2efcb4de7761c01622440f9d985d07dbfe03c9f1n) === 0xb2303b6f2efcb4de7761c01622440f9d986c9f5dbaa6b7e9n)
+assert((-0xd858541b8eb3e6ae247b1f84dbd8cc2db66n ^ 0x0811a0e70710fcf965n) === -0xd858541b8eb3e6ae24fa058aaba9c3e2201n)
+assert((0x38d00faa3f33n ^ -0x89c40cdc4a064dcd8b3663feb322026dn) === -0x89c40cdc4a064dcd8b365b2ebc883d60n)
+assert((-0x66cb3001b88361a25b8715922n ^ -0x66cb3001b88361a25b8715922n) === 0n)
+assert((-0x893bff556397300afe6411d8727c0aaffn ^ -0xef69f24dfcd1447397d62217c6ad2n) === 0x893b103c91daccdbba17860e506bcc02fn)
diff --git a/tests/test262-esnext-excludelist.xml b/tests/test262-esnext-excludelist.xml
index 5f3a4a7b4..414fe6a0a 100644
--- a/tests/test262-esnext-excludelist.xml
+++ b/tests/test262-esnext-excludelist.xml
@@ -4259,20 +4259,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
@@ -6882,10 +6870,6 @@
-
-
-
-