Storing Number as UInt32 in ecma-string if the Number may be represented as UInt32. Calculating length for Number-represented ecma-strings in ecma-string constructor. loop_arithmetics_1kk.js: 2.9112 -> 2.8536.
This commit is contained in:
@@ -536,11 +536,14 @@ typedef struct
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECMA_STRING_CONTAINER_LIT_TABLE, /**< actual data is in literal table */
|
||||
ECMA_STRING_CONTAINER_HEAP_CHUNKS, /**< actual data is on the heap
|
||||
in a ecma_collection_chunk_t chain */
|
||||
ECMA_STRING_CONTAINER_LIT_TABLE, /**< actual data is in literal table */
|
||||
ECMA_STRING_CONTAINER_IN_DESCRIPTOR, /**< actual data is locally in the string's descriptor */
|
||||
ECMA_STRING_CONTAINER_HEAP_NUMBER /**< actual data is on the heap as a ecma_number_t */
|
||||
ECMA_STRING_CONTAINER_HEAP_NUMBER, /**< actual data is on the heap as a ecma_number_t */
|
||||
ECMA_STRING_CONTAINER_CHARS_IN_DESC, /**< actual data are several characters
|
||||
stored locally in the string's descriptor */
|
||||
ECMA_STRING_CONTAINER_UINT32_IN_DESC /**< actual data is UInt32-represeneted Number
|
||||
stored locally in the string's descriptor */
|
||||
} ecma_string_container_t;
|
||||
|
||||
FIXME (Move to library that should define the type (libserializer /* ? */))
|
||||
@@ -558,7 +561,7 @@ typedef struct
|
||||
unsigned int refs : CONFIG_ECMA_REFERENCE_COUNTER_WIDTH;
|
||||
|
||||
/** Where the string's data is placed (ecma_string_container_t) */
|
||||
unsigned int container : 2;
|
||||
unsigned int container : 3;
|
||||
|
||||
/** Flag indicating whether the length field is valid */
|
||||
unsigned int is_length_valid : 1;
|
||||
@@ -580,8 +583,11 @@ typedef struct
|
||||
/** Compressed pointer to an ecma_number_t */
|
||||
unsigned int number_cp : ECMA_POINTER_FIELD_WIDTH;
|
||||
|
||||
/** Actual data if placed locally in the descriptor */
|
||||
ecma_char_t chars[ sizeof (uint64_t) - sizeof (uint32_t) ];
|
||||
/** Actual data placed locally in the descriptor */
|
||||
ecma_char_t chars[ sizeof (uint32_t) ];
|
||||
|
||||
/** UInt32-represented number placed locally in the descriptor */
|
||||
uint32_t uint32_number;
|
||||
} u;
|
||||
} ecma_string_t;
|
||||
|
||||
|
||||
@@ -57,23 +57,29 @@ ecma_zt_string_to_number (const ecma_char_t *str_p) /**< zero-terminated string
|
||||
|
||||
/**
|
||||
* ECMA-defined conversion of UInt32 to String (zero-terminated).
|
||||
*
|
||||
* @return number of bytes copied to buffer
|
||||
*/
|
||||
void
|
||||
ecma_length_t
|
||||
ecma_uint32_to_string (uint32_t value, /**< value to convert */
|
||||
ecma_char_t *out_buffer_p, /**< buffer for zero-terminated string */
|
||||
size_t buffer_size) /**< size of buffer */
|
||||
ssize_t buffer_size) /**< size of buffer */
|
||||
{
|
||||
FIXME (Implement according to ECMA);
|
||||
|
||||
ecma_char_t *p = (ecma_char_t*) ((uint8_t*) out_buffer_p + buffer_size) - 1;
|
||||
*p-- = '\0';
|
||||
|
||||
ecma_length_t bytes_copied = 1;
|
||||
|
||||
do
|
||||
{
|
||||
JERRY_ASSERT (p != out_buffer_p);
|
||||
|
||||
*p-- = (ecma_char_t) ("0123456789"[value % 10]);
|
||||
value /= 10;
|
||||
|
||||
bytes_copied++;
|
||||
}
|
||||
while (value != 0);
|
||||
|
||||
@@ -82,6 +88,8 @@ ecma_uint32_to_string (uint32_t value, /**< value to convert */
|
||||
ssize_t bytes_to_move = ((uint8_t*) out_buffer_p + buffer_size) - (uint8_t*) p;
|
||||
__memmove (out_buffer_p, p, (size_t) bytes_to_move);
|
||||
}
|
||||
|
||||
return bytes_copied;
|
||||
} /* ecma_uint32_to_string */
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,7 +57,7 @@ ecma_new_ecma_string (const ecma_char_t *string_p) /**< zero-terminated string *
|
||||
|
||||
if (bytes_needed_for_current_string <= bytes_for_chars_in_string_descriptor)
|
||||
{
|
||||
string_desc_p->container = ECMA_STRING_CONTAINER_IN_DESCRIPTOR;
|
||||
string_desc_p->container = ECMA_STRING_CONTAINER_CHARS_IN_DESC;
|
||||
__memcpy (string_desc_p->u.chars, string_p, bytes_needed_for_current_string);
|
||||
|
||||
return string_desc_p;
|
||||
@@ -99,12 +99,63 @@ ecma_new_ecma_string (const ecma_char_t *string_p) /**< zero-terminated string *
|
||||
* @return pointer to ecma-string descriptor
|
||||
*/
|
||||
ecma_string_t*
|
||||
ecma_new_ecma_string_from_number (ecma_number_t num) /**< ecma-number */
|
||||
ecma_new_ecma_string_from_uint32 (uint32_t uint32_number) /**< UInt32-represented ecma-number */
|
||||
{
|
||||
ecma_string_t* string_desc_p = ecma_alloc_string ();
|
||||
string_desc_p->refs = 1;
|
||||
string_desc_p->length = 0;
|
||||
string_desc_p->is_length_valid = false;
|
||||
string_desc_p->container = ECMA_STRING_CONTAINER_UINT32_IN_DESC;
|
||||
string_desc_p->u.uint32_number = uint32_number;
|
||||
|
||||
const uint32_t max_uint32_len = 10;
|
||||
const uint32_t nums_with_ascending_length[10] =
|
||||
{
|
||||
1u,
|
||||
10u,
|
||||
100u,
|
||||
1000u,
|
||||
10000u,
|
||||
100000u,
|
||||
1000000u,
|
||||
10000000u,
|
||||
100000000u,
|
||||
1000000000u
|
||||
};
|
||||
|
||||
string_desc_p->length = 1;
|
||||
|
||||
while (string_desc_p->length < max_uint32_len
|
||||
&& uint32_number >= nums_with_ascending_length [string_desc_p->length])
|
||||
{
|
||||
string_desc_p->length++;
|
||||
}
|
||||
string_desc_p->is_length_valid = true;
|
||||
|
||||
return string_desc_p;
|
||||
} /* ecma_new_ecma_string_from_uint32 */
|
||||
|
||||
/**
|
||||
* Allocate new ecma-string and fill it with ecma-number
|
||||
*
|
||||
* @return pointer to ecma-string descriptor
|
||||
*/
|
||||
ecma_string_t*
|
||||
ecma_new_ecma_string_from_number (ecma_number_t num) /**< ecma-number */
|
||||
{
|
||||
uint32_t uint32_num = ecma_number_to_uint32 (num);
|
||||
if (num == ecma_uint32_to_number (uint32_num))
|
||||
{
|
||||
return ecma_new_ecma_string_from_uint32 (uint32_num);
|
||||
}
|
||||
|
||||
ecma_char_t buffer[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER + 1];
|
||||
ecma_length_t length = ecma_number_to_zt_string (num,
|
||||
buffer,
|
||||
sizeof (buffer));
|
||||
|
||||
ecma_string_t* string_desc_p = ecma_alloc_string ();
|
||||
string_desc_p->refs = 1;
|
||||
string_desc_p->length = length;
|
||||
string_desc_p->is_length_valid = true;
|
||||
string_desc_p->container = ECMA_STRING_CONTAINER_HEAP_NUMBER;
|
||||
|
||||
ecma_number_t *num_p = ecma_alloc_number ();
|
||||
@@ -197,7 +248,7 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (string_p->container == ECMA_STRING_CONTAINER_IN_DESCRIPTOR
|
||||
JERRY_ASSERT (string_p->container == ECMA_STRING_CONTAINER_CHARS_IN_DESC
|
||||
|| string_p->container == ECMA_STRING_CONTAINER_LIT_TABLE);
|
||||
|
||||
/* only the string descriptor itself should be freed */
|
||||
@@ -206,42 +257,6 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */
|
||||
ecma_dealloc_string (string_p);
|
||||
} /* ecma_deref_ecma_string */
|
||||
|
||||
/**
|
||||
* Get length of the ecma-string
|
||||
*
|
||||
* @return length
|
||||
*/
|
||||
ecma_length_t
|
||||
ecma_get_ecma_string_length (ecma_string_t *string_desc_p) /**< ecma-string descriptor */
|
||||
{
|
||||
switch ((ecma_string_container_t)string_desc_p->container)
|
||||
{
|
||||
case ECMA_STRING_CONTAINER_HEAP_CHUNKS:
|
||||
case ECMA_STRING_CONTAINER_LIT_TABLE:
|
||||
case ECMA_STRING_CONTAINER_IN_DESCRIPTOR:
|
||||
{
|
||||
JERRY_ASSERT (string_desc_p->is_length_valid);
|
||||
|
||||
return string_desc_p->length;
|
||||
}
|
||||
|
||||
case ECMA_STRING_CONTAINER_HEAP_NUMBER:
|
||||
{
|
||||
if (string_desc_p->is_length_valid)
|
||||
{
|
||||
return string_desc_p->length;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* calculate length */
|
||||
JERRY_UNIMPLEMENTED();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_UNREACHABLE();
|
||||
} /* ecma_get_ecma_string_length */
|
||||
|
||||
/**
|
||||
* Convert ecma-string to number
|
||||
*/
|
||||
@@ -249,8 +264,15 @@ ecma_number_t
|
||||
ecma_string_to_number (ecma_string_t *str_p) /**< ecma-string */
|
||||
{
|
||||
JERRY_ASSERT (str_p != NULL);
|
||||
JERRY_ASSERT (str_p->is_length_valid);
|
||||
|
||||
if (str_p->container == ECMA_STRING_CONTAINER_HEAP_NUMBER)
|
||||
if (str_p->container == ECMA_STRING_CONTAINER_UINT32_IN_DESC)
|
||||
{
|
||||
uint32_t uint32_number = str_p->u.uint32_number;
|
||||
|
||||
return ecma_uint32_to_number (uint32_number);
|
||||
}
|
||||
else if (str_p->container == ECMA_STRING_CONTAINER_HEAP_NUMBER)
|
||||
{
|
||||
ecma_number_t *num_p = ECMA_GET_POINTER (str_p->u.number_cp);
|
||||
|
||||
@@ -258,8 +280,6 @@ ecma_string_to_number (ecma_string_t *str_p) /**< ecma-string */
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_ASSERT (str_p->is_length_valid);
|
||||
|
||||
ecma_char_t zt_string_buffer [str_p->length + 1];
|
||||
|
||||
ssize_t bytes_copied = ecma_string_to_zt_string (str_p,
|
||||
@@ -277,31 +297,9 @@ ecma_string_to_number (ecma_string_t *str_p) /**< ecma-string */
|
||||
static ssize_t
|
||||
ecma_string_get_required_buffer_size_for_zt_form (const ecma_string_t *string_desc_p) /**< ecma-string */
|
||||
{
|
||||
ecma_length_t string_length = 0;
|
||||
JERRY_ASSERT (string_desc_p->is_length_valid);
|
||||
|
||||
switch ((ecma_string_container_t)string_desc_p->container)
|
||||
{
|
||||
case ECMA_STRING_CONTAINER_IN_DESCRIPTOR:
|
||||
case ECMA_STRING_CONTAINER_HEAP_CHUNKS:
|
||||
case ECMA_STRING_CONTAINER_LIT_TABLE:
|
||||
{
|
||||
JERRY_ASSERT (string_desc_p->is_length_valid);
|
||||
|
||||
string_length = string_desc_p->length;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_STRING_CONTAINER_HEAP_NUMBER:
|
||||
{
|
||||
string_length = (string_desc_p->is_length_valid ?
|
||||
string_desc_p->length : ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (ssize_t) ((ssize_t) sizeof (ecma_char_t) * (string_length + 1));
|
||||
return (ssize_t) ((string_desc_p->length + 1u) * sizeof (ecma_char_t));
|
||||
} /* ecma_string_get_required_buffer_size_for_zt_form */
|
||||
|
||||
/**
|
||||
@@ -322,6 +320,7 @@ ecma_string_to_zt_string (ecma_string_t *string_desc_p, /**< ecma-string descrip
|
||||
JERRY_ASSERT (string_desc_p->refs > 0);
|
||||
JERRY_ASSERT (buffer_p != NULL);
|
||||
JERRY_ASSERT (buffer_size > 0);
|
||||
JERRY_ASSERT (string_desc_p->is_length_valid);
|
||||
|
||||
ssize_t required_buffer_size = ecma_string_get_required_buffer_size_for_zt_form (string_desc_p);
|
||||
ssize_t bytes_copied = 0;
|
||||
@@ -335,9 +334,8 @@ ecma_string_to_zt_string (ecma_string_t *string_desc_p, /**< ecma-string descrip
|
||||
|
||||
switch ((ecma_string_container_t)string_desc_p->container)
|
||||
{
|
||||
case ECMA_STRING_CONTAINER_IN_DESCRIPTOR:
|
||||
case ECMA_STRING_CONTAINER_CHARS_IN_DESC:
|
||||
{
|
||||
JERRY_ASSERT (string_desc_p->is_length_valid);
|
||||
ecma_length_t string_length = string_desc_p->length;
|
||||
|
||||
__memcpy (dest_p, string_desc_p->u.chars, string_length * sizeof (ecma_char_t));
|
||||
@@ -349,7 +347,6 @@ ecma_string_to_zt_string (ecma_string_t *string_desc_p, /**< ecma-string descrip
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_HEAP_CHUNKS:
|
||||
{
|
||||
JERRY_ASSERT (string_desc_p->is_length_valid);
|
||||
ecma_length_t string_length = string_desc_p->length;
|
||||
|
||||
ecma_collection_chunk_t *string_chunk_p = ECMA_GET_POINTER (string_desc_p->u.chunk_cp);
|
||||
@@ -382,26 +379,20 @@ ecma_string_to_zt_string (ecma_string_t *string_desc_p, /**< ecma-string descrip
|
||||
|
||||
break;
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
|
||||
{
|
||||
uint32_t uint32_number = string_desc_p->u.uint32_number;
|
||||
bytes_copied = ecma_uint32_to_string (uint32_number, buffer_p, required_buffer_size);
|
||||
|
||||
break;
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_HEAP_NUMBER:
|
||||
{
|
||||
const ssize_t buffer_size_required = (ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER + 1) * sizeof (ecma_char_t);
|
||||
if (buffer_size_required < buffer_size)
|
||||
{
|
||||
return -(ssize_t) buffer_size_required;
|
||||
}
|
||||
|
||||
ecma_number_t *num_p = ECMA_GET_POINTER (string_desc_p->u.number_cp);
|
||||
|
||||
ecma_length_t length = ecma_number_to_zt_string (*num_p, buffer_p, buffer_size);
|
||||
|
||||
if (!string_desc_p->is_length_valid)
|
||||
{
|
||||
string_desc_p->length = length;
|
||||
string_desc_p->is_length_valid = true;
|
||||
}
|
||||
|
||||
JERRY_ASSERT (string_desc_p->is_length_valid
|
||||
&& string_desc_p->length == length);
|
||||
JERRY_ASSERT (string_desc_p->length == length);
|
||||
|
||||
bytes_copied = (length + 1) * ((ssize_t) sizeof (ecma_char_t));
|
||||
}
|
||||
@@ -626,19 +617,17 @@ ecma_compare_ecma_string_to_ecma_string (ecma_string_t *string1_p, /* ecma-strin
|
||||
ecma_string_t *string2_p) /* ecma-string */
|
||||
{
|
||||
JERRY_ASSERT (string1_p != NULL && string2_p != NULL);
|
||||
JERRY_ASSERT (string1_p->is_length_valid
|
||||
&& string2_p->is_length_valid);
|
||||
|
||||
if (unlikely (string1_p == string2_p))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (string1_p->is_length_valid
|
||||
&& string2_p->is_length_valid)
|
||||
if (likely (string1_p->length != string2_p->length))
|
||||
{
|
||||
if (likely (string1_p->length != string2_p->length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (string1_p->container == string2_p->container)
|
||||
@@ -661,10 +650,8 @@ ecma_compare_ecma_string_to_ecma_string (ecma_string_t *string1_p, /* ecma-strin
|
||||
|
||||
return (*num1_p == *num2_p);
|
||||
}
|
||||
else if (string1_p->container == ECMA_STRING_CONTAINER_IN_DESCRIPTOR)
|
||||
else if (string1_p->container == ECMA_STRING_CONTAINER_CHARS_IN_DESC)
|
||||
{
|
||||
JERRY_ASSERT (string1_p->is_length_valid);
|
||||
JERRY_ASSERT (string2_p->is_length_valid);
|
||||
JERRY_ASSERT (string1_p->length == string2_p->length);
|
||||
|
||||
return (__memcmp (string1_p->u.chars, string2_p->u.chars, string1_p->length * sizeof (ecma_char_t)) == 0);
|
||||
|
||||
@@ -88,11 +88,11 @@ extern bool ecma_is_empty_completion_value (ecma_completion_value_t value);
|
||||
|
||||
/* ecma-helpers-string.c */
|
||||
extern ecma_string_t* ecma_new_ecma_string (const ecma_char_t *string_p);
|
||||
extern ecma_string_t* ecma_new_ecma_string_from_uint32 (uint32_t uint_number);
|
||||
extern ecma_string_t* ecma_new_ecma_string_from_number (ecma_number_t number);
|
||||
extern ecma_string_t* ecma_new_ecma_string_from_lit_index (literal_index_t lit_index);
|
||||
extern void ecma_ref_ecma_string (ecma_string_t *string_desc_p);
|
||||
extern void ecma_deref_ecma_string (ecma_string_t *string_p);
|
||||
extern ecma_length_t ecma_get_ecma_string_length (ecma_string_t *string_desc_p);
|
||||
extern ecma_number_t ecma_string_to_number (ecma_string_t *str_p);
|
||||
extern ssize_t ecma_string_to_zt_string (ecma_string_t *string_desc_p,
|
||||
ecma_char_t *buffer_p,
|
||||
@@ -187,7 +187,7 @@ extern ecma_property_descriptor_t ecma_make_empty_property_descriptor (void);
|
||||
|
||||
/* ecma-helpers-conversion.c */
|
||||
extern ecma_number_t ecma_zt_string_to_number (const ecma_char_t *str_p);
|
||||
extern void ecma_uint32_to_string (uint32_t value, ecma_char_t *out_buffer_p, size_t buffer_size);
|
||||
extern ecma_length_t ecma_uint32_to_string (uint32_t value, ecma_char_t *out_buffer_p, ssize_t buffer_size);
|
||||
extern uint32_t ecma_number_to_uint32 (ecma_number_t value);
|
||||
extern int32_t ecma_number_to_int32 (ecma_number_t value);
|
||||
extern ecma_number_t ecma_int32_to_number (int32_t value);
|
||||
|
||||
Reference in New Issue
Block a user