Skip to content

Implement the core of the map object. #2447

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 4, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions jerry-core/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
# define CONFIG_DISABLE_ES2015_ARROW_FUNCTION
# define CONFIG_DISABLE_ES2015_BUILTIN
# define CONFIG_DISABLE_ES2015_CLASS
# define CONFIG_DISABLE_ES2015_MAP_BUILTIN
# define CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER
# define CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
# define CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS
Expand Down
131 changes: 107 additions & 24 deletions jerry-core/ecma/base/ecma-gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,13 @@

#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
#include "ecma-typedarray-object.h"
#endif
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
#include "ecma-promise-object.h"
#endif
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
#ifndef CONFIG_DISABLE_ES2015_MAP_BUILTIN
#include "ecma-map-object.h"
#endif /* !CONFIG_DISABLE_ES2015_MAP_BUILTIN */

/* TODO: Extract GC to a separate component */

Expand Down Expand Up @@ -206,6 +209,87 @@ ecma_gc_mark_property (ecma_property_pair_t *property_pair_p, /**< property pair
}
} /* ecma_gc_mark_property */

#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN

/**
* Mark objects referenced by Promise built-in.
*/
static void
ecma_gc_mark_promise_object (ecma_extended_object_t *ext_object_p) /**< extended object */
{
/* Mark promise result. */
ecma_value_t result = ext_object_p->u.class_prop.u.value;

if (ecma_is_value_object (result))
{
ecma_gc_set_object_visited (ecma_get_object_from_value (result));
}

/* Mark all reactions. */
ecma_value_t *ecma_value_p;
ecma_value_p = ecma_collection_iterator_init (((ecma_promise_object_t *) ext_object_p)->fulfill_reactions);

while (ecma_value_p != NULL)
{
ecma_gc_set_object_visited (ecma_get_object_from_value (*ecma_value_p));
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
}

ecma_value_p = ecma_collection_iterator_init (((ecma_promise_object_t *) ext_object_p)->reject_reactions);

while (ecma_value_p != NULL)
{
ecma_gc_set_object_visited (ecma_get_object_from_value (*ecma_value_p));
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
}
} /* ecma_gc_mark_promise_object */

#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */

#ifndef CONFIG_DISABLE_ES2015_MAP_BUILTIN

/**
* 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))
Copy link
Contributor

@robertsipka robertsipka Sep 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is just a nit-picking, but I think you could merge these two conditions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We cannot because we would enter into the else branch when value is pointer.

{
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 /* !CONFIG_DISABLE_ES2015_MAP_BUILTIN */

/**
* Mark objects as visited starting from specified object as root
*/
Expand Down Expand Up @@ -243,43 +327,34 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */

switch (ecma_get_object_type (object_p))
{
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
case ECMA_OBJECT_TYPE_CLASS:
{
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;

if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_PROMISE_UL)
switch (ext_object_p->u.class_prop.class_id)
{
/* Mark promise result. */
ecma_value_t result = ext_object_p->u.class_prop.u.value;

if (ecma_is_value_object (result))
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
case LIT_MAGIC_STRING_PROMISE_UL:
{
ecma_gc_set_object_visited (ecma_get_object_from_value (result));
ecma_gc_mark_promise_object (ext_object_p);
break;
}

/* Mark all reactions. */
ecma_value_t *ecma_value_p;
ecma_value_p = ecma_collection_iterator_init (((ecma_promise_object_t *) ext_object_p)->fulfill_reactions);

while (ecma_value_p != NULL)
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
#ifndef CONFIG_DISABLE_ES2015_MAP_BUILTIN
case LIT_MAGIC_STRING_MAP_UL:
{
ecma_gc_set_object_visited (ecma_get_object_from_value (*ecma_value_p));
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
ecma_gc_mark_map_object (ext_object_p);
break;
}

ecma_value_p = ecma_collection_iterator_init (((ecma_promise_object_t *) ext_object_p)->reject_reactions);

while (ecma_value_p != NULL)
#endif /* !CONFIG_DISABLE_ES2015_MAP_BUILTIN */
default:
{
ecma_gc_set_object_visited (ecma_get_object_from_value (*ecma_value_p));
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
break;
}
}

break;
}
#endif /*! CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
{
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
Expand Down Expand Up @@ -582,6 +657,14 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
return;
}
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
#ifndef CONFIG_DISABLE_ES2015_MAP_BUILTIN
case LIT_MAGIC_STRING_MAP_UL:
{
ecma_op_map_clear_map ((ecma_map_object_t *) object_p);
ecma_dealloc_extended_object (object_p, sizeof (ecma_map_object_t));
return;
}
#endif /* !CONFIG_DISABLE_ES2015_MAP_BUILTIN */
default:
{
/* The undefined id represents an uninitialized class. */
Expand Down
43 changes: 35 additions & 8 deletions jerry-core/ecma/base/ecma-globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,12 @@ typedef enum
ECMA_TYPE_FLOAT = 2, /**< pointer to a 64 or 32 bit floating point number */
ECMA_TYPE_OBJECT = 3, /**< pointer to description of an object */
ECMA_TYPE_DIRECT_STRING = 5, /**< directly encoded string values */
ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference */
ECMA_TYPE_COLLECTION_CHUNK = ECMA_TYPE_ERROR, /**< pointer to description of a collection chunk */
ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference (only supported by C API) */
ECMA_TYPE_POINTER = ECMA_TYPE_ERROR, /**< a generic aligned pointer */
ECMA_TYPE_SNAPSHOT_OFFSET = ECMA_TYPE_ERROR, /**< offset to a snapshot number/string */
ECMA_TYPE___MAX = ECMA_TYPE_ERROR /** highest value for ecma types */
} ecma_type_t;


/**
* Option flags for script parsing.
*/
Expand Down Expand Up @@ -166,11 +165,11 @@ enum
ECMA_VALUE_UNDEFINED = ECMA_MAKE_VALUE (4), /**< undefined value */
ECMA_VALUE_NULL = ECMA_MAKE_VALUE (5), /**< null value */
ECMA_VALUE_ARRAY_HOLE = ECMA_MAKE_VALUE (6), /**< array hole, used for
* initialization of an array literal */
* initialization of an array literal */
ECMA_VALUE_NOT_FOUND = ECMA_MAKE_VALUE (7), /**< a special value returned by
* ecma_op_object_find */
* ecma_op_object_find */
ECMA_VALUE_REGISTER_REF = ECMA_MAKE_VALUE (8), /**< register reference,
* a special "base" value for vm */
* a special "base" value for vm */
};

#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
Expand Down Expand Up @@ -826,8 +825,8 @@ typedef struct
*/
typedef struct
{
ecma_extended_object_t header;
const ecma_compiled_code_t *bytecode_p;
ecma_extended_object_t header; /**< header part */
const ecma_compiled_code_t *bytecode_p; /**< real byte code pointer */
} ecma_static_function_t;

#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
Expand Down Expand Up @@ -860,6 +859,34 @@ typedef struct

#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */

#ifndef CONFIG_DISABLE_ES2015_MAP_BUILTIN

/**
* Map item count of chunks
*/
#define ECMA_MAP_OBJECT_ITEM_COUNT 3

/**
* Description of Map objects.
*/
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 */
} ecma_map_object_t;

/**
* Description of Map memory chunk.
*/
typedef struct
{
ecma_value_t items[ECMA_MAP_OBJECT_ITEM_COUNT + 1]; /**< the last item is always a pointer to the next chunk,
* the rest can be ECMA_VALUE_ARRAY_HOLE or any valid value. */
} ecma_map_object_chunk_t;

#endif /* !CONFIG_DISABLE_ES2015_MAP_BUILTIN */

/**
* Description of ECMA property descriptor
*
Expand Down
58 changes: 35 additions & 23 deletions jerry-core/ecma/base/ecma-helpers-value.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,9 +312,9 @@ ecma_is_value_string (ecma_value_t value) /**< ecma value */
} /* ecma_is_value_string */

/**
* Check if the value is direct_ecma-string.
* Check if the value is direct ecma-string.
*
* @return true - if the value contains ecma-string value,
* @return true - if the value contains direct ecma-string value,
* false - otherwise
*/
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
Expand All @@ -323,6 +323,18 @@ ecma_is_value_direct_string (ecma_value_t value) /**< ecma value */
return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING);
} /* ecma_is_value_direct_string */

/**
* Check if the value is non-direct ecma-string.
*
* @return true - if the value contains non-direct ecma-string value,
* false - otherwise
*/
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
ecma_is_value_non_direct_string (ecma_value_t value) /**< ecma value */
{
return (ecma_get_value_type_field (value) == ECMA_TYPE_STRING);
} /* ecma_is_value_non_direct_string */

/**
* Check if the value is object.
*
Expand All @@ -348,16 +360,16 @@ ecma_is_value_error_reference (ecma_value_t value) /**< ecma value */
} /* ecma_is_value_error_reference */

/**
* Check if the value is collection chunk.
* Check if the value is an aligned pointer.
*
* @return true - if the value contains a collection chunk,
* @return true - if the value contains an aligned pointer,
* false - otherwise
*/
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
ecma_is_value_collection_chunk (ecma_value_t value) /**< ecma value */
ecma_is_value_pointer (ecma_value_t value) /**< ecma value */
{
return (ecma_get_value_type_field (value) == ECMA_TYPE_COLLECTION_CHUNK);
} /* ecma_is_value_collection_chunk */
return (ecma_get_value_type_field (value) == ECMA_TYPE_POINTER);
} /* ecma_is_value_pointer */

/**
* Debug assertion that specified value's type is one of ECMA-defined
Expand Down Expand Up @@ -566,27 +578,27 @@ ecma_make_error_reference_value (const ecma_error_reference_t *error_ref_p) /**<
} /* ecma_make_error_reference_value */

/**
* Collection chunk constructor
* Create an ecma value from an aligned pointer
*
* @return ecma-value representation of the collection chunk
* @return ecma-value representation of the aligned pointer
*/
inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
ecma_make_collection_chunk_value (const ecma_collection_chunk_t *collection_chunk_p) /**< collection chunk */
ecma_make_pointer_value (const void *any_p) /**< any aligned pointer */
{
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY

uintptr_t uint_ptr = (uintptr_t) collection_chunk_p;
uintptr_t uint_ptr = (uintptr_t) any_p;
JERRY_ASSERT ((uint_ptr & ECMA_VALUE_TYPE_MASK) == 0);
return ((ecma_value_t) uint_ptr) | ECMA_TYPE_COLLECTION_CHUNK;
return ((ecma_value_t) uint_ptr) | ECMA_TYPE_POINTER;

#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */

jmem_cpointer_t ptr_cp;
ECMA_SET_POINTER (ptr_cp, collection_chunk_p);
return (((ecma_value_t) ptr_cp) << ECMA_VALUE_SHIFT) | ECMA_TYPE_COLLECTION_CHUNK;
ECMA_SET_POINTER (ptr_cp, any_p);
return (((ecma_value_t) ptr_cp) << ECMA_VALUE_SHIFT) | ECMA_TYPE_POINTER;

#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
} /* ecma_make_collection_chunk_value */
} /* ecma_make_pointer_value */

/**
* Get integer value from an integer ecma value
Expand Down Expand Up @@ -675,21 +687,21 @@ ecma_get_error_reference_from_value (ecma_value_t value) /**< ecma value */
} /* ecma_get_error_reference_from_value */

/**
* Get pointer to collection chunk from ecma value
* Get an aligned pointer from an ecma value
*
* @return the pointer
* @return pointer value
*/
inline ecma_collection_chunk_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
ecma_get_collection_chunk_from_value (ecma_value_t value) /**< ecma value */
inline void * JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
ecma_get_pointer_from_value (ecma_value_t value) /**< ecma value */
{
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_COLLECTION_CHUNK);
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_POINTER);

#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
return (ecma_collection_chunk_t *) (uintptr_t) ((value) & ~ECMA_VALUE_TYPE_MASK);
return (void *) (uintptr_t) ((value) & ~ECMA_VALUE_TYPE_MASK);
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
return ECMA_GET_POINTER (ecma_collection_chunk_t, value >> ECMA_VALUE_SHIFT);
return ECMA_GET_POINTER (void, value >> ECMA_VALUE_SHIFT);
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
} /* ecma_get_collection_chunk_from_value */
} /* ecma_get_pointer_from_value */

/**
* Invert a boolean value
Expand Down
Loading