Reduce Math object binary size. (#1491)
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
This commit is contained in:
committed by
Tilmann Scheller
parent
f2b17bca8b
commit
0c7d99e8e7
@@ -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,452 +84,77 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* @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 */
|
||||
{
|
||||
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);
|
||||
|
||||
ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (atan2 (x, y)));
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (y);
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (x);
|
||||
return ret_value;
|
||||
} /* ecma_builtin_math_object_atan2 */
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value);
|
||||
|
||||
ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (ceil (arg_num)));
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (arg_num);
|
||||
return ret_value;
|
||||
} /* ecma_builtin_math_object_ceil */
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value);
|
||||
|
||||
ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (cos (arg_num)));
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (arg_num);
|
||||
return ret_value;
|
||||
} /* ecma_builtin_math_object_cos */
|
||||
|
||||
/**
|
||||
* The Math object's 'exp' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 15.8.2.8
|
||||
*
|
||||
* @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 */
|
||||
{
|
||||
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);
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_builtin_math_object_exp */
|
||||
|
||||
/**
|
||||
* The Math object's 'floor' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 15.8.2.9
|
||||
*
|
||||
* @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 */
|
||||
{
|
||||
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);
|
||||
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value);
|
||||
|
||||
ret_value = ecma_make_number_value (DOUBLE_TO_ECMA_NUMBER_T (log (arg_num)));
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (arg_num);
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_builtin_math_object_log */
|
||||
|
||||
/**
|
||||
* The Math object's 'max' routine
|
||||
* The Math object's 'max' 'min' routines.
|
||||
*
|
||||
* 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);
|
||||
|
||||
ecma_number_t ret_num = ecma_number_make_infinity (true);
|
||||
|
||||
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)))
|
||||
{
|
||||
ret_num = arg_num;
|
||||
is_NaN = true;
|
||||
}
|
||||
else if (ecma_number_is_zero (arg_num) /* both numbers are zeroes */
|
||||
&& ecma_number_is_zero (ret_num))
|
||||
{
|
||||
if (!ecma_number_is_negative (arg_num))
|
||||
{
|
||||
ret_num = arg_num;
|
||||
}
|
||||
}
|
||||
else if (ecma_number_is_infinity (arg_num))
|
||||
{
|
||||
if (!ecma_number_is_negative (arg_num))
|
||||
{
|
||||
ret_num = arg_num;
|
||||
}
|
||||
}
|
||||
else if (ecma_number_is_infinity (ret_num))
|
||||
{
|
||||
if (ecma_number_is_negative (ret_num))
|
||||
{
|
||||
ret_num = arg_num;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
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_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++)
|
||||
while (args_number > 0)
|
||||
{
|
||||
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, args[arg_index], ret_value);
|
||||
ecma_number_t arg_num;
|
||||
|
||||
if (!is_NaN)
|
||||
if (ecma_is_value_number (*arg))
|
||||
{
|
||||
if (unlikely (ecma_number_is_nan (arg_num)))
|
||||
{
|
||||
ret_num = arg_num;
|
||||
is_NaN = true;
|
||||
}
|
||||
else if (ecma_number_is_zero (arg_num) /* both numbers are zeroes */
|
||||
&& ecma_number_is_zero (ret_num))
|
||||
{
|
||||
if (ecma_number_is_negative (arg_num))
|
||||
{
|
||||
ret_num = arg_num;
|
||||
}
|
||||
}
|
||||
else if (ecma_number_is_infinity (arg_num))
|
||||
{
|
||||
if (ecma_number_is_negative (arg_num))
|
||||
{
|
||||
ret_num = arg_num;
|
||||
}
|
||||
}
|
||||
else if (ecma_number_is_infinity (ret_num))
|
||||
{
|
||||
if (!ecma_number_is_negative (ret_num))
|
||||
{
|
||||
ret_num = arg_num;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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));
|
||||
arg_num = ecma_get_number_from_value (*arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_value_t value = ecma_op_to_number (*arg);
|
||||
|
||||
if (arg_num < ret_num)
|
||||
{
|
||||
ret_num = arg_num;
|
||||
}
|
||||
if (ECMA_IS_VALUE_ERROR (value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
arg_num = ecma_get_number_from_value (value);
|
||||
|
||||
ecma_fast_free_value (value);
|
||||
}
|
||||
|
||||
if (unlikely (ecma_number_is_nan (arg_num)))
|
||||
{
|
||||
result_num = arg_num;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ecma_number_is_zero (arg_num)
|
||||
&& ecma_number_is_zero (result_num))
|
||||
{
|
||||
bool is_negative = ecma_number_is_negative (arg_num);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (arg_num);
|
||||
arg++;
|
||||
args_number--;
|
||||
}
|
||||
|
||||
if (ecma_is_value_empty (ret_value))
|
||||
{
|
||||
ret_value = ecma_make_number_value (ret_num);
|
||||
}
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_builtin_math_object_min */
|
||||
return ecma_make_number_value (result_num);
|
||||
} /* ecma_builtin_math_object_max_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
|
||||
* The Math object's 'random' routine.
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 15.8.2.14
|
||||
@@ -503,10 +163,8 @@ ecma_builtin_math_object_pow (ecma_value_t this_arg, /**< 'this' argument */
|
||||
* 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 */
|
||||
ecma_builtin_math_object_random (void)
|
||||
{
|
||||
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);
|
||||
|
||||
@@ -514,131 +172,200 @@ ecma_builtin_math_object_random (ecma_value_t this_arg) /**< 'this' argument */
|
||||
} /* ecma_builtin_math_object_random */
|
||||
|
||||
/**
|
||||
* The Math object's 'round' routine
|
||||
*
|
||||
* See also:
|
||||
* ECMA-262 v5, 15.8.2.15
|
||||
* 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_round (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);
|
||||
|
||||
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))
|
||||
if (builtin_routine_id <= ECMA_MATH_OBJECT_POW)
|
||||
{
|
||||
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);
|
||||
ecma_number_t x = ecma_number_make_nan ();
|
||||
ecma_number_t y = ecma_number_make_nan ();
|
||||
|
||||
if (up_rounded - arg_num <= arg_num - down_rounded)
|
||||
if (arguments_number >= 1)
|
||||
{
|
||||
num = up_rounded;
|
||||
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]);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
x = ecma_get_number_from_value (value);
|
||||
|
||||
ecma_fast_free_value (value);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (builtin_routine_id >= ECMA_MATH_OBJECT_ATAN2)
|
||||
{
|
||||
num = down_rounded;
|
||||
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]);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
y = ecma_get_number_from_value (value);
|
||||
|
||||
ecma_fast_free_value (value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (builtin_routine_id)
|
||||
{
|
||||
case ECMA_MATH_OBJECT_ABS:
|
||||
{
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (fabs (x));
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_ACOS:
|
||||
{
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (acos (x));
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_ASIN:
|
||||
{
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (asin (x));
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_ATAN:
|
||||
{
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (atan (x));
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_CEIL:
|
||||
{
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (ceil (x));
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_COS:
|
||||
{
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (cos (x));
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_EXP:
|
||||
{
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (exp (x));
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_FLOOR:
|
||||
{
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (floor (x));
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_LOG:
|
||||
{
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (log (x));
|
||||
break;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_ROUND:
|
||||
{
|
||||
if (ecma_number_is_nan (x)
|
||||
|| ecma_number_is_zero (x)
|
||||
|| ecma_number_is_infinity (x))
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
case ECMA_MATH_OBJECT_SIN:
|
||||
{
|
||||
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
|
||||
{
|
||||
x = DOUBLE_TO_ECMA_NUMBER_T (pow (x, y));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ecma_make_number_value (x);
|
||||
}
|
||||
|
||||
ret_value = ecma_make_number_value (num);
|
||||
if (builtin_routine_id <= ECMA_MATH_OBJECT_MIN)
|
||||
{
|
||||
return ecma_builtin_math_object_max_min (builtin_routine_id == ECMA_MATH_OBJECT_MAX,
|
||||
arguments_list,
|
||||
arguments_number);
|
||||
}
|
||||
|
||||
ECMA_OP_TO_NUMBER_FINALIZE (arg_num);
|
||||
|
||||
return ret_value;
|
||||
} /* ecma_builtin_math_object_round */
|
||||
JERRY_ASSERT (builtin_routine_id == ECMA_MATH_OBJECT_RANDOM);
|
||||
|
||||
/**
|
||||
* 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)));
|
||||
|
||||
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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user