Implement unary operators: bitwise not, pre/post increment/decrement (#4116)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -373,6 +373,138 @@ ecma_big_uint_to_string (ecma_extended_primitive_t *value_p, /**< BigUInt value
|
||||
return result_p;
|
||||
} /* ecma_big_uint_to_string */
|
||||
|
||||
/**
|
||||
* Increase the value of a BigUInt value by 1
|
||||
*
|
||||
* return new BigInt value, NULL on error
|
||||
*/
|
||||
ecma_extended_primitive_t *
|
||||
ecma_big_uint_increase (ecma_extended_primitive_t *value_p) /**< BigUInt value */
|
||||
{
|
||||
uint32_t size = ECMA_BIGINT_GET_SIZE (value_p);
|
||||
|
||||
JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0);
|
||||
|
||||
ecma_bigint_digit_t *digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0);
|
||||
ecma_bigint_digit_t *digits_end_p = ECMA_BIGINT_GET_DIGITS (value_p, size);
|
||||
|
||||
if (JERRY_UNLIKELY (digits_p[0] == ~((ecma_bigint_digit_t) 0) && digits_end_p[-1] == ~((ecma_bigint_digit_t) 0)))
|
||||
{
|
||||
do
|
||||
{
|
||||
digits_p++;
|
||||
}
|
||||
while (digits_p < digits_end_p && digits_p[0] == ~((ecma_bigint_digit_t) 0));
|
||||
|
||||
if (digits_p == digits_end_p)
|
||||
{
|
||||
ecma_extended_primitive_t *result_value_p;
|
||||
result_value_p = ecma_bigint_create ((uint32_t) (size + sizeof (ecma_bigint_digit_t)));
|
||||
|
||||
if (JERRY_UNLIKELY (result_value_p == NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset (ECMA_BIGINT_GET_DIGITS (result_value_p, 0), 0, size);
|
||||
*ECMA_BIGINT_GET_DIGITS (result_value_p, size) = 1;
|
||||
return result_value_p;
|
||||
}
|
||||
|
||||
digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0);
|
||||
}
|
||||
|
||||
ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size);
|
||||
|
||||
if (JERRY_UNLIKELY (result_value_p == NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0);
|
||||
|
||||
while (digits_p[0] == ~((ecma_bigint_digit_t) 0))
|
||||
{
|
||||
digits_p++;
|
||||
*result_p++ = 0;
|
||||
}
|
||||
|
||||
*result_p++ = (*digits_p++) + 1;
|
||||
|
||||
if (digits_p < digits_end_p)
|
||||
{
|
||||
memcpy (result_p, digits_p, (size_t) ((uint8_t *) digits_end_p - (uint8_t *) digits_p));
|
||||
}
|
||||
return result_value_p;
|
||||
} /* ecma_big_uint_increase */
|
||||
|
||||
/**
|
||||
* Decrease the value of a BigUInt value by 1
|
||||
*
|
||||
* return new BigInt value, NULL on error
|
||||
*/
|
||||
ecma_extended_primitive_t *
|
||||
ecma_big_uint_decrease (ecma_extended_primitive_t *value_p) /**< BigUInt value */
|
||||
{
|
||||
uint32_t size = ECMA_BIGINT_GET_SIZE (value_p);
|
||||
|
||||
JERRY_ASSERT (size > 0 && ECMA_BIGINT_GET_LAST_DIGIT (value_p, size) != 0);
|
||||
|
||||
ecma_bigint_digit_t *digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0);
|
||||
ecma_bigint_digit_t *digits_end_p = ECMA_BIGINT_GET_DIGITS (value_p, size);
|
||||
|
||||
JERRY_ASSERT (size > sizeof (ecma_bigint_digit_t) || *digits_p > 1);
|
||||
|
||||
if (JERRY_UNLIKELY (digits_p[0] == 0 && digits_end_p[-1] == 1))
|
||||
{
|
||||
do
|
||||
{
|
||||
digits_p++;
|
||||
JERRY_ASSERT (digits_p < digits_end_p);
|
||||
}
|
||||
while (digits_p[0] == 0);
|
||||
|
||||
if (digits_p + 1 == digits_end_p)
|
||||
{
|
||||
size -= (uint32_t) sizeof (ecma_bigint_digit_t);
|
||||
ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size);
|
||||
|
||||
if (JERRY_UNLIKELY (result_value_p == NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset (ECMA_BIGINT_GET_DIGITS (result_value_p, 0), 0xff, size);
|
||||
return result_value_p;
|
||||
}
|
||||
|
||||
digits_p = ECMA_BIGINT_GET_DIGITS (value_p, 0);
|
||||
}
|
||||
|
||||
ecma_extended_primitive_t *result_value_p = ecma_bigint_create (size);
|
||||
|
||||
if (JERRY_UNLIKELY (result_value_p == NULL))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ecma_bigint_digit_t *result_p = ECMA_BIGINT_GET_DIGITS (result_value_p, 0);
|
||||
|
||||
while (digits_p[0] == 0)
|
||||
{
|
||||
digits_p++;
|
||||
*result_p++ = ~((ecma_bigint_digit_t) 0);
|
||||
}
|
||||
|
||||
*result_p++ = (*digits_p++) - 1;
|
||||
|
||||
if (digits_p < digits_end_p)
|
||||
{
|
||||
memcpy (result_p, digits_p, (size_t) ((uint8_t *) digits_end_p - (uint8_t *) digits_p));
|
||||
}
|
||||
return result_value_p;
|
||||
} /* ecma_big_uint_decrease */
|
||||
|
||||
/**
|
||||
* Add right BigUInt value to the left BigUInt value
|
||||
*
|
||||
|
||||
@@ -103,6 +103,9 @@ ecma_extended_primitive_t *ecma_big_uint_mul_digit (ecma_extended_primitive_t *v
|
||||
uint8_t *ecma_big_uint_to_string (ecma_extended_primitive_t *value_p, uint32_t radix,
|
||||
uint32_t *char_start_p, uint32_t *char_size_p);
|
||||
|
||||
ecma_extended_primitive_t *ecma_big_uint_increase (ecma_extended_primitive_t *value_p);
|
||||
ecma_extended_primitive_t *ecma_big_uint_decrease (ecma_extended_primitive_t *value_p);
|
||||
|
||||
ecma_extended_primitive_t *ecma_big_uint_add (ecma_extended_primitive_t *left_value_p,
|
||||
ecma_extended_primitive_t *right_value_p);
|
||||
ecma_extended_primitive_t *ecma_big_uint_sub (ecma_extended_primitive_t *left_value_p,
|
||||
|
||||
@@ -34,6 +34,34 @@ ecma_bigint_raise_memory_error (void)
|
||||
return ecma_raise_range_error (ECMA_ERR_MSG ("Cannot allocate memory for a BigInt value"));
|
||||
} /* ecma_bigint_raise_memory_error */
|
||||
|
||||
/**
|
||||
* Create a single digit long BigInt value
|
||||
*
|
||||
* @return ecma BigInt value or ECMA_VALUE_ERROR
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
static ecma_value_t
|
||||
ecma_bigint_create_from_digit (ecma_bigint_digit_t digit, /* single digit */
|
||||
bool sign) /* set ECMA_BIGINT_SIGN if true */
|
||||
{
|
||||
JERRY_ASSERT (digit != 0);
|
||||
|
||||
ecma_extended_primitive_t *result_value_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t));
|
||||
|
||||
if (JERRY_UNLIKELY (result_value_p == NULL))
|
||||
{
|
||||
return ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
|
||||
if (sign)
|
||||
{
|
||||
result_value_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN;
|
||||
}
|
||||
|
||||
*ECMA_BIGINT_GET_DIGITS (result_value_p, 0) = digit;
|
||||
return ecma_make_extended_primitive_value (result_value_p, ECMA_TYPE_BIGINT);
|
||||
} /* ecma_bigint_create_from_digit */
|
||||
|
||||
/**
|
||||
* Parse a string and create a BigInt value
|
||||
*
|
||||
@@ -443,17 +471,7 @@ ecma_bigint_to_bigint (ecma_value_t value, /**< any value */
|
||||
}
|
||||
else if (ecma_is_value_true (value))
|
||||
{
|
||||
ecma_extended_primitive_t *result_p = ecma_bigint_create (sizeof (ecma_bigint_digit_t));
|
||||
|
||||
if (result_p != NULL)
|
||||
{
|
||||
*ECMA_BIGINT_GET_DIGITS (result_p, 0) = 1;
|
||||
result = ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
result = ecma_bigint_create_from_digit (1, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -911,6 +929,62 @@ ecma_bigint_negate (ecma_extended_primitive_t *value_p) /**< BigInt value */
|
||||
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
} /* ecma_bigint_negate */
|
||||
|
||||
/**
|
||||
* Invert all bits of a BigInt value
|
||||
*
|
||||
* @return ecma BigInt value or ECMA_VALUE_ERROR
|
||||
* Returned value must be freed with ecma_free_value.
|
||||
*/
|
||||
ecma_value_t
|
||||
ecma_bigint_unary (ecma_value_t value, /**< BigInt value */
|
||||
ecma_bigint_unary_operation_type type) /**< type of unary operation */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_bigint (value));
|
||||
|
||||
if (value == ECMA_BIGINT_ZERO)
|
||||
{
|
||||
return ecma_bigint_create_from_digit (1, type != ECMA_BIGINT_UNARY_INCREASE);
|
||||
}
|
||||
|
||||
ecma_extended_primitive_t *value_p = ecma_get_extended_primitive_from_value (value);
|
||||
|
||||
uint32_t sign = (type != ECMA_BIGINT_UNARY_DECREASE) ? ECMA_BIGINT_SIGN : 0;
|
||||
|
||||
if ((value_p->u.bigint_sign_and_size == (uint32_t) (sizeof (ecma_bigint_digit_t) | sign))
|
||||
&& *ECMA_BIGINT_GET_DIGITS (value_p, 0) == 1)
|
||||
{
|
||||
return ECMA_BIGINT_ZERO;
|
||||
}
|
||||
|
||||
ecma_extended_primitive_t *result_p;
|
||||
|
||||
if ((value_p->u.bigint_sign_and_size & ECMA_BIGINT_SIGN) == (sign ^ ECMA_BIGINT_SIGN))
|
||||
{
|
||||
result_p = ecma_big_uint_increase (value_p);
|
||||
|
||||
if (type != ECMA_BIGINT_UNARY_INCREASE && result_p != NULL)
|
||||
{
|
||||
result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result_p = ecma_big_uint_decrease (value_p);
|
||||
|
||||
if (type == ECMA_BIGINT_UNARY_INCREASE && result_p != NULL)
|
||||
{
|
||||
result_p->u.bigint_sign_and_size |= ECMA_BIGINT_SIGN;
|
||||
}
|
||||
}
|
||||
|
||||
if (JERRY_UNLIKELY (result_p == NULL))
|
||||
{
|
||||
return ecma_bigint_raise_memory_error ();
|
||||
}
|
||||
|
||||
return ecma_make_extended_primitive_value (result_p, ECMA_TYPE_BIGINT);
|
||||
} /* ecma_bigint_unary */
|
||||
|
||||
/**
|
||||
* Add/subtract right BigInt value to/from left BigInt value
|
||||
*
|
||||
|
||||
@@ -38,6 +38,16 @@ typedef enum
|
||||
* return with ECMA_VALUE_NULL instead */
|
||||
} ecma_bigint_parse_string_options_t;
|
||||
|
||||
/**
|
||||
* Types for unary operations
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_BIGINT_UNARY_BITWISE_NOT, /**< bitwise not operation */
|
||||
ECMA_BIGINT_UNARY_INCREASE, /**< increase operation */
|
||||
ECMA_BIGINT_UNARY_DECREASE, /**< decrease operation */
|
||||
} ecma_bigint_unary_operation_type;
|
||||
|
||||
ecma_value_t ecma_bigint_parse_string (const lit_utf8_byte_t *string_p, lit_utf8_size_t size,
|
||||
uint32_t options);
|
||||
ecma_value_t ecma_bigint_parse_string_value (ecma_value_t string, uint32_t options);
|
||||
@@ -54,6 +64,7 @@ int ecma_bigint_compare_to_bigint (ecma_value_t left_value, ecma_value_t right_v
|
||||
int ecma_bigint_compare_to_number (ecma_value_t left_value, ecma_number_t right_value);
|
||||
|
||||
ecma_value_t ecma_bigint_negate (ecma_extended_primitive_t *value_p);
|
||||
ecma_value_t ecma_bigint_unary (ecma_value_t value, ecma_bigint_unary_operation_type type);
|
||||
ecma_value_t ecma_bigint_add_sub (ecma_value_t left_value, ecma_value_t right_value, bool is_add);
|
||||
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);
|
||||
|
||||
@@ -30,7 +30,7 @@ extern "C"
|
||||
/**
|
||||
* Jerry snapshot format version.
|
||||
*/
|
||||
#define JERRY_SNAPSHOT_VERSION (55u)
|
||||
#define JERRY_SNAPSHOT_VERSION (56u)
|
||||
|
||||
/**
|
||||
* Flags for jerry_generate_snapshot and jerry_generate_function_snapshot.
|
||||
|
||||
@@ -1074,32 +1074,60 @@ parser_post_processing (parser_context_t *context_p) /**< context */
|
||||
flags = cbc_flags[last_opcode];
|
||||
length++;
|
||||
|
||||
if (last_opcode == CBC_EXT_OPCODE)
|
||||
switch (last_opcode)
|
||||
{
|
||||
cbc_ext_opcode_t ext_opcode;
|
||||
case CBC_EXT_OPCODE:
|
||||
{
|
||||
cbc_ext_opcode_t ext_opcode;
|
||||
|
||||
ext_opcode = (cbc_ext_opcode_t) page_p->bytes[offset];
|
||||
branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (ext_opcode);
|
||||
flags = cbc_ext_flags[ext_opcode];
|
||||
PARSER_NEXT_BYTE (page_p, offset);
|
||||
length++;
|
||||
ext_opcode = (cbc_ext_opcode_t) page_p->bytes[offset];
|
||||
branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (ext_opcode);
|
||||
flags = cbc_ext_flags[ext_opcode];
|
||||
PARSER_NEXT_BYTE (page_p, offset);
|
||||
length++;
|
||||
|
||||
#if ENABLED (JERRY_LINE_INFO)
|
||||
if (ext_opcode == CBC_EXT_LINE)
|
||||
{
|
||||
uint8_t last_byte = 0;
|
||||
|
||||
do
|
||||
if (ext_opcode == CBC_EXT_LINE)
|
||||
{
|
||||
last_byte = page_p->bytes[offset];
|
||||
PARSER_NEXT_BYTE (page_p, offset);
|
||||
length++;
|
||||
}
|
||||
while (last_byte & CBC_HIGHEST_BIT_MASK);
|
||||
uint8_t last_byte = 0;
|
||||
|
||||
continue;
|
||||
}
|
||||
do
|
||||
{
|
||||
last_byte = page_p->bytes[offset];
|
||||
PARSER_NEXT_BYTE (page_p, offset);
|
||||
length++;
|
||||
}
|
||||
while (last_byte & CBC_HIGHEST_BIT_MASK);
|
||||
|
||||
continue;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_LINE_INFO) */
|
||||
break;
|
||||
}
|
||||
case CBC_POST_DECR:
|
||||
{
|
||||
*opcode_p = CBC_PRE_DECR;
|
||||
break;
|
||||
}
|
||||
case CBC_POST_INCR:
|
||||
{
|
||||
*opcode_p = CBC_PRE_INCR;
|
||||
break;
|
||||
}
|
||||
case CBC_POST_DECR_IDENT:
|
||||
{
|
||||
*opcode_p = CBC_PRE_DECR_IDENT;
|
||||
break;
|
||||
}
|
||||
case CBC_POST_INCR_IDENT:
|
||||
{
|
||||
*opcode_p = CBC_PRE_INCR_IDENT;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2))
|
||||
|
||||
@@ -97,17 +97,14 @@ do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic o
|
||||
result = (ecma_number_t) (ecma_number_to_int32 (left_number) >> (right_uint32 & 0x1F));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_SHIFT_URIGHT:
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (op == NUMBER_BITWISE_SHIFT_URIGHT);
|
||||
|
||||
uint32_t left_uint32 = ecma_number_to_uint32 (left_number);
|
||||
result = (ecma_number_t) (left_uint32 >> (right_uint32 & 0x1F));
|
||||
break;
|
||||
}
|
||||
case NUMBER_BITWISE_NOT:
|
||||
{
|
||||
result = (ecma_number_t) ((int32_t) ~right_uint32);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret_value = ecma_make_number_value (result);
|
||||
@@ -155,7 +152,9 @@ do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic o
|
||||
}
|
||||
default:
|
||||
{
|
||||
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Not supported BigInt operation"));
|
||||
JERRY_ASSERT (op == NUMBER_BITWISE_SHIFT_URIGHT);
|
||||
|
||||
ret_value = ecma_raise_type_error (ECMA_ERR_MSG ("Unsigned right shift is not allowed for BigInts"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -171,6 +170,39 @@ do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic o
|
||||
return ret_value;
|
||||
} /* do_number_bitwise_logic */
|
||||
|
||||
/**
|
||||
* Perform ECMA number bitwise not operation.
|
||||
*
|
||||
* @return ecma value
|
||||
* Returned value must be freed with ecma_free_value
|
||||
*/
|
||||
ecma_value_t
|
||||
do_number_bitwise_not (ecma_value_t value) /**< value */
|
||||
{
|
||||
JERRY_ASSERT (!ECMA_IS_VALUE_ERROR (value));
|
||||
|
||||
ecma_number_t number;
|
||||
value = ecma_op_to_numeric (value, &number, ECMA_TO_NUMERIC_ALLOW_BIGINT);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
if (JERRY_LIKELY (!ecma_is_value_bigint (value)))
|
||||
{
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
return ecma_make_number_value ((ecma_number_t) ((int32_t) ~ecma_number_to_uint32 (number)));
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ecma_bigint_unary (value, ECMA_BIGINT_UNARY_BITWISE_NOT);
|
||||
ecma_free_value (value);
|
||||
return ret_value;
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
} /* do_number_bitwise_not */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -51,7 +51,6 @@ typedef enum
|
||||
NUMBER_BITWISE_SHIFT_LEFT, /**< bitwise LEFT SHIFT calculation */
|
||||
NUMBER_BITWISE_SHIFT_RIGHT, /**< bitwise RIGHT_SHIFT calculation */
|
||||
NUMBER_BITWISE_SHIFT_URIGHT, /**< bitwise UNSIGNED RIGHT SHIFT calculation */
|
||||
NUMBER_BITWISE_NOT, /**< bitwise NOT calculation */
|
||||
} number_bitwise_logic_op;
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
@@ -90,6 +89,9 @@ opfunc_unary_operation (ecma_value_t left_value, bool is_plus);
|
||||
ecma_value_t
|
||||
do_number_bitwise_logic (number_bitwise_logic_op op, ecma_value_t left_value, ecma_value_t right_value);
|
||||
|
||||
ecma_value_t
|
||||
do_number_bitwise_not (ecma_value_t value);
|
||||
|
||||
ecma_value_t
|
||||
opfunc_addition (ecma_value_t left_value, ecma_value_t right_value);
|
||||
|
||||
|
||||
+83
-65
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-array-object.h"
|
||||
#include "ecma-bigint.h"
|
||||
#include "ecma-builtins.h"
|
||||
#include "ecma-builtin-object.h"
|
||||
#include "ecma-comparison.h"
|
||||
@@ -952,6 +953,41 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/**
|
||||
* Store the original value for post increase/decrease operators
|
||||
*
|
||||
* @param value original value
|
||||
*/
|
||||
#define POST_INCREASE_DECREASE_PUT_RESULT(value) \
|
||||
if (opcode_data & VM_OC_PUT_STACK) \
|
||||
{ \
|
||||
if (opcode_flags & VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG) \
|
||||
{ \
|
||||
JERRY_ASSERT (opcode == CBC_POST_INCR_IDENT_PUSH_RESULT \
|
||||
|| opcode == CBC_POST_DECR_IDENT_PUSH_RESULT); \
|
||||
*stack_top_p++ = (value); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* The parser ensures there is enough space for the \
|
||||
* extra value on the stack. See js-parser-expr.c. */ \
|
||||
JERRY_ASSERT (opcode == CBC_POST_INCR_PUSH_RESULT \
|
||||
|| opcode == CBC_POST_DECR_PUSH_RESULT); \
|
||||
stack_top_p++; \
|
||||
stack_top_p[-1] = stack_top_p[-2]; \
|
||||
stack_top_p[-2] = stack_top_p[-3]; \
|
||||
stack_top_p[-3] = (value); \
|
||||
} \
|
||||
opcode_data &= (uint32_t) ~VM_OC_PUT_STACK; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
JERRY_ASSERT (opcode_data & VM_OC_PUT_BLOCK); \
|
||||
ecma_free_value (frame_ctx_p->block_result); \
|
||||
frame_ctx_p->block_result = (value); \
|
||||
opcode_data &= (uint32_t) ~VM_OC_PUT_BLOCK; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Run generic byte code.
|
||||
*
|
||||
@@ -2597,6 +2633,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
case VM_OC_POST_DECR:
|
||||
{
|
||||
uint32_t opcode_flags = VM_OC_GROUP_GET_INDEX (opcode_data) - VM_OC_PROP_PRE_INCR;
|
||||
ecma_number_t result_number;
|
||||
|
||||
byte_code_p = byte_code_start_p + 1;
|
||||
|
||||
@@ -2625,59 +2662,68 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
/* Postfix operators require the unmodifed number value. */
|
||||
if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG)
|
||||
{
|
||||
if (opcode_data & VM_OC_PUT_STACK)
|
||||
{
|
||||
if (opcode_flags & VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG)
|
||||
{
|
||||
JERRY_ASSERT (opcode == CBC_POST_INCR_IDENT_PUSH_RESULT
|
||||
|| opcode == CBC_POST_DECR_IDENT_PUSH_RESULT);
|
||||
|
||||
*stack_top_p++ = result;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The parser ensures there is enough space for the
|
||||
* extra value on the stack. See js-parser-expr.c. */
|
||||
|
||||
JERRY_ASSERT (opcode == CBC_POST_INCR_PUSH_RESULT
|
||||
|| opcode == CBC_POST_DECR_PUSH_RESULT);
|
||||
|
||||
stack_top_p++;
|
||||
stack_top_p[-1] = stack_top_p[-2];
|
||||
stack_top_p[-2] = stack_top_p[-3];
|
||||
stack_top_p[-3] = result;
|
||||
}
|
||||
opcode_data &= (uint32_t) ~VM_OC_PUT_STACK;
|
||||
}
|
||||
else if (opcode_data & VM_OC_PUT_BLOCK)
|
||||
{
|
||||
ecma_free_value (frame_ctx_p->block_result);
|
||||
frame_ctx_p->block_result = result;
|
||||
opcode_data &= (uint32_t) ~VM_OC_PUT_BLOCK;
|
||||
}
|
||||
POST_INCREASE_DECREASE_PUT_RESULT (result);
|
||||
}
|
||||
|
||||
result = (ecma_value_t) (int_value + int_increase);
|
||||
break;
|
||||
}
|
||||
result_number = ecma_get_integer_from_value (result);
|
||||
}
|
||||
else if (ecma_is_value_float_number (left_value))
|
||||
{
|
||||
result = left_value;
|
||||
left_value = ECMA_VALUE_UNDEFINED;
|
||||
result_number = ecma_get_number_from_value (result);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ecma_op_to_number (left_value);
|
||||
result = ecma_op_to_numeric (left_value, &result_number, ECMA_TO_NUMERIC_ALLOW_BIGINT);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
ecma_free_value (left_value);
|
||||
left_value = ECMA_VALUE_UNDEFINED;
|
||||
|
||||
#if ENABLED (JERRY_BUILTIN_BIGINT)
|
||||
if (JERRY_UNLIKELY (ecma_is_value_bigint (result)))
|
||||
{
|
||||
ecma_bigint_unary_operation_type operation_type = ECMA_BIGINT_UNARY_INCREASE;
|
||||
|
||||
if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG)
|
||||
{
|
||||
operation_type = ECMA_BIGINT_UNARY_DECREASE;
|
||||
}
|
||||
|
||||
/* Postfix operators require the unmodifed number value. */
|
||||
if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG)
|
||||
{
|
||||
POST_INCREASE_DECREASE_PUT_RESULT (result);
|
||||
|
||||
result = ecma_bigint_unary (result, operation_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_value_t original_value = result;
|
||||
result = ecma_bigint_unary (original_value, operation_type);
|
||||
ecma_free_value (original_value);
|
||||
}
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_BUILTIN_BIGINT) */
|
||||
|
||||
result = ecma_make_number_value (result_number);
|
||||
}
|
||||
|
||||
ecma_number_t increase = ECMA_NUMBER_ONE;
|
||||
ecma_number_t result_number = ecma_get_number_from_value (result);
|
||||
|
||||
if (opcode_flags & VM_OC_DECREMENT_OPERATOR_FLAG)
|
||||
{
|
||||
@@ -2685,39 +2731,13 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
increase = ECMA_NUMBER_MINUS_ONE;
|
||||
}
|
||||
|
||||
/* Post operators require the unmodifed number value. */
|
||||
/* Postfix operators require the unmodifed number value. */
|
||||
if (opcode_flags & VM_OC_POST_INCR_DECR_OPERATOR_FLAG)
|
||||
{
|
||||
if (opcode_data & VM_OC_PUT_STACK)
|
||||
{
|
||||
if (opcode_flags & VM_OC_IDENT_INCR_DECR_OPERATOR_FLAG)
|
||||
{
|
||||
JERRY_ASSERT (opcode == CBC_POST_INCR_IDENT_PUSH_RESULT
|
||||
|| opcode == CBC_POST_DECR_IDENT_PUSH_RESULT);
|
||||
POST_INCREASE_DECREASE_PUT_RESULT (result);
|
||||
|
||||
*stack_top_p++ = ecma_copy_value (result);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The parser ensures there is enough space for the
|
||||
* extra value on the stack. See js-parser-expr.c. */
|
||||
|
||||
JERRY_ASSERT (opcode == CBC_POST_INCR_PUSH_RESULT
|
||||
|| opcode == CBC_POST_DECR_PUSH_RESULT);
|
||||
|
||||
stack_top_p++;
|
||||
stack_top_p[-1] = stack_top_p[-2];
|
||||
stack_top_p[-2] = stack_top_p[-3];
|
||||
stack_top_p[-3] = ecma_copy_value (result);
|
||||
}
|
||||
opcode_data &= (uint32_t) ~VM_OC_PUT_STACK;
|
||||
}
|
||||
else if (opcode_data & VM_OC_PUT_BLOCK)
|
||||
{
|
||||
ecma_free_value (frame_ctx_p->block_result);
|
||||
frame_ctx_p->block_result = ecma_copy_value (result);
|
||||
opcode_data &= (uint32_t) ~VM_OC_PUT_BLOCK;
|
||||
}
|
||||
result = ecma_make_number_value (result_number + increase);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ecma_is_value_integer_number (result))
|
||||
@@ -2975,9 +2995,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
goto free_left_value;
|
||||
}
|
||||
|
||||
result = do_number_bitwise_logic (NUMBER_BITWISE_NOT,
|
||||
left_value,
|
||||
left_value);
|
||||
result = do_number_bitwise_not (left_value);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
// Bitwise not
|
||||
|
||||
assert(~BigInt("0") === -1n)
|
||||
assert(~BigInt("-1") === 0n)
|
||||
|
||||
assert(~BigInt("0xffffffff") === -0x100000000n)
|
||||
assert(~BigInt("0x100000000") === -0x100000001n)
|
||||
assert(~BigInt("0x10000ffff") === -0x100010000n)
|
||||
assert(~(-BigInt("0xffffffff")) === 0xfffffffen)
|
||||
assert(~(-BigInt("0x100000000")) === 0xffffffffn)
|
||||
assert(~(-BigInt("0x10000ffff")) === 0x10000fffen)
|
||||
|
||||
assert(~BigInt("0xffffffffffffffff") === -0x10000000000000000n)
|
||||
assert(~BigInt("0xffffffffffffffffffffffffffffffff") === -0x100000000000000000000000000000000n)
|
||||
assert(~BigInt("0x100000000000000000000000000000000") === -0x100000000000000000000000000000001n)
|
||||
assert(~BigInt("0x100000000000000ffffffffffffffffff") === -0x100000000000001000000000000000000n)
|
||||
assert(~(-BigInt("0xffffffffffffffff")) === 0xfffffffffffffffen)
|
||||
assert(~(-BigInt("0xffffffffffffffffffffffffffffffff")) === 0xfffffffffffffffffffffffffffffffen)
|
||||
assert(~(-BigInt("0x100000000000000000000000000000000")) === 0xffffffffffffffffffffffffffffffffn)
|
||||
assert(~(-BigInt("0xffffffffffffff000000000000000000")) === 0xfffffffffffffeffffffffffffffffffn)
|
||||
|
||||
// Increase
|
||||
|
||||
var a = 0n
|
||||
assert(++a === 1n)
|
||||
assert(a === 1n)
|
||||
|
||||
a = -1n
|
||||
assert(++a === 0n)
|
||||
assert(a === 0n)
|
||||
|
||||
a = 1n
|
||||
assert(++a === 2n)
|
||||
assert(a === 2n)
|
||||
|
||||
a = 0xffffffffn
|
||||
assert(++a === 0x100000000n)
|
||||
assert(a === 0x100000000n)
|
||||
|
||||
a = { b:0xffffffffffffffffn }
|
||||
assert(++a.b === 0x10000000000000000n)
|
||||
assert(a.b === 0x10000000000000000n)
|
||||
|
||||
a = 0xffffffffffffffffffffffffffffffffn
|
||||
assert(a++ === 0xffffffffffffffffffffffffffffffffn)
|
||||
assert(a === 0x100000000000000000000000000000000n)
|
||||
|
||||
a = { b:0x100000000000000ffffffffffffffffffn }
|
||||
assert(a.b++ === 0x100000000000000ffffffffffffffffffn)
|
||||
assert(a.b === 0x100000000000001000000000000000000n)
|
||||
|
||||
a = -0x10000000000000001n;
|
||||
for (var i = 0; i < 1; i++, a++) ;
|
||||
assert(a === -0x10000000000000000n)
|
||||
|
||||
a = { b:-0x100000000000001000000000000000000n }
|
||||
for (var i = 0; i < 1; i++, ++a.b) ;
|
||||
assert(a.b === -0x100000000000000ffffffffffffffffffn)
|
||||
|
||||
// Decrease
|
||||
|
||||
a = 0n
|
||||
assert(--a === -1n)
|
||||
assert(a === -1n)
|
||||
|
||||
a = 1n
|
||||
assert(--a === 0n)
|
||||
assert(a === 0n)
|
||||
|
||||
a = -1n
|
||||
assert(--a === -2n)
|
||||
assert(a === -2n)
|
||||
|
||||
a = 0x100000000n
|
||||
assert(--a === 0xffffffffn)
|
||||
assert(a === 0xffffffffn)
|
||||
|
||||
a = -0xffffffffffffffffn
|
||||
assert(a-- === -0xffffffffffffffffn)
|
||||
assert(a === -0x10000000000000000n)
|
||||
|
||||
a = { b:0x10000000000000000n }
|
||||
assert(--a.b === 0xffffffffffffffffn)
|
||||
assert(a.b === 0xffffffffffffffffn)
|
||||
|
||||
a = 0x100000000000000000000000000000000n
|
||||
assert(a-- === 0x100000000000000000000000000000000n)
|
||||
assert(a === 0xffffffffffffffffffffffffffffffffn)
|
||||
|
||||
a = { b:0x100000000000001000000000000000000n }
|
||||
assert(a.b-- === 0x100000000000001000000000000000000n)
|
||||
assert(a.b === 0x100000000000000ffffffffffffffffffn)
|
||||
|
||||
a = 0x10000000000000001n;
|
||||
for (var i = 0; i < 1; i++, a--) ;
|
||||
assert(a === 0x10000000000000000n)
|
||||
|
||||
a = { b:-0x100000000000000ffffffffffffffffffn }
|
||||
for (var i = 0; i < 1; i++, --a.b) ;
|
||||
assert(a.b === -0x100000000000001000000000000000000n)
|
||||
@@ -4202,8 +4202,6 @@
|
||||
<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-not/bigint-non-primitive.js"><reason></reason></test>
|
||||
<test id="language/expressions/bitwise-not/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>
|
||||
@@ -6761,28 +6759,24 @@
|
||||
<test id="language/expressions/postfix-decrement/S11.3.2_A5_T4.js"><reason></reason></test>
|
||||
<test id="language/expressions/postfix-decrement/S11.3.2_A5_T5.js"><reason></reason></test>
|
||||
<test id="language/expressions/postfix-decrement/S11.3.2_A6_T3.js"><reason></reason></test>
|
||||
<test id="language/expressions/postfix-decrement/bigint.js"><reason></reason></test>
|
||||
<test id="language/expressions/postfix-increment/S11.3.1_A5_T1.js"><reason></reason></test>
|
||||
<test id="language/expressions/postfix-increment/S11.3.1_A5_T2.js"><reason></reason></test>
|
||||
<test id="language/expressions/postfix-increment/S11.3.1_A5_T3.js"><reason></reason></test>
|
||||
<test id="language/expressions/postfix-increment/S11.3.1_A5_T4.js"><reason></reason></test>
|
||||
<test id="language/expressions/postfix-increment/S11.3.1_A5_T5.js"><reason></reason></test>
|
||||
<test id="language/expressions/postfix-increment/S11.3.1_A6_T3.js"><reason></reason></test>
|
||||
<test id="language/expressions/postfix-increment/bigint.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-decrement/S11.4.5_A5_T1.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-decrement/S11.4.5_A5_T2.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-decrement/S11.4.5_A5_T3.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-decrement/S11.4.5_A5_T4.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-decrement/S11.4.5_A5_T5.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-decrement/S11.4.5_A6_T3.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-decrement/bigint.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-increment/S11.4.4_A5_T1.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-increment/S11.4.4_A5_T2.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-increment/S11.4.4_A5_T3.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-increment/S11.4.4_A5_T4.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-increment/S11.4.4_A5_T5.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-increment/S11.4.4_A6_T3.js"><reason></reason></test>
|
||||
<test id="language/expressions/prefix-increment/bigint.js"><reason></reason></test>
|
||||
<test id="language/expressions/right-shift/bigint.js"><reason></reason></test>
|
||||
<test id="language/expressions/strict-does-not-equals/bigint-and-number-extremes.js"><reason></reason></test>
|
||||
<test id="language/expressions/strict-equals/bigint-and-number-extremes.js"><reason></reason></test>
|
||||
|
||||
Reference in New Issue
Block a user