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:
Zoltan Herczeg
2020-08-10 22:38:34 +02:00
committed by GitHub
parent 43a82cddb9
commit 39fe04814e
11 changed files with 519 additions and 110 deletions
+39 -7
View File
@@ -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 */
/**
* @}
* @}
+3 -1
View File
@@ -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
View File
@@ -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))
{