Rework the core of class parsing/runtime semantic (#3598)

Changes:
 - Use the pre-scanner to provide information for the parser about the existence of the class constructor
 - The allocation of the super declarative environment is no longer needed
 - The VM frame context holds the information about the this binding status
 - Reduce the number of class related VM/CBC instructions
 - Improve ecma_op_function_{construct, call} to properly set new.target

JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik frobert@inf.u-szeged.hu
This commit is contained in:
Robert Fancsik
2020-03-16 14:37:47 +01:00
committed by GitHub
parent 56b9f098ab
commit bfd2639634
49 changed files with 1671 additions and 1490 deletions
@@ -128,7 +128,7 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */
{
ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor);
array = ecma_op_function_construct (constructor_obj_p, ECMA_VALUE_UNDEFINED, NULL, 0);
array = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, NULL, 0);
if (ecma_is_value_undefined (array) || ecma_is_value_null (array))
{
@@ -289,7 +289,7 @@ iterator_cleanup:
{
ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor);
array = ecma_op_function_construct (constructor_obj_p, ECMA_VALUE_UNDEFINED, &len_value, 1);
array = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, &len_value, 1);
if (ecma_is_value_undefined (array) || ecma_is_value_null (array))
{
@@ -414,7 +414,7 @@ ecma_builtin_array_object_of (ecma_value_t this_arg, /**< 'this' argument */
ecma_value_t len = ecma_make_uint32_value (arguments_list_len);
ecma_value_t ret_val = ecma_op_function_construct (ecma_get_object_from_value (this_arg),
ECMA_VALUE_UNDEFINED,
ecma_get_object_from_value (this_arg),
&len,
1);
@@ -103,7 +103,7 @@ ecma_builtin_global_object_eval (ecma_value_t x) /**< routine's first argument *
#if ENABLED (JERRY_ES2015)
if (vm_is_direct_eval_form_call ())
{
parse_opts |= ECMA_GET_SUPER_EVAL_PARSER_OPTS ();
parse_opts |= ECMA_GET_LOCAL_PARSE_OPTS ();
}
#endif /* ENABLED (JERRY_ES2015) */
@@ -60,12 +60,10 @@ ecma_builtin_helper_error_dispatch_call (ecma_standard_error_t error_type, /**<
ecma_deref_ecma_string (message_string_p);
return ecma_make_object_value (new_error_object_p);
}
else
{
ecma_object_t *new_error_object_p = ecma_new_standard_error (error_type);
return ecma_make_object_value (new_error_object_p);
}
ecma_object_t *new_error_object_p = ecma_new_standard_error (error_type);
return ecma_make_object_value (new_error_object_p);
} /* ecma_builtin_helper_error_dispatch_call */
/**
@@ -205,10 +205,8 @@ ecma_builtin_reflect_dispatch_routine (uint16_t builtin_routine_id, /**< built-i
return ECMA_VALUE_ERROR;
}
// TODO: add new_target_p to construct when it'll be supported
JERRY_UNUSED (new_target_p);
ecma_value_t ret_value = ecma_op_function_construct (target_p,
ECMA_VALUE_UNDEFINED,
new_target_p,
coll_p->buffer_p,
coll_p->item_count);
+35 -25
View File
@@ -15,6 +15,7 @@
#include "ecma-alloc.h"
#include "ecma-builtins.h"
#include "ecma-exceptions.h"
#include "ecma-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
@@ -1020,15 +1021,12 @@ ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in
* Returned value must be freed with ecma_free_value.
*/
static ecma_value_t
ecma_builtin_dispatch_routine (ecma_builtin_id_t builtin_object_id, /**< built-in object' identifier */
uint16_t builtin_routine_id, /**< builtin-wide identifier
* of the built-in object's
* routine property */
ecma_builtin_dispatch_routine (ecma_extended_object_t *func_obj_p, /**< builtin object */
ecma_value_t this_arg_value, /**< 'this' argument value */
const ecma_value_t *arguments_list_p, /**< list of arguments passed to routine */
ecma_length_t arguments_list_len) /**< length of arguments' list */
{
JERRY_ASSERT (builtin_object_id < ECMA_BUILTIN_ID__COUNT);
JERRY_ASSERT (ecma_builtin_function_is_routine ((ecma_object_t *) func_obj_p));
ecma_value_t padded_arguments_list_p[3] = { ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED };
@@ -1055,10 +1053,10 @@ ecma_builtin_dispatch_routine (ecma_builtin_id_t builtin_object_id, /**< built-i
arguments_list_p = padded_arguments_list_p;
}
return ecma_builtin_routines[builtin_object_id] (builtin_routine_id,
this_arg_value,
arguments_list_p,
arguments_list_len);
return ecma_builtin_routines[func_obj_p->u.built_in.id] (func_obj_p->u.built_in.routine_id,
this_arg_value,
arguments_list_p,
arguments_list_len);
} /* ecma_builtin_dispatch_routine */
/**
@@ -1075,27 +1073,19 @@ ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */
JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION);
JERRY_ASSERT (ecma_get_object_is_builtin (obj_p));
ecma_value_t ret_value = ECMA_VALUE_EMPTY;
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
if (ecma_builtin_function_is_routine (obj_p))
{
ret_value = ecma_builtin_dispatch_routine (ext_obj_p->u.built_in.id,
ext_obj_p->u.built_in.routine_id,
this_arg_value,
arguments_list_p,
arguments_list_len);
}
else
{
ecma_builtin_id_t builtin_object_id = ext_obj_p->u.built_in.id;
JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_call_functions) / sizeof (ecma_builtin_dispatch_call_t));
return ecma_builtin_call_functions[builtin_object_id] (arguments_list_p, arguments_list_len);
return ecma_builtin_dispatch_routine (ext_obj_p,
this_arg_value,
arguments_list_p,
arguments_list_len);
}
JERRY_ASSERT (!ecma_is_value_empty (ret_value));
return ret_value;
ecma_builtin_id_t builtin_object_id = ext_obj_p->u.built_in.id;
JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_call_functions) / sizeof (ecma_builtin_dispatch_call_t));
return ecma_builtin_call_functions[builtin_object_id] (arguments_list_p, arguments_list_len);
} /* ecma_builtin_dispatch_call */
/**
@@ -1105,16 +1095,36 @@ ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */
*/
ecma_value_t
ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */
ecma_object_t *new_target_p, /**< new target */
const ecma_value_t *arguments_list_p, /**< arguments list */
ecma_length_t arguments_list_len) /**< arguments list length */
{
JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION);
JERRY_ASSERT (ecma_get_object_is_builtin (obj_p));
if (ecma_builtin_function_is_routine (obj_p))
{
return ecma_raise_type_error (ECMA_ERR_MSG ("Built-in routines have no constructor."));
}
ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
ecma_builtin_id_t builtin_object_id = ext_obj_p->u.built_in.id;
JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_construct_functions) / sizeof (ecma_builtin_dispatch_call_t));
return ecma_builtin_construct_functions[builtin_object_id] (arguments_list_p, arguments_list_len);
#if ENABLED (JERRY_ES2015)
ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target);
JERRY_CONTEXT (current_new_target) = new_target_p;
#else /* !ENABLED (JERRY_ES2015) */
JERRY_UNUSED (new_target_p);
#endif /* ENABLED (JERRY_ES2015) */
ecma_value_t ret_value = ecma_builtin_construct_functions[builtin_object_id] (arguments_list_p, arguments_list_len);
#if ENABLED (JERRY_ES2015)
JERRY_CONTEXT (current_new_target) = old_new_target;
#endif /* ENABLED (JERRY_ES2015) */
return ret_value;
} /* ecma_builtin_dispatch_construct */
/**
@@ -85,7 +85,7 @@ ecma_value_t
ecma_builtin_dispatch_call (ecma_object_t *obj_p, ecma_value_t this_arg_value,
const ecma_value_t *arguments_list_p, ecma_length_t arguments_list_len);
ecma_value_t
ecma_builtin_dispatch_construct (ecma_object_t *obj_p,
ecma_builtin_dispatch_construct (ecma_object_t *obj_p, ecma_object_t *new_target_p,
const ecma_value_t *arguments_list_p, ecma_length_t arguments_list_len);
ecma_property_t *
ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, ecma_string_t *string_p);