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); ecma_object_t *array_obj_p = ecma_get_object_from_value (array);
/* 6.d */ /* 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); ecma_free_value (using_iterator);
/* 6.e */ /* 6.e */
@@ -170,7 +171,7 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */
while (true) while (true)
{ {
/* 6.g.ii */ /* 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 */ /* 6.g.iii */
if (ECMA_IS_VALUE_ERROR (next)) 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 (iterator);
ecma_free_value (next_method);
/* 6.g.iv.3 */ /* 6.g.iv.3 */
return array; return array;
} }
@@ -254,6 +256,7 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */
iterator_cleanup: iterator_cleanup:
ecma_free_value (iterator); ecma_free_value (iterator);
ecma_free_value (next_method);
ecma_free_value (array); ecma_free_value (array);
return ret_value; return ret_value;
@@ -126,6 +126,7 @@ ecma_builtin_promise_resolve (ecma_value_t this_arg, /**< 'this' argument */
*/ */
inline static ecma_value_t inline static ecma_value_t
ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for race */ 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 capability, /**< PromiseCapability record */
ecma_value_t ctor, /**< Constructor value */ ecma_value_t ctor, /**< Constructor value */
bool *done_p) /**< [out] iteratorRecord[[done]] */ bool *done_p) /**< [out] iteratorRecord[[done]] */
@@ -138,7 +139,7 @@ ecma_builtin_promise_perform_race (ecma_value_t iterator, /**< the iterator for
while (true) while (true)
{ {
/* a. */ /* a. */
ecma_value_t next = ecma_op_iterator_step (iterator); ecma_value_t next = ecma_op_iterator_step (iterator, next_method);
/* b, c. */ /* b, c. */
if (ECMA_IS_VALUE_ERROR (next)) 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 inline static ecma_value_t
ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */ 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 capability, /**< PromiseCapability record */
ecma_value_t ctor, /**< the caller of Promise.race */
bool *done_p) /**< [out] iteratorRecord[[done]] */ bool *done_p) /**< [out] iteratorRecord[[done]] */
{ {
/* 1. - 2. */ /* 1. - 2. */
@@ -350,7 +352,7 @@ ecma_builtin_promise_perform_all (ecma_value_t iterator, /**< iteratorRecord */
while (true) while (true)
{ {
/* a. */ /* a. */
ecma_value_t next = ecma_op_iterator_step (iterator); ecma_value_t next = ecma_op_iterator_step (iterator, next_method);
/* b. - c. */ /* b. - c. */
if (ECMA_IS_VALUE_ERROR (next)) 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; return capability;
} }
ecma_value_t iterator; ecma_value_t next_method;
iterator = ecma_builtin_promise_reject_abrupt (ecma_op_get_iterator (iterable, ECMA_VALUE_SYNC_ITERATOR, NULL), ecma_value_t iterator = ecma_op_get_iterator (iterable, ECMA_VALUE_SYNC_ITERATOR, &next_method);
capability); iterator = ecma_builtin_promise_reject_abrupt (iterator, capability);
if (ECMA_IS_VALUE_ERROR (iterator)) 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) 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 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); 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 (iterator);
ecma_free_value (next_method);
ecma_free_value (capability); ecma_free_value (capability);
return ret; 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); 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)) if (ECMA_IS_VALUE_ERROR (result))
{ {
goto cleanup_adder; goto cleanup_adder;
} }
const ecma_value_t iter = result; const ecma_value_t iterator = result;
while (true) while (true)
{ {
result = ecma_op_iterator_step (iter); result = ecma_op_iterator_step (iterator, next_method);
if (ECMA_IS_VALUE_ERROR (result)) if (ECMA_IS_VALUE_ERROR (result))
{ {
goto cleanup_iter; goto cleanup_iterator;
} }
if (ecma_is_value_false (result)) 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)) 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) 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_free_value (result);
ecma_raise_type_error (ECMA_ERR_MSG ("Iterator value is not an object.")); 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)); 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); 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)) if (ECMA_IS_VALUE_ERROR (result))
{ {
ecma_deref_object (next_object_p); ecma_deref_object (next_object_p);
ecma_op_iterator_close (iter); ecma_op_iterator_close (iterator);
goto cleanup_iter; goto cleanup_iterator;
} }
const ecma_value_t key = result; 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_deref_object (next_object_p);
ecma_free_value (key); ecma_free_value (key);
ecma_op_iterator_close (iter); ecma_op_iterator_close (iterator);
goto cleanup_iter; goto cleanup_iterator;
} }
const ecma_value_t value = result; 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)) if (ECMA_IS_VALUE_ERROR (result))
{ {
ecma_op_iterator_close (iter); ecma_op_iterator_close (iterator);
goto cleanup_iter; goto cleanup_iterator;
} }
ecma_free_value (result); ecma_free_value (result);
} }
ecma_free_value (iter); ecma_ref_object (object_p);
ecma_deref_object (adder_func_p); result = ecma_make_object_value (object_p);
return ecma_make_object_value (object_p);
cleanup_iter: cleanup_iterator:
ecma_free_value (iter); ecma_free_value (iterator);
ecma_free_value (next_method);
cleanup_adder: cleanup_adder:
ecma_deref_object (adder_func_p); ecma_deref_object (adder_func_p);
cleanup_object: cleanup_object:
@@ -579,10 +579,20 @@ ecma_op_iterator_close (ecma_value_t iterator) /**< iterator value */
* raised error - otherwise * raised error - otherwise
*/ */
ecma_value_t 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. */ /* 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. */ /* 2. */
if (ECMA_IS_VALUE_ERROR (result)) if (ECMA_IS_VALUE_ERROR (result))
@@ -66,7 +66,7 @@ ecma_value_t
ecma_op_iterator_close (ecma_value_t iterator); ecma_op_iterator_close (ecma_value_t iterator);
ecma_value_t 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_value_t
ecma_op_iterator_do (ecma_iterator_command_type_t command, ecma_value_t iterator, 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)) if (!ecma_is_value_undefined (using_iterator))
{ {
/* 8.a */ /* 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); ecma_free_value (using_iterator);
/* 8.b */ /* 8.b */
@@ -794,7 +795,7 @@ ecma_op_typedarray_from (ecma_value_t items_val, /**< the source array-like obje
while (true) while (true)
{ {
/* 8.e.i */ /* 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 */ /* 8.e.ii */
if (ECMA_IS_VALUE_ERROR (next)) 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 (iterator);
ecma_free_value (next_method);
if (ECMA_IS_VALUE_ERROR (ret_value)) if (ECMA_IS_VALUE_ERROR (ret_value))
{ {
+2 -2
View File
@@ -194,8 +194,8 @@
#define PARSER_FINALLY_CONTEXT_STACK_ALLOCATION 2 #define PARSER_FINALLY_CONTEXT_STACK_ALLOCATION 2
/* PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION must be <= 4 */ /* PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION must be <= 4 */
#define PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION 4 #define PARSER_FOR_IN_CONTEXT_STACK_ALLOCATION 4
/* PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION must be <= 3 */ /* PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION must be <= 4 */
#define PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION 3 #define PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION 4
/* PARSER_WITH_CONTEXT_STACK_ALLOCATION must be <= 4 */ /* PARSER_WITH_CONTEXT_STACK_ALLOCATION must be <= 4 */
#define PARSER_WITH_CONTEXT_STACK_ALLOCATION 1 #define PARSER_WITH_CONTEXT_STACK_ALLOCATION 1
/* PARSER_BLOCK_CONTEXT_STACK_ALLOCATION must be <= 3 */ /* PARSER_BLOCK_CONTEXT_STACK_ALLOCATION must be <= 3 */
+8 -4
View File
@@ -339,13 +339,14 @@ opfunc_append_to_spread_array (ecma_value_t *stack_top_p, /**< current stack top
ecma_value_t ret_value = ECMA_VALUE_ERROR; ecma_value_t ret_value = ECMA_VALUE_ERROR;
ecma_value_t spread_value = stack_top_p[i]; ecma_value_t spread_value = stack_top_p[i];
ecma_value_t iterator = ecma_op_get_iterator (spread_value, ECMA_VALUE_SYNC_ITERATOR, NULL); ecma_value_t next_method;
ecma_value_t iterator = ecma_op_get_iterator (spread_value, ECMA_VALUE_SYNC_ITERATOR, &next_method);
if (!ECMA_IS_VALUE_ERROR (iterator)) if (!ECMA_IS_VALUE_ERROR (iterator))
{ {
while (true) while (true)
{ {
ecma_value_t next_value = ecma_op_iterator_step (iterator); ecma_value_t next_value = ecma_op_iterator_step (iterator, next_method);
if (ECMA_IS_VALUE_ERROR (next_value)) if (ECMA_IS_VALUE_ERROR (next_value))
{ {
@@ -380,6 +381,7 @@ opfunc_append_to_spread_array (ecma_value_t *stack_top_p, /**< current stack top
} }
ecma_free_value (iterator); ecma_free_value (iterator);
ecma_free_value (next_method);
ecma_free_value (spread_value); ecma_free_value (spread_value);
if (ECMA_IS_VALUE_ERROR (ret_value)) if (ECMA_IS_VALUE_ERROR (ret_value))
@@ -432,13 +434,14 @@ opfunc_spread_arguments (ecma_value_t *stack_top_p, /**< pointer to the current
ecma_value_t spread_value = *stack_top_p++; ecma_value_t spread_value = *stack_top_p++;
i++; i++;
ecma_value_t iterator = ecma_op_get_iterator (spread_value, ECMA_VALUE_SYNC_ITERATOR, NULL); ecma_value_t next_method;
ecma_value_t iterator = ecma_op_get_iterator (spread_value, ECMA_VALUE_SYNC_ITERATOR, &next_method);
if (!ECMA_IS_VALUE_ERROR (iterator)) if (!ECMA_IS_VALUE_ERROR (iterator))
{ {
while (true) while (true)
{ {
ecma_value_t next_value = ecma_op_iterator_step (iterator); ecma_value_t next_value = ecma_op_iterator_step (iterator, next_method);
if (ECMA_IS_VALUE_ERROR (next_value)) if (ECMA_IS_VALUE_ERROR (next_value))
{ {
@@ -465,6 +468,7 @@ opfunc_spread_arguments (ecma_value_t *stack_top_p, /**< pointer to the current
} }
ecma_free_value (iterator); ecma_free_value (iterator);
ecma_free_value (next_method);
ecma_free_value (spread_value); ecma_free_value (spread_value);
if (ECMA_IS_VALUE_ERROR (ret_value)) if (ECMA_IS_VALUE_ERROR (ret_value))
+4 -2
View File
@@ -81,6 +81,8 @@ vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
case VM_CONTEXT_FOR_OF: case VM_CONTEXT_FOR_OF:
{ {
ecma_value_t iterator = vm_stack_top_p[-3]; ecma_value_t iterator = vm_stack_top_p[-3];
ecma_free_value (vm_stack_top_p[-2]);
ecma_free_value (vm_stack_top_p[-4]);
if (context_info & VM_CONTEXT_CLOSE_ITERATOR) if (context_info & VM_CONTEXT_CLOSE_ITERATOR)
{ {
@@ -88,7 +90,6 @@ vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
} }
ecma_free_value (iterator); ecma_free_value (iterator);
ecma_free_value (vm_stack_top_p[-2]);
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION); VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION);
vm_stack_top_p -= PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION; vm_stack_top_p -= PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION;
break; break;
@@ -339,7 +340,8 @@ vm_get_context_value_offsets (ecma_value_t *context_item_p) /**< any item of a c
} }
case VM_CONTEXT_FOR_OF: case VM_CONTEXT_FOR_OF:
{ {
return ((3 << (VM_CONTEXT_OFFSET_SHIFT * 2)) return ((4 << (VM_CONTEXT_OFFSET_SHIFT * 3))
| (3 << (VM_CONTEXT_OFFSET_SHIFT * 2))
| (2 << (VM_CONTEXT_OFFSET_SHIFT)) | (2 << (VM_CONTEXT_OFFSET_SHIFT))
| PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION); | PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION);
} }
+45 -29
View File
@@ -2055,7 +2055,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
{ {
JERRY_ASSERT (opcode >= CBC_EXT_ITERATOR_STEP && opcode <= CBC_EXT_ITERATOR_STEP_3); JERRY_ASSERT (opcode >= CBC_EXT_ITERATOR_STEP && opcode <= CBC_EXT_ITERATOR_STEP_3);
const uint8_t index = (uint8_t) (1 + (opcode - CBC_EXT_ITERATOR_STEP)); const uint8_t index = (uint8_t) (1 + (opcode - CBC_EXT_ITERATOR_STEP));
result = ecma_op_iterator_step (stack_top_p[-index]); result = ecma_op_iterator_step (stack_top_p[-index], ECMA_VALUE_EMPTY);
if (ECMA_IS_VALUE_ERROR (result)) if (ECMA_IS_VALUE_ERROR (result))
{ {
@@ -2113,7 +2113,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
while (true) while (true)
{ {
result = ecma_op_iterator_step (iterator); result = ecma_op_iterator_step (iterator, ECMA_VALUE_EMPTY);
if (ECMA_IS_VALUE_ERROR (result)) if (ECMA_IS_VALUE_ERROR (result))
{ {
@@ -3786,7 +3786,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
ecma_value_t iterator = ecma_op_get_iterator (value, ECMA_VALUE_SYNC_ITERATOR, NULL); ecma_value_t next_method;
ecma_value_t iterator = ecma_op_get_iterator (value, ECMA_VALUE_SYNC_ITERATOR, &next_method);
ecma_free_value (value); ecma_free_value (value);
@@ -3796,22 +3797,34 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
goto error; goto error;
} }
ecma_value_t next_value = ecma_op_iterator_step (iterator); result = ecma_op_iterator_step (iterator, next_method);
if (ECMA_IS_VALUE_ERROR (next_value)) if (ECMA_IS_VALUE_ERROR (result))
{ {
ecma_free_value (iterator); ecma_free_value (iterator);
result = next_value; ecma_free_value (next_method);
goto error; goto error;
} }
if (ecma_is_value_false (next_value)) if (ecma_is_value_false (result))
{ {
ecma_free_value (iterator); ecma_free_value (iterator);
ecma_free_value (next_method);
byte_code_p = byte_code_start_p + branch_offset; byte_code_p = byte_code_start_p + branch_offset;
continue; continue;
} }
ecma_value_t next_value = ecma_op_iterator_value (result);
ecma_free_value (result);
if (ECMA_IS_VALUE_ERROR (next_value))
{
result = next_value;
ecma_free_value (iterator);
ecma_free_value (next_method);
goto error;
}
branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p); branch_offset += (int32_t) (byte_code_start_p - frame_ctx_p->byte_code_start_p);
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION); VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION);
@@ -3819,6 +3832,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FOR_OF, branch_offset) | VM_CONTEXT_CLOSE_ITERATOR; stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_FOR_OF, branch_offset) | VM_CONTEXT_CLOSE_ITERATOR;
stack_top_p[-2] = next_value; stack_top_p[-2] = next_value;
stack_top_p[-3] = iterator; stack_top_p[-3] = iterator;
stack_top_p[-4] = next_method;
if (byte_code_p[0] == CBC_EXT_OPCODE && byte_code_p[1] == CBC_EXT_CLONE_CONTEXT) if (byte_code_p[0] == CBC_EXT_OPCODE && byte_code_p[1] == CBC_EXT_CLONE_CONTEXT)
{ {
@@ -3832,22 +3846,33 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
ecma_value_t *context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth; ecma_value_t *context_top_p = VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth;
JERRY_ASSERT (VM_GET_CONTEXT_TYPE (context_top_p[-1]) == VM_CONTEXT_FOR_OF); JERRY_ASSERT (VM_GET_CONTEXT_TYPE (context_top_p[-1]) == VM_CONTEXT_FOR_OF);
ecma_value_t next_value = ecma_op_iterator_value (context_top_p[-2]); *stack_top_p++ = context_top_p[-2];
context_top_p[-2] = ECMA_VALUE_UNDEFINED;
if (ECMA_IS_VALUE_ERROR (next_value))
{
result = next_value;
goto error;
}
*stack_top_p++ = next_value;
continue; continue;
} }
case VM_OC_FOR_OF_HAS_NEXT: case VM_OC_FOR_OF_HAS_NEXT:
{ {
JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p); JERRY_ASSERT (VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth == stack_top_p);
ecma_value_t next_value = ecma_op_iterator_step (stack_top_p[-3]); result = ecma_op_iterator_step (stack_top_p[-3], stack_top_p[-4]);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
if (ecma_is_value_false (result))
{
ecma_free_value (stack_top_p[-2]);
ecma_free_value (stack_top_p[-3]);
ecma_free_value (stack_top_p[-4]);
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION);
stack_top_p -= PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION;
continue;
}
ecma_value_t next_value = ecma_op_iterator_value (result);
ecma_free_value (result);
if (ECMA_IS_VALUE_ERROR (next_value)) if (ECMA_IS_VALUE_ERROR (next_value))
{ {
@@ -3855,18 +3880,9 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
goto error; goto error;
} }
if (!ecma_is_value_false (next_value)) JERRY_ASSERT (stack_top_p[-2] == ECMA_VALUE_UNDEFINED);
{ stack_top_p[-2] = next_value;
ecma_free_value (stack_top_p[-2]); byte_code_p = byte_code_start_p + branch_offset;
stack_top_p[-2] = next_value;
byte_code_p = byte_code_start_p + branch_offset;
continue;
}
ecma_free_value (stack_top_p[-2]);
ecma_free_value (stack_top_p[-3]);
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION);
stack_top_p -= PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION;
continue; continue;
} }
#endif /* ENABLED (JERRY_ESNEXT) */ #endif /* ENABLED (JERRY_ESNEXT) */
+38
View File
@@ -119,3 +119,41 @@ var i = 0;
for (var a of obj) { for (var a of obj) {
assert (a === i++); assert (a === i++);
} }
var status = 0;
i = 0;
function yieldNext() {
++status
assert(status === 3 || status === 6 || status === 9)
return {
get value() {
++status
assert(status === 4 || status === 7)
return "Res"
},
done: ++i >= 3
}
}
obj = {
[Symbol.iterator]() {
assert(++status === 1)
return {
get next() {
assert(++status === 2)
return yieldNext
}
}
}
}
function getX() {
++status
assert(status === 5 || status === 8)
return { x:0 }
}
for (getX().x of obj)
;
assert(status == 9)
+1
View File
@@ -360,6 +360,7 @@
<test id="language/statements/continue/simple-and-labeled.js"><reason></reason></test> <test id="language/statements/continue/simple-and-labeled.js"><reason></reason></test>
<test id="language/statements/for-of/body-dstr-assign-error.js"><reason></reason></test> <test id="language/statements/for-of/body-dstr-assign-error.js"><reason></reason></test>
<test id="language/statements/for-of/body-dstr-assign.js"><reason></reason></test> <test id="language/statements/for-of/body-dstr-assign.js"><reason></reason></test>
<test id="language/statements/for-of/iterator-next-reference.js"><reason>ES spec change: next method must be cached</reason></test>
<test id="language/statements/for/S12.6.3_A9.1.js"><reason></reason></test> <test id="language/statements/for/S12.6.3_A9.1.js"><reason></reason></test>
<test id="language/statements/for/S12.6.3_A9.js"><reason></reason></test> <test id="language/statements/for/S12.6.3_A9.js"><reason></reason></test>
<test id="language/statements/generators/has-instance.js"><reason></reason></test> <test id="language/statements/generators/has-instance.js"><reason></reason></test>