Support caching of next method in for-of and built-in methods. (#3939)

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2020-06-26 14:47:39 +02:00
committed by GitHub
parent 264bb210c1
commit 0b404ea893
12 changed files with 150 additions and 70 deletions
@@ -153,7 +153,8 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */
ecma_object_t *array_obj_p = ecma_get_object_from_value (array);
/* 6.d */
ecma_value_t iterator = ecma_op_get_iterator (items, using_iterator, NULL);
ecma_value_t next_method;
ecma_value_t iterator = ecma_op_get_iterator (items, using_iterator, &next_method);
ecma_free_value (using_iterator);
/* 6.e */
@@ -170,7 +171,7 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */
while (true)
{
/* 6.g.ii */
ecma_value_t next = ecma_op_iterator_step (iterator);
ecma_value_t next = ecma_op_iterator_step (iterator, next_method);
/* 6.g.iii */
if (ECMA_IS_VALUE_ERROR (next))
@@ -196,6 +197,7 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */
}
ecma_free_value (iterator);
ecma_free_value (next_method);
/* 6.g.iv.3 */
return array;
}
@@ -254,6 +256,7 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */
iterator_cleanup:
ecma_free_value (iterator);
ecma_free_value (next_method);
ecma_free_value (array);
return ret_value;
@@ -126,6 +126,7 @@ ecma_builtin_promise_resolve (ecma_value_t this_arg, /**< 'this' argument */
*/
inline static ecma_value_t
ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for race */
ecma_value_t next_method, /**< next method */
ecma_value_t capability, /**< PromiseCapability record */
ecma_value_t ctor, /**< Constructor value */
bool *done_p) /**< [out] iteratorRecord[[done]] */
@@ -138,7 +139,7 @@ ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for
while (true)
{
/* a. */
ecma_value_t next = ecma_op_iterator_step (iterator);
ecma_value_t next = ecma_op_iterator_step (iterator, next_method);
/* b, c. */
if (ECMA_IS_VALUE_ERROR (next))
{
@@ -321,8 +322,9 @@ ecma_builtin_promise_all_handler (const ecma_value_t function, /**< the function
*/
inline static ecma_value_t
ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */
ecma_value_t ctor, /**< the caller of Promise.race */
ecma_value_t next_method, /**< next method */
ecma_value_t capability, /**< PromiseCapability record */
ecma_value_t ctor, /**< the caller of Promise.race */
bool *done_p) /**< [out] iteratorRecord[[done]] */
{
/* 1. - 2. */
@@ -350,7 +352,7 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */
while (true)
{
/* a. */
ecma_value_t next = ecma_op_iterator_step (iterator);
ecma_value_t next = ecma_op_iterator_step (iterator, next_method);
/* b. - c. */
if (ECMA_IS_VALUE_ERROR (next))
{
@@ -527,9 +529,9 @@ ecma_builtin_promise_race_or_all (ecma_value_t this_arg, /**< 'this' argument */
return capability;
}
ecma_value_t iterator;
iterator = ecma_builtin_promise_reject_abrupt (ecma_op_get_iterator (iterable, ECMA_VALUE_SYNC_ITERATOR, NULL),
capability);
ecma_value_t next_method;
ecma_value_t iterator = ecma_op_get_iterator (iterable, ECMA_VALUE_SYNC_ITERATOR, &next_method);
iterator = ecma_builtin_promise_reject_abrupt (iterator, capability);
if (ECMA_IS_VALUE_ERROR (iterator))
{
@@ -543,11 +545,11 @@ ecma_builtin_promise_race_or_all (ecma_value_t this_arg, /**< 'this' argument */
if (is_race)
{
ret = ecma_builtin_promise_perform_race (iterator, capability, constructor_value, &is_done);
ret = ecma_builtin_promise_perform_race (iterator, next_method, capability, constructor_value, &is_done);
}
else
{
ret = ecma_builtin_promise_perform_all (iterator, constructor_value, capability, &is_done);
ret = ecma_builtin_promise_perform_all (iterator, next_method, capability, constructor_value, &is_done);
}
ecma_free_value (constructor_value);
@@ -563,6 +565,7 @@ ecma_builtin_promise_race_or_all (ecma_value_t this_arg, /**< 'this' argument */
}
ecma_free_value (iterator);
ecma_free_value (next_method);
ecma_free_value (capability);
return ret;
@@ -439,22 +439,23 @@ ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments l
ecma_object_t *adder_func_p = ecma_get_object_from_value (result);
result = ecma_op_get_iterator (iterable, ECMA_VALUE_SYNC_ITERATOR, NULL);
ecma_value_t next_method;
result = ecma_op_get_iterator (iterable, ECMA_VALUE_SYNC_ITERATOR, &next_method);
if (ECMA_IS_VALUE_ERROR (result))
{
goto cleanup_adder;
}
const ecma_value_t iter = result;
const ecma_value_t iterator = result;
while (true)
{
result = ecma_op_iterator_step (iter);
result = ecma_op_iterator_step (iterator, next_method);
if (ECMA_IS_VALUE_ERROR (result))
{
goto cleanup_iter;
goto cleanup_iterator;
}
if (ecma_is_value_false (result))
@@ -468,7 +469,7 @@ ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments l
if (ECMA_IS_VALUE_ERROR (result))
{
goto cleanup_iter;
goto cleanup_iterator;
}
if (lit_id == LIT_MAGIC_STRING_SET_UL || lit_id == LIT_MAGIC_STRING_WEAKSET_UL)
@@ -486,9 +487,9 @@ ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments l
{
ecma_free_value (result);
ecma_raise_type_error (ECMA_ERR_MSG ("Iterator value is not an object."));
result = ecma_op_iterator_close (iter);
result = ecma_op_iterator_close (iterator);
JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result));
goto cleanup_iter;
goto cleanup_iterator;
}
ecma_object_t *next_object_p = ecma_get_object_from_value (result);
@@ -498,8 +499,8 @@ ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments l
if (ECMA_IS_VALUE_ERROR (result))
{
ecma_deref_object (next_object_p);
ecma_op_iterator_close (iter);
goto cleanup_iter;
ecma_op_iterator_close (iterator);
goto cleanup_iterator;
}
const ecma_value_t key = result;
@@ -510,8 +511,8 @@ ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments l
{
ecma_deref_object (next_object_p);
ecma_free_value (key);
ecma_op_iterator_close (iter);
goto cleanup_iter;
ecma_op_iterator_close (iterator);
goto cleanup_iterator;
}
const ecma_value_t value = result;
@@ -525,19 +526,19 @@ ecma_op_container_create (const ecma_value_t *arguments_list_p, /**< arguments l
if (ECMA_IS_VALUE_ERROR (result))
{
ecma_op_iterator_close (iter);
goto cleanup_iter;
ecma_op_iterator_close (iterator);
goto cleanup_iterator;
}
ecma_free_value (result);
}
ecma_free_value (iter);
ecma_deref_object (adder_func_p);
return ecma_make_object_value (object_p);
ecma_ref_object (object_p);
result = ecma_make_object_value (object_p);
cleanup_iter:
ecma_free_value (iter);
cleanup_iterator:
ecma_free_value (iterator);
ecma_free_value (next_method);
cleanup_adder:
ecma_deref_object (adder_func_p);
cleanup_object:
@@ -579,10 +579,20 @@ ecma_op_iterator_close (ecma_value_t iterator) /**< iterator value */
* raised error - otherwise
*/
ecma_value_t
ecma_op_iterator_step (ecma_value_t iterator) /**< iterator value */
ecma_op_iterator_step (ecma_value_t iterator, /**< iterator value */
ecma_value_t next_method) /**< next method */
{
/* 1. */
ecma_value_t result = ecma_op_iterator_next_old (iterator, ECMA_VALUE_EMPTY);
ecma_value_t result;
if (next_method == ECMA_VALUE_EMPTY)
{
/* TODO: EMPTY support should be removed after all functions support next method caching. */
result = ecma_op_iterator_next_old (iterator, ECMA_VALUE_EMPTY);
}
else
{
result = ecma_op_iterator_next (iterator, next_method, ECMA_VALUE_EMPTY);
}
/* 2. */
if (ECMA_IS_VALUE_ERROR (result))
@@ -66,7 +66,7 @@ ecma_value_t
ecma_op_iterator_close (ecma_value_t iterator);
ecma_value_t
ecma_op_iterator_step (ecma_value_t iterator);
ecma_op_iterator_step (ecma_value_t iterator, ecma_value_t next_method);
ecma_value_t
ecma_op_iterator_do (ecma_iterator_command_type_t command, ecma_value_t iterator,
@@ -777,7 +777,8 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje
if (!ecma_is_value_undefined (using_iterator))
{
/* 8.a */
ecma_value_t iterator = ecma_op_get_iterator (items_val, using_iterator, NULL);
ecma_value_t next_method;
ecma_value_t iterator = ecma_op_get_iterator (items_val, using_iterator, &next_method);
ecma_free_value (using_iterator);
/* 8.b */
@@ -794,7 +795,7 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje
while (true)
{
/* 8.e.i */
ecma_value_t next = ecma_op_iterator_step (iterator);
ecma_value_t next = ecma_op_iterator_step (iterator, next_method);
/* 8.e.ii */
if (ECMA_IS_VALUE_ERROR (next))
@@ -822,6 +823,7 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje
}
ecma_free_value (iterator);
ecma_free_value (next_method);
if (ECMA_IS_VALUE_ERROR (ret_value))
{