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:
Robert Fancsik
2019-07-17 14:10:20 +02:00
committed by Dániel Bátyai
parent 7aa3bfdc6d
commit 329b1fd3f7
2 changed files with 685 additions and 649 deletions
@@ -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) */