Use custom dispatcher for Number.prototype routines (#2968)
Binary size gain:
- Intel: ~630B (gcc-7.3)
- Arm: ~280B (arm-linux-gnueabi-gcc-7.3)
Futher improvements:
- Separate toFixed, toExponential, toPrecision common part into a helper function
Co-authored-by: Gabor Loki loki@inf.u-szeged.hu
JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
committed by
Dániel Bátyai
parent
7aa3bfdc6d
commit
329b1fd3f7
@@ -33,6 +33,25 @@
|
|||||||
#define ECMA_BUILTINS_INTERNAL
|
#define ECMA_BUILTINS_INTERNAL
|
||||||
#include "ecma-builtins-internal.h"
|
#include "ecma-builtins-internal.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This object has a custom dispatch function.
|
||||||
|
*/
|
||||||
|
#define BUILTIN_CUSTOM_DISPATCH
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of built-in routine identifiers.
|
||||||
|
*/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
ECMA_NUMBER_PROTOTYPE_ROUTINE_START = ECMA_BUILTIN_ID__COUNT - 1,
|
||||||
|
ECMA_NUMBER_PROTOTYPE_VALUE_OF,
|
||||||
|
ECMA_NUMBER_PROTOTYPE_TO_STRING,
|
||||||
|
ECMA_NUMBER_PROTOTYPE_TO_LOCALE_STRING,
|
||||||
|
ECMA_NUMBER_PROTOTYPE_TO_FIXED,
|
||||||
|
ECMA_NUMBER_PROTOTYPE_TO_EXPONENTIAL,
|
||||||
|
ECMA_NUMBER_PROTOTYPE_TO_PRECISION,
|
||||||
|
};
|
||||||
|
|
||||||
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-number-prototype.inc.h"
|
#define BUILTIN_INC_HEADER_NAME "ecma-builtin-number-prototype.inc.h"
|
||||||
#define BUILTIN_UNDERSCORED_ID number_prototype
|
#define BUILTIN_UNDERSCORED_ID number_prototype
|
||||||
#include "ecma-builtin-internal-routines-template.inc.h"
|
#include "ecma-builtin-internal-routines-template.inc.h"
|
||||||
@@ -216,23 +235,20 @@ ecma_builtin_number_prototype_helper_round (lit_utf8_byte_t *digits_p, /**< [in,
|
|||||||
} /* ecma_builtin_number_prototype_helper_round */
|
} /* ecma_builtin_number_prototype_helper_round */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Number.prototype object's 'toString' routine
|
* The Number.prototype object's 'toString' and 'toLocaleString' routines
|
||||||
*
|
*
|
||||||
* See also:
|
* See also:
|
||||||
* ECMA-262 v5, 15.7.4.2
|
* ECMA-262 v5, 15.7.4.2
|
||||||
|
* ECMA-262 v5, 15.7.4.7
|
||||||
*
|
*
|
||||||
* @return ecma value
|
* @return ecma value
|
||||||
* Returned value must be freed with ecma_free_value.
|
* Returned value must be freed with ecma_free_value.
|
||||||
*/
|
*/
|
||||||
static ecma_value_t
|
static ecma_value_t
|
||||||
ecma_builtin_number_prototype_object_to_string (ecma_value_t this_arg, /**< this argument */
|
ecma_builtin_number_prototype_object_to_string (ecma_number_t this_arg_number, /**< this argument number */
|
||||||
const ecma_value_t *arguments_list_p, /**< arguments list */
|
const ecma_value_t *arguments_list_p, /**< arguments list */
|
||||||
ecma_length_t arguments_list_len) /**< number of arguments */
|
ecma_length_t arguments_list_len) /**< number of arguments */
|
||||||
{
|
{
|
||||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
|
||||||
|
|
||||||
ECMA_TRY_CATCH (this_value, ecma_builtin_number_prototype_object_value_of (this_arg), ret_value);
|
|
||||||
ecma_number_t this_arg_number = ecma_get_number_from_value (this_value);
|
|
||||||
|
|
||||||
if (arguments_list_len == 0
|
if (arguments_list_len == 0
|
||||||
|| ecma_number_is_nan (this_arg_number)
|
|| ecma_number_is_nan (this_arg_number)
|
||||||
@@ -241,11 +257,8 @@ ecma_builtin_number_prototype_object_to_string (ecma_value_t this_arg, /**< this
|
|||||||
|| (arguments_list_len > 0 && ecma_is_value_undefined (arguments_list_p[0])))
|
|| (arguments_list_len > 0 && ecma_is_value_undefined (arguments_list_p[0])))
|
||||||
{
|
{
|
||||||
ecma_string_t *ret_str_p = ecma_new_ecma_string_from_number (this_arg_number);
|
ecma_string_t *ret_str_p = ecma_new_ecma_string_from_number (this_arg_number);
|
||||||
|
return ecma_make_string_value (ret_str_p);
|
||||||
ret_value = ecma_make_string_value (ret_str_p);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
static const lit_utf8_byte_t digit_chars[36] =
|
static const lit_utf8_byte_t digit_chars[36] =
|
||||||
{
|
{
|
||||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||||
@@ -254,22 +267,27 @@ ecma_builtin_number_prototype_object_to_string (ecma_value_t this_arg, /**< this
|
|||||||
'u', 'v', 'w', 'x', 'y', 'z'
|
'u', 'v', 'w', 'x', 'y', 'z'
|
||||||
};
|
};
|
||||||
|
|
||||||
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arguments_list_p[0], ret_value);
|
ecma_number_t arg_num;
|
||||||
|
ecma_value_t radix_num = ecma_get_number (arguments_list_p[0], &arg_num);
|
||||||
|
|
||||||
|
if (!ecma_is_value_empty (radix_num))
|
||||||
|
{
|
||||||
|
return radix_num;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t radix = ecma_number_to_uint32 (arg_num);
|
uint32_t radix = ecma_number_to_uint32 (arg_num);
|
||||||
|
|
||||||
if (radix < 2 || radix > 36)
|
if (radix < 2 || radix > 36)
|
||||||
{
|
{
|
||||||
ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("Radix must be between 2 and 36."));
|
return ecma_raise_range_error (ECMA_ERR_MSG ("Radix must be between 2 and 36."));
|
||||||
}
|
}
|
||||||
else if (radix == 10)
|
|
||||||
|
if (radix == 10)
|
||||||
{
|
{
|
||||||
ecma_string_t *ret_str_p = ecma_new_ecma_string_from_number (this_arg_number);
|
ecma_string_t *ret_str_p = ecma_new_ecma_string_from_number (this_arg_number);
|
||||||
|
|
||||||
ret_value = ecma_make_string_value (ret_str_p);
|
return ecma_make_string_value (ret_str_p);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
int buff_size = 0;
|
int buff_size = 0;
|
||||||
|
|
||||||
bool is_number_negative = false;
|
bool is_number_negative = false;
|
||||||
@@ -384,6 +402,7 @@ ecma_builtin_number_prototype_object_to_string (ecma_value_t this_arg, /**< this
|
|||||||
|
|
||||||
/* Get the total required buffer size and allocate the buffer. */
|
/* Get the total required buffer size and allocate the buffer. */
|
||||||
buff_size += required_digits;
|
buff_size += required_digits;
|
||||||
|
ecma_value_t ret_value;
|
||||||
JMEM_DEFINE_LOCAL_ARRAY (buff, buff_size, lit_utf8_byte_t);
|
JMEM_DEFINE_LOCAL_ARRAY (buff, buff_size, lit_utf8_byte_t);
|
||||||
int buff_index = 0;
|
int buff_index = 0;
|
||||||
|
|
||||||
@@ -510,28 +529,10 @@ ecma_builtin_number_prototype_object_to_string (ecma_value_t this_arg, /**< this
|
|||||||
ecma_string_t *str_p = ecma_new_ecma_string_from_utf8 (buff, (lit_utf8_size_t) buff_index);
|
ecma_string_t *str_p = ecma_new_ecma_string_from_utf8 (buff, (lit_utf8_size_t) buff_index);
|
||||||
ret_value = ecma_make_string_value (str_p);
|
ret_value = ecma_make_string_value (str_p);
|
||||||
JMEM_FINALIZE_LOCAL_ARRAY (buff);
|
JMEM_FINALIZE_LOCAL_ARRAY (buff);
|
||||||
}
|
|
||||||
ECMA_OP_TO_NUMBER_FINALIZE (arg_num);
|
|
||||||
}
|
|
||||||
ECMA_FINALIZE (this_value);
|
|
||||||
return ret_value;
|
return ret_value;
|
||||||
} /* ecma_builtin_number_prototype_object_to_string */
|
} /* ecma_builtin_number_prototype_object_to_string */
|
||||||
|
|
||||||
/**
|
|
||||||
* The Number.prototype object's 'toLocaleString' routine
|
|
||||||
*
|
|
||||||
* See also:
|
|
||||||
* ECMA-262 v5, 15.7.4.3
|
|
||||||
*
|
|
||||||
* @return ecma value
|
|
||||||
* Returned value must be freed with ecma_free_value.
|
|
||||||
*/
|
|
||||||
static ecma_value_t
|
|
||||||
ecma_builtin_number_prototype_object_to_locale_string (ecma_value_t this_arg) /**< this argument */
|
|
||||||
{
|
|
||||||
return ecma_builtin_number_prototype_object_to_string (this_arg, NULL, 0);
|
|
||||||
} /* ecma_builtin_number_prototype_object_to_locale_string */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Number.prototype object's 'valueOf' routine
|
* The Number.prototype object's 'valueOf' routine
|
||||||
*
|
*
|
||||||
@@ -546,7 +547,7 @@ ecma_builtin_number_prototype_object_value_of (ecma_value_t this_arg) /**< this
|
|||||||
{
|
{
|
||||||
if (ecma_is_value_number (this_arg))
|
if (ecma_is_value_number (this_arg))
|
||||||
{
|
{
|
||||||
return ecma_copy_value (this_arg);
|
return this_arg;
|
||||||
}
|
}
|
||||||
else if (ecma_is_value_object (this_arg))
|
else if (ecma_is_value_object (this_arg))
|
||||||
{
|
{
|
||||||
@@ -558,13 +559,89 @@ ecma_builtin_number_prototype_object_value_of (ecma_value_t this_arg) /**< this
|
|||||||
|
|
||||||
JERRY_ASSERT (ecma_is_value_number (ext_object_p->u.class_prop.u.value));
|
JERRY_ASSERT (ecma_is_value_number (ext_object_p->u.class_prop.u.value));
|
||||||
|
|
||||||
return ecma_copy_value (ext_object_p->u.class_prop.u.value);
|
return ext_object_p->u.class_prop.u.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a Number or a Number object."));
|
return ecma_raise_type_error (ECMA_ERR_MSG ("Argument 'this' is not a Number or a Number object."));
|
||||||
} /* ecma_builtin_number_prototype_object_value_of */
|
} /* ecma_builtin_number_prototype_object_value_of */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of number routine
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
NUMBER_ROUTINE_TO_FIXED, /**< Number.prototype.toFixed: ECMA-262 v5, 15.7.4.4 */
|
||||||
|
NUMBER_ROUTINE_TO_EXPONENTIAL, /**< Number.prototype.toExponential: ECMA-262 v5, 15.7.4.5 */
|
||||||
|
NUMBER_ROUTINE_TO_PRECISION, /**< Number.prototype.toPrecision: ECMA-262 v5, 15.7.4.6 */
|
||||||
|
NUMBER_ROUTINE__COUNT, /**< count of the modes */
|
||||||
|
} number_routine_mode_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for the Number.prototype object's
|
||||||
|
* 'toFixed', 'toExponential' and 'toPrecision' routines to
|
||||||
|
* check the special cases before the conversion
|
||||||
|
*
|
||||||
|
* @return ECMA_VALUE_EMPTY - if the conversion should continue
|
||||||
|
* ecma-value - otherwise
|
||||||
|
*/
|
||||||
|
static ecma_value_t
|
||||||
|
ecma_builtin_number_prepare_conversion (ecma_number_t *this_num_p, /**< [out] this argument number */
|
||||||
|
ecma_value_t arg_1, /**< routine's argument */
|
||||||
|
bool *is_negative_p, /**< [out] is negative */
|
||||||
|
int32_t *arg_1_int32_p, /**< [out] routine's argument number
|
||||||
|
* converted to int32_t */
|
||||||
|
number_routine_mode_t mode) /**< number routine mode */
|
||||||
|
{
|
||||||
|
JERRY_ASSERT (mode < NUMBER_ROUTINE__COUNT);
|
||||||
|
|
||||||
|
ecma_number_t arg_num;
|
||||||
|
arg_1 = ecma_get_number (arg_1, &arg_num);
|
||||||
|
|
||||||
|
if (!ecma_is_value_empty (arg_1))
|
||||||
|
{
|
||||||
|
return arg_1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode != NUMBER_ROUTINE_TO_PRECISION
|
||||||
|
&& (arg_num <= -1 || arg_num >= 21))
|
||||||
|
{
|
||||||
|
return ecma_raise_range_error (ECMA_ERR_MSG ("Fraction digits must be between 0 and 20."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ecma_number_is_nan (*this_num_p))
|
||||||
|
{
|
||||||
|
return ecma_make_magic_string_value (LIT_MAGIC_STRING_NAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_negative = false;
|
||||||
|
|
||||||
|
if (ecma_number_is_negative (*this_num_p))
|
||||||
|
{
|
||||||
|
is_negative = ecma_number_is_zero (*this_num_p) ? false : true;
|
||||||
|
*this_num_p *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*is_negative_p = is_negative;
|
||||||
|
|
||||||
|
/* We handle infinities separately. */
|
||||||
|
if (ecma_number_is_infinity (*this_num_p))
|
||||||
|
{
|
||||||
|
return ecma_make_magic_string_value ((is_negative ? LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL
|
||||||
|
: LIT_MAGIC_STRING_INFINITY_UL));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == NUMBER_ROUTINE_TO_PRECISION &&
|
||||||
|
(arg_num < 1 || arg_num >= 22))
|
||||||
|
{
|
||||||
|
return ecma_raise_range_error (ECMA_ERR_MSG ("Precision digits must be between 0 and 21."));
|
||||||
|
}
|
||||||
|
|
||||||
|
*arg_1_int32_p = ecma_number_to_int32 (arg_num);
|
||||||
|
|
||||||
|
return ECMA_VALUE_EMPTY;
|
||||||
|
} /* ecma_builtin_number_prepare_conversion */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Number.prototype object's 'toFixed' routine
|
* The Number.prototype object's 'toFixed' routine
|
||||||
*
|
*
|
||||||
@@ -575,53 +652,27 @@ ecma_builtin_number_prototype_object_value_of (ecma_value_t this_arg) /**< this
|
|||||||
* Returned value must be freed with ecma_free_value.
|
* Returned value must be freed with ecma_free_value.
|
||||||
*/
|
*/
|
||||||
static ecma_value_t
|
static ecma_value_t
|
||||||
ecma_builtin_number_prototype_object_to_fixed (ecma_value_t this_arg, /**< this argument */
|
ecma_builtin_number_prototype_object_to_fixed (ecma_number_t this_num, /**< this argument number */
|
||||||
ecma_value_t arg) /**< routine's argument */
|
ecma_value_t radix) /**< routine's argument */
|
||||||
{
|
{
|
||||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
bool is_negative;
|
||||||
|
int32_t frac_digits;
|
||||||
|
|
||||||
ECMA_TRY_CATCH (this_value, ecma_builtin_number_prototype_object_value_of (this_arg), ret_value);
|
ecma_value_t comp_value = ecma_builtin_number_prepare_conversion (&this_num,
|
||||||
ecma_number_t this_num = ecma_get_number_from_value (this_value);
|
radix,
|
||||||
|
&is_negative,
|
||||||
|
&frac_digits,
|
||||||
|
NUMBER_ROUTINE_TO_FIXED);
|
||||||
|
|
||||||
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value);
|
if (!ecma_is_value_empty (comp_value))
|
||||||
|
|
||||||
/* 2. */
|
|
||||||
if (arg_num <= -1 || arg_num >= 21)
|
|
||||||
{
|
{
|
||||||
ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("Fraction digits must be between 0 and 20."));
|
return comp_value;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 4. */
|
|
||||||
if (ecma_number_is_nan (this_num))
|
|
||||||
{
|
|
||||||
ret_value = ecma_make_magic_string_value (LIT_MAGIC_STRING_NAN);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 6. */
|
|
||||||
bool is_negative = false;
|
|
||||||
if (ecma_number_is_negative (this_num))
|
|
||||||
{
|
|
||||||
is_negative = ecma_number_is_zero (this_num) ? false : true;
|
|
||||||
this_num *= -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We handle infinities separately. */
|
|
||||||
if (ecma_number_is_infinity (this_num))
|
|
||||||
{
|
|
||||||
lit_magic_string_id_t id = (is_negative ? LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL
|
|
||||||
: LIT_MAGIC_STRING_INFINITY_UL);
|
|
||||||
|
|
||||||
ret_value = ecma_make_magic_string_value (id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Get the parameters of the number if non-zero. */
|
/* Get the parameters of the number if non-zero. */
|
||||||
lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
|
lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
|
||||||
lit_utf8_size_t num_digits;
|
lit_utf8_size_t num_digits;
|
||||||
int32_t exponent;
|
int32_t exponent;
|
||||||
int32_t frac_digits = ecma_number_to_int32 (arg_num);
|
|
||||||
|
|
||||||
if (!ecma_number_is_zero (this_num))
|
if (!ecma_number_is_zero (this_num))
|
||||||
{
|
{
|
||||||
@@ -640,12 +691,10 @@ ecma_builtin_number_prototype_object_to_fixed (ecma_value_t this_arg, /**< this
|
|||||||
/* 7. */
|
/* 7. */
|
||||||
if (exponent > 21)
|
if (exponent > 21)
|
||||||
{
|
{
|
||||||
ret_value = ecma_builtin_number_prototype_object_to_string (this_arg, NULL, 0);
|
return ecma_builtin_number_prototype_object_to_string (this_num, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 8. */
|
/* 8. */
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 1. */
|
|
||||||
num_digits = ecma_builtin_number_prototype_helper_round (digits,
|
num_digits = ecma_builtin_number_prototype_helper_round (digits,
|
||||||
num_digits + 1,
|
num_digits + 1,
|
||||||
exponent + frac_digits,
|
exponent + frac_digits,
|
||||||
@@ -661,6 +710,8 @@ ecma_builtin_number_prototype_object_to_fixed (ecma_value_t this_arg, /**< this
|
|||||||
}
|
}
|
||||||
|
|
||||||
JERRY_ASSERT (buffer_size > 0);
|
JERRY_ASSERT (buffer_size > 0);
|
||||||
|
|
||||||
|
ecma_value_t ret_value;
|
||||||
JMEM_DEFINE_LOCAL_ARRAY (buff, buffer_size, lit_utf8_byte_t);
|
JMEM_DEFINE_LOCAL_ARRAY (buff, buffer_size, lit_utf8_byte_t);
|
||||||
|
|
||||||
lit_utf8_byte_t *p = buff;
|
lit_utf8_byte_t *p = buff;
|
||||||
@@ -684,13 +735,7 @@ ecma_builtin_number_prototype_object_to_fixed (ecma_value_t this_arg, /**< this
|
|||||||
|
|
||||||
ret_value = ecma_make_string_value (str);
|
ret_value = ecma_make_string_value (str);
|
||||||
JMEM_FINALIZE_LOCAL_ARRAY (buff);
|
JMEM_FINALIZE_LOCAL_ARRAY (buff);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ECMA_OP_TO_NUMBER_FINALIZE (arg_num);
|
|
||||||
ECMA_FINALIZE (this_value);
|
|
||||||
return ret_value;
|
return ret_value;
|
||||||
} /* ecma_builtin_number_prototype_object_to_fixed */
|
} /* ecma_builtin_number_prototype_object_to_fixed */
|
||||||
|
|
||||||
@@ -704,49 +749,23 @@ ecma_builtin_number_prototype_object_to_fixed (ecma_value_t this_arg, /**< this
|
|||||||
* Returned value must be freed with ecma_free_value.
|
* Returned value must be freed with ecma_free_value.
|
||||||
*/
|
*/
|
||||||
static ecma_value_t
|
static ecma_value_t
|
||||||
ecma_builtin_number_prototype_object_to_exponential (ecma_value_t this_arg, /**< this argument */
|
ecma_builtin_number_prototype_object_to_exponential (ecma_number_t this_num, /**< this argument number */
|
||||||
ecma_value_t arg) /**< routine's argument */
|
ecma_value_t fraction_digits) /**< routine's argument */
|
||||||
{
|
{
|
||||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
bool is_negative;
|
||||||
|
int32_t frac_digits;
|
||||||
|
|
||||||
/* 1. */
|
ecma_value_t comp_value = ecma_builtin_number_prepare_conversion (&this_num,
|
||||||
ECMA_TRY_CATCH (this_value, ecma_builtin_number_prototype_object_value_of (this_arg), ret_value);
|
fraction_digits,
|
||||||
ecma_number_t this_num = ecma_get_number_from_value (this_value);
|
&is_negative,
|
||||||
|
&frac_digits,
|
||||||
|
NUMBER_ROUTINE_TO_EXPONENTIAL);
|
||||||
|
|
||||||
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value);
|
if (!ecma_is_value_empty (comp_value))
|
||||||
|
|
||||||
/* 7. */
|
|
||||||
if (arg_num <= -1.0 || arg_num >= 21.0)
|
|
||||||
{
|
{
|
||||||
ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("Fraction digits must be between 0 and 20."));
|
return comp_value;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 3. */
|
|
||||||
if (ecma_number_is_nan (this_num))
|
|
||||||
{
|
|
||||||
ret_value = ecma_make_magic_string_value (LIT_MAGIC_STRING_NAN);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 5. */
|
|
||||||
bool is_negative = false;
|
|
||||||
if (ecma_number_is_negative (this_num) && !ecma_number_is_zero (this_num))
|
|
||||||
{
|
|
||||||
is_negative = true;
|
|
||||||
this_num *= -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 6. */
|
|
||||||
if (ecma_number_is_infinity (this_num))
|
|
||||||
{
|
|
||||||
lit_magic_string_id_t id = (is_negative ? LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL
|
|
||||||
: LIT_MAGIC_STRING_INFINITY_UL);
|
|
||||||
|
|
||||||
ret_value = ecma_make_magic_string_value (id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Get the parameters of the number if non zero. */
|
/* Get the parameters of the number if non zero. */
|
||||||
lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
|
lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
|
||||||
lit_utf8_size_t num_digits;
|
lit_utf8_size_t num_digits;
|
||||||
@@ -763,15 +782,10 @@ ecma_builtin_number_prototype_object_to_exponential (ecma_value_t this_arg, /**<
|
|||||||
exponent = 1;
|
exponent = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t frac_digits;
|
if (ecma_is_value_undefined (fraction_digits))
|
||||||
if (ecma_is_value_undefined (arg))
|
|
||||||
{
|
{
|
||||||
frac_digits = (int32_t) num_digits - 1;
|
frac_digits = (int32_t) num_digits - 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
frac_digits = ecma_number_to_int32 (arg_num);
|
|
||||||
}
|
|
||||||
|
|
||||||
num_digits = ecma_builtin_number_prototype_helper_round (digits, num_digits, frac_digits + 1, &exponent, false);
|
num_digits = ecma_builtin_number_prototype_helper_round (digits, num_digits, frac_digits + 1, &exponent, false);
|
||||||
|
|
||||||
@@ -784,6 +798,7 @@ ecma_builtin_number_prototype_object_to_exponential (ecma_value_t this_arg, /**<
|
|||||||
buffer_size++;
|
buffer_size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ecma_value_t ret_value;
|
||||||
JMEM_DEFINE_LOCAL_ARRAY (buff, buffer_size, lit_utf8_byte_t);
|
JMEM_DEFINE_LOCAL_ARRAY (buff, buffer_size, lit_utf8_byte_t);
|
||||||
|
|
||||||
lit_utf8_byte_t *actual_char_p = buff;
|
lit_utf8_byte_t *actual_char_p = buff;
|
||||||
@@ -820,12 +835,7 @@ ecma_builtin_number_prototype_object_to_exponential (ecma_value_t this_arg, /**<
|
|||||||
ecma_string_t *str = ecma_new_ecma_string_from_utf8 (buff, (lit_utf8_size_t) (actual_char_p - buff));
|
ecma_string_t *str = ecma_new_ecma_string_from_utf8 (buff, (lit_utf8_size_t) (actual_char_p - buff));
|
||||||
ret_value = ecma_make_string_value (str);
|
ret_value = ecma_make_string_value (str);
|
||||||
JMEM_FINALIZE_LOCAL_ARRAY (buff);
|
JMEM_FINALIZE_LOCAL_ARRAY (buff);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ECMA_OP_TO_NUMBER_FINALIZE (arg_num);
|
|
||||||
ECMA_FINALIZE (this_value);
|
|
||||||
return ret_value;
|
return ret_value;
|
||||||
} /* ecma_builtin_number_prototype_object_to_exponential */
|
} /* ecma_builtin_number_prototype_object_to_exponential */
|
||||||
|
|
||||||
@@ -839,55 +849,28 @@ ecma_builtin_number_prototype_object_to_exponential (ecma_value_t this_arg, /**<
|
|||||||
* Returned value must be freed with ecma_free_value.
|
* Returned value must be freed with ecma_free_value.
|
||||||
*/
|
*/
|
||||||
static ecma_value_t
|
static ecma_value_t
|
||||||
ecma_builtin_number_prototype_object_to_precision (ecma_value_t this_arg, /**< this argument */
|
ecma_builtin_number_prototype_object_to_precision (ecma_number_t this_num, /**< this argument number */
|
||||||
ecma_value_t arg) /**< routine's argument */
|
ecma_value_t precision_value) /**< routine's argument */
|
||||||
{
|
{
|
||||||
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
|
if (ecma_is_value_undefined (precision_value))
|
||||||
|
|
||||||
/* 1. */
|
|
||||||
ECMA_TRY_CATCH (this_value, ecma_builtin_number_prototype_object_value_of (this_arg), ret_value);
|
|
||||||
ecma_number_t this_num = ecma_get_number_from_value (this_value);
|
|
||||||
|
|
||||||
/* 2. */
|
|
||||||
if (ecma_is_value_undefined (arg))
|
|
||||||
{
|
{
|
||||||
ret_value = ecma_builtin_number_prototype_object_to_string (this_arg, NULL, 0);
|
return ecma_builtin_number_prototype_object_to_string (this_num, NULL, 0);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 3. */
|
|
||||||
ECMA_OP_TO_NUMBER_TRY_CATCH (arg_num, arg, ret_value);
|
|
||||||
|
|
||||||
/* 4. */
|
|
||||||
if (ecma_number_is_nan (this_num))
|
|
||||||
{
|
|
||||||
ret_value = ecma_make_magic_string_value (LIT_MAGIC_STRING_NAN);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* 6. */
|
|
||||||
bool is_negative = false;
|
|
||||||
if (ecma_number_is_negative (this_num) && !ecma_number_is_zero (this_num))
|
|
||||||
{
|
|
||||||
is_negative = true;
|
|
||||||
this_num *= -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 7. */
|
bool is_negative;
|
||||||
if (ecma_number_is_infinity (this_num))
|
int32_t precision;
|
||||||
{
|
|
||||||
lit_magic_string_id_t id = (is_negative ? LIT_MAGIC_STRING_NEGATIVE_INFINITY_UL
|
|
||||||
: LIT_MAGIC_STRING_INFINITY_UL);
|
|
||||||
|
|
||||||
ret_value = ecma_make_magic_string_value (id);
|
ecma_value_t comp_value = ecma_builtin_number_prepare_conversion (&this_num,
|
||||||
}
|
precision_value,
|
||||||
/* 8. */
|
&is_negative,
|
||||||
else if (arg_num < 1.0 || arg_num >= 22.0)
|
&precision,
|
||||||
|
NUMBER_ROUTINE_TO_PRECISION);
|
||||||
|
|
||||||
|
if (!ecma_is_value_empty (comp_value))
|
||||||
{
|
{
|
||||||
ret_value = ecma_raise_range_error (ECMA_ERR_MSG ("Precision must be between 1 and 21."));
|
return comp_value;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Get the parameters of the number if non-zero. */
|
/* Get the parameters of the number if non-zero. */
|
||||||
lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
|
lit_utf8_byte_t digits[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
|
||||||
lit_utf8_size_t num_digits;
|
lit_utf8_size_t num_digits;
|
||||||
@@ -904,8 +887,6 @@ ecma_builtin_number_prototype_object_to_precision (ecma_value_t this_arg, /**< t
|
|||||||
exponent = 1;
|
exponent = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t precision = ecma_number_to_int32 (arg_num);
|
|
||||||
|
|
||||||
num_digits = ecma_builtin_number_prototype_helper_round (digits, num_digits, precision, &exponent, false);
|
num_digits = ecma_builtin_number_prototype_helper_round (digits, num_digits, precision, &exponent, false);
|
||||||
|
|
||||||
int buffer_size;
|
int buffer_size;
|
||||||
@@ -930,6 +911,7 @@ ecma_builtin_number_prototype_object_to_precision (ecma_value_t this_arg, /**< t
|
|||||||
buffer_size++;
|
buffer_size++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ecma_value_t ret_value;
|
||||||
JMEM_DEFINE_LOCAL_ARRAY (buff, buffer_size, lit_utf8_byte_t);
|
JMEM_DEFINE_LOCAL_ARRAY (buff, buffer_size, lit_utf8_byte_t);
|
||||||
lit_utf8_byte_t *actual_char_p = buff;
|
lit_utf8_byte_t *actual_char_p = buff;
|
||||||
|
|
||||||
@@ -982,15 +964,69 @@ ecma_builtin_number_prototype_object_to_precision (ecma_value_t this_arg, /**< t
|
|||||||
|
|
||||||
ret_value = ecma_make_string_value (str_p);
|
ret_value = ecma_make_string_value (str_p);
|
||||||
JMEM_FINALIZE_LOCAL_ARRAY (buff);
|
JMEM_FINALIZE_LOCAL_ARRAY (buff);
|
||||||
}
|
|
||||||
}
|
|
||||||
ECMA_OP_TO_NUMBER_FINALIZE (arg_num);
|
|
||||||
}
|
|
||||||
ECMA_FINALIZE (this_value);
|
|
||||||
|
|
||||||
return ret_value;
|
return ret_value;
|
||||||
} /* ecma_builtin_number_prototype_object_to_precision */
|
} /* ecma_builtin_number_prototype_object_to_precision */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispatcher of the built-in's routines
|
||||||
|
*
|
||||||
|
* @return ecma value
|
||||||
|
* Returned value must be freed with ecma_free_value.
|
||||||
|
*/
|
||||||
|
ecma_value_t
|
||||||
|
ecma_builtin_number_prototype_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_p[], /**< list of arguments
|
||||||
|
* passed to routine */
|
||||||
|
ecma_length_t arguments_number) /**< length of arguments' list */
|
||||||
|
{
|
||||||
|
ecma_value_t this_value = ecma_builtin_number_prototype_object_value_of (this_arg);
|
||||||
|
|
||||||
|
if (ECMA_IS_VALUE_ERROR (this_value))
|
||||||
|
{
|
||||||
|
return this_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (builtin_routine_id == ECMA_NUMBER_PROTOTYPE_VALUE_OF)
|
||||||
|
{
|
||||||
|
return ecma_copy_value (this_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ecma_number_t this_arg_number = ecma_get_number_from_value (this_value);
|
||||||
|
|
||||||
|
ecma_value_t routine_arg_1 = arguments_list_p[0];
|
||||||
|
|
||||||
|
switch (builtin_routine_id)
|
||||||
|
{
|
||||||
|
case ECMA_NUMBER_PROTOTYPE_TO_STRING:
|
||||||
|
{
|
||||||
|
return ecma_builtin_number_prototype_object_to_string (this_arg_number, arguments_list_p, arguments_number);
|
||||||
|
}
|
||||||
|
case ECMA_NUMBER_PROTOTYPE_TO_LOCALE_STRING:
|
||||||
|
{
|
||||||
|
return ecma_builtin_number_prototype_object_to_string (this_arg_number, NULL, 0);
|
||||||
|
}
|
||||||
|
case ECMA_NUMBER_PROTOTYPE_TO_FIXED:
|
||||||
|
{
|
||||||
|
return ecma_builtin_number_prototype_object_to_fixed (this_arg_number, routine_arg_1);
|
||||||
|
}
|
||||||
|
case ECMA_NUMBER_PROTOTYPE_TO_EXPONENTIAL:
|
||||||
|
{
|
||||||
|
return ecma_builtin_number_prototype_object_to_exponential (this_arg_number, routine_arg_1);
|
||||||
|
}
|
||||||
|
case ECMA_NUMBER_PROTOTYPE_TO_PRECISION:
|
||||||
|
{
|
||||||
|
return ecma_builtin_number_prototype_object_to_precision (this_arg_number, routine_arg_1);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
JERRY_UNREACHABLE ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} /* ecma_builtin_number_prototype_dispatch_routine */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
* @}
|
* @}
|
||||||
|
|||||||
@@ -31,12 +31,12 @@ OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR,
|
|||||||
|
|
||||||
/* Routine properties:
|
/* Routine properties:
|
||||||
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
* (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
|
||||||
ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ecma_builtin_number_prototype_object_to_string, NON_FIXED, 1)
|
ROUTINE (LIT_MAGIC_STRING_TO_STRING_UL, ECMA_NUMBER_PROTOTYPE_TO_STRING, NON_FIXED, 1)
|
||||||
ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ecma_builtin_number_prototype_object_value_of, 0, 0)
|
ROUTINE (LIT_MAGIC_STRING_VALUE_OF_UL, ECMA_NUMBER_PROTOTYPE_VALUE_OF, 0, 0)
|
||||||
ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ecma_builtin_number_prototype_object_to_locale_string, 0, 0)
|
ROUTINE (LIT_MAGIC_STRING_TO_LOCALE_STRING_UL, ECMA_NUMBER_PROTOTYPE_TO_LOCALE_STRING, 0, 0)
|
||||||
ROUTINE (LIT_MAGIC_STRING_TO_FIXED_UL, ecma_builtin_number_prototype_object_to_fixed, 1, 1)
|
ROUTINE (LIT_MAGIC_STRING_TO_FIXED_UL, ECMA_NUMBER_PROTOTYPE_TO_FIXED, 1, 1)
|
||||||
ROUTINE (LIT_MAGIC_STRING_TO_EXPONENTIAL_UL, ecma_builtin_number_prototype_object_to_exponential, 1, 1)
|
ROUTINE (LIT_MAGIC_STRING_TO_EXPONENTIAL_UL, ECMA_NUMBER_PROTOTYPE_TO_EXPONENTIAL, 1, 1)
|
||||||
ROUTINE (LIT_MAGIC_STRING_TO_PRECISION_UL, ecma_builtin_number_prototype_object_to_precision, 1, 1)
|
ROUTINE (LIT_MAGIC_STRING_TO_PRECISION_UL, ECMA_NUMBER_PROTOTYPE_TO_PRECISION, 1, 1)
|
||||||
|
|
||||||
#endif /* ENABLED (JERRY_BUILTIN_NUMBER) */
|
#endif /* ENABLED (JERRY_BUILTIN_NUMBER) */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user