Integer acceleration for basic arithmetic and comparison.
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
@@ -163,6 +163,15 @@ typedef int32_t ecma_integer_value_t;
|
||||
#define ECMA_IS_INTEGER_NUMBER(num) \
|
||||
(ECMA_INTEGER_NUMBER_MIN <= (num) && (num) <= ECMA_INTEGER_NUMBER_MAX)
|
||||
|
||||
/**
|
||||
* Maximum integer number, which if squared, still fits in ecma_integer_value_t
|
||||
*/
|
||||
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
|
||||
#define ECMA_INTEGER_MULTIPLY_MAX 0xb50
|
||||
#else /* CONFIG_ECMA_NUMBER_TYPE != CONFIG_ECMA_NUMBER_FLOAT32 */
|
||||
#define ECMA_INTEGER_MULTIPLY_MAX 0x2d41
|
||||
#endif /* CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32 */
|
||||
|
||||
/**
|
||||
* Internal properties' identifiers.
|
||||
*/
|
||||
|
||||
@@ -218,6 +218,22 @@ ecma_is_value_integer_number (ecma_value_t value) /**< ecma value */
|
||||
return (value & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_INTEGER_VALUE;
|
||||
} /* ecma_is_value_integer_number */
|
||||
|
||||
/**
|
||||
* Check if both values are integer ecma-numbers.
|
||||
*
|
||||
* @return true - if both values contain integer ecma-number values,
|
||||
* false - otherwise.
|
||||
*/
|
||||
inline bool __attr_pure___ __attr_always_inline___
|
||||
ecma_are_values_integer_numbers (ecma_value_t first_value, /**< first ecma value */
|
||||
ecma_value_t second_value) /**< second ecma value */
|
||||
{
|
||||
JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_INTEGER_VALUE == 0,
|
||||
ecma_direct_type_integer_value_must_be_zero);
|
||||
|
||||
return ((first_value | second_value) & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_INTEGER_VALUE;
|
||||
} /* ecma_are_values_integer_numbers */
|
||||
|
||||
/**
|
||||
* Check if the value is floating-point ecma-number.
|
||||
*
|
||||
@@ -471,6 +487,19 @@ ecma_make_error_obj_value (const ecma_object_t *object_p) /**< object to referen
|
||||
return ecma_make_error_value (ecma_make_object_value (object_p));
|
||||
} /* ecma_make_error_obj_value */
|
||||
|
||||
/**
|
||||
* Get integer value from an integer ecma value
|
||||
*
|
||||
* @return floating point value
|
||||
*/
|
||||
inline ecma_integer_value_t __attr_pure___ __attr_always_inline___
|
||||
ecma_get_integer_from_value (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
JERRY_ASSERT (ecma_is_value_integer_number (value));
|
||||
|
||||
return ((ecma_integer_value_t) value) >> ECMA_DIRECT_SHIFT;
|
||||
} /* ecma_get_integer_from_value */
|
||||
|
||||
/**
|
||||
* Get floating point value from an ecma value
|
||||
*
|
||||
@@ -481,7 +510,7 @@ ecma_get_number_from_value (ecma_value_t value) /**< ecma value */
|
||||
{
|
||||
if (ecma_is_value_integer_number (value))
|
||||
{
|
||||
return (ecma_number_t) (((ecma_integer_value_t) value) >> ECMA_DIRECT_SHIFT);
|
||||
return (ecma_number_t) ecma_get_integer_from_value (value);
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT);
|
||||
|
||||
@@ -123,6 +123,7 @@ extern bool ecma_is_value_false (ecma_value_t);
|
||||
extern bool ecma_is_value_array_hole (ecma_value_t);
|
||||
|
||||
extern bool ecma_is_value_integer_number (ecma_value_t);
|
||||
extern bool ecma_are_values_integer_numbers (ecma_value_t, ecma_value_t);
|
||||
extern bool ecma_is_value_float_number (ecma_value_t);
|
||||
extern bool ecma_is_value_number (ecma_value_t);
|
||||
extern bool ecma_is_value_string (ecma_value_t);
|
||||
@@ -141,6 +142,7 @@ extern ecma_value_t ecma_make_string_value (const ecma_string_t *);
|
||||
extern ecma_value_t ecma_make_object_value (const ecma_object_t *);
|
||||
extern ecma_value_t ecma_make_error_value (ecma_value_t);
|
||||
extern ecma_value_t ecma_make_error_obj_value (const ecma_object_t *);
|
||||
extern ecma_integer_value_t ecma_get_integer_from_value (ecma_value_t);
|
||||
extern ecma_number_t ecma_get_number_from_value (ecma_value_t) __attr_pure___;
|
||||
extern uint32_t ecma_get_uint32_from_value (ecma_value_t) __attr_pure___;
|
||||
extern ecma_string_t *ecma_get_string_from_value (ecma_value_t) __attr_pure___;
|
||||
|
||||
@@ -45,6 +45,69 @@ do_number_arithmetic (number_arithmetic_op op, /**< number arithmetic operation
|
||||
ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /**< right value */
|
||||
{
|
||||
JERRY_STATIC_ASSERT (ECMA_INTEGER_MULTIPLY_MAX * ECMA_INTEGER_MULTIPLY_MAX <= ECMA_INTEGER_NUMBER_MAX
|
||||
&& -(ECMA_INTEGER_MULTIPLY_MAX * ECMA_INTEGER_MULTIPLY_MAX) >= ECMA_INTEGER_NUMBER_MIN,
|
||||
square_of_integer_multiply_max_must_fit_into_integer_value_range);
|
||||
JERRY_STATIC_ASSERT (ECMA_INTEGER_NUMBER_MAX * 2 <= INT32_MAX
|
||||
&& ECMA_INTEGER_NUMBER_MIN * 2 >= INT32_MIN,
|
||||
doubled_ecma_numbers_must_fit_into_int32_range);
|
||||
|
||||
JERRY_ASSERT (!ecma_is_value_error (left_value)
|
||||
&& !ecma_is_value_error (right_value));
|
||||
|
||||
if (ecma_are_values_integer_numbers (left_value, right_value))
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case NUMBER_ARITHMETIC_ADDITION:
|
||||
{
|
||||
ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value);
|
||||
ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value);
|
||||
return ecma_make_int32_value ((int32_t) (left_integer + right_integer));
|
||||
}
|
||||
case NUMBER_ARITHMETIC_SUBSTRACTION:
|
||||
{
|
||||
ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value);
|
||||
ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value);
|
||||
return ecma_make_int32_value ((int32_t) (left_integer - right_integer));
|
||||
}
|
||||
case NUMBER_ARITHMETIC_MULTIPLICATION:
|
||||
{
|
||||
ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value);
|
||||
ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value);
|
||||
|
||||
if (-ECMA_INTEGER_MULTIPLY_MAX <= left_integer
|
||||
&& left_integer <= ECMA_INTEGER_MULTIPLY_MAX
|
||||
&& -ECMA_INTEGER_MULTIPLY_MAX <= right_integer
|
||||
&& right_integer <= ECMA_INTEGER_MULTIPLY_MAX)
|
||||
{
|
||||
return ecma_make_integer_value (left_integer * right_integer);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NUMBER_ARITHMETIC_DIVISION:
|
||||
{
|
||||
/* Not optimized since the result is likely not an integer number. */
|
||||
break;
|
||||
}
|
||||
case NUMBER_ARITHMETIC_REMAINDER:
|
||||
{
|
||||
ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value);
|
||||
ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value);
|
||||
if (right_integer != 0)
|
||||
{
|
||||
ecma_integer_value_t result = left_integer % right_integer;
|
||||
|
||||
if (result != 0 || left_integer >= 0)
|
||||
{
|
||||
return ecma_make_integer_value (result);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value);
|
||||
|
||||
@@ -43,6 +43,55 @@ do_number_bitwise_logic (number_bitwise_logic_op op, /**< number bitwise logic o
|
||||
ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /**< right value */
|
||||
{
|
||||
JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_INTEGER_VALUE == 0,
|
||||
ecma_direct_type_integer_value_must_be_zero_for_bitwise_logic);
|
||||
JERRY_STATIC_ASSERT ((ECMA_DIRECT_TYPE_MASK | ECMA_VALUE_ERROR_FLAG) == ((1 << ECMA_DIRECT_SHIFT) - 1),
|
||||
direct_type_mask_and_error_flag_must_fill_all_bits_before_the_value_starts);
|
||||
|
||||
JERRY_ASSERT (!ecma_is_value_error (left_value)
|
||||
&& !ecma_is_value_error (right_value));
|
||||
|
||||
if (ecma_are_values_integer_numbers (left_value, right_value))
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case NUMBER_BITWISE_LOGIC_AND:
|
||||
{
|
||||
return left_value & right_value;
|
||||
}
|
||||
case NUMBER_BITWISE_LOGIC_OR:
|
||||
{
|
||||
return left_value | right_value;
|
||||
}
|
||||
case NUMBER_BITWISE_LOGIC_XOR:
|
||||
{
|
||||
return (left_value ^ right_value) & (ecma_value_t) (~((1 << ECMA_DIRECT_SHIFT) - 1));
|
||||
}
|
||||
case NUMBER_BITWISE_SHIFT_LEFT:
|
||||
{
|
||||
ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value);
|
||||
ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value);
|
||||
return ecma_make_int32_value ((int32_t) (left_integer << (right_integer & 0x1f)));
|
||||
}
|
||||
case NUMBER_BITWISE_SHIFT_RIGHT:
|
||||
{
|
||||
ecma_integer_value_t left_integer = ecma_get_integer_from_value (left_value);
|
||||
ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value);
|
||||
return ecma_make_integer_value (left_integer >> (right_integer & 0x1f));
|
||||
}
|
||||
case NUMBER_BITWISE_SHIFT_URIGHT:
|
||||
{
|
||||
uint32_t left_uint32 = (uint32_t) ecma_get_integer_from_value (left_value);
|
||||
ecma_integer_value_t right_integer = ecma_get_integer_from_value (right_value);
|
||||
return ecma_make_uint32_value (left_uint32 >> (right_integer & 0x1f));
|
||||
}
|
||||
case NUMBER_BITWISE_NOT:
|
||||
{
|
||||
return (~right_value) & (ecma_value_t) (~((1 << ECMA_DIRECT_SHIFT) - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value);
|
||||
|
||||
@@ -44,6 +44,18 @@ ecma_value_t
|
||||
opfunc_equal_value (ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /**< right value */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_is_value_error (left_value)
|
||||
&& !ecma_is_value_error (right_value));
|
||||
|
||||
if (ecma_are_values_integer_numbers (left_value, right_value))
|
||||
{
|
||||
if (left_value == right_value)
|
||||
{
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
ECMA_TRY_CATCH (compare_result,
|
||||
@@ -72,6 +84,18 @@ ecma_value_t
|
||||
opfunc_not_equal_value (ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /**< right value */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_is_value_error (left_value)
|
||||
&& !ecma_is_value_error (right_value));
|
||||
|
||||
if (ecma_are_values_integer_numbers (left_value, right_value))
|
||||
{
|
||||
if (left_value == right_value)
|
||||
{
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
|
||||
}
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
ECMA_TRY_CATCH (compare_result,
|
||||
@@ -102,6 +126,18 @@ ecma_value_t
|
||||
opfunc_equal_value_type (ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /**< right value */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_is_value_error (left_value)
|
||||
&& !ecma_is_value_error (right_value));
|
||||
|
||||
if (ecma_are_values_integer_numbers (left_value, right_value))
|
||||
{
|
||||
if (left_value == right_value)
|
||||
{
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
|
||||
}
|
||||
|
||||
bool is_equal = ecma_op_strict_equality_compare (left_value, right_value);
|
||||
|
||||
return ecma_make_simple_value (is_equal ? ECMA_SIMPLE_VALUE_TRUE
|
||||
@@ -120,6 +156,18 @@ ecma_value_t
|
||||
opfunc_not_equal_value_type (ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /**< right value */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_is_value_error (left_value)
|
||||
&& !ecma_is_value_error (right_value));
|
||||
|
||||
if (ecma_are_values_integer_numbers (left_value, right_value))
|
||||
{
|
||||
if (left_value == right_value)
|
||||
{
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
|
||||
}
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
|
||||
bool is_equal = ecma_op_strict_equality_compare (left_value, right_value);
|
||||
|
||||
return ecma_make_simple_value (is_equal ? ECMA_SIMPLE_VALUE_FALSE
|
||||
|
||||
@@ -41,6 +41,18 @@ ecma_value_t
|
||||
opfunc_less_than (ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /**< right value */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_is_value_error (left_value)
|
||||
&& !ecma_is_value_error (right_value));
|
||||
|
||||
if (ecma_are_values_integer_numbers (left_value, right_value))
|
||||
{
|
||||
if ((ecma_integer_value_t) left_value < (ecma_integer_value_t) right_value)
|
||||
{
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
ECMA_TRY_CATCH (compare_result,
|
||||
@@ -75,6 +87,18 @@ ecma_value_t
|
||||
opfunc_greater_than (ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /**< right value */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_is_value_error (left_value)
|
||||
&& !ecma_is_value_error (right_value));
|
||||
|
||||
if (ecma_are_values_integer_numbers (left_value, right_value))
|
||||
{
|
||||
if ((ecma_integer_value_t) left_value > (ecma_integer_value_t) right_value)
|
||||
{
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
ECMA_TRY_CATCH (compare_result,
|
||||
@@ -109,6 +133,18 @@ ecma_value_t
|
||||
opfunc_less_or_equal_than (ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /**< right value */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_is_value_error (left_value)
|
||||
&& !ecma_is_value_error (right_value));
|
||||
|
||||
if (ecma_are_values_integer_numbers (left_value, right_value))
|
||||
{
|
||||
if ((ecma_integer_value_t) left_value <= (ecma_integer_value_t) right_value)
|
||||
{
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
ECMA_TRY_CATCH (compare_result,
|
||||
@@ -150,6 +186,18 @@ ecma_value_t
|
||||
opfunc_greater_or_equal_than (ecma_value_t left_value, /**< left value */
|
||||
ecma_value_t right_value) /**< right value */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_is_value_error (left_value)
|
||||
&& !ecma_is_value_error (right_value));
|
||||
|
||||
if (ecma_are_values_integer_numbers (left_value, right_value))
|
||||
{
|
||||
if ((ecma_integer_value_t) left_value >= (ecma_integer_value_t) right_value)
|
||||
{
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_TRUE);
|
||||
}
|
||||
return ecma_make_simple_value (ECMA_SIMPLE_VALUE_FALSE);
|
||||
}
|
||||
|
||||
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY);
|
||||
|
||||
ECMA_TRY_CATCH (compare_result,
|
||||
|
||||
Reference in New Issue
Block a user