mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
New External Magic String API to save heap memory
JerryScript-DCO-1.0-Signed-off-by: SaeHie Park saehie.park@samsung.com
This commit is contained in:
parent
603fa56acf
commit
723924f36f
@ -574,6 +574,12 @@ typedef uint8_t ecma_char_t;
|
||||
typedef uint16_t ecma_char_t;
|
||||
#endif /* CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_UTF16 */
|
||||
|
||||
/**
|
||||
* Description of an ecma-character pointer
|
||||
*/
|
||||
typedef ecma_char_t* ecma_char_ptr_t;
|
||||
|
||||
|
||||
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
|
||||
/**
|
||||
* Description of an ecma-number
|
||||
@ -746,7 +752,8 @@ typedef enum
|
||||
ECMA_STRING_CONTAINER_UINT32_IN_DESC, /**< actual data is UInt32-represeneted Number
|
||||
stored locally in the string's descriptor */
|
||||
ECMA_STRING_CONTAINER_CONCATENATION, /**< the ecma-string is concatenation of two specified ecma-strings */
|
||||
ECMA_STRING_CONTAINER_MAGIC_STRING /**< the ecma-string is equal to one of ECMA magic strings */
|
||||
ECMA_STRING_CONTAINER_MAGIC_STRING, /**< the ecma-string is equal to one of ECMA magic strings */
|
||||
ECMA_STRING_CONTAINER_MAGIC_STRING_EX /**< the ecma-string is equal to one of external magic strings */
|
||||
} ecma_string_container_t;
|
||||
|
||||
FIXME (Move to library that should define the type (literal.h /* ? */))
|
||||
@ -768,6 +775,11 @@ typedef enum
|
||||
ECMA_MAGIC_STRING__COUNT /**< number of magic strings */
|
||||
} ecma_magic_string_id_t;
|
||||
|
||||
/**
|
||||
* Identifiers of implementation-defined external magic string constants
|
||||
*/
|
||||
typedef uint32_t ecma_magic_string_ex_id_t;
|
||||
|
||||
/**
|
||||
* ECMA string hash
|
||||
*/
|
||||
@ -823,6 +835,9 @@ typedef struct ecma_string_t
|
||||
/** Identifier of magic string */
|
||||
ecma_magic_string_id_t magic_string_id;
|
||||
|
||||
/** Identifier of external magic string */
|
||||
ecma_magic_string_ex_id_t magic_string_ex_id;
|
||||
|
||||
/** For zeroing and comparison in some cases */
|
||||
uint32_t common_field;
|
||||
} u;
|
||||
|
||||
@ -51,6 +51,13 @@ JERRY_STATIC_ASSERT ((uint32_t) ((int32_t) ECMA_STRING_MAX_CONCATENATION_LENGTH)
|
||||
*/
|
||||
static ecma_length_t ecma_magic_string_lengths[ECMA_MAGIC_STRING__COUNT];
|
||||
|
||||
/**
|
||||
* External magic strings data array, count and lengths
|
||||
*/
|
||||
static const ecma_char_ptr_t* ecma_magic_string_ex_array = NULL;
|
||||
static uint32_t ecma_magic_string_ex_count = 0;
|
||||
static const ecma_length_t* ecma_magic_string_ex_lengths = NULL;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
/**
|
||||
* Maximum length among lengths of magic strings
|
||||
@ -67,6 +74,10 @@ ecma_init_ecma_string_from_magic_string_id (ecma_string_t *string_p,
|
||||
ecma_magic_string_id_t magic_string_id,
|
||||
bool is_stack_var);
|
||||
|
||||
static void
|
||||
ecma_init_ecma_string_from_magic_string_ex_id (ecma_string_t *string_p,
|
||||
ecma_magic_string_ex_id_t magic_string_ex_id,
|
||||
bool is_stack_var);
|
||||
/**
|
||||
* Allocate a collection of ecma-chars.
|
||||
*
|
||||
@ -296,6 +307,65 @@ ecma_strings_init (void)
|
||||
}
|
||||
} /* ecma_strings_init */
|
||||
|
||||
/**
|
||||
* Initialize external magic strings
|
||||
*/
|
||||
void
|
||||
ecma_strings_ex_init (void)
|
||||
{
|
||||
ecma_magic_string_ex_array = NULL;
|
||||
ecma_magic_string_ex_count = 0;
|
||||
ecma_magic_string_ex_lengths = NULL;
|
||||
} /* ecma_strings_ex_init */
|
||||
|
||||
/**
|
||||
* Register external magic strings
|
||||
*/
|
||||
void
|
||||
ecma_strings_ex_set (const ecma_char_ptr_t* ex_str_items, /**< character arrays, representing
|
||||
* external magic strings' contents */
|
||||
uint32_t count, /**< number of the strings */
|
||||
const ecma_length_t* ex_str_lengths) /**< lengths of the strings */
|
||||
{
|
||||
JERRY_ASSERT (ex_str_items != NULL);
|
||||
JERRY_ASSERT (count > 0);
|
||||
JERRY_ASSERT (ex_str_lengths != NULL);
|
||||
|
||||
JERRY_ASSERT (ecma_magic_string_ex_array == NULL);
|
||||
JERRY_ASSERT (ecma_magic_string_ex_count == 0);
|
||||
JERRY_ASSERT (ecma_magic_string_ex_lengths == NULL);
|
||||
|
||||
/* Set external magic strings information */
|
||||
ecma_magic_string_ex_array = ex_str_items;
|
||||
ecma_magic_string_ex_count = count;
|
||||
ecma_magic_string_ex_lengths = ex_str_lengths;
|
||||
|
||||
#ifndef JERRY_NDEBUG
|
||||
for (ecma_magic_string_ex_id_t id = (ecma_magic_string_ex_id_t) 0;
|
||||
id < ecma_magic_string_ex_count;
|
||||
id = (ecma_magic_string_ex_id_t) (id + 1))
|
||||
{
|
||||
JERRY_ASSERT (ecma_magic_string_ex_lengths[id] == ecma_zt_string_length (ecma_get_magic_string_ex_zt (id)));
|
||||
|
||||
ecma_magic_string_max_length = JERRY_MAX (ecma_magic_string_max_length, ecma_magic_string_ex_lengths[id]);
|
||||
|
||||
JERRY_ASSERT (ecma_magic_string_max_length <= ECMA_STRING_MAGIC_STRING_LENGTH_LIMIT);
|
||||
}
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
} /* ecma_strings_ex_init */
|
||||
|
||||
/**
|
||||
* Get number of external magic strings
|
||||
*
|
||||
* @return number of the strings, if there were registered,
|
||||
* zero - otherwise.
|
||||
*/
|
||||
uint32_t
|
||||
ecma_get_magic_string_ex_count (void)
|
||||
{
|
||||
return ecma_magic_string_ex_count;
|
||||
} /* ecma_get_magic_string_ex_count */
|
||||
|
||||
/**
|
||||
* Initialize ecma-string descriptor with string described by index in literal table
|
||||
*/
|
||||
@ -318,7 +388,14 @@ ecma_init_ecma_string_from_lit_index (ecma_string_t *string_p, /**< descriptor t
|
||||
|
||||
return;
|
||||
}
|
||||
else if (lit.type == LIT_MAGIC_STR_EX)
|
||||
{
|
||||
ecma_init_ecma_string_from_magic_string_ex_id (string_p,
|
||||
lit.data.magic_str_ex_id,
|
||||
is_stack_var);
|
||||
|
||||
return;
|
||||
}
|
||||
JERRY_ASSERT (lit.type == LIT_STR);
|
||||
|
||||
string_p->refs = 1;
|
||||
@ -354,6 +431,30 @@ ecma_init_ecma_string_from_magic_string_id (ecma_string_t *string_p, /**< descri
|
||||
string_p->u.magic_string_id = magic_string_id;
|
||||
} /* ecma_init_ecma_string_from_magic_string_id */
|
||||
|
||||
/**
|
||||
* Initialize external ecma-string descriptor with specified magic string
|
||||
*/
|
||||
static void
|
||||
ecma_init_ecma_string_from_magic_string_ex_id (ecma_string_t *string_p, /**< descriptor to initialize */
|
||||
ecma_magic_string_ex_id_t magic_string_ex_id, /**< identifier of
|
||||
the external magic string */
|
||||
bool is_stack_var) /**< flag indicating whether the string descriptor
|
||||
is placed on stack (true) or in the heap (false) */
|
||||
{
|
||||
#ifndef JERRY_NDEBUG
|
||||
JERRY_ASSERT (is_stack_var == (!mem_is_heap_pointer (string_p)));
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
|
||||
string_p->refs = 1;
|
||||
string_p->is_stack_var = (is_stack_var != 0);
|
||||
string_p->container = ECMA_STRING_CONTAINER_MAGIC_STRING_EX;
|
||||
string_p->hash = ecma_chars_buffer_calc_hash_last_chars (ecma_get_magic_string_ex_zt (magic_string_ex_id),
|
||||
ecma_magic_string_ex_lengths[magic_string_ex_id]);
|
||||
|
||||
string_p->u.common_field = 0;
|
||||
string_p->u.magic_string_ex_id = magic_string_ex_id;
|
||||
} /* ecma_init_ecma_string_from_magic_string_ex_id */
|
||||
|
||||
/**
|
||||
* Allocate new ecma-string and fill it with characters from specified buffer
|
||||
*
|
||||
@ -370,6 +471,12 @@ ecma_new_ecma_string (const ecma_char_t *string_p) /**< zero-terminated string *
|
||||
return ecma_get_magic_string (magic_string_id);
|
||||
}
|
||||
|
||||
ecma_magic_string_ex_id_t magic_string_ex_id;
|
||||
if (ecma_is_zt_ex_string_magic (string_p, &magic_string_ex_id))
|
||||
{
|
||||
return ecma_get_magic_string_ex (magic_string_ex_id);
|
||||
}
|
||||
|
||||
ecma_length_t length = 0;
|
||||
const ecma_char_t *iter_p = string_p;
|
||||
|
||||
@ -533,6 +640,23 @@ ecma_new_ecma_string_from_magic_string_id (ecma_magic_string_id_t id) /**< ident
|
||||
return string_desc_p;
|
||||
} /* ecma_new_ecma_string_from_magic_string_id */
|
||||
|
||||
/**
|
||||
* Allocate new ecma-string and fill it with reference to ECMA magic string
|
||||
*
|
||||
* @return pointer to ecma-string descriptor
|
||||
*/
|
||||
ecma_string_t*
|
||||
ecma_new_ecma_string_from_magic_string_ex_id (ecma_magic_string_ex_id_t id) /**< identifier of externl magic string */
|
||||
{
|
||||
JERRY_ASSERT (id < ecma_magic_string_ex_count);
|
||||
|
||||
ecma_string_t* string_desc_p = ecma_alloc_string ();
|
||||
ecma_init_ecma_string_from_magic_string_ex_id (string_desc_p, id, false);
|
||||
|
||||
return string_desc_p;
|
||||
} /* ecma_new_ecma_string_from_magic_string_ex_id */
|
||||
|
||||
|
||||
/**
|
||||
* Concatenate ecma-strings
|
||||
*
|
||||
@ -616,6 +740,7 @@ ecma_copy_ecma_string (ecma_string_t *string_desc_p) /**< string descriptor */
|
||||
case ECMA_STRING_CONTAINER_LIT_TABLE:
|
||||
case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING:
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING_EX:
|
||||
{
|
||||
new_str_p = ecma_alloc_string ();
|
||||
|
||||
@ -778,6 +903,7 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */
|
||||
case ECMA_STRING_CONTAINER_LIT_TABLE:
|
||||
case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING:
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING_EX:
|
||||
{
|
||||
/* only the string descriptor itself should be freed */
|
||||
}
|
||||
@ -812,6 +938,7 @@ ecma_check_that_ecma_string_need_not_be_freed (const ecma_string_t *string_p) /*
|
||||
|
||||
JERRY_ASSERT (container_type == ECMA_STRING_CONTAINER_LIT_TABLE ||
|
||||
container_type == ECMA_STRING_CONTAINER_MAGIC_STRING ||
|
||||
container_type == ECMA_STRING_CONTAINER_MAGIC_STRING_EX ||
|
||||
container_type == ECMA_STRING_CONTAINER_UINT32_IN_DESC);
|
||||
#endif /* !JERRY_NDEBUG */
|
||||
} /* ecma_check_that_ecma_string_need_not_be_freed */
|
||||
@ -845,6 +972,7 @@ ecma_string_to_number (const ecma_string_t *str_p) /**< ecma-string */
|
||||
case ECMA_STRING_CONTAINER_HEAP_CHUNKS:
|
||||
case ECMA_STRING_CONTAINER_CONCATENATION:
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING:
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING_EX:
|
||||
{
|
||||
const int32_t string_len = ecma_string_get_length (str_p);
|
||||
const size_t string_buf_size = (size_t) (string_len + 1) * sizeof (ecma_char_t);
|
||||
@ -976,6 +1104,19 @@ ecma_string_to_zt_string (const ecma_string_t *string_desc_p, /**< ecma-string d
|
||||
|
||||
JERRY_ASSERT (required_buffer_size == (ssize_t) bytes_to_copy);
|
||||
|
||||
break;
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING_EX:
|
||||
{
|
||||
const ecma_magic_string_ex_id_t id = string_desc_p->u.magic_string_ex_id;
|
||||
const size_t length = ecma_magic_string_ex_lengths[id];
|
||||
|
||||
size_t bytes_to_copy = (length + 1) * sizeof (ecma_char_t);
|
||||
|
||||
memcpy (buffer_p, ecma_get_magic_string_ex_zt (id), bytes_to_copy);
|
||||
|
||||
JERRY_ASSERT (required_buffer_size == (ssize_t) bytes_to_copy);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1010,6 +1151,12 @@ ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /* ecma-stri
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (string1_p->container == ECMA_STRING_CONTAINER_MAGIC_STRING_EX)
|
||||
{
|
||||
JERRY_ASSERT (string1_p->u.magic_string_ex_id != string2_p->u.magic_string_ex_id);
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (string1_p->container == ECMA_STRING_CONTAINER_UINT32_IN_DESC)
|
||||
{
|
||||
JERRY_ASSERT (string1_p->u.uint32_number != string2_p->u.uint32_number);
|
||||
@ -1077,6 +1224,12 @@ ecma_compare_ecma_strings_longpath (const ecma_string_t *string1_p, /* ecma-stri
|
||||
|
||||
return false;
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING_EX:
|
||||
{
|
||||
JERRY_ASSERT (string1_p->u.magic_string_ex_id != string2_p->u.magic_string_ex_id);
|
||||
|
||||
return false;
|
||||
}
|
||||
case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
|
||||
{
|
||||
JERRY_ASSERT (string1_p->u.uint32_number != string2_p->u.uint32_number);
|
||||
@ -1300,6 +1453,10 @@ ecma_string_get_length (const ecma_string_t *string_p) /**< ecma-string */
|
||||
{
|
||||
return ecma_magic_string_lengths[string_p->u.magic_string_id];
|
||||
}
|
||||
else if (container == ECMA_STRING_CONTAINER_MAGIC_STRING_EX)
|
||||
{
|
||||
return ecma_magic_string_ex_lengths[string_p->u.magic_string_ex_id];
|
||||
}
|
||||
else if (container == ECMA_STRING_CONTAINER_UINT32_IN_DESC)
|
||||
{
|
||||
const uint32_t uint32_number = string_p->u.uint32_number;
|
||||
@ -1607,6 +1764,25 @@ ecma_get_magic_string_zt (ecma_magic_string_id_t id) /**< magic string id */
|
||||
JERRY_UNREACHABLE ();
|
||||
} /* ecma_get_magic_string_zt */
|
||||
|
||||
/**
|
||||
* Get specified magic string as zero-terminated string from external table
|
||||
*
|
||||
* @return pointer to zero-terminated magic string
|
||||
*/
|
||||
const ecma_char_t*
|
||||
ecma_get_magic_string_ex_zt (ecma_magic_string_ex_id_t id) /**< extern magic string id */
|
||||
{
|
||||
TODO (Support UTF-16);
|
||||
|
||||
if (ecma_magic_string_ex_array && id < ecma_magic_string_ex_count)
|
||||
{
|
||||
return ecma_magic_string_ex_array[id];
|
||||
}
|
||||
|
||||
JERRY_UNREACHABLE ();
|
||||
} /* ecma_get_magic_string_ex_zt */
|
||||
|
||||
|
||||
/**
|
||||
* Get specified magic string
|
||||
*
|
||||
@ -1618,6 +1794,17 @@ ecma_get_magic_string (ecma_magic_string_id_t id) /**< magic string id */
|
||||
return ecma_new_ecma_string_from_magic_string_id (id);
|
||||
} /* ecma_get_magic_string */
|
||||
|
||||
/**
|
||||
* Get specified external magic string
|
||||
*
|
||||
* @return ecma-string containing specified external magic string
|
||||
*/
|
||||
ecma_string_t*
|
||||
ecma_get_magic_string_ex (ecma_magic_string_ex_id_t id) /**< external magic string id */
|
||||
{
|
||||
return ecma_new_ecma_string_from_magic_string_ex_id (id);
|
||||
} /* ecma_get_magic_string_ex */
|
||||
|
||||
/**
|
||||
* Check if passed zt-string equals to one of magic strings
|
||||
* and if equal magic string was found, return it's id in 'out_id_p' argument.
|
||||
@ -1648,6 +1835,36 @@ ecma_is_zt_string_magic (const ecma_char_t *zt_string_p, /**< zero-terminated st
|
||||
return false;
|
||||
} /* ecma_is_zt_string_magic */
|
||||
|
||||
/**
|
||||
* Check if passed zt-string equals to one of external magic strings
|
||||
* and if equal magic string was found, return it's id in 'out_id_p' argument.
|
||||
*
|
||||
* @return true - if external magic string equal to passed string was found,
|
||||
* false - otherwise.
|
||||
*/
|
||||
bool
|
||||
ecma_is_zt_ex_string_magic (const ecma_char_t *zt_string_p, /**< zero-terminated string */
|
||||
ecma_magic_string_ex_id_t *out_id_p) /**< out: external magic string's id */
|
||||
{
|
||||
TODO (Improve performance of search);
|
||||
|
||||
for (ecma_magic_string_ex_id_t id = (ecma_magic_string_ex_id_t) 0;
|
||||
id < ecma_magic_string_ex_count;
|
||||
id = (ecma_magic_string_ex_id_t) (id + 1))
|
||||
{
|
||||
if (ecma_compare_zt_strings (zt_string_p, ecma_get_magic_string_ex_zt (id)))
|
||||
{
|
||||
*out_id_p = id;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
*out_id_p = ecma_magic_string_ex_count;
|
||||
|
||||
return false;
|
||||
} /* ecma_is_zt_ex_string_magic */
|
||||
|
||||
/**
|
||||
* Long path part of ecma_is_string_magic
|
||||
*
|
||||
@ -1669,6 +1886,27 @@ ecma_is_string_magic_longpath (const ecma_string_t *string_p, /**< ecma-string *
|
||||
return ecma_is_zt_string_magic (zt_string_buffer, out_id_p);
|
||||
} /* ecma_is_string_magic_longpath */
|
||||
|
||||
/**
|
||||
* Long path part of ecma_is_ex_string_magic
|
||||
*
|
||||
* Converts passed ecma-string to zt-string and
|
||||
* checks if it is equal to one of magic string
|
||||
*
|
||||
* @return true - if magic string equal to passed string was found,
|
||||
* false - otherwise.
|
||||
*/
|
||||
static bool
|
||||
ecma_is_ex_string_magic_longpath (const ecma_string_t *string_p, /**< ecma-string */
|
||||
ecma_magic_string_ex_id_t *out_id_p) /**< out: external magic string's id */
|
||||
{
|
||||
ecma_char_t zt_string_buffer[ECMA_STRING_MAGIC_STRING_LENGTH_LIMIT + 1];
|
||||
|
||||
ssize_t copied = ecma_string_to_zt_string (string_p, zt_string_buffer, (ssize_t) sizeof (zt_string_buffer));
|
||||
JERRY_ASSERT (copied > 0);
|
||||
|
||||
return ecma_is_zt_ex_string_magic (zt_string_buffer, out_id_p);
|
||||
} /* ecma_is_ex_string_magic_longpath */
|
||||
|
||||
/**
|
||||
* Check if passed string equals to one of magic strings
|
||||
* and if equal magic string was found, return it's id in 'out_id_p' argument.
|
||||
@ -1707,6 +1945,44 @@ ecma_is_string_magic (const ecma_string_t *string_p, /**< ecma-string */
|
||||
}
|
||||
} /* ecma_is_string_magic */
|
||||
|
||||
/**
|
||||
* Check if passed string equals to one of external magic strings
|
||||
* and if equal external magic string was found, return it's id in 'out_id_p' argument.
|
||||
*
|
||||
* @return true - if external magic string equal to passed string was found,
|
||||
* false - otherwise.
|
||||
*/
|
||||
bool
|
||||
ecma_is_ex_string_magic (const ecma_string_t *string_p, /**< ecma-string */
|
||||
ecma_magic_string_ex_id_t *out_id_p) /**< out: external magic string's id */
|
||||
{
|
||||
if (string_p->container == ECMA_STRING_CONTAINER_MAGIC_STRING_EX)
|
||||
{
|
||||
JERRY_ASSERT (string_p->u.magic_string_ex_id < ecma_magic_string_ex_count);
|
||||
|
||||
*out_id_p = (ecma_magic_string_ex_id_t) string_p->u.magic_string_ex_id;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (string_p->container == ECMA_STRING_CONTAINER_CONCATENATION
|
||||
&& ecma_string_get_length (string_p) <= ECMA_STRING_MAGIC_STRING_LENGTH_LIMIT)
|
||||
{
|
||||
return ecma_is_ex_string_magic_longpath (string_p, out_id_p);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Any ecma-string constructor except ecma_concat_ecma_strings
|
||||
* should return ecma-string with ECMA_STRING_CONTAINER_MAGIC_STRING_EX
|
||||
* container type if new ecma-string's content is equal to one of external magic strings.
|
||||
*/
|
||||
JERRY_ASSERT (ecma_string_get_length (string_p) > ECMA_STRING_MAGIC_STRING_LENGTH_LIMIT
|
||||
|| !ecma_is_ex_string_magic_longpath (string_p, out_id_p));
|
||||
|
||||
return false;
|
||||
}
|
||||
} /* ecma_is_ex_string_magic */
|
||||
|
||||
/**
|
||||
* Try to calculate hash of the ecma-string
|
||||
*
|
||||
|
||||
@ -118,6 +118,7 @@ extern ecma_string_t* ecma_new_ecma_string_from_lit_index (literal_index_t lit_i
|
||||
extern void ecma_new_ecma_string_on_stack_from_magic_string_id (ecma_string_t *string_p,
|
||||
ecma_magic_string_id_t id);
|
||||
extern ecma_string_t* ecma_new_ecma_string_from_magic_string_id (ecma_magic_string_id_t id);
|
||||
extern ecma_string_t* ecma_new_ecma_string_from_magic_string_ex_id (ecma_magic_string_ex_id_t id);
|
||||
extern ecma_string_t* ecma_concat_ecma_strings (ecma_string_t *string1_p, ecma_string_t *string2_p);
|
||||
extern ecma_string_t* ecma_copy_or_ref_ecma_string (ecma_string_t *string_desc_p);
|
||||
extern void ecma_deref_ecma_string (ecma_string_t *string_p);
|
||||
@ -143,10 +144,19 @@ ecma_copy_zt_string_to_buffer (const ecma_char_t *string_p,
|
||||
extern ecma_length_t ecma_zt_string_length (const ecma_char_t *string_p);
|
||||
|
||||
extern void ecma_strings_init (void);
|
||||
extern void ecma_strings_ex_init (void);
|
||||
extern void ecma_strings_ex_set (const ecma_char_ptr_t* ex_str_items,
|
||||
uint32_t count,
|
||||
const ecma_length_t* ex_str_lengths);
|
||||
extern uint32_t ecma_get_magic_string_ex_count (void);
|
||||
extern const ecma_char_t* ecma_get_magic_string_zt (ecma_magic_string_id_t id);
|
||||
extern const ecma_char_t* ecma_get_magic_string_ex_zt (ecma_magic_string_ex_id_t id);
|
||||
extern ecma_string_t* ecma_get_magic_string (ecma_magic_string_id_t id);
|
||||
extern ecma_string_t* ecma_get_magic_string_ex (ecma_magic_string_ex_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_ex_string_magic (const ecma_string_t *string_p, ecma_magic_string_ex_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_is_zt_ex_string_magic (const ecma_char_t *zt_string_p, ecma_magic_string_ex_id_t *out_id_p);
|
||||
extern ecma_string_hash_t ecma_string_hash (const ecma_string_t *string_p);
|
||||
extern ecma_string_hash_t ecma_chars_buffer_calc_hash_last_chars (const ecma_char_t *chars, ecma_length_t length);
|
||||
|
||||
|
||||
@ -36,6 +36,7 @@ void
|
||||
ecma_init (void)
|
||||
{
|
||||
ecma_strings_init ();
|
||||
ecma_strings_ex_init ();
|
||||
ecma_init_builtins ();
|
||||
ecma_lcache_init ();
|
||||
ecma_stack_init ();
|
||||
|
||||
@ -71,6 +71,25 @@ typedef enum
|
||||
JERRY_API_ERROR_URI /**< URIError */
|
||||
} jerry_api_error_t;
|
||||
|
||||
/**
|
||||
* Jerry's char value
|
||||
*/
|
||||
#if CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_ASCII
|
||||
typedef uint8_t jerry_api_char_t;
|
||||
#elif CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_UTF16
|
||||
typedef uint16_t jerry_api_char_t;
|
||||
#endif /* CONFIG_ECMA_CHAR_ENCODING == CONFIG_ECMA_CHAR_UTF16 */
|
||||
|
||||
/**
|
||||
* Pointer to an array of character values
|
||||
*/
|
||||
typedef jerry_api_char_t* jerry_api_char_ptr_t;
|
||||
|
||||
/**
|
||||
* Jerry's length
|
||||
*/
|
||||
typedef uint16_t jerry_api_length_t;
|
||||
|
||||
/**
|
||||
* Jerry's string value
|
||||
*/
|
||||
@ -198,6 +217,11 @@ jerry_completion_code_t jerry_api_eval (const char *source_p,
|
||||
extern EXTERN_C
|
||||
jerry_api_object_t* jerry_api_get_global (void);
|
||||
|
||||
extern EXTERN_C
|
||||
void jerry_register_external_magic_strings (const jerry_api_char_ptr_t* ex_str_items,
|
||||
uint32_t count,
|
||||
const jerry_api_length_t* str_lengths);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@ -1337,3 +1337,16 @@ jerry_pop_ctx (void)
|
||||
JERRY_UNIMPLEMENTED ("Run contexts are not implemented");
|
||||
} /* jerry_pop_ctx */
|
||||
#endif /* CONFIG_JERRY_ENABLE_CONTEXTS */
|
||||
|
||||
|
||||
/**
|
||||
* Register external magic string array
|
||||
*/
|
||||
void
|
||||
jerry_register_external_magic_strings (const jerry_api_char_ptr_t* ex_str_items, /**< character arrays, representing
|
||||
* external magic strings' contents */
|
||||
uint32_t count, /**< number of the strings */
|
||||
const jerry_api_length_t* str_lengths) /**< lengths of the strings */
|
||||
{
|
||||
ecma_strings_ex_set ((const ecma_char_ptr_t*)ex_str_items, count, (const ecma_length_t*)str_lengths);
|
||||
} /* jerry_register_external_magic_strings */
|
||||
|
||||
@ -133,6 +133,16 @@ string_equals_to_literal (const ecma_char_t *str_p, /**< characters buffer */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (lit.type == LIT_MAGIC_STR_EX)
|
||||
{
|
||||
const char *magic_str_p = (const char *) ecma_get_magic_string_ex_zt (lit.data.magic_str_ex_id);
|
||||
|
||||
if (strlen (magic_str_p) == length
|
||||
&& strncmp (magic_str_p, (const char*) str_p, length) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
} /* string_equals_to_literal */
|
||||
@ -194,7 +204,7 @@ convert_string_to_token (token_type tt, /**< token type */
|
||||
for (literal_index_t i = 0; i < STACK_SIZE (literals); i++)
|
||||
{
|
||||
const literal lit = STACK_ELEMENT (literals, i);
|
||||
if ((lit.type == LIT_STR || lit.type == LIT_MAGIC_STR)
|
||||
if ((lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX)
|
||||
&& string_equals_to_literal (str_p, length, lit))
|
||||
{
|
||||
return create_token (tt, i);
|
||||
@ -202,7 +212,7 @@ convert_string_to_token (token_type tt, /**< token type */
|
||||
}
|
||||
|
||||
literal lit = create_literal_from_str (str_p, length);
|
||||
JERRY_ASSERT (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR);
|
||||
JERRY_ASSERT (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX);
|
||||
if (lit.type == LIT_STR)
|
||||
{
|
||||
lit = add_string_to_string_cache (str_p, length);
|
||||
|
||||
@ -79,6 +79,27 @@ create_literal_from_zt (const ecma_char_t *s, ecma_length_t len)
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ex_count = ecma_get_magic_string_ex_count ();
|
||||
for (ecma_magic_string_ex_id_t msi = (ecma_magic_string_ex_id_t) 0;
|
||||
msi < ex_count;
|
||||
msi = (ecma_magic_string_id_t) (msi + 1))
|
||||
{
|
||||
const ecma_char_t* ex_string = ecma_get_magic_string_ex_zt (msi);
|
||||
if (ecma_zt_string_length (ex_string) != len)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!strncmp ((const char *) s, (const char *) ex_string, len))
|
||||
{
|
||||
literal ret;
|
||||
|
||||
ret.type = LIT_MAGIC_STR_EX;
|
||||
ret.data.magic_str_ex_id = msi;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
literal ret;
|
||||
|
||||
ret.type = LIT_STR;
|
||||
@ -108,7 +129,7 @@ literal_equal_type_s (literal lit, const char *s)
|
||||
bool
|
||||
literal_equal_type_zt (literal lit, const ecma_char_t *s)
|
||||
{
|
||||
if (lit.type != LIT_STR && lit.type != LIT_MAGIC_STR)
|
||||
if (lit.type != LIT_STR && lit.type != LIT_MAGIC_STR && lit.type != LIT_MAGIC_STR_EX)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -142,6 +163,10 @@ literal_equal_lp (literal lit, lp_string lp)
|
||||
{
|
||||
return lp_string_equal_zt (lp, ecma_get_magic_string_zt (lit.data.magic_str_id));
|
||||
}
|
||||
case LIT_MAGIC_STR_EX:
|
||||
{
|
||||
return lp_string_equal_zt (lp, ecma_get_magic_string_ex_zt (lit.data.magic_str_ex_id));
|
||||
}
|
||||
case LIT_NUMBER:
|
||||
{
|
||||
ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
|
||||
@ -172,6 +197,10 @@ literal_equal (literal lit1, literal lit2)
|
||||
{
|
||||
return literal_equal_zt (lit1, ecma_get_magic_string_zt (lit2.data.magic_str_id));
|
||||
}
|
||||
case LIT_MAGIC_STR_EX:
|
||||
{
|
||||
return literal_equal_zt (lit1, ecma_get_magic_string_ex_zt (lit2.data.magic_str_ex_id));
|
||||
}
|
||||
case LIT_NUMBER:
|
||||
{
|
||||
return literal_equal_num (lit1, lit2.data.num);
|
||||
@ -206,6 +235,10 @@ literal_equal_zt (literal lit, const ecma_char_t *s)
|
||||
{
|
||||
return ecma_compare_zt_strings (s, ecma_get_magic_string_zt (lit.data.magic_str_id));
|
||||
}
|
||||
case LIT_MAGIC_STR_EX:
|
||||
{
|
||||
return ecma_compare_zt_strings (s, ecma_get_magic_string_ex_zt (lit.data.magic_str_ex_id));
|
||||
}
|
||||
case LIT_NUMBER:
|
||||
{
|
||||
ecma_char_t buff[ECMA_MAX_CHARS_IN_STRINGIFIED_NUMBER];
|
||||
@ -230,12 +263,13 @@ literal_equal_num (literal lit, ecma_number_t num)
|
||||
const ecma_char_t *
|
||||
literal_to_zt (literal lit)
|
||||
{
|
||||
JERRY_ASSERT (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR);
|
||||
JERRY_ASSERT (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX);
|
||||
|
||||
switch (lit.type)
|
||||
{
|
||||
case LIT_STR: return lit.data.lp.str;
|
||||
case LIT_MAGIC_STR: return ecma_get_magic_string_zt (lit.data.magic_str_id);
|
||||
case LIT_MAGIC_STR_EX: return ecma_get_magic_string_ex_zt (lit.data.magic_str_ex_id);
|
||||
default: JERRY_UNREACHABLE ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,6 +24,7 @@ typedef enum __attr_packed___
|
||||
LIT_UNKNOWN,
|
||||
LIT_STR,
|
||||
LIT_MAGIC_STR,
|
||||
LIT_MAGIC_STR_EX,
|
||||
LIT_NUMBER
|
||||
} literal_type;
|
||||
|
||||
@ -32,6 +33,7 @@ typedef struct
|
||||
union
|
||||
{
|
||||
ecma_magic_string_id_t magic_str_id;
|
||||
ecma_magic_string_ex_id_t magic_str_ex_id;
|
||||
ecma_number_t num;
|
||||
lp_string lp;
|
||||
void *none;
|
||||
|
||||
@ -1099,7 +1099,7 @@ dump_prop_name_and_value (operand name, operand value)
|
||||
JERRY_ASSERT (name.type == OPERAND_LITERAL);
|
||||
const literal lit = lexer_get_literal_by_id (name.data.lit_id);
|
||||
operand tmp;
|
||||
if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR)
|
||||
if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX)
|
||||
{
|
||||
tmp = dump_string_assignment_res (name.data.lit_id);
|
||||
}
|
||||
@ -1132,7 +1132,7 @@ dump_prop_getter_decl (operand name, operand func)
|
||||
JERRY_ASSERT (func.type == OPERAND_TMP);
|
||||
const literal lit = lexer_get_literal_by_id (name.data.lit_id);
|
||||
operand tmp;
|
||||
if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR)
|
||||
if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX)
|
||||
{
|
||||
tmp = dump_string_assignment_res (name.data.lit_id);
|
||||
}
|
||||
@ -1152,7 +1152,7 @@ dump_prop_setter_decl (operand name, operand func)
|
||||
JERRY_ASSERT (func.type == OPERAND_TMP);
|
||||
const literal lit = lexer_get_literal_by_id (name.data.lit_id);
|
||||
operand tmp;
|
||||
if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR)
|
||||
if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX)
|
||||
{
|
||||
tmp = dump_string_assignment_res (name.data.lit_id);
|
||||
}
|
||||
@ -1348,7 +1348,7 @@ dump_delete (operand res, operand op, bool is_strict, locus loc)
|
||||
case OPERAND_LITERAL:
|
||||
{
|
||||
const literal lit = lexer_get_literal_by_id (op.data.lit_id);
|
||||
if (lit.type == LIT_MAGIC_STR || lit.type == LIT_STR)
|
||||
if (lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX || lit.type == LIT_STR)
|
||||
{
|
||||
syntax_check_delete (is_strict, loc);
|
||||
switch (res.type)
|
||||
|
||||
@ -180,12 +180,12 @@ syntax_check_for_syntax_errors_in_formal_param_list (bool is_strict, locus loc _
|
||||
{
|
||||
JERRY_ASSERT (STACK_ELEMENT (props, i).type == VARG);
|
||||
const literal previous = STACK_ELEMENT (props, i).lit;
|
||||
JERRY_ASSERT (previous.type == LIT_STR || previous.type == LIT_MAGIC_STR);
|
||||
JERRY_ASSERT (previous.type == LIT_STR || previous.type == LIT_MAGIC_STR || previous.type == LIT_MAGIC_STR_EX);
|
||||
for (uint8_t j = STACK_TOP (U8); j < i; j = (uint8_t) (j + 1))
|
||||
{
|
||||
JERRY_ASSERT (STACK_ELEMENT (props, j).type == VARG);
|
||||
const literal current = STACK_ELEMENT (props, j).lit;
|
||||
JERRY_ASSERT (current.type == LIT_STR || current.type == LIT_MAGIC_STR);
|
||||
JERRY_ASSERT (current.type == LIT_STR || current.type == LIT_MAGIC_STR || current.type == LIT_MAGIC_STR_EX);
|
||||
if (literal_equal_type (previous, current))
|
||||
{
|
||||
PARSE_ERROR_VARG ("Duplication of literal '%s' in FormalParameterList is not allowed in strict mode",
|
||||
|
||||
@ -66,6 +66,11 @@ dump_literal (literal lit)
|
||||
printf ("%s : MAGIC STRING", (const char *) ecma_get_magic_string_zt (lit.data.magic_str_id));
|
||||
break;
|
||||
}
|
||||
case LIT_MAGIC_STR_EX:
|
||||
{
|
||||
printf ("%s : EXT MAGIC STRING", (const char *) ecma_get_magic_string_ex_zt (lit.data.magic_str_ex_id));
|
||||
break;
|
||||
}
|
||||
case LIT_STR:
|
||||
{
|
||||
printf ("%s : STRING", (const char *) (lit.data.lp.str));
|
||||
@ -102,7 +107,7 @@ static const char *
|
||||
lit_id_to_str (literal_index_t id)
|
||||
{
|
||||
literal lit = lexer_get_literal_by_id (id);
|
||||
if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR)
|
||||
if (lit.type == LIT_STR || lit.type == LIT_MAGIC_STR || lit.type == LIT_MAGIC_STR_EX)
|
||||
{
|
||||
return (char *) literal_to_zt (lit);
|
||||
}
|
||||
|
||||
@ -180,6 +180,44 @@ handler_construct (const jerry_api_object_t *function_obj_p,
|
||||
return true;
|
||||
} /* handler_construct */
|
||||
|
||||
|
||||
/**
|
||||
* Extended Magic Strings
|
||||
*/
|
||||
#define JERRY_MAGIC_STRING_ITEMS \
|
||||
JERRY_MAGIC_STRING_DEF (GLOBAL, global) \
|
||||
JERRY_MAGIC_STRING_DEF (CONSOLE, console)
|
||||
|
||||
|
||||
#define JERRY_MAGIC_STRING_DEF(NAME, STRING) \
|
||||
static const char jerry_magic_string_ex_ ## NAME[] = # STRING;
|
||||
|
||||
JERRY_MAGIC_STRING_ITEMS
|
||||
|
||||
#undef JERRY_MAGIC_STRING_DEF
|
||||
|
||||
const jerry_api_length_t magic_string_lengths[] =
|
||||
{
|
||||
#define JERRY_MAGIC_STRING_DEF(NAME, STRING) \
|
||||
(jerry_api_length_t)(sizeof(jerry_magic_string_ex_ ## NAME) - 1u),
|
||||
|
||||
JERRY_MAGIC_STRING_ITEMS
|
||||
|
||||
#undef JERRY_MAGIC_STRING_DEF
|
||||
};
|
||||
|
||||
const jerry_api_char_ptr_t magic_string_items[] =
|
||||
{
|
||||
#define JERRY_MAGIC_STRING_DEF(NAME, STRING) \
|
||||
(const jerry_api_char_ptr_t)jerry_magic_string_ex_ ## NAME,
|
||||
|
||||
JERRY_MAGIC_STRING_ITEMS
|
||||
|
||||
#undef JERRY_MAGIC_STRING_DEF
|
||||
};
|
||||
|
||||
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
@ -408,5 +446,22 @@ main (void)
|
||||
|
||||
assert (test_api_is_free_callback_was_called);
|
||||
|
||||
// External Magic String
|
||||
jerry_init (JERRY_FLAG_SHOW_OPCODES);
|
||||
|
||||
uint32_t num_magic_string_items = sizeof (magic_string_items) / sizeof (jerry_api_char_ptr_t);
|
||||
jerry_register_external_magic_strings (magic_string_items,
|
||||
num_magic_string_items,
|
||||
magic_string_lengths);
|
||||
|
||||
const char *ms_code_src_p = "var global = {}; var console = [1]; var process = 1;";
|
||||
is_ok = jerry_parse (ms_code_src_p, strlen (ms_code_src_p));
|
||||
assert (is_ok);
|
||||
|
||||
is_ok = (jerry_run () == JERRY_COMPLETION_CODE_OK);
|
||||
assert (is_ok);
|
||||
|
||||
jerry_cleanup ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user