Improve destructuring patterns (#4527)
- Fix evaluation order of the operands - Implement proper iterator closing of array destructuring - Support next method caching JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
+123
-48
@@ -41,6 +41,41 @@ JERRY_STATIC_ASSERT (PARSER_WITH_CONTEXT_STACK_ALLOCATION == PARSER_TRY_CONTEXT_
|
||||
JERRY_STATIC_ASSERT (PARSER_FOR_OF_CONTEXT_STACK_ALLOCATION == PARSER_FOR_AWAIT_OF_CONTEXT_STACK_ALLOCATION,
|
||||
for_of_context_stack_allocation_must_be_equal_to_for_await_of_context_stack_allocation);
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
/**
|
||||
* Abort (finalize) the current variable length stack context, and remove it.
|
||||
*
|
||||
* @return new stack top
|
||||
*/
|
||||
ecma_value_t *
|
||||
vm_stack_context_abort_variable_length (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
ecma_value_t *vm_stack_top_p, /**< current stack top */
|
||||
uint32_t context_stack_allocation) /**< 0 - if all context element
|
||||
* should be released
|
||||
* context stack allocation - otherwise */
|
||||
{
|
||||
JERRY_ASSERT (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (vm_stack_top_p[-1])));
|
||||
|
||||
uint32_t context_size = VM_GET_CONTEXT_END (vm_stack_top_p[-1]);
|
||||
VM_MINUS_EQUAL_U16 (frame_ctx_p->context_depth, context_size);
|
||||
|
||||
JERRY_ASSERT (context_size > 0);
|
||||
--vm_stack_top_p;
|
||||
|
||||
if (context_stack_allocation == 0)
|
||||
{
|
||||
context_stack_allocation = context_size;
|
||||
}
|
||||
|
||||
for (uint32_t i = 1; i < context_stack_allocation; i++)
|
||||
{
|
||||
ecma_free_value (*(--vm_stack_top_p));
|
||||
}
|
||||
|
||||
return vm_stack_top_p;
|
||||
} /* vm_stack_context_abort_variable_length */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
* Abort (finalize) the current stack context, and remove it.
|
||||
*
|
||||
@@ -86,6 +121,13 @@ vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
break;
|
||||
}
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
case VM_CONTEXT_ITERATOR:
|
||||
case VM_CONTEXT_OBJ_INIT:
|
||||
case VM_CONTEXT_OBJ_INIT_REST:
|
||||
{
|
||||
vm_stack_top_p = vm_stack_context_abort_variable_length (frame_ctx_p, vm_stack_top_p, 0);
|
||||
break;
|
||||
}
|
||||
case VM_CONTEXT_FOR_OF:
|
||||
case VM_CONTEXT_FOR_AWAIT_OF:
|
||||
{
|
||||
@@ -189,16 +231,16 @@ vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
|
||||
while (frame_ctx_p->context_depth > 0)
|
||||
{
|
||||
vm_stack_context_type_t context_type;
|
||||
vm_stack_context_type_t context_type = VM_GET_CONTEXT_TYPE (stack_top_p[-1]);
|
||||
uint32_t context_end = VM_GET_CONTEXT_END (stack_top_p[-1]);
|
||||
JERRY_ASSERT (!VM_CONTEXT_IS_VARIABLE_LENGTH (context_type) || finally_type != VM_CONTEXT_FINALLY_JUMP);
|
||||
|
||||
if (search_limit < context_end)
|
||||
if (!VM_CONTEXT_IS_VARIABLE_LENGTH (context_type) && search_limit < context_end)
|
||||
{
|
||||
frame_ctx_p->stack_top_p = stack_top_p;
|
||||
return VM_CONTEXT_FOUND_EXPECTED;
|
||||
}
|
||||
|
||||
context_type = VM_GET_CONTEXT_TYPE (stack_top_p[-1]);
|
||||
if (context_type == VM_CONTEXT_TRY || context_type == VM_CONTEXT_CATCH)
|
||||
{
|
||||
const uint8_t *byte_code_p;
|
||||
@@ -314,7 +356,9 @@ vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
else if (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR)
|
||||
{
|
||||
JERRY_ASSERT (context_type == VM_CONTEXT_FOR_OF || context_type == VM_CONTEXT_FOR_AWAIT_OF);
|
||||
JERRY_ASSERT (context_type == VM_CONTEXT_FOR_OF
|
||||
|| context_type == VM_CONTEXT_FOR_AWAIT_OF
|
||||
|| context_type == VM_CONTEXT_ITERATOR);
|
||||
JERRY_ASSERT (finally_type == VM_CONTEXT_FINALLY_THROW || !jcontext_has_pending_exception ());
|
||||
|
||||
ecma_value_t exception = ECMA_VALUE_UNDEFINED;
|
||||
@@ -323,62 +367,71 @@ vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, /**< frame context */
|
||||
exception = jcontext_take_exception ();
|
||||
}
|
||||
|
||||
ecma_value_t iterator = stack_top_p[-3];
|
||||
ecma_value_t result = ecma_op_get_method_by_magic_id (iterator, LIT_MAGIC_STRING_RETURN);
|
||||
ecma_value_t result;
|
||||
|
||||
if (!ECMA_IS_VALUE_ERROR (result) && !ecma_is_value_undefined (result))
|
||||
if (context_type == VM_CONTEXT_ITERATOR)
|
||||
{
|
||||
if (!ecma_is_value_object (result) || !ecma_op_is_callable (result))
|
||||
{
|
||||
ecma_free_value (result);
|
||||
result = ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'return' is not callable"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *return_obj_p = ecma_get_object_from_value (result);
|
||||
result = ecma_op_function_call (return_obj_p, iterator, NULL, 0);
|
||||
ecma_deref_object (return_obj_p);
|
||||
result = ecma_op_iterator_close (stack_top_p[-2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_value_t iterator = stack_top_p[-3];
|
||||
result = ecma_op_get_method_by_magic_id (iterator, LIT_MAGIC_STRING_RETURN);
|
||||
|
||||
if (context_type == VM_CONTEXT_FOR_AWAIT_OF && !ECMA_IS_VALUE_ERROR (result))
|
||||
if (!ECMA_IS_VALUE_ERROR (result) && !ecma_is_value_undefined (result))
|
||||
{
|
||||
if (!ecma_op_is_callable (result))
|
||||
{
|
||||
ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p);
|
||||
ecma_free_value (result);
|
||||
result = ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'return' is not callable"));
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_object_t *return_obj_p = ecma_get_object_from_value (result);
|
||||
result = ecma_op_function_call (return_obj_p, iterator, NULL, 0);
|
||||
ecma_deref_object (return_obj_p);
|
||||
|
||||
result = ecma_promise_async_await (async_generator_object_p, result);
|
||||
if (context_type == VM_CONTEXT_FOR_AWAIT_OF && !ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
ecma_extended_object_t *async_generator_object_p = VM_GET_EXECUTABLE_OBJECT (frame_ctx_p);
|
||||
|
||||
result = ecma_promise_async_await (async_generator_object_p, result);
|
||||
|
||||
if (!ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
uint16_t extra_flags = (ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD
|
||||
| (ECMA_AWAIT_FOR_CLOSE << ECMA_AWAIT_STATE_SHIFT));
|
||||
async_generator_object_p->u.class_prop.extra_info |= extra_flags;
|
||||
|
||||
stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p);
|
||||
|
||||
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION);
|
||||
stack_top_p += PARSER_FINALLY_CONTEXT_STACK_ALLOCATION;
|
||||
|
||||
stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, context_end);
|
||||
if (finally_type == VM_CONTEXT_FINALLY_THROW)
|
||||
{
|
||||
stack_top_p[-2] = exception;
|
||||
}
|
||||
|
||||
frame_ctx_p->call_operation = VM_EXEC_RETURN;
|
||||
frame_ctx_p->byte_code_p = vm_stack_resume_executable_object_with_context_end;
|
||||
frame_ctx_p->stack_top_p = stack_top_p;
|
||||
return VM_CONTEXT_FOUND_AWAIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
uint16_t extra_flags = (ECMA_EXECUTABLE_OBJECT_DO_AWAIT_OR_YIELD
|
||||
| (ECMA_AWAIT_FOR_CLOSE << ECMA_AWAIT_STATE_SHIFT));
|
||||
async_generator_object_p->u.class_prop.extra_info |= extra_flags;
|
||||
bool is_object = ecma_is_value_object (result);
|
||||
|
||||
stack_top_p = vm_stack_context_abort (frame_ctx_p, stack_top_p);
|
||||
ecma_free_value (result);
|
||||
result = ECMA_VALUE_UNDEFINED;
|
||||
|
||||
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, PARSER_FINALLY_CONTEXT_STACK_ALLOCATION);
|
||||
stack_top_p += PARSER_FINALLY_CONTEXT_STACK_ALLOCATION;
|
||||
|
||||
stack_top_p[-1] = VM_CREATE_CONTEXT ((uint32_t) finally_type, context_end);
|
||||
if (finally_type == VM_CONTEXT_FINALLY_THROW)
|
||||
if (!is_object)
|
||||
{
|
||||
stack_top_p[-2] = exception;
|
||||
result = ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'return' result is not object"));
|
||||
}
|
||||
|
||||
frame_ctx_p->call_operation = VM_EXEC_RETURN;
|
||||
frame_ctx_p->byte_code_p = vm_stack_resume_executable_object_with_context_end;
|
||||
frame_ctx_p->stack_top_p = stack_top_p;
|
||||
return VM_CONTEXT_FOUND_AWAIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
bool is_object = ecma_is_value_object (result);
|
||||
|
||||
ecma_free_value (result);
|
||||
result = ECMA_VALUE_UNDEFINED;
|
||||
|
||||
if (!is_object)
|
||||
{
|
||||
result = ecma_raise_type_error (ECMA_ERR_MSG ("Iterator 'return' result is not object"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -487,6 +540,28 @@ vm_ref_lex_env_chain (ecma_object_t *lex_env_p, /**< top of lexical environment
|
||||
lex_env_p = next_lex_env_p;
|
||||
}
|
||||
|
||||
if (VM_CONTEXT_IS_VARIABLE_LENGTH (VM_GET_CONTEXT_TYPE (context_top_p[-1])))
|
||||
{
|
||||
ecma_value_t *last_item_p = context_top_p - VM_GET_CONTEXT_END (context_top_p[-1]);
|
||||
JERRY_ASSERT (last_item_p >= context_end_p);
|
||||
context_top_p--;
|
||||
|
||||
do
|
||||
{
|
||||
if (do_ref)
|
||||
{
|
||||
ecma_ref_if_object (*(--context_top_p));
|
||||
}
|
||||
else
|
||||
{
|
||||
ecma_deref_if_object (*(--context_top_p));
|
||||
}
|
||||
}
|
||||
while (context_top_p > last_item_p);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t offsets = vm_get_context_value_offsets (context_top_p);
|
||||
|
||||
while (VM_CONTEXT_HAS_NEXT_OFFSET (offsets))
|
||||
|
||||
@@ -75,6 +75,11 @@ typedef enum
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
VM_CONTEXT_FOR_OF, /**< for-of context */
|
||||
VM_CONTEXT_FOR_AWAIT_OF, /**< for-await-of context */
|
||||
|
||||
/* contexts with variable length */
|
||||
VM_CONTEXT_ITERATOR, /**< iterator context */
|
||||
VM_CONTEXT_OBJ_INIT, /**< object-initializer context */
|
||||
VM_CONTEXT_OBJ_INIT_REST, /**< object-initializer-rest context */
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
} vm_stack_context_type_t;
|
||||
|
||||
@@ -91,6 +96,21 @@ typedef enum
|
||||
VM_CONTEXT_FOUND_EXPECTED, /**< found the type specified in finally_type */
|
||||
} vm_stack_found_type;
|
||||
|
||||
/**
|
||||
* Checks whether the context has variable context size
|
||||
*
|
||||
* Layout:
|
||||
* - [context descriptor]
|
||||
* - [JS values belong to the context]
|
||||
* - [previous JS values stored by the VM stack]
|
||||
*/
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
#define VM_CONTEXT_IS_VARIABLE_LENGTH(context_type) \
|
||||
((context_type) >= VM_CONTEXT_ITERATOR)
|
||||
#else /* !ENABLED (JERRY_ESNEXT) */
|
||||
#define VM_CONTEXT_IS_VARIABLE_LENGTH(context_type) false
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
|
||||
/**
|
||||
* Checks whether the context type is a finally type.
|
||||
*/
|
||||
@@ -112,6 +132,10 @@ typedef enum
|
||||
*/
|
||||
#define VM_CONTEXT_GET_NEXT_OFFSET(offsets) (-((int32_t) ((offsets) & ((1 << VM_CONTEXT_OFFSET_SHIFT) - 1))))
|
||||
|
||||
#if ENABLED (JERRY_ESNEXT)
|
||||
ecma_value_t *vm_stack_context_abort_variable_length (vm_frame_ctx_t *frame_ctx_p, ecma_value_t *vm_stack_top_p,
|
||||
uint32_t context_stack_allocation);
|
||||
#endif /* ENABLED (JERRY_ESNEXT) */
|
||||
ecma_value_t *vm_stack_context_abort (vm_frame_ctx_t *frame_ctx_p, ecma_value_t *vm_stack_top_p);
|
||||
vm_stack_found_type vm_stack_find_finally (vm_frame_ctx_t *frame_ctx_p, ecma_value_t *stack_top_p,
|
||||
vm_stack_context_type_t finally_type, uint32_t search_limit);
|
||||
|
||||
+115
-38
@@ -1001,6 +1001,12 @@ opfunc_construct (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
opcode_data &= (uint32_t) ~VM_OC_PUT_BLOCK; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the end of the existing topmost context
|
||||
*/
|
||||
#define VM_LAST_CONTEXT_END() \
|
||||
(VM_GET_REGISTERS (frame_ctx_p) + register_end + frame_ctx_p->context_depth)
|
||||
|
||||
/**
|
||||
* Run generic byte code.
|
||||
*
|
||||
@@ -2307,24 +2313,39 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
*stack_top_p++ = result;
|
||||
continue;
|
||||
}
|
||||
case VM_OC_GET_ITERATOR:
|
||||
case VM_OC_ITERATOR_CONTEXT_CREATE:
|
||||
{
|
||||
result = ecma_op_get_iterator (stack_top_p[-1], ECMA_VALUE_SYNC_ITERATOR, NULL);
|
||||
result = ecma_op_get_iterator (stack_top_p[-1], ECMA_VALUE_SYNC_ITERATOR, &left_value);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
*stack_top_p++ = result;
|
||||
uint32_t context_size = (uint32_t) (stack_top_p
|
||||
+ PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION
|
||||
- VM_LAST_CONTEXT_END ());
|
||||
stack_top_p += PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION;
|
||||
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, context_size);
|
||||
|
||||
stack_top_p[-1] = VM_CREATE_CONTEXT (VM_CONTEXT_ITERATOR, context_size) | VM_CONTEXT_CLOSE_ITERATOR;
|
||||
stack_top_p[-2] = result;
|
||||
stack_top_p[-3] = left_value;
|
||||
|
||||
continue;
|
||||
}
|
||||
case VM_OC_ITERATOR_STEP:
|
||||
{
|
||||
result = ecma_op_iterator_step (stack_top_p[-1], ECMA_VALUE_EMPTY);
|
||||
ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
|
||||
|
||||
ecma_value_t iterator = last_context_end_p[-2];
|
||||
ecma_value_t next_method = last_context_end_p[-3];
|
||||
|
||||
result = ecma_op_iterator_step (iterator, next_method);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR;
|
||||
goto error;
|
||||
}
|
||||
|
||||
@@ -2337,24 +2358,38 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (value))
|
||||
{
|
||||
last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR;
|
||||
result = value;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR;
|
||||
}
|
||||
|
||||
*stack_top_p++ = value;
|
||||
continue;
|
||||
}
|
||||
case VM_OC_ITERATOR_CLOSE:
|
||||
case VM_OC_ITERATOR_CONTEXT_END:
|
||||
{
|
||||
result = ecma_op_iterator_close (left_value);
|
||||
JERRY_ASSERT (VM_LAST_CONTEXT_END () == stack_top_p);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
if (stack_top_p[-1] & VM_CONTEXT_CLOSE_ITERATOR)
|
||||
{
|
||||
goto error;
|
||||
stack_top_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR;
|
||||
result = ecma_op_iterator_close (stack_top_p[-2]);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
goto free_left_value;
|
||||
stack_top_p = vm_stack_context_abort_variable_length (frame_ctx_p,
|
||||
stack_top_p,
|
||||
PARSER_ITERATOR_CONTEXT_STACK_ALLOCATION);
|
||||
continue;
|
||||
}
|
||||
case VM_OC_DEFAULT_INITIALIZER:
|
||||
{
|
||||
@@ -2373,21 +2408,26 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
{
|
||||
ecma_object_t *array_p = ecma_op_new_array_object (0);
|
||||
JERRY_ASSERT (ecma_op_object_is_fast_array (array_p));
|
||||
ecma_value_t iterator = stack_top_p[-1];
|
||||
|
||||
ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
|
||||
ecma_value_t iterator = last_context_end_p[-2];
|
||||
ecma_value_t next_method = last_context_end_p[-3];
|
||||
uint32_t index = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
result = ecma_op_iterator_step (iterator, ECMA_VALUE_EMPTY);
|
||||
result = ecma_op_iterator_step (iterator, next_method);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR;
|
||||
ecma_deref_object (array_p);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ecma_is_value_false (result))
|
||||
{
|
||||
last_context_end_p[-1] &= (uint32_t) ~VM_CONTEXT_CLOSE_ITERATOR;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2409,16 +2449,51 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
*stack_top_p++ = ecma_make_object_value (array_p);
|
||||
continue;
|
||||
}
|
||||
case VM_OC_INITIALIZER_PUSH_LIST:
|
||||
case VM_OC_OBJ_INIT_CONTEXT_CREATE:
|
||||
{
|
||||
stack_top_p++;
|
||||
stack_top_p[-1] = stack_top_p[-2];
|
||||
stack_top_p[-2] = ecma_make_object_value (ecma_op_new_array_object (0));
|
||||
left_value = stack_top_p[-1];
|
||||
vm_stack_context_type_t context_type = VM_CONTEXT_OBJ_INIT;
|
||||
uint32_t context_stack_allocation = PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION;
|
||||
|
||||
if (opcode == CBC_EXT_OBJ_INIT_REST_CONTEXT_CREATE)
|
||||
{
|
||||
context_type = VM_CONTEXT_OBJ_INIT_REST;
|
||||
context_stack_allocation = PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION;
|
||||
}
|
||||
|
||||
uint32_t context_size = (uint32_t) (stack_top_p + context_stack_allocation - VM_LAST_CONTEXT_END ());
|
||||
stack_top_p += context_stack_allocation;
|
||||
VM_PLUS_EQUAL_U16 (frame_ctx_p->context_depth, context_size);
|
||||
|
||||
stack_top_p[-1] = VM_CREATE_CONTEXT (context_type, context_size);
|
||||
stack_top_p[-2] = left_value;
|
||||
|
||||
if (context_type == VM_CONTEXT_OBJ_INIT_REST)
|
||||
{
|
||||
stack_top_p[-3] = ecma_make_object_value (ecma_op_new_array_object (0));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case VM_OC_INITIALIZER_PUSH_REST:
|
||||
case VM_OC_OBJ_INIT_CONTEXT_END:
|
||||
{
|
||||
if (!ecma_op_require_object_coercible (stack_top_p[-1]))
|
||||
JERRY_ASSERT (stack_top_p == VM_LAST_CONTEXT_END ());
|
||||
|
||||
uint32_t context_stack_allocation = PARSER_OBJ_INIT_CONTEXT_STACK_ALLOCATION;
|
||||
|
||||
if (VM_GET_CONTEXT_TYPE (stack_top_p[-1]) == VM_CONTEXT_OBJ_INIT_REST)
|
||||
{
|
||||
context_stack_allocation = PARSER_OBJ_INIT_REST_CONTEXT_STACK_ALLOCATION;
|
||||
}
|
||||
|
||||
stack_top_p = vm_stack_context_abort_variable_length (frame_ctx_p,
|
||||
stack_top_p,
|
||||
context_stack_allocation);
|
||||
continue;
|
||||
}
|
||||
case VM_OC_OBJ_INIT_PUSH_REST:
|
||||
{
|
||||
ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
|
||||
if (!ecma_op_require_object_coercible (last_context_end_p[-2]))
|
||||
{
|
||||
result = ECMA_VALUE_ERROR;
|
||||
goto error;
|
||||
@@ -2428,16 +2503,18 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
ecma_object_t *result_object_p = ecma_create_object (prototype_p, 0, ECMA_OBJECT_TYPE_GENERAL);
|
||||
|
||||
left_value = ecma_make_object_value (result_object_p);
|
||||
result = opfunc_copy_data_properties (left_value, stack_top_p[-1], stack_top_p[-2]);
|
||||
result = opfunc_copy_data_properties (left_value, last_context_end_p[-2], last_context_end_p[-3]);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
goto error;
|
||||
}
|
||||
|
||||
ecma_free_value (stack_top_p[-2]);
|
||||
stack_top_p[-2] = stack_top_p[-1];
|
||||
stack_top_p[-1] = left_value;
|
||||
ecma_free_value (last_context_end_p[-3]);
|
||||
last_context_end_p[-3] = last_context_end_p[-2];
|
||||
last_context_end_p[-2] = ECMA_VALUE_UNDEFINED;
|
||||
|
||||
*stack_top_p++ = left_value;
|
||||
continue;
|
||||
}
|
||||
case VM_OC_INITIALIZER_PUSH_NAME:
|
||||
@@ -2456,7 +2533,8 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
left_value = ecma_make_string_value (property_key);
|
||||
}
|
||||
|
||||
ecma_object_t *array_obj_p = ecma_get_object_from_value (stack_top_p[-2]);
|
||||
ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
|
||||
ecma_object_t *array_obj_p = ecma_get_object_from_value (last_context_end_p[-3]);
|
||||
JERRY_ASSERT (ecma_get_object_type (array_obj_p) == ECMA_OBJECT_TYPE_ARRAY);
|
||||
|
||||
ecma_extended_object_t *ext_array_obj_p = (ecma_extended_object_t *) array_obj_p;
|
||||
@@ -2465,7 +2543,21 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
}
|
||||
case VM_OC_INITIALIZER_PUSH_PROP:
|
||||
{
|
||||
result = vm_op_get_value (stack_top_p[-1], left_value);
|
||||
ecma_value_t *last_context_end_p = VM_LAST_CONTEXT_END ();
|
||||
right_value = last_context_end_p[-2];
|
||||
|
||||
if (opcode == CBC_EXT_INITIALIZER_PUSH_PROP)
|
||||
{
|
||||
left_value = *last_context_end_p++;
|
||||
while (last_context_end_p < stack_top_p)
|
||||
{
|
||||
last_context_end_p[-1] = *last_context_end_p;
|
||||
last_context_end_p++;
|
||||
}
|
||||
stack_top_p--;
|
||||
}
|
||||
|
||||
result = vm_op_get_value (right_value, left_value);
|
||||
|
||||
if (ECMA_IS_VALUE_ERROR (result))
|
||||
{
|
||||
@@ -2475,21 +2567,6 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
|
||||
*stack_top_p++ = result;
|
||||
goto free_left_value;
|
||||
}
|
||||
case VM_OC_MOVE:
|
||||
{
|
||||
JERRY_ASSERT (opcode >= CBC_EXT_MOVE && opcode <= CBC_EXT_MOVE_3);
|
||||
const uint8_t index = (uint8_t) (1 + (opcode - CBC_EXT_MOVE));
|
||||
|
||||
ecma_value_t element = stack_top_p[-index];
|
||||
|
||||
for (int32_t i = -index; i < -1; i++)
|
||||
{
|
||||
stack_top_p[i] = stack_top_p[i + 1];
|
||||
}
|
||||
|
||||
stack_top_p[-1] = element;
|
||||
continue;
|
||||
}
|
||||
case VM_OC_SPREAD_ARGUMENTS:
|
||||
{
|
||||
uint8_t arguments_list_len = *byte_code_p++;
|
||||
|
||||
+10
-10
@@ -275,16 +275,16 @@ typedef enum
|
||||
|
||||
VM_OC_PUSH_SPREAD_ELEMENT, /**< push spread element */
|
||||
VM_OC_PUSH_REST_OBJECT, /**< push rest object */
|
||||
VM_OC_GET_ITERATOR, /**< GetIterator abstract operation */
|
||||
VM_OC_ITERATOR_CONTEXT_CREATE, /**< create iterator conext */
|
||||
VM_OC_ITERATOR_CONTEXT_END, /**< finalize iterator cotnext */
|
||||
VM_OC_ITERATOR_STEP, /**< IteratorStep abstract operation */
|
||||
VM_OC_ITERATOR_CLOSE, /**< IteratorClose abstract operation */
|
||||
VM_OC_INITIALIZER_PUSH_LIST, /**< push name list array */
|
||||
VM_OC_INITIALIZER_PUSH_REST, /**< push the object with the rest properties */
|
||||
VM_OC_OBJ_INIT_CONTEXT_CREATE, /**< create object initializer context */
|
||||
VM_OC_OBJ_INIT_CONTEXT_END, /**< finalize object initializer context */
|
||||
VM_OC_OBJ_INIT_PUSH_REST, /**< push the object with the rest properties */
|
||||
VM_OC_INITIALIZER_PUSH_NAME, /**< append string to name list array and push the string */
|
||||
VM_OC_DEFAULT_INITIALIZER, /**< default initializer inside a pattern */
|
||||
VM_OC_REST_INITIALIZER, /**< create rest object inside an array pattern */
|
||||
VM_OC_INITIALIZER_PUSH_PROP, /**< push property for object initializer */
|
||||
VM_OC_MOVE, /**< move element to the stack-top */
|
||||
VM_OC_SPREAD_ARGUMENTS, /**< perform function call/construct with spreaded arguments */
|
||||
VM_OC_CREATE_GENERATOR, /**< create a generator object */
|
||||
VM_OC_YIELD, /**< yield operation */
|
||||
@@ -362,16 +362,16 @@ typedef enum
|
||||
|
||||
VM_OC_PUSH_SPREAD_ELEMENT = VM_OC_NONE, /**< push spread element */
|
||||
VM_OC_PUSH_REST_OBJECT = VM_OC_NONE, /**< push rest object */
|
||||
VM_OC_GET_ITERATOR = VM_OC_NONE, /**< GetIterator abstract operation */
|
||||
VM_OC_ITERATOR_CONTEXT_CREATE = VM_OC_NONE, /**< create iterator context */
|
||||
VM_OC_ITERATOR_STEP = VM_OC_NONE, /**< IteratorStep abstract operation */
|
||||
VM_OC_ITERATOR_CLOSE = VM_OC_NONE, /**< IteratorClose abstract operation */
|
||||
VM_OC_INITIALIZER_PUSH_LIST = VM_OC_NONE, /**< push name list array */
|
||||
VM_OC_INITIALIZER_PUSH_REST = VM_OC_NONE, /**< push the object with the rest properties */
|
||||
VM_OC_ITERATOR_CONTEXT_END = VM_OC_NONE, /**< finalize iterator cotnext */
|
||||
VM_OC_OBJ_INIT_CONTEXT_CREATE = VM_OC_NONE, /**< create object initializer context */
|
||||
VM_OC_OBJ_INIT_CONTEXT_END = VM_OC_NONE, /**< finalize object initializer context */
|
||||
VM_OC_OBJ_INIT_PUSH_REST = VM_OC_NONE, /**< push the object with the rest properties */
|
||||
VM_OC_INITIALIZER_PUSH_NAME = VM_OC_NONE, /**< append string to name list array and push the string */
|
||||
VM_OC_DEFAULT_INITIALIZER = VM_OC_NONE, /**< default initializer inside a pattern */
|
||||
VM_OC_REST_INITIALIZER = VM_OC_NONE, /**< create rest object inside an array pattern */
|
||||
VM_OC_INITIALIZER_PUSH_PROP = VM_OC_NONE, /**< push property for object initializer */
|
||||
VM_OC_MOVE = VM_OC_NONE, /**< move element to the stack-top */
|
||||
VM_OC_SPREAD_ARGUMENTS = VM_OC_NONE, /**< perform function call/construct with spreaded arguments */
|
||||
VM_OC_CREATE_GENERATOR = VM_OC_NONE, /**< create a generator object */
|
||||
VM_OC_YIELD = VM_OC_NONE, /**< yield operation */
|
||||
|
||||
Reference in New Issue
Block a user