Skip to content

Commit 110f75c

Browse files
zherczegdbatyai
authored andcommitted
Implement the core of the generator functions. (#3368)
Some things are missing: - yield* support - generator definition in object literal - the hidden GeneratorFunction JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg [email protected]
1 parent 14e95a4 commit 110f75c

35 files changed

+1531
-81
lines changed

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

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ ecma_gc_mark_promise_object (ecma_extended_object_t *ext_object_p) /**< extended
293293
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROMISE) */
294294

295295
#if ENABLED (JERRY_ES2015_BUILTIN_CONTAINER)
296+
296297
/**
297298
* Mark objects referenced by Map/Set built-in.
298299
*/
@@ -359,6 +360,73 @@ ecma_gc_mark_container_object (ecma_object_t *object_p) /**< object */
359360

360361
#endif /* ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */
361362

363+
#if ENABLED (JERRY_ES2015)
364+
365+
/**
366+
* Mark objects referenced by inactive generator functions, async functions, etc.
367+
*/
368+
static void
369+
ecma_gc_mark_executable_object (ecma_object_t *object_p) /**< object */
370+
{
371+
vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p;
372+
373+
if (!ECMA_EXECUTABLE_OBJECT_IS_SUSPENDED (executable_object_p->extended_object.u.class_prop.extra_info))
374+
{
375+
/* All objects referenced by running executable objects are strong roots,
376+
* and a finished executable object cannot refer to other values. */
377+
return;
378+
}
379+
380+
ecma_gc_set_object_visited (executable_object_p->frame_ctx.lex_env_p);
381+
382+
if (ecma_is_value_object (executable_object_p->frame_ctx.this_binding))
383+
{
384+
ecma_gc_set_object_visited (ecma_get_object_from_value (executable_object_p->frame_ctx.this_binding));
385+
}
386+
387+
const ecma_compiled_code_t *bytecode_header_p = executable_object_p->frame_ctx.bytecode_header_p;
388+
size_t register_end;
389+
390+
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
391+
{
392+
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p;
393+
register_end = args_p->register_end;
394+
}
395+
else
396+
{
397+
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p;
398+
register_end = args_p->register_end;
399+
}
400+
401+
ecma_value_t *register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx);
402+
ecma_value_t *register_end_p = register_p + register_end;
403+
404+
while (register_p < register_end_p)
405+
{
406+
if (ecma_is_value_object (*register_p))
407+
{
408+
ecma_gc_set_object_visited (ecma_get_object_from_value (*register_p));
409+
}
410+
411+
register_p++;
412+
}
413+
414+
register_p += executable_object_p->frame_ctx.context_depth;
415+
register_end_p = executable_object_p->frame_ctx.stack_top_p;
416+
417+
while (register_p < register_end_p)
418+
{
419+
if (ecma_is_value_object (*register_p))
420+
{
421+
ecma_gc_set_object_visited (ecma_get_object_from_value (*register_p));
422+
}
423+
424+
register_p++;
425+
}
426+
} /* ecma_gc_mark_executable_object */
427+
428+
#endif /* ENABLED (JERRY_ES2015) */
429+
362430
/**
363431
* Mark objects as visited starting from specified object as root
364432
*/
@@ -435,6 +503,13 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
435503
break;
436504
}
437505
#endif /* ENABLED (JERRY_ES2015_BUILTIN_CONTAINER) */
506+
#if ENABLED (JERRY_ES2015)
507+
case LIT_MAGIC_STRING_GENERATOR_UL:
508+
{
509+
ecma_gc_mark_executable_object (object_p);
510+
break;
511+
}
512+
#endif /* ENABLED (JERRY_ES2015) */
438513
default:
439514
{
440515
break;
@@ -641,6 +716,100 @@ ecma_free_fast_access_array (ecma_object_t *object_p) /**< fast access mode arra
641716
ecma_dealloc_extended_object (object_p, sizeof (ecma_extended_object_t));
642717
} /* ecma_free_fast_access_array */
643718

719+
#if ENABLED (JERRY_ES2015)
720+
721+
/**
722+
* Free non-objects referenced by inactive generator functions, async functions, etc.
723+
*
724+
* @return total object size
725+
*/
726+
static size_t
727+
ecma_gc_free_executable_object (ecma_object_t *object_p) /**< object */
728+
{
729+
vm_executable_object_t *executable_object_p = (vm_executable_object_t *) object_p;
730+
731+
const ecma_compiled_code_t *bytecode_header_p = executable_object_p->frame_ctx.bytecode_header_p;
732+
size_t size, register_end;
733+
734+
if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
735+
{
736+
cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_header_p;
737+
738+
register_end = args_p->register_end;
739+
size = (register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t);
740+
}
741+
else
742+
{
743+
cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_header_p;
744+
745+
register_end = args_p->register_end;
746+
size = (register_end + (size_t) args_p->stack_limit) * sizeof (ecma_value_t);
747+
}
748+
749+
size = JERRY_ALIGNUP (sizeof (vm_executable_object_t) + size, sizeof (uintptr_t));
750+
751+
JERRY_ASSERT (!(executable_object_p->extended_object.u.class_prop.extra_info & ECMA_EXECUTABLE_OBJECT_RUNNING));
752+
753+
ecma_bytecode_deref ((ecma_compiled_code_t *) bytecode_header_p);
754+
755+
if (executable_object_p->extended_object.u.class_prop.extra_info & ECMA_EXECUTABLE_OBJECT_COMPLETED)
756+
{
757+
return size;
758+
}
759+
760+
ecma_free_value_if_not_object (executable_object_p->frame_ctx.this_binding);
761+
762+
ecma_value_t *register_p = VM_GET_REGISTERS (&executable_object_p->frame_ctx);
763+
ecma_value_t *register_end_p = register_p + register_end;
764+
765+
while (register_p < register_end_p)
766+
{
767+
ecma_free_value_if_not_object (*register_p++);
768+
}
769+
770+
if (executable_object_p->frame_ctx.context_depth > 0)
771+
{
772+
ecma_value_t *context_end_p = register_p;
773+
774+
register_p += executable_object_p->frame_ctx.context_depth;
775+
776+
ecma_value_t *context_top_p = register_p;
777+
778+
do
779+
{
780+
context_top_p[-1] &= (uint32_t) ~VM_CONTEXT_HAS_LEX_ENV;
781+
782+
uint32_t offsets = vm_get_context_value_offsets (context_top_p);
783+
784+
while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets))
785+
{
786+
int32_t offset = VM_CONTEXT_GET_NEXT_OFFSET (offsets);
787+
788+
if (ecma_is_value_object (context_top_p[offset]))
789+
{
790+
context_top_p[offset] = ECMA_VALUE_UNDEFINED;
791+
}
792+
793+
offsets >>= VM_CONTEXT_OFFSET_SHIFT;
794+
}
795+
796+
context_top_p = vm_stack_context_abort (&executable_object_p->frame_ctx, context_top_p);
797+
}
798+
while (context_top_p > context_end_p);
799+
}
800+
801+
register_end_p = executable_object_p->frame_ctx.stack_top_p;
802+
803+
while (register_p < register_end_p)
804+
{
805+
ecma_free_value_if_not_object (*register_p++);
806+
}
807+
808+
return size;
809+
} /* ecma_gc_free_executable_object */
810+
811+
#endif /* ENABLED (JERRY_ES2015) */
812+
644813
/**
645814
* Free properties of an object
646815
*/
@@ -930,6 +1099,13 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
9301099
break;
9311100
}
9321101
#endif /* ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW) */
1102+
#if ENABLED (JERRY_ES2015)
1103+
case LIT_MAGIC_STRING_GENERATOR_UL:
1104+
{
1105+
ext_object_size = ecma_gc_free_executable_object (object_p);
1106+
break;
1107+
}
1108+
#endif /* ENABLED (JERRY_ES2015) */
9331109
default:
9341110
{
9351111
/* The undefined id represents an uninitialized class. */

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,6 +1750,35 @@ typedef struct
17501750

17511751
#endif /* ENABLED (JERRY_ES2015_BUILTIN_TYPEDARRAY) */
17521752

1753+
#if ENABLED (JERRY_ES2015)
1754+
1755+
/**
1756+
* Executable (e.g. generator, async) object flags.
1757+
*/
1758+
typedef enum
1759+
{
1760+
ECMA_EXECUTABLE_OBJECT_COMPLETED = (1u << 0), /**< executable object is completed and cannot be resumed */
1761+
ECMA_EXECUTABLE_OBJECT_RUNNING = (1u << 1), /**< executable object is currently running */
1762+
} ecma_executable_object_flags_t;
1763+
1764+
/**
1765+
* Checks whether the executable object is waiting for resuming.
1766+
*/
1767+
#define ECMA_EXECUTABLE_OBJECT_IS_SUSPENDED(extra_info) \
1768+
(!((extra_info) & (ECMA_EXECUTABLE_OBJECT_COMPLETED | ECMA_EXECUTABLE_OBJECT_RUNNING)))
1769+
1770+
/**
1771+
* Executable (e.g. generator, async) object flags.
1772+
*/
1773+
typedef enum
1774+
{
1775+
ECMA_GENERATOR_NEXT, /**< generator should continue its execution */
1776+
ECMA_GENERATOR_RETURN, /**< generator should perform a return operation */
1777+
ECMA_GENERATOR_THROW, /**< generator should perform a throw operation */
1778+
} ecma_generator_yield_mode_t;
1779+
1780+
#endif /* ENABLED (JERRY_ES2015) */
1781+
17531782
#if ENABLED (JERRY_ES2015_BUILTIN_DATAVIEW)
17541783
/**
17551784
* Description of DataView objects.

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

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -855,17 +855,41 @@ ecma_fast_copy_value (ecma_value_t value) /**< value description */
855855
*
856856
* @return copy of the given value
857857
*/
858-
ecma_value_t
858+
inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
859859
ecma_copy_value_if_not_object (ecma_value_t value) /**< value description */
860860
{
861-
if (ecma_get_value_type_field (value) != ECMA_TYPE_OBJECT)
861+
if (!ecma_is_value_object (value))
862862
{
863863
return ecma_copy_value (value);
864864
}
865865

866866
return value;
867867
} /* ecma_copy_value_if_not_object */
868868

869+
/**
870+
* Increase reference counter of a value if it is an object.
871+
*/
872+
inline void JERRY_ATTR_ALWAYS_INLINE
873+
ecma_ref_if_object (ecma_value_t value) /**< value description */
874+
{
875+
if (ecma_is_value_object (value))
876+
{
877+
ecma_ref_object (ecma_get_object_from_value (value));
878+
}
879+
} /* ecma_ref_if_object */
880+
881+
/**
882+
* Decrease reference counter of a value if it is an object.
883+
*/
884+
inline void JERRY_ATTR_ALWAYS_INLINE
885+
ecma_deref_if_object (ecma_value_t value) /**< value description */
886+
{
887+
if (ecma_is_value_object (value))
888+
{
889+
ecma_deref_object (ecma_get_object_from_value (value));
890+
}
891+
} /* ecma_deref_if_object */
892+
869893
/**
870894
* Assign a new value to an ecma-value
871895
*

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ ecma_value_t JERRY_ATTR_CONST ecma_invert_boolean_value (ecma_value_t value);
218218
ecma_value_t ecma_copy_value (ecma_value_t value);
219219
ecma_value_t ecma_fast_copy_value (ecma_value_t value);
220220
ecma_value_t ecma_copy_value_if_not_object (ecma_value_t value);
221+
void ecma_ref_if_object (ecma_value_t value);
222+
void ecma_deref_if_object (ecma_value_t value);
221223
ecma_value_t ecma_update_float_number (ecma_value_t float_value, ecma_number_t new_number);
222224
void ecma_value_assign_value (ecma_value_t *value_p, ecma_value_t ecma_value);
223225
void ecma_value_assign_number (ecma_value_t *value_p, ecma_number_t ecma_number);

0 commit comments

Comments
 (0)