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:
Robert Fancsik
2019-04-17 14:50:03 +02:00
committed by László Langó
parent bc9efb07a5
commit d2931c6e40
14 changed files with 525 additions and 406 deletions
-51
View File
@@ -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;
+5 -2
View File
@@ -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;
+4
View File
@@ -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);