Implement binary bitwise BigInt operators (#4105)

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2020-08-04 16:53:38 +02:00
committed by GitHub
parent b749c4c267
commit bdb39f1f03
7 changed files with 647 additions and 43 deletions
+342 -26
View File
@@ -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) */
@@ -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 */
+194
View File
@@ -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) */
+4
View File
@@ -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 */
+16 -1
View File
@@ -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;
}
}
+54
View File
@@ -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)
-16
View File
@@ -4259,20 +4259,8 @@
<test id="language/expressions/async-generator/yield-thenable-create-resolving-functions-reject.js"><reason></reason></test>
<test id="language/expressions/async-generator/yield-thenable-create-resolving-functions-resolve.js"><reason></reason></test>
<test id="language/expressions/await/for-await-of-interleaved.js"><reason></reason></test>
<test id="language/expressions/bitwise-and/bigint-non-primitive.js"><reason></reason></test>
<test id="language/expressions/bitwise-and/bigint-toprimitive.js"><reason></reason></test>
<test id="language/expressions/bitwise-and/bigint-wrapped-values.js"><reason></reason></test>
<test id="language/expressions/bitwise-and/bigint.js"><reason></reason></test>
<test id="language/expressions/bitwise-not/bigint-non-primitive.js"><reason></reason></test>
<test id="language/expressions/bitwise-not/bigint.js"><reason></reason></test>
<test id="language/expressions/bitwise-or/bigint-non-primitive.js"><reason></reason></test>
<test id="language/expressions/bitwise-or/bigint-toprimitive.js"><reason></reason></test>
<test id="language/expressions/bitwise-or/bigint-wrapped-values.js"><reason></reason></test>
<test id="language/expressions/bitwise-or/bigint.js"><reason></reason></test>
<test id="language/expressions/bitwise-xor/bigint-non-primitive.js"><reason></reason></test>
<test id="language/expressions/bitwise-xor/bigint-toprimitive.js"><reason></reason></test>
<test id="language/expressions/bitwise-xor/bigint-wrapped-values.js"><reason></reason></test>
<test id="language/expressions/bitwise-xor/bigint.js"><reason></reason></test>
<test id="language/expressions/call/eval-realm-indirect.js"><reason></reason></test>
<test id="language/expressions/call/eval-spread-empty-leading.js"><reason></reason></test>
<test id="language/expressions/call/eval-spread-empty-trailing.js"><reason></reason></test>
@@ -6882,10 +6870,6 @@
<test id="language/expressions/typeof/bigint.js"><reason></reason></test>
<test id="language/expressions/typeof/proxy.js"><reason></reason></test>
<test id="language/expressions/unary-plus/bigint-throws.js"><reason></reason></test>
<test id="language/expressions/unsigned-right-shift/bigint-non-primitive.js"><reason></reason></test>
<test id="language/expressions/unsigned-right-shift/bigint-toprimitive.js"><reason></reason></test>
<test id="language/expressions/unsigned-right-shift/bigint-wrapped-values.js"><reason></reason></test>
<test id="language/expressions/unsigned-right-shift/bigint.js"><reason></reason></test>
<test id="language/expressions/yield/star-return-is-null.js"><reason></reason></test>
<test id="language/expressions/yield/star-rhs-iter-rtrn-no-rtrn.js"><reason></reason></test>
<test id="language/expressions/yield/star-throw-is-null.js"><reason></reason></test>