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:
Ruben Ayrapetyan
2014-08-25 19:58:55 +04:00
parent 57965bf160
commit 8998189bc0
4 changed files with 105 additions and 104 deletions
+12 -6
View File
@@ -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;
+10 -2
View File
@@ -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 */
/**
+81 -94
View File
@@ -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);
+2 -2
View File
@@ -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);