mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Adding ecma-string's hash to ecma_string_t.
This commit is contained in:
parent
6c65c48772
commit
fe7e34d93e
@ -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)
|
||||
|
||||
@ -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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@ typedef struct
|
||||
{
|
||||
const ecma_char_t *str;
|
||||
ecma_length_t length;
|
||||
ecma_string_hash_t hash;
|
||||
}
|
||||
lp_string;
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user