Rework Map object (#2760)
This patch reworks the core of the builtin Map object. Advantages: - Provide sublinear access time for the elements via Lcache and property hashmap - This implementation is suitable for the builtin Set object as well Also add the missing 'forEach' routine for the builtin object as well. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
committed by
László Langó
parent
bc9efb07a5
commit
d2931c6e40
@@ -246,50 +246,6 @@ ecma_gc_mark_promise_object (ecma_extended_object_t *ext_object_p) /**< extended
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
|
||||
|
||||
/**
|
||||
* Mark objects referenced by Map built-in.
|
||||
*/
|
||||
static void
|
||||
ecma_gc_mark_map_object (ecma_extended_object_t *ext_object_p) /**< extended object */
|
||||
{
|
||||
ecma_map_object_t *map_object_p = (ecma_map_object_t *) ext_object_p;
|
||||
|
||||
jmem_cpointer_t first_chunk_cp = map_object_p->first_chunk_cp;
|
||||
|
||||
if (JERRY_UNLIKELY (first_chunk_cp == ECMA_NULL_POINTER))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ecma_value_t *item_p = ECMA_GET_NON_NULL_POINTER (ecma_map_object_chunk_t, first_chunk_cp)->items;
|
||||
|
||||
while (true)
|
||||
{
|
||||
ecma_value_t item = *item_p++;
|
||||
|
||||
if (!ecma_is_value_pointer (item))
|
||||
{
|
||||
if (ecma_is_value_object (item))
|
||||
{
|
||||
ecma_gc_set_object_visited (ecma_get_object_from_value (item));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
item_p = (ecma_value_t *) ecma_get_pointer_from_value (item);
|
||||
|
||||
if (item_p == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* ecma_gc_mark_map_object */
|
||||
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
|
||||
|
||||
/**
|
||||
* Mark objects as visited starting from specified object as root
|
||||
*/
|
||||
@@ -340,13 +296,6 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
|
||||
case LIT_MAGIC_STRING_MAP_UL:
|
||||
{
|
||||
ecma_gc_mark_map_object (ext_object_p);
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
|
||||
default:
|
||||
{
|
||||
break;
|
||||
|
||||
@@ -968,8 +968,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
ecma_extended_object_t header; /**< header part */
|
||||
jmem_cpointer_t first_chunk_cp; /**< first chunk of item list */
|
||||
jmem_cpointer_t last_chunk_cp; /**< last chunk of item list */
|
||||
uint32_t size; /**< size of the map object */
|
||||
} ecma_map_object_t;
|
||||
|
||||
/**
|
||||
@@ -1273,6 +1272,7 @@ typedef enum
|
||||
ECMA_DIRECT_STRING_PTR = 0, /**< string is a string pointer, only used by property names */
|
||||
ECMA_DIRECT_STRING_MAGIC = 1, /**< string is a magic string */
|
||||
ECMA_DIRECT_STRING_UINT = 2, /**< string is an unsigned int */
|
||||
ECMA_DIRECT_STRING_ECMA_INTEGER = 3, /**< string is an ecma-integer */
|
||||
} ecma_direct_string_type_t;
|
||||
|
||||
/**
|
||||
@@ -1351,6 +1351,8 @@ typedef enum
|
||||
|
||||
ECMA_STRING_CONTAINER_SYMBOL, /**< the ecma-string is a symbol */
|
||||
|
||||
ECMA_STRING_CONTAINER_MAP_KEY, /**< the ecma-string is a map key string */
|
||||
|
||||
ECMA_STRING_LITERAL_NUMBER, /**< a literal number which is used solely by the literal storage
|
||||
* so no string processing function supports this type except
|
||||
* the ecma_deref_ecma_string function. */
|
||||
@@ -1422,6 +1424,7 @@ typedef struct
|
||||
ecma_value_t lit_number; /**< number (see ECMA_STRING_LITERAL_NUMBER) */
|
||||
uint32_t common_uint32_field; /**< for zeroing and comparison in some cases */
|
||||
ecma_value_t symbol_descriptor; /**< symbol descriptor string-value */
|
||||
ecma_value_t value; /**< original key value corresponds to the map key string */
|
||||
} u;
|
||||
} ecma_string_t;
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "ecma-alloc.h"
|
||||
#include "ecma-conversion.h"
|
||||
#include "ecma-gc.h"
|
||||
#include "ecma-globals.h"
|
||||
#include "ecma-helpers.h"
|
||||
@@ -236,6 +237,41 @@ ecma_prop_name_is_symbol (ecma_string_t *string_p) /**< ecma-string */
|
||||
} /* ecma_prop_name_is_symbol */
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
|
||||
/**
|
||||
* Allocate new ecma-string and fill it with reference to the map key descriptor
|
||||
*
|
||||
* @return pointer to ecma-string descriptor
|
||||
*/
|
||||
ecma_string_t *
|
||||
ecma_new_map_key_string (ecma_value_t value) /**< non prop-name ecma-value */
|
||||
{
|
||||
JERRY_ASSERT (!ecma_is_value_prop_name (value));
|
||||
|
||||
ecma_string_t *string_p = ecma_alloc_string ();
|
||||
string_p->refs_and_container = ECMA_STRING_REF_ONE | ECMA_STRING_CONTAINER_MAP_KEY;
|
||||
string_p->u.value = ecma_copy_value_if_not_object (value);
|
||||
string_p->hash = ecma_is_value_simple (value) ? (uint16_t) value : 0;
|
||||
|
||||
return string_p;
|
||||
} /* ecma_new_map_key_string */
|
||||
|
||||
/**
|
||||
* Check whether an ecma-string contains a map key string
|
||||
*
|
||||
* @return true - if the ecma-string contains a map key string
|
||||
* false - otherwise
|
||||
*/
|
||||
bool
|
||||
ecma_prop_name_is_map_key (ecma_string_t *string_p) /**< ecma-string */
|
||||
{
|
||||
JERRY_ASSERT (string_p != NULL);
|
||||
|
||||
return (!ECMA_IS_DIRECT_STRING (string_p)
|
||||
&& ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_MAP_KEY);
|
||||
} /* ecma_prop_name_is_map_key */
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
|
||||
|
||||
/**
|
||||
* Allocate new ecma-string and fill it with characters from the utf8 string
|
||||
*
|
||||
@@ -984,6 +1020,13 @@ ecma_deref_ecma_string (ecma_string_t *string_p) /**< ecma-string */
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
|
||||
case ECMA_STRING_CONTAINER_MAP_KEY:
|
||||
{
|
||||
ecma_free_value_if_not_object (string_p->u.value);
|
||||
break;
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
|
||||
default:
|
||||
{
|
||||
JERRY_ASSERT (ECMA_STRING_GET_CONTAINER (string_p) == ECMA_STRING_CONTAINER_UINT32_IN_DESC
|
||||
@@ -1865,6 +1908,13 @@ ecma_compare_ecma_non_direct_strings (const ecma_string_t *string1_p, /**< ecma-
|
||||
return false;
|
||||
}
|
||||
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
|
||||
if (string1_container == ECMA_STRING_CONTAINER_MAP_KEY)
|
||||
{
|
||||
return ecma_op_same_value_zero (string1_p->u.value, string2_p->u.value);
|
||||
}
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
|
||||
|
||||
if (string1_container >= ECMA_STRING_CONTAINER_UINT32_IN_DESC)
|
||||
{
|
||||
return string1_p->u.common_uint32_field == string2_p->u.common_uint32_field;
|
||||
|
||||
@@ -222,6 +222,10 @@ lit_magic_string_id_t ecma_get_typeof_lit_id (ecma_value_t value);
|
||||
ecma_string_t *ecma_new_symbol_from_descriptor_string (ecma_value_t string_desc);
|
||||
bool ecma_prop_name_is_symbol (ecma_string_t *string_p);
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
|
||||
#if ENABLED (JERRY_ES2015_BUILTIN_MAP)
|
||||
ecma_string_t *ecma_new_map_key_string (ecma_value_t value);
|
||||
bool ecma_prop_name_is_map_key (ecma_string_t *string_p);
|
||||
#endif /* ENABLED (JERRY_ES2015_BUILTIN_MAP) */
|
||||
ecma_string_t *ecma_new_ecma_string_from_utf8 (const lit_utf8_byte_t *string_p, lit_utf8_size_t string_size);
|
||||
ecma_string_t *ecma_new_ecma_string_from_utf8_converted_to_cesu8 (const lit_utf8_byte_t *string_p,
|
||||
lit_utf8_size_t string_size);
|
||||
|
||||
Reference in New Issue
Block a user