Adding ecma-string's hash to ecma_string_t.

This commit is contained in:
Ruben Ayrapetyan 2014-11-28 18:00:24 +03:00
parent 6c65c48772
commit fe7e34d93e
6 changed files with 109 additions and 8 deletions

View File

@ -740,6 +740,16 @@ typedef enum
ECMA_MAGIC_STRING__COUNT /**< number of magic strings */
} ecma_magic_string_id_t;
/**
* ECMA string hash
*/
typedef uint16_t ecma_string_hash_t;
/**
* Number of string's last characters to use for hash calculation
*/
#define ECMA_STRING_HASH_LAST_CHARS_COUNT (2)
/**
* ECMA string-value descriptor
*/
@ -755,8 +765,8 @@ typedef struct
* in a stack variable (not in the heap) */
unsigned int is_stack_var : 1;
/** Padding */
ecma_length_t padding;
/** Hash of the string (calculated from two last characters of the string) */
ecma_string_hash_t hash;
/**
* Actual data or identifier of it's place in container (depending on 'container' field)

View File

@ -305,8 +305,8 @@ ecma_init_ecma_string_from_lit_index (ecma_string_t *string_p, /**< descriptor t
string_p->refs = 1;
string_p->is_stack_var = is_stack_var;
string_p->container = ECMA_STRING_CONTAINER_LIT_TABLE;
string_p->hash = lit.data.lp.hash;
string_p->u.lit_index = lit_index;
} /* ecma_init_ecma_string_from_lit_index */
@ -327,8 +327,9 @@ ecma_init_ecma_string_from_magic_string_id (ecma_string_t *string_p, /**< descri
string_p->refs = 1;
string_p->is_stack_var = is_stack_var;
string_p->container = ECMA_STRING_CONTAINER_MAGIC_STRING;
string_p->hash = ecma_chars_buffer_calc_hash_last_chars (ecma_get_magic_string_zt (magic_string_id),
ecma_magic_string_lengths [magic_string_id]);
string_p->u.magic_string_id = magic_string_id;
} /* ecma_init_ecma_string_from_magic_string_id */
@ -363,6 +364,7 @@ ecma_new_ecma_string (const ecma_char_t *string_p) /**< zero-terminated string *
string_desc_p->refs = 1;
string_desc_p->is_stack_var = false;
string_desc_p->container = ECMA_STRING_CONTAINER_HEAP_CHUNKS;
string_desc_p->hash = ecma_chars_buffer_calc_hash_last_chars (string_p, length);
ecma_collection_header_t *collection_p = ecma_new_chars_collection (string_p, length);
ECMA_SET_NON_NULL_POINTER (string_desc_p->u.collection_cp, collection_p);
@ -384,6 +386,34 @@ ecma_new_ecma_string_from_uint32 (uint32_t uint32_number) /**< UInt32-represente
string_desc_p->container = ECMA_STRING_CONTAINER_UINT32_IN_DESC;
string_desc_p->u.uint32_number = uint32_number;
uint32_t last_two_digits = uint32_number % 100;
uint32_t digit_pl = last_two_digits / 10;
uint32_t digit_l = last_two_digits % 10;
FIXME (/* Use digit to char conversion routine */);
const ecma_char_t digits[10] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
const bool is_one_char_or_more = (uint32_number >= 10);
const ecma_char_t last_chars [ECMA_STRING_HASH_LAST_CHARS_COUNT] =
{
is_one_char_or_more ? digits [digit_pl] : digits[digit_l],
is_one_char_or_more ? digits [digit_l] : ECMA_CHAR_NULL
};
/* Only last two chars are really used for hash calculation */
string_desc_p->hash = ecma_chars_buffer_calc_hash_last_chars (last_chars,
is_one_char_or_more ? 2 : 1);
#ifndef JERRY_NDEBUG
ecma_char_t char_buf [ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32];
ssize_t chars_copied = ecma_uint32_to_string (uint32_number,
char_buf,
ECMA_MAX_CHARS_IN_STRINGIFIED_UINT32);
JERRY_ASSERT ((ecma_length_t) chars_copied == chars_copied);
JERRY_ASSERT (string_desc_p->hash == ecma_chars_buffer_calc_hash_last_chars (char_buf,
ecma_zt_string_length (char_buf)));
#endif /* !JERRY_NDEBUG */
return string_desc_p;
} /* ecma_new_ecma_string_from_uint32 */
@ -401,10 +431,16 @@ ecma_new_ecma_string_from_number (ecma_number_t num) /**< ecma-number */
return ecma_new_ecma_string_from_uint32 (uint32_num);
}
ecma_char_t str_buf[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER + 1];
ecma_length_t length = ecma_number_to_zt_string (num,
str_buf,
sizeof (str_buf));
ecma_string_t* string_desc_p = ecma_alloc_string ();
string_desc_p->refs = 1;
string_desc_p->is_stack_var = false;
string_desc_p->container = ECMA_STRING_CONTAINER_HEAP_NUMBER;
string_desc_p->hash = ecma_chars_buffer_calc_hash_last_chars (str_buf, length);
ecma_number_t *num_p = ecma_alloc_number ();
*num_p = num;
@ -479,7 +515,19 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */
JERRY_ASSERT (string1_p != NULL
&& string2_p != NULL);
int64_t length = (int64_t)ecma_string_get_length (string1_p) + (int64_t) ecma_string_get_length (string2_p);
uint32_t str1_len = (uint32_t) ecma_string_get_length (string1_p);
uint32_t str2_len = (uint32_t) ecma_string_get_length (string2_p);
if (str1_len == 0)
{
return ecma_copy_or_ref_ecma_string (string2_p);
}
else if (str2_len == 0)
{
return ecma_copy_or_ref_ecma_string (string1_p);
}
int64_t length = (int64_t) str1_len + (int64_t) str2_len;
ecma_string_t* string_desc_p = ecma_alloc_string ();
string_desc_p->refs = 1;
@ -497,6 +545,24 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */
ECMA_SET_NON_NULL_POINTER (string_desc_p->u.concatenation.string1_cp, string1_p);
ECMA_SET_NON_NULL_POINTER (string_desc_p->u.concatenation.string2_cp, string2_p);
if (str2_len >= ECMA_STRING_HASH_LAST_CHARS_COUNT)
{
string_desc_p->hash = string2_p->hash;
}
else
{
JERRY_STATIC_ASSERT (ECMA_STRING_HASH_LAST_CHARS_COUNT == 2);
JERRY_ASSERT (str2_len == 1);
ecma_char_t chars_buf[ECMA_STRING_HASH_LAST_CHARS_COUNT] =
{
ecma_string_get_char_at_pos (string1_p, str1_len - 1u),
ecma_string_get_char_at_pos (string2_p, 0)
};
string_desc_p->hash = ecma_chars_buffer_calc_hash_last_chars (chars_buf, ECMA_STRING_HASH_LAST_CHARS_COUNT);
}
return string_desc_p;
} /* ecma_concat_ecma_strings */
@ -982,9 +1048,9 @@ ecma_compare_ecma_strings (const ecma_string_t *string1_p, /* ecma-string */
{
JERRY_ASSERT (string1_p != NULL && string2_p != NULL);
if (unlikely (string1_p == string2_p))
if (string1_p->hash != string2_p->hash)
{
return true;
return false;
}
if (string1_p->container == string2_p->container)
@ -1583,6 +1649,27 @@ ecma_string_try_hash (const ecma_string_t *string_p, /**< ecma-string to calcula
return false;
} /* ecma_string_try_hash */
/**
* Calculate hash from last ECMA_STRING_HASH_LAST_CHARS_COUNT characters from the buffer.
*
* @return ecma-string's hash
*/
ecma_string_hash_t
ecma_chars_buffer_calc_hash_last_chars (const ecma_char_t *chars, /**< characters buffer */
ecma_length_t length) /**< number of characters in the buffer */
{
JERRY_ASSERT (chars != NULL);
ecma_char_t char1 = (length > 0) ? chars[length - 1] : ECMA_CHAR_NULL;
ecma_char_t char2 = (length > 1) ? chars[length - 2] : ECMA_CHAR_NULL;
uint32_t t1 = (uint32_t) char1 + (uint32_t) char2;
uint32_t t2 = t1 * 0x24418b66;
uint32_t t3 = (t2 >> 16) ^ (t2 & 0xffffu);
return (ecma_string_hash_t) t3;
} /* ecma_chars_buffer_calc_hash_last_chars */
/**
* @}
* @}

View File

@ -157,6 +157,7 @@ extern ecma_string_t* ecma_get_magic_string (ecma_magic_string_id_t id);
extern bool ecma_is_string_magic (const ecma_string_t *string_p, ecma_magic_string_id_t *out_id_p);
extern bool ecma_is_zt_string_magic (const ecma_char_t *zt_string_p, ecma_magic_string_id_t *out_id_p);
extern bool ecma_string_try_hash (const ecma_string_t *string_p, uint32_t hash_length_bits, uint32_t *out_hash_p);
extern ecma_string_hash_t ecma_chars_buffer_calc_hash_last_chars (const ecma_char_t *chars, ecma_length_t length);
/* ecma-helpers-number.c */
extern const ecma_number_t ecma_number_relative_eps;

View File

@ -73,7 +73,8 @@ create_literal_from_zt (const ecma_char_t *s, ecma_length_t len)
.data.lp = (lp_string)
{
.length = len,
.str = s
.str = s,
.hash = ecma_chars_buffer_calc_hash_last_chars (s, len)
}
};
}

View File

@ -23,6 +23,7 @@ typedef struct
{
const ecma_char_t *str;
ecma_length_t length;
ecma_string_hash_t hash;
}
lp_string;

View File

@ -165,6 +165,7 @@ adjust_string_ptrs (literal lit, size_t diff)
.data.lp = (lp_string)
{
.length = lit.data.lp.length,
.hash = lit.data.lp.hash,
.str = lit.data.lp.str + diff
}
};