Skip to content

Commit d3d42f7

Browse files
zherczegrobertsipka
authored andcommitted
Implement the core of the map object. (#2447)
JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
1 parent 65e81f3 commit d3d42f7

20 files changed

+1267
-79
lines changed

jerry-core/config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
# define CONFIG_DISABLE_ES2015_ARROW_FUNCTION
4040
# define CONFIG_DISABLE_ES2015_BUILTIN
4141
# define CONFIG_DISABLE_ES2015_CLASS
42+
# define CONFIG_DISABLE_ES2015_MAP_BUILTIN
4243
# define CONFIG_DISABLE_ES2015_OBJECT_INITIALIZER
4344
# define CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
4445
# define CONFIG_DISABLE_ES2015_TEMPLATE_STRINGS

jerry-core/ecma/base/ecma-gc.c

Lines changed: 107 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,13 @@
3232

3333
#ifndef CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN
3434
#include "ecma-typedarray-object.h"
35-
#endif
35+
#endif /* !CONFIG_DISABLE_ES2015_TYPEDARRAY_BUILTIN */
3636
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
3737
#include "ecma-promise-object.h"
38-
#endif
38+
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
39+
#ifndef CONFIG_DISABLE_ES2015_MAP_BUILTIN
40+
#include "ecma-map-object.h"
41+
#endif /* !CONFIG_DISABLE_ES2015_MAP_BUILTIN */
3942

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

@@ -206,6 +209,87 @@ ecma_gc_mark_property (ecma_property_pair_t *property_pair_p, /**< property pair
206209
}
207210
} /* ecma_gc_mark_property */
208211

212+
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
213+
214+
/**
215+
* Mark objects referenced by Promise built-in.
216+
*/
217+
static void
218+
ecma_gc_mark_promise_object (ecma_extended_object_t *ext_object_p) /**< extended object */
219+
{
220+
/* Mark promise result. */
221+
ecma_value_t result = ext_object_p->u.class_prop.u.value;
222+
223+
if (ecma_is_value_object (result))
224+
{
225+
ecma_gc_set_object_visited (ecma_get_object_from_value (result));
226+
}
227+
228+
/* Mark all reactions. */
229+
ecma_value_t *ecma_value_p;
230+
ecma_value_p = ecma_collection_iterator_init (((ecma_promise_object_t *) ext_object_p)->fulfill_reactions);
231+
232+
while (ecma_value_p != NULL)
233+
{
234+
ecma_gc_set_object_visited (ecma_get_object_from_value (*ecma_value_p));
235+
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
236+
}
237+
238+
ecma_value_p = ecma_collection_iterator_init (((ecma_promise_object_t *) ext_object_p)->reject_reactions);
239+
240+
while (ecma_value_p != NULL)
241+
{
242+
ecma_gc_set_object_visited (ecma_get_object_from_value (*ecma_value_p));
243+
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
244+
}
245+
} /* ecma_gc_mark_promise_object */
246+
247+
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
248+
249+
#ifndef CONFIG_DISABLE_ES2015_MAP_BUILTIN
250+
251+
/**
252+
* Mark objects referenced by Map built-in.
253+
*/
254+
static void
255+
ecma_gc_mark_map_object (ecma_extended_object_t *ext_object_p) /**< extended object */
256+
{
257+
ecma_map_object_t *map_object_p = (ecma_map_object_t *) ext_object_p;
258+
259+
jmem_cpointer_t first_chunk_cp = map_object_p->first_chunk_cp;
260+
261+
if (JERRY_UNLIKELY (first_chunk_cp == ECMA_NULL_POINTER))
262+
{
263+
return;
264+
}
265+
266+
ecma_value_t *item_p = ECMA_GET_NON_NULL_POINTER (ecma_map_object_chunk_t, first_chunk_cp)->items;
267+
268+
while (true)
269+
{
270+
ecma_value_t item = *item_p++;
271+
272+
if (!ecma_is_value_pointer (item))
273+
{
274+
if (ecma_is_value_object (item))
275+
{
276+
ecma_gc_set_object_visited (ecma_get_object_from_value (item));
277+
}
278+
}
279+
else
280+
{
281+
item_p = (ecma_value_t *) ecma_get_pointer_from_value (item);
282+
283+
if (item_p == NULL)
284+
{
285+
return;
286+
}
287+
}
288+
}
289+
} /* ecma_gc_mark_map_object */
290+
291+
#endif /* !CONFIG_DISABLE_ES2015_MAP_BUILTIN */
292+
209293
/**
210294
* Mark objects as visited starting from specified object as root
211295
*/
@@ -243,43 +327,34 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
243327

244328
switch (ecma_get_object_type (object_p))
245329
{
246-
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
247330
case ECMA_OBJECT_TYPE_CLASS:
248331
{
249332
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
250333

251-
if (ext_object_p->u.class_prop.class_id == LIT_MAGIC_STRING_PROMISE_UL)
334+
switch (ext_object_p->u.class_prop.class_id)
252335
{
253-
/* Mark promise result. */
254-
ecma_value_t result = ext_object_p->u.class_prop.u.value;
255-
256-
if (ecma_is_value_object (result))
336+
#ifndef CONFIG_DISABLE_ES2015_PROMISE_BUILTIN
337+
case LIT_MAGIC_STRING_PROMISE_UL:
257338
{
258-
ecma_gc_set_object_visited (ecma_get_object_from_value (result));
339+
ecma_gc_mark_promise_object (ext_object_p);
340+
break;
259341
}
260-
261-
/* Mark all reactions. */
262-
ecma_value_t *ecma_value_p;
263-
ecma_value_p = ecma_collection_iterator_init (((ecma_promise_object_t *) ext_object_p)->fulfill_reactions);
264-
265-
while (ecma_value_p != NULL)
342+
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
343+
#ifndef CONFIG_DISABLE_ES2015_MAP_BUILTIN
344+
case LIT_MAGIC_STRING_MAP_UL:
266345
{
267-
ecma_gc_set_object_visited (ecma_get_object_from_value (*ecma_value_p));
268-
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
346+
ecma_gc_mark_map_object (ext_object_p);
347+
break;
269348
}
270-
271-
ecma_value_p = ecma_collection_iterator_init (((ecma_promise_object_t *) ext_object_p)->reject_reactions);
272-
273-
while (ecma_value_p != NULL)
349+
#endif /* !CONFIG_DISABLE_ES2015_MAP_BUILTIN */
350+
default:
274351
{
275-
ecma_gc_set_object_visited (ecma_get_object_from_value (*ecma_value_p));
276-
ecma_value_p = ecma_collection_iterator_next (ecma_value_p);
352+
break;
277353
}
278354
}
279355

280356
break;
281357
}
282-
#endif /*! CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
283358
case ECMA_OBJECT_TYPE_PSEUDO_ARRAY:
284359
{
285360
ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) object_p;
@@ -582,6 +657,14 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
582657
return;
583658
}
584659
#endif /* !CONFIG_DISABLE_ES2015_PROMISE_BUILTIN */
660+
#ifndef CONFIG_DISABLE_ES2015_MAP_BUILTIN
661+
case LIT_MAGIC_STRING_MAP_UL:
662+
{
663+
ecma_op_map_clear_map ((ecma_map_object_t *) object_p);
664+
ecma_dealloc_extended_object (object_p, sizeof (ecma_map_object_t));
665+
return;
666+
}
667+
#endif /* !CONFIG_DISABLE_ES2015_MAP_BUILTIN */
585668
default:
586669
{
587670
/* The undefined id represents an uninitialized class. */

jerry-core/ecma/base/ecma-globals.h

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,13 +74,12 @@ typedef enum
7474
ECMA_TYPE_FLOAT = 2, /**< pointer to a 64 or 32 bit floating point number */
7575
ECMA_TYPE_OBJECT = 3, /**< pointer to description of an object */
7676
ECMA_TYPE_DIRECT_STRING = 5, /**< directly encoded string values */
77-
ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference */
78-
ECMA_TYPE_COLLECTION_CHUNK = ECMA_TYPE_ERROR, /**< pointer to description of a collection chunk */
77+
ECMA_TYPE_ERROR = 7, /**< pointer to description of an error reference (only supported by C API) */
78+
ECMA_TYPE_POINTER = ECMA_TYPE_ERROR, /**< a generic aligned pointer */
7979
ECMA_TYPE_SNAPSHOT_OFFSET = ECMA_TYPE_ERROR, /**< offset to a snapshot number/string */
8080
ECMA_TYPE___MAX = ECMA_TYPE_ERROR /** highest value for ecma types */
8181
} ecma_type_t;
8282

83-
8483
/**
8584
* Option flags for script parsing.
8685
*/
@@ -166,11 +165,11 @@ enum
166165
ECMA_VALUE_UNDEFINED = ECMA_MAKE_VALUE (4), /**< undefined value */
167166
ECMA_VALUE_NULL = ECMA_MAKE_VALUE (5), /**< null value */
168167
ECMA_VALUE_ARRAY_HOLE = ECMA_MAKE_VALUE (6), /**< array hole, used for
169-
* initialization of an array literal */
168+
* initialization of an array literal */
170169
ECMA_VALUE_NOT_FOUND = ECMA_MAKE_VALUE (7), /**< a special value returned by
171-
* ecma_op_object_find */
170+
* ecma_op_object_find */
172171
ECMA_VALUE_REGISTER_REF = ECMA_MAKE_VALUE (8), /**< register reference,
173-
* a special "base" value for vm */
172+
* a special "base" value for vm */
174173
};
175174

176175
#if CONFIG_ECMA_NUMBER_TYPE == CONFIG_ECMA_NUMBER_FLOAT32
@@ -826,8 +825,8 @@ typedef struct
826825
*/
827826
typedef struct
828827
{
829-
ecma_extended_object_t header;
830-
const ecma_compiled_code_t *bytecode_p;
828+
ecma_extended_object_t header; /**< header part */
829+
const ecma_compiled_code_t *bytecode_p; /**< real byte code pointer */
831830
} ecma_static_function_t;
832831

833832
#endif /* JERRY_ENABLE_SNAPSHOT_EXEC */
@@ -860,6 +859,34 @@ typedef struct
860859

861860
#endif /* !CONFIG_DISABLE_ES2015_ARROW_FUNCTION */
862861

862+
#ifndef CONFIG_DISABLE_ES2015_MAP_BUILTIN
863+
864+
/**
865+
* Map item count of chunks
866+
*/
867+
#define ECMA_MAP_OBJECT_ITEM_COUNT 3
868+
869+
/**
870+
* Description of Map objects.
871+
*/
872+
typedef struct
873+
{
874+
ecma_extended_object_t header; /**< header part */
875+
jmem_cpointer_t first_chunk_cp; /**< first chunk of item list */
876+
jmem_cpointer_t last_chunk_cp; /**< last chunk of item list */
877+
} ecma_map_object_t;
878+
879+
/**
880+
* Description of Map memory chunk.
881+
*/
882+
typedef struct
883+
{
884+
ecma_value_t items[ECMA_MAP_OBJECT_ITEM_COUNT + 1]; /**< the last item is always a pointer to the next chunk,
885+
* the rest can be ECMA_VALUE_ARRAY_HOLE or any valid value. */
886+
} ecma_map_object_chunk_t;
887+
888+
#endif /* !CONFIG_DISABLE_ES2015_MAP_BUILTIN */
889+
863890
/**
864891
* Description of ECMA property descriptor
865892
*

jerry-core/ecma/base/ecma-helpers-value.c

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -312,9 +312,9 @@ ecma_is_value_string (ecma_value_t value) /**< ecma value */
312312
} /* ecma_is_value_string */
313313

314314
/**
315-
* Check if the value is direct_ecma-string.
315+
* Check if the value is direct ecma-string.
316316
*
317-
* @return true - if the value contains ecma-string value,
317+
* @return true - if the value contains direct ecma-string value,
318318
* false - otherwise
319319
*/
320320
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
@@ -323,6 +323,18 @@ ecma_is_value_direct_string (ecma_value_t value) /**< ecma value */
323323
return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING);
324324
} /* ecma_is_value_direct_string */
325325

326+
/**
327+
* Check if the value is non-direct ecma-string.
328+
*
329+
* @return true - if the value contains non-direct ecma-string value,
330+
* false - otherwise
331+
*/
332+
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
333+
ecma_is_value_non_direct_string (ecma_value_t value) /**< ecma value */
334+
{
335+
return (ecma_get_value_type_field (value) == ECMA_TYPE_STRING);
336+
} /* ecma_is_value_non_direct_string */
337+
326338
/**
327339
* Check if the value is object.
328340
*
@@ -348,16 +360,16 @@ ecma_is_value_error_reference (ecma_value_t value) /**< ecma value */
348360
} /* ecma_is_value_error_reference */
349361

350362
/**
351-
* Check if the value is collection chunk.
363+
* Check if the value is an aligned pointer.
352364
*
353-
* @return true - if the value contains a collection chunk,
365+
* @return true - if the value contains an aligned pointer,
354366
* false - otherwise
355367
*/
356368
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
357-
ecma_is_value_collection_chunk (ecma_value_t value) /**< ecma value */
369+
ecma_is_value_pointer (ecma_value_t value) /**< ecma value */
358370
{
359-
return (ecma_get_value_type_field (value) == ECMA_TYPE_COLLECTION_CHUNK);
360-
} /* ecma_is_value_collection_chunk */
371+
return (ecma_get_value_type_field (value) == ECMA_TYPE_POINTER);
372+
} /* ecma_is_value_pointer */
361373

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

568580
/**
569-
* Collection chunk constructor
581+
* Create an ecma value from an aligned pointer
570582
*
571-
* @return ecma-value representation of the collection chunk
583+
* @return ecma-value representation of the aligned pointer
572584
*/
573585
inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
574-
ecma_make_collection_chunk_value (const ecma_collection_chunk_t *collection_chunk_p) /**< collection chunk */
586+
ecma_make_pointer_value (const void *any_p) /**< any aligned pointer */
575587
{
576588
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
577589

578-
uintptr_t uint_ptr = (uintptr_t) collection_chunk_p;
590+
uintptr_t uint_ptr = (uintptr_t) any_p;
579591
JERRY_ASSERT ((uint_ptr & ECMA_VALUE_TYPE_MASK) == 0);
580-
return ((ecma_value_t) uint_ptr) | ECMA_TYPE_COLLECTION_CHUNK;
592+
return ((ecma_value_t) uint_ptr) | ECMA_TYPE_POINTER;
581593

582594
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
583595

584596
jmem_cpointer_t ptr_cp;
585-
ECMA_SET_POINTER (ptr_cp, collection_chunk_p);
586-
return (((ecma_value_t) ptr_cp) << ECMA_VALUE_SHIFT) | ECMA_TYPE_COLLECTION_CHUNK;
597+
ECMA_SET_POINTER (ptr_cp, any_p);
598+
return (((ecma_value_t) ptr_cp) << ECMA_VALUE_SHIFT) | ECMA_TYPE_POINTER;
587599

588600
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
589-
} /* ecma_make_collection_chunk_value */
601+
} /* ecma_make_pointer_value */
590602

591603
/**
592604
* Get integer value from an integer ecma value
@@ -675,21 +687,21 @@ ecma_get_error_reference_from_value (ecma_value_t value) /**< ecma value */
675687
} /* ecma_get_error_reference_from_value */
676688

677689
/**
678-
* Get pointer to collection chunk from ecma value
690+
* Get an aligned pointer from an ecma value
679691
*
680-
* @return the pointer
692+
* @return pointer value
681693
*/
682-
inline ecma_collection_chunk_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
683-
ecma_get_collection_chunk_from_value (ecma_value_t value) /**< ecma value */
694+
inline void * JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
695+
ecma_get_pointer_from_value (ecma_value_t value) /**< ecma value */
684696
{
685-
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_COLLECTION_CHUNK);
697+
JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_POINTER);
686698

687699
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
688-
return (ecma_collection_chunk_t *) (uintptr_t) ((value) & ~ECMA_VALUE_TYPE_MASK);
700+
return (void *) (uintptr_t) ((value) & ~ECMA_VALUE_TYPE_MASK);
689701
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
690-
return ECMA_GET_POINTER (ecma_collection_chunk_t, value >> ECMA_VALUE_SHIFT);
702+
return ECMA_GET_POINTER (void, value >> ECMA_VALUE_SHIFT);
691703
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
692-
} /* ecma_get_collection_chunk_from_value */
704+
} /* ecma_get_pointer_from_value */
693705

694706
/**
695707
* Invert a boolean value

0 commit comments

Comments
 (0)