From d63bb4e9a3b1f52caa25dc9c2089e2304945c289 Mon Sep 17 00:00:00 2001 From: Zoltan Herczeg Date: Mon, 19 Dec 2016 04:22:54 -0800 Subject: [PATCH] Reduce Math object binary size. Although many Math built-in functions have a similar structure these code paths were implemented as separate C functions. After this patch only one common dispatcher remains which shares the common code paths of different built-in functions. This reduces the binary size by 1 Kbyte. JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com --- .../ecma/builtin-objects/ecma-builtin-math.c | 745 ++++++------------ .../builtin-objects/ecma-builtin-math.inc.h | 36 +- 2 files changed, 254 insertions(+), 527 deletions(-) diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-math.c b/jerry-core/ecma/builtin-objects/ecma-builtin-math.c index ef6f748c96..afe62d5f41 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-math.c +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-math.c @@ -34,6 +34,41 @@ #define ECMA_BUILTINS_INTERNAL #include "ecma-builtins-internal.h" +/** + * This object has a custom dispatch function. + */ +#define BUILTIN_CUSTOM_DISPATCH + +/** + * List of built-in routine identifiers. + */ +enum +{ + ECMA_MATH_OBJECT_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1, + + ECMA_MATH_OBJECT_ABS, /* ECMA-262 v5, 15.8.2.1 */ + ECMA_MATH_OBJECT_ACOS, /* ECMA-262 v5, 15.8.2.2 */ + ECMA_MATH_OBJECT_ASIN, /* ECMA-262 v5, 15.8.2.3 */ + ECMA_MATH_OBJECT_ATAN, /* ECMA-262 v5, 15.8.2.4 */ + ECMA_MATH_OBJECT_CEIL, /* ECMA-262 v5, 15.8.2.6 */ + ECMA_MATH_OBJECT_COS, /* ECMA-262 v5, 15.8.2.7 */ + ECMA_MATH_OBJECT_EXP, /* ECMA-262 v5, 15.8.2.8 */ + ECMA_MATH_OBJECT_FLOOR, /* ECMA-262 v5, 15.8.2.9 */ + ECMA_MATH_OBJECT_LOG, /* ECMA-262 v5, 15.8.2.10 */ + ECMA_MATH_OBJECT_ROUND, /* ECMA-262 v5, 15.8.2.15 */ + ECMA_MATH_OBJECT_SIN, /* ECMA-262 v5, 15.8.2.16 */ + ECMA_MATH_OBJECT_SQRT, /* ECMA-262 v5, 15.8.2.17 */ + ECMA_MATH_OBJECT_TAN, /* ECMA-262 v5, 15.8.2.18 */ + + ECMA_MATH_OBJECT_ATAN2, /* ECMA-262 v5, 15.8.2.5 */ + ECMA_MATH_OBJECT_POW, /* ECMA-262 v5, 15.8.2.13 */ + + ECMA_MATH_OBJECT_MAX, /* ECMA-262 v5, 15.8.2.11 */ + ECMA_MATH_OBJECT_MIN, /* ECMA-262 v5, 15.8.2.12 */ + + ECMA_MATH_OBJECT_RANDOM, /* ECMA-262 v5, 15.8.2.14 */ +}; + #define BUILTIN_INC_HEADER_NAME "ecma-builtin-math.inc.h" #define BUILTIN_UNDERSCORED_ID math #include "ecma-builtin-internal-routines-template.inc.h" @@ -49,596 +84,288 @@ */ /** - * The Math object's 'abs' routine - * - * See also: - * ECMA-262 v5, 15.8.2.1 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_abs (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); - - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (fabs (arg_num))); - - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); - - return ret_value; -} /* ecma_builtin_math_object_abs */ - -/** - * The Math object's 'acos' routine - * - * See also: - * ECMA-262 v5, 15.8.2.2 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_acos (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); - - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (acos (arg_num))); - - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); - return ret_value; -} /* ecma_builtin_math_object_acos */ - -/** - * The Math object's 'asin' routine - * - * See also: - * ECMA-262 v5, 15.8.2.3 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_asin (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); - - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (asin (arg_num))); - - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); - return ret_value; -} /* ecma_builtin_math_object_asin */ - -/** - * The Math object's 'atan' routine + * The Math object's 'max' 'min' routines. * * See also: - * ECMA-262 v5, 15.8.2.4 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_atan (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); - - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (atan (arg_num))); - - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); - return ret_value; -} /* ecma_builtin_math_object_atan */ - -/** - * The Math object's 'atan2' routine - * - * See also: - * ECMA-262 v5, 15.8.2.5 + * ECMA-262 v5, 15.8.2.11 + * ECMA-262 v5, 15.8.2.12 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_math_object_atan2 (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg1, /**< first routine's argument */ - ecma_value_t arg2) /**< second routine's argument */ +ecma_builtin_math_object_max_min (bool is_max, /**< 'max' or 'min' operation */ + const ecma_value_t *arg, /**< arguments list */ + ecma_length_t args_number) /**< number of arguments */ { - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); + ecma_number_t result_num = ecma_number_make_infinity (is_max); - ECMA_OP_TO_NUMBER_TRY_CATCH (x, arg1, ret_value); - ECMA_OP_TO_NUMBER_TRY_CATCH (y, arg2, ret_value); - - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (atan2 (x, y))); + while (args_number > 0) + { + ecma_number_t arg_num; - ECMA_OP_TO_NUMBER_FINALIZE (y); - ECMA_OP_TO_NUMBER_FINALIZE (x); - return ret_value; -} /* ecma_builtin_math_object_atan2 */ + if (ecma_is_value_number (*arg)) + { + arg_num = ecma_get_number_from_value (*arg); + } + else + { + ecma_value_t value = ecma_op_to_number (*arg); -/** - * The Math object's 'ceil' routine - * - * See also: - * ECMA-262 v5, 15.8.2.6 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_ceil (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); + arg_num = ecma_get_number_from_value (value); - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (ceil (arg_num))); + ecma_fast_free_value (value); + } - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); - return ret_value; -} /* ecma_builtin_math_object_ceil */ + if (unlikely (ecma_number_is_nan (arg_num))) + { + result_num = arg_num; + break; + } -/** - * The Math object's 'cos' routine - * - * See also: - * ECMA-262 v5, 15.8.2.7 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_cos (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); + if (ecma_number_is_zero (arg_num) + && ecma_number_is_zero (result_num)) + { + bool is_negative = ecma_number_is_negative (arg_num); - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); + if (is_max ? !is_negative : is_negative) + { + result_num = arg_num; + } + } + else + { + if (is_max ? (arg_num > result_num) : (arg_num < result_num)) + { + result_num = arg_num; + } + } - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (cos (arg_num))); + arg++; + args_number--; + } - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); - return ret_value; -} /* ecma_builtin_math_object_cos */ + return ecma_make_number_value (result_num); +} /* ecma_builtin_math_object_max_min */ /** - * The Math object's 'exp' routine + * The Math object's 'random' routine. * * See also: - * ECMA-262 v5, 15.8.2.8 + * ECMA-262 v5, 15.8.2.14 * * @return ecma value * Returned value must be freed with ecma_free_value. */ static ecma_value_t -ecma_builtin_math_object_exp (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ +ecma_builtin_math_object_random (void) { - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); - - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (exp (arg_num))); - - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); + const ecma_number_t rand_max = (ecma_number_t) RAND_MAX; + const ecma_number_t rand_max_min_1 = (ecma_number_t) (RAND_MAX - 1); - return ret_value; -} /* ecma_builtin_math_object_exp */ + return ecma_make_number_value (((ecma_number_t) rand ()) / rand_max * rand_max_min_1 / rand_max); +} /* ecma_builtin_math_object_random */ /** - * The Math object's 'floor' routine - * - * See also: - * ECMA-262 v5, 15.8.2.9 + * Dispatcher for the built-in's routines. * * @return ecma value * Returned value must be freed with ecma_free_value. */ -static ecma_value_t -ecma_builtin_math_object_floor (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ +ecma_value_t +ecma_builtin_math_dispatch_routine (uint16_t builtin_routine_id, /**< built-in wide routine + * identifier */ + ecma_value_t this_arg, /**< 'this' argument value */ + const ecma_value_t arguments_list[], /**< list of arguments + * passed to routine */ + ecma_length_t arguments_number) /**< length of arguments' list */ { JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); - - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (floor (arg_num))); - - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); - return ret_value; -} /* ecma_builtin_math_object_floor */ -/** - * The Math object's 'log' routine - * - * See also: - * ECMA-262 v5, 15.8.2.10 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_log (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); + if (builtin_routine_id <= ECMA_MATH_OBJECT_POW) + { + ecma_number_t x = ecma_number_make_nan (); + ecma_number_t y = ecma_number_make_nan (); - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); + if (arguments_number >= 1) + { + if (ecma_is_value_number (arguments_list[0])) + { + x = ecma_get_number_from_value (arguments_list[0]); + } + else + { + ecma_value_t value = ecma_op_to_number (arguments_list[0]); - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (log (arg_num))); + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); + x = ecma_get_number_from_value (value); - return ret_value; -} /* ecma_builtin_math_object_log */ + ecma_fast_free_value (value); + } + } -/** - * The Math object's 'max' routine - * - * See also: - * ECMA-262 v5, 15.8.2.11 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_max (ecma_value_t this_arg, /**< 'this' argument */ - const ecma_value_t args[], /**< arguments list */ - ecma_length_t args_number) /**< number of arguments */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); + if (builtin_routine_id >= ECMA_MATH_OBJECT_ATAN2) + { + if (arguments_number >= 2) + { + if (ecma_is_value_number (arguments_list[1])) + { + y = ecma_get_number_from_value (arguments_list[1]); + } + else + { + ecma_value_t value = ecma_op_to_number (arguments_list[1]); - ecma_number_t ret_num = ecma_number_make_infinity (true); + if (ECMA_IS_VALUE_ERROR (value)) + { + return value; + } - bool is_NaN = false; + y = ecma_get_number_from_value (value); - for (ecma_length_t arg_index = 0; - arg_index < args_number && ecma_is_value_empty (ret_value); - arg_index++) - { - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, args[arg_index], ret_value); + ecma_fast_free_value (value); + } + } + } - if (!is_NaN) + switch (builtin_routine_id) { - if (unlikely (ecma_number_is_nan (arg_num))) + case ECMA_MATH_OBJECT_ABS: { - ret_num = arg_num; - is_NaN = true; + x = DOUBLE_TO_ECMA_NUMBER_T (fabs (x)); + break; } - else if (ecma_number_is_zero (arg_num) /* both numbers are zeroes */ - && ecma_number_is_zero (ret_num)) + case ECMA_MATH_OBJECT_ACOS: { - if (!ecma_number_is_negative (arg_num)) - { - ret_num = arg_num; - } + x = DOUBLE_TO_ECMA_NUMBER_T (acos (x)); + break; } - else if (ecma_number_is_infinity (arg_num)) + case ECMA_MATH_OBJECT_ASIN: { - if (!ecma_number_is_negative (arg_num)) - { - ret_num = arg_num; - } + x = DOUBLE_TO_ECMA_NUMBER_T (asin (x)); + break; } - else if (ecma_number_is_infinity (ret_num)) + case ECMA_MATH_OBJECT_ATAN: { - if (ecma_number_is_negative (ret_num)) - { - ret_num = arg_num; - } + x = DOUBLE_TO_ECMA_NUMBER_T (atan (x)); + break; } - else + case ECMA_MATH_OBJECT_CEIL: { - JERRY_ASSERT (!ecma_number_is_nan (arg_num) - && !ecma_number_is_infinity (arg_num)); - JERRY_ASSERT (!ecma_number_is_nan (ret_num) - && !ecma_number_is_infinity (ret_num)); - - if (arg_num > ret_num) - { - ret_num = arg_num; - } + x = DOUBLE_TO_ECMA_NUMBER_T (ceil (x)); + break; } - } - - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); - } - - if (ecma_is_value_empty (ret_value)) - { - ret_value = ecma_make_number_value (ret_num); - } - - return ret_value; -} /* ecma_builtin_math_object_max */ - -/** - * The Math object's 'min' routine - * - * See also: - * ECMA-262 v5, 15.8.2.12 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_min (ecma_value_t this_arg, /**< 'this' argument */ - const ecma_value_t args[], /**< arguments list */ - ecma_length_t args_number) /**< number of arguments */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ecma_number_t ret_num = ecma_number_make_infinity (false); - - bool is_NaN = false; - - for (ecma_length_t arg_index = 0; - arg_index < args_number && ecma_is_value_empty (ret_value); - arg_index++) - { - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, args[arg_index], ret_value); - - if (!is_NaN) - { - if (unlikely (ecma_number_is_nan (arg_num))) + case ECMA_MATH_OBJECT_COS: { - ret_num = arg_num; - is_NaN = true; + x = DOUBLE_TO_ECMA_NUMBER_T (cos (x)); + break; } - else if (ecma_number_is_zero (arg_num) /* both numbers are zeroes */ - && ecma_number_is_zero (ret_num)) + case ECMA_MATH_OBJECT_EXP: { - if (ecma_number_is_negative (arg_num)) - { - ret_num = arg_num; - } + x = DOUBLE_TO_ECMA_NUMBER_T (exp (x)); + break; } - else if (ecma_number_is_infinity (arg_num)) + case ECMA_MATH_OBJECT_FLOOR: { - if (ecma_number_is_negative (arg_num)) - { - ret_num = arg_num; - } + x = DOUBLE_TO_ECMA_NUMBER_T (floor (x)); + break; + } + case ECMA_MATH_OBJECT_LOG: + { + x = DOUBLE_TO_ECMA_NUMBER_T (log (x)); + break; } - else if (ecma_number_is_infinity (ret_num)) + case ECMA_MATH_OBJECT_ROUND: { - if (!ecma_number_is_negative (ret_num)) + if (ecma_number_is_nan (x) + || ecma_number_is_zero (x) + || ecma_number_is_infinity (x)) { - ret_num = arg_num; + /* Do nothing. */ } + else if (ecma_number_is_negative (x) + && x >= -ECMA_NUMBER_HALF) + { + x = ecma_number_negate (ECMA_NUMBER_ZERO); + } + else + { + const ecma_number_t up_half = x + ECMA_NUMBER_HALF; + const ecma_number_t down_half = x - ECMA_NUMBER_HALF; + const ecma_number_t up_rounded = up_half - ecma_op_number_remainder (up_half, ECMA_NUMBER_ONE); + const ecma_number_t down_rounded = down_half - ecma_op_number_remainder (down_half, ECMA_NUMBER_ONE); + + if (up_rounded - x <= x - down_rounded) + { + x = up_rounded; + } + else + { + x = down_rounded; + } + } + break; } - else + case ECMA_MATH_OBJECT_SIN: { - JERRY_ASSERT (!ecma_number_is_nan (arg_num) - && !ecma_number_is_infinity (arg_num)); - JERRY_ASSERT (!ecma_number_is_nan (ret_num) - && !ecma_number_is_infinity (ret_num)); - - if (arg_num < ret_num) + x = DOUBLE_TO_ECMA_NUMBER_T (sin (x)); + break; + } + case ECMA_MATH_OBJECT_SQRT: + { + x = DOUBLE_TO_ECMA_NUMBER_T (sqrt (x)); + break; + } + case ECMA_MATH_OBJECT_TAN: + { + x = DOUBLE_TO_ECMA_NUMBER_T (tan (x)); + break; + } + case ECMA_MATH_OBJECT_ATAN2: + { + x = DOUBLE_TO_ECMA_NUMBER_T (atan2 (x, y)); + break; + } + case ECMA_MATH_OBJECT_POW: + { + if (ecma_number_is_nan (y) || + (ecma_number_is_infinity (y) && (x == 1.0 || x == -1.0))) + { + /* Handle differences between ES5.1 and ISO C standards for pow. */ + x = ecma_number_make_nan (); + } + else { - ret_num = arg_num; + x = DOUBLE_TO_ECMA_NUMBER_T (pow (x, y)); } + break; } } - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); + return ecma_make_number_value (x); } - if (ecma_is_value_empty (ret_value)) + if (builtin_routine_id <= ECMA_MATH_OBJECT_MIN) { - ret_value = ecma_make_number_value (ret_num); + return ecma_builtin_math_object_max_min (builtin_routine_id == ECMA_MATH_OBJECT_MAX, + arguments_list, + arguments_number); } - return ret_value; -} /* ecma_builtin_math_object_min */ - -/** - * The Math object's 'pow' routine - * - * See also: - * ECMA-262 v5, 15.8.2.13 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_pow (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg1, /**< first routine's argument */ - ecma_value_t arg2) /**< second routine's argument */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ECMA_OP_TO_NUMBER_TRY_CATCH (x, arg1, ret_value); - ECMA_OP_TO_NUMBER_TRY_CATCH (y, arg2, ret_value); - - if (ecma_number_is_nan (y) || - (ecma_number_is_infinity (y) && (x == 1.0 || x == -1.0))) - { - /* Handle differences between ES5.1 and ISO C standards for pow. */ - ret_value = ecma_make_number_value (ecma_number_make_nan ()); - } - else - { - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (pow (x, y))); - } - - ECMA_OP_TO_NUMBER_FINALIZE (y); - ECMA_OP_TO_NUMBER_FINALIZE (x); - - return ret_value; -} /* ecma_builtin_math_object_pow */ - -/** - * The Math object's 'random' routine - * - * See also: - * ECMA-262 v5, 15.8.2.14 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_random (ecma_value_t this_arg) /**< 'this' argument */ -{ - JERRY_UNUSED (this_arg); - - const ecma_number_t rand_max = (ecma_number_t) RAND_MAX; - const ecma_number_t rand_max_min_1 = (ecma_number_t) (RAND_MAX - 1); - - return ecma_make_number_value (((ecma_number_t) rand ()) / rand_max * rand_max_min_1 / rand_max); -} /* ecma_builtin_math_object_random */ - -/** - * The Math object's 'round' routine - * - * See also: - * ECMA-262 v5, 15.8.2.15 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_round (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); - - ecma_number_t num = ECMA_NUMBER_ZERO; - - if (ecma_number_is_nan (arg_num) - || ecma_number_is_zero (arg_num) - || ecma_number_is_infinity (arg_num)) - { - num = arg_num; - } - else if (ecma_number_is_negative (arg_num) - && arg_num >= -ECMA_NUMBER_HALF) - { - num = ecma_number_negate (ECMA_NUMBER_ZERO); - } - else - { - const ecma_number_t up_half = arg_num + ECMA_NUMBER_HALF; - const ecma_number_t down_half = arg_num - ECMA_NUMBER_HALF; - const ecma_number_t up_rounded = up_half - ecma_op_number_remainder (up_half, ECMA_NUMBER_ONE); - const ecma_number_t down_rounded = down_half - ecma_op_number_remainder (down_half, ECMA_NUMBER_ONE); - - if (up_rounded - arg_num <= arg_num - down_rounded) - { - num = up_rounded; - } - else - { - num = down_rounded; - } - } - - ret_value = ecma_make_number_value (num); - - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); - - return ret_value; -} /* ecma_builtin_math_object_round */ - -/** - * The Math object's 'sin' routine - * - * See also: - * ECMA-262 v5, 15.8.2.16 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_sin (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); - - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (sin (arg_num))); - - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); - return ret_value; -} /* ecma_builtin_math_object_sin */ - -/** - * The Math object's 'sqrt' routine - * - * See also: - * ECMA-262 v5, 15.8.2.17 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_sqrt (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); - - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (sqrt (arg_num))); - - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); - return ret_value; -} /* ecma_builtin_math_object_sqrt */ - -/** - * The Math object's 'tan' routine - * - * See also: - * ECMA-262 v5, 15.8.2.18 - * - * @return ecma value - * Returned value must be freed with ecma_free_value. - */ -static ecma_value_t -ecma_builtin_math_object_tan (ecma_value_t this_arg, /**< 'this' argument */ - ecma_value_t arg) /**< routine's argument */ -{ - JERRY_UNUSED (this_arg); - ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY); - - ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value); - ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (tan (arg_num))); + JERRY_ASSERT (builtin_routine_id == ECMA_MATH_OBJECT_RANDOM); - ECMA_OP_TO_NUMBER_FINALIZE (arg_num); - return ret_value; -} /* ecma_builtin_math_object_tan */ + return ecma_builtin_math_object_random (); +} /* ecma_builtin_math_dispatch_routine */ /** * @} diff --git a/jerry-core/ecma/builtin-objects/ecma-builtin-math.inc.h b/jerry-core/ecma/builtin-objects/ecma-builtin-math.inc.h index cf4974cdda..15dc4a0962 100644 --- a/jerry-core/ecma/builtin-objects/ecma-builtin-math.inc.h +++ b/jerry-core/ecma/builtin-objects/ecma-builtin-math.inc.h @@ -85,24 +85,24 @@ NUMBER_VALUE (LIT_MAGIC_STRING_SQRT2_U, /* Routine properties: * (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */ -ROUTINE (LIT_MAGIC_STRING_ABS, ecma_builtin_math_object_abs, 1, 1) -ROUTINE (LIT_MAGIC_STRING_ACOS, ecma_builtin_math_object_acos, 1, 1) -ROUTINE (LIT_MAGIC_STRING_ASIN, ecma_builtin_math_object_asin, 1, 1) -ROUTINE (LIT_MAGIC_STRING_ATAN, ecma_builtin_math_object_atan, 1, 1) -ROUTINE (LIT_MAGIC_STRING_ATAN2, ecma_builtin_math_object_atan2, 2, 2) -ROUTINE (LIT_MAGIC_STRING_CEIL, ecma_builtin_math_object_ceil, 1, 1) -ROUTINE (LIT_MAGIC_STRING_COS, ecma_builtin_math_object_cos, 1, 1) -ROUTINE (LIT_MAGIC_STRING_EXP, ecma_builtin_math_object_exp, 1, 1) -ROUTINE (LIT_MAGIC_STRING_FLOOR, ecma_builtin_math_object_floor, 1, 1) -ROUTINE (LIT_MAGIC_STRING_LOG, ecma_builtin_math_object_log, 1, 1) -ROUTINE (LIT_MAGIC_STRING_MAX, ecma_builtin_math_object_max, NON_FIXED, 2) -ROUTINE (LIT_MAGIC_STRING_MIN, ecma_builtin_math_object_min, NON_FIXED, 2) -ROUTINE (LIT_MAGIC_STRING_POW, ecma_builtin_math_object_pow, 2, 2) -ROUTINE (LIT_MAGIC_STRING_RANDOM, ecma_builtin_math_object_random, 0, 0) -ROUTINE (LIT_MAGIC_STRING_ROUND, ecma_builtin_math_object_round, 1, 1) -ROUTINE (LIT_MAGIC_STRING_SIN, ecma_builtin_math_object_sin, 1, 1) -ROUTINE (LIT_MAGIC_STRING_SQRT, ecma_builtin_math_object_sqrt, 1, 1) -ROUTINE (LIT_MAGIC_STRING_TAN, ecma_builtin_math_object_tan, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ABS, ECMA_MATH_OBJECT_ABS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ACOS, ECMA_MATH_OBJECT_ACOS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ASIN, ECMA_MATH_OBJECT_ASIN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ATAN, ECMA_MATH_OBJECT_ATAN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_ATAN2, ECMA_MATH_OBJECT_ATAN2, 2, 2) +ROUTINE (LIT_MAGIC_STRING_CEIL, ECMA_MATH_OBJECT_CEIL, 1, 1) +ROUTINE (LIT_MAGIC_STRING_COS, ECMA_MATH_OBJECT_COS, 1, 1) +ROUTINE (LIT_MAGIC_STRING_EXP, ECMA_MATH_OBJECT_EXP, 1, 1) +ROUTINE (LIT_MAGIC_STRING_FLOOR, ECMA_MATH_OBJECT_FLOOR, 1, 1) +ROUTINE (LIT_MAGIC_STRING_LOG, ECMA_MATH_OBJECT_LOG, 1, 1) +ROUTINE (LIT_MAGIC_STRING_MAX, ECMA_MATH_OBJECT_MAX, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_MIN, ECMA_MATH_OBJECT_MIN, NON_FIXED, 2) +ROUTINE (LIT_MAGIC_STRING_POW, ECMA_MATH_OBJECT_POW, 2, 2) +ROUTINE (LIT_MAGIC_STRING_RANDOM, ECMA_MATH_OBJECT_RANDOM, 0, 0) +ROUTINE (LIT_MAGIC_STRING_ROUND, ECMA_MATH_OBJECT_ROUND, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SIN, ECMA_MATH_OBJECT_SIN, 1, 1) +ROUTINE (LIT_MAGIC_STRING_SQRT, ECMA_MATH_OBJECT_SQRT, 1, 1) +ROUTINE (LIT_MAGIC_STRING_TAN, ECMA_MATH_OBJECT_TAN, 1, 1) #undef OBJECT_ID #undef SIMPLE_VALUE