mirror of
https://github.com/jerryscript-project/jerryscript.git
synced 2025-12-15 16:29:21 +00:00
Implementing routine for copying ecma-string and using it to duplicate ecma-string upon it's reference counter overflow.
This commit is contained in:
parent
4735570b31
commit
459750b1d0
@ -22,6 +22,7 @@
|
||||
|
||||
#include "deserializer.h"
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
#include "globals.h"
|
||||
@ -274,6 +275,100 @@ ecma_concat_ecma_strings (ecma_string_t *string1_p, /**< first ecma-string */
|
||||
return string_desc_p;
|
||||
} /* ecma_concat_ecma_strings */
|
||||
|
||||
/**
|
||||
* Copy ecma-string
|
||||
*
|
||||
* @return pointer to copy of ecma-string with reference counter set to 1
|
||||
*/
|
||||
static ecma_string_t*
|
||||
ecma_copy_ecma_string (ecma_string_t *string_desc_p) /**< string descriptor */
|
||||
{
|
||||
JERRY_ASSERT (string_desc_p != NULL);
|
||||
JERRY_ASSERT (string_desc_p->refs > 0);
|
||||
|
||||
ecma_string_t *new_str_p;
|
||||
|
||||
switch ((ecma_string_container_t) string_desc_p->container)
|
||||
{
|
||||
case ECMA_STRING_CONTAINER_CHARS_IN_DESC:
|
||||
case ECMA_STRING_CONTAINER_LIT_TABLE:
|
||||
case ECMA_STRING_CONTAINER_UINT32_IN_DESC:
|
||||
case ECMA_STRING_CONTAINER_MAGIC_STRING:
|
||||
{
|
||||
new_str_p = ecma_alloc_string ();
|
||||
|
||||
*new_str_p = *string_desc_p;
|
||||
|
||||
new_str_p->refs = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_STRING_CONTAINER_CONCATENATION:
|
||||
{
|
||||
ecma_string_t *part1_p = ECMA_GET_POINTER (string_desc_p->u.concatenation.string1_cp);
|
||||
ecma_string_t *part2_p = ECMA_GET_POINTER (string_desc_p->u.concatenation.string2_cp);
|
||||
|
||||
new_str_p = ecma_concat_ecma_strings (part1_p, part2_p);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_STRING_CONTAINER_HEAP_NUMBER:
|
||||
{
|
||||
ecma_number_t *num_p = ECMA_GET_POINTER (string_desc_p->u.number_cp);
|
||||
|
||||
new_str_p = ecma_new_ecma_string_from_number (*num_p);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ECMA_STRING_CONTAINER_HEAP_CHUNKS:
|
||||
{
|
||||
ecma_collection_chunk_t *str_heap_chunk_p = ECMA_GET_POINTER (string_desc_p->u.chunk_cp);
|
||||
JERRY_ASSERT (str_heap_chunk_p != NULL);
|
||||
|
||||
new_str_p = ecma_alloc_string ();
|
||||
*new_str_p = *string_desc_p;
|
||||
|
||||
ecma_collection_chunk_t *new_str_heap_chunk_p = ecma_alloc_collection_chunk ();
|
||||
ECMA_SET_NON_NULL_POINTER (new_str_p->u.chunk_cp, new_str_heap_chunk_p);
|
||||
|
||||
while (true)
|
||||
{
|
||||
__memcpy (new_str_heap_chunk_p->data, str_heap_chunk_p->data, sizeof (new_str_heap_chunk_p->data));
|
||||
|
||||
str_heap_chunk_p = ECMA_GET_POINTER (str_heap_chunk_p->next_chunk_cp);
|
||||
|
||||
if (str_heap_chunk_p != NULL)
|
||||
{
|
||||
ecma_collection_chunk_t *new_str_next_heap_chunk_p = ecma_alloc_collection_chunk ();
|
||||
|
||||
ECMA_SET_NON_NULL_POINTER (new_str_heap_chunk_p->next_chunk_cp, new_str_next_heap_chunk_p);
|
||||
new_str_heap_chunk_p = new_str_next_heap_chunk_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
new_str_heap_chunk_p->next_chunk_cp = ECMA_NULL_POINTER;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
JERRY_UNREACHABLE ();
|
||||
}
|
||||
}
|
||||
|
||||
JERRY_ASSERT (ecma_compare_ecma_strings (string_desc_p, new_str_p));
|
||||
|
||||
return new_str_p;
|
||||
} /* ecma_copy_ecma_string */
|
||||
|
||||
/**
|
||||
* Increase reference counter of ecma-string.
|
||||
*
|
||||
@ -290,25 +385,24 @@ ecma_copy_or_ref_ecma_string (ecma_string_t *string_desc_p) /**< string descript
|
||||
|
||||
if (unlikely (string_desc_p->refs == 0))
|
||||
{
|
||||
/* reference counter has overflowed */
|
||||
string_desc_p->refs--;
|
||||
|
||||
if (string_desc_p->container == ECMA_STRING_CONTAINER_CHARS_IN_DESC
|
||||
|| string_desc_p->container == ECMA_STRING_CONTAINER_LIT_TABLE
|
||||
|| string_desc_p->container == ECMA_STRING_CONTAINER_UINT32_IN_DESC)
|
||||
uint32_t current_refs = string_desc_p->refs;
|
||||
|
||||
/* First trying to free unreachable objects that maybe refer to the string */
|
||||
ecma_gc_run (ECMA_GC_GEN_COUNT - 1);
|
||||
|
||||
if (current_refs == string_desc_p->refs)
|
||||
{
|
||||
ecma_string_t *new_str_p = ecma_alloc_string ();
|
||||
/* reference counter was not changed during GC, copying string */
|
||||
|
||||
*new_str_p = *string_desc_p;
|
||||
|
||||
new_str_p->refs = 1;
|
||||
|
||||
return new_str_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
JERRY_UNIMPLEMENTED ("Unimplemented copy operation for strings, "
|
||||
"stored in heap chunks or number, or concatenated strings.");
|
||||
return ecma_copy_ecma_string (string_desc_p);
|
||||
}
|
||||
|
||||
string_desc_p->refs++;
|
||||
|
||||
JERRY_ASSERT (string_desc_p->refs != 0);
|
||||
}
|
||||
|
||||
return string_desc_p;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user