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
+6
View File
@@ -670,6 +670,11 @@ ecma_gc_mark (ecma_object_t *object_p) /**< object to mark from */
{
ecma_gc_set_object_visited (ecma_get_object_from_value (arrow_func_p->this_binding));
}
if (ecma_is_value_object (arrow_func_p->new_target))
{
ecma_gc_set_object_visited (ecma_get_object_from_value (arrow_func_p->new_target));
}
}
#endif /* ENABLED (JERRY_ES2015) */
}
@@ -1218,6 +1223,7 @@ ecma_gc_free_object (ecma_object_t *object_p) /**< object to free */
if (byte_code_p->status_flags & CBC_CODE_FLAGS_ARROW_FUNCTION)
{
ecma_free_value_if_not_object (((ecma_arrow_function_t *) object_p)->this_binding);
ecma_free_value_if_not_object (((ecma_arrow_function_t *) object_p)->new_target);
ext_object_size = sizeof (ecma_arrow_function_t);
}
#endif /* ENABLED (JERRY_ES2015) */
+19 -17
View File
@@ -111,15 +111,14 @@ typedef enum
ECMA_PARSE_EVAL = (1u << 2), /**< eval is called */
ECMA_PARSE_DIRECT_EVAL = (1u << 3), /**< eval is called directly (ECMA-262 v5, 15.1.2.1.1) */
/* These four status flags must be in this order. See PARSER_CLASS_PARSE_OPTS_OFFSET. */
/* These three status flags must be in this order. See PARSER_SAVED_FLAGS_OFFSET. */
ECMA_PARSE_CLASS_CONSTRUCTOR = (1u << 4), /**< a class constructor is being parsed (this value must be kept in
* in sync with PARSER_CLASS_CONSTRUCTOR) */
ECMA_PARSE_HAS_SUPER = (1u << 5), /**< the current context has super reference */
ECMA_PARSE_HAS_IMPL_SUPER = (1u << 6), /**< the current context has implicit parent class */
ECMA_PARSE_HAS_STATIC_SUPER = (1u << 7), /**< the current context is a static class method */
ECMA_PARSE_ALLOW_SUPER = (1u << 5), /**< allow super property access */
ECMA_PARSE_ALLOW_SUPER_CALL = (1u << 6), /**< allow super constructor call */
ECMA_PARSE_CALLED_FROM_FUNCTION = (1u << 8), /**< a function body is parsed or the code is inside a function */
ECMA_PARSE_GENERATOR_FUNCTION = (1u << 9), /**< generator function is parsed */
ECMA_PARSE_CALLED_FROM_FUNCTION = (1u << 7), /**< a function body is parsed or the code is inside a function */
ECMA_PARSE_GENERATOR_FUNCTION = (1u << 8), /**< generator function is parsed */
/* These flags are internally used by the parser. */
} ecma_parse_opts_t;
@@ -195,7 +194,8 @@ enum
* ecma_op_object_find */
ECMA_VALUE_REGISTER_REF = ECMA_MAKE_VALUE (8), /**< register reference,
* a special "base" value for vm */
ECMA_VALUE_IMPLICIT_CONSTRUCTOR = ECMA_MAKE_VALUE (9), /**< special value for bound class constructors */
ECMA_VALUE_RELEASE_LEX_ENV = ECMA_MAKE_VALUE (9), /**< if this error remains on the stack when an exception occours
the top lexical environment of the VM frame should be popped */
ECMA_VALUE_UNINITIALIZED = ECMA_MAKE_VALUE (10), /**< a special value for uninitialized let/const declarations */
ECMA_VALUE_SPREAD_ELEMENT = ECMA_MAKE_VALUE (11), /**< a special value for spread elements in array initialization
* or function call argument list */
@@ -661,12 +661,12 @@ typedef enum
ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE = 13, /**< declarative lexical environment */
ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND = 14, /**< object-bound lexical environment
* with provideThis flag */
ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND = 15, /**< object-bound lexical environment
* with provided super reference */
ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND = 15, /**< object-bound lexical environment
* with provided home object reference */
ECMA_LEXICAL_ENVIRONMENT_TYPE_START = ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE, /**< first lexical
* environment type */
ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX = ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND /**< maximum value */
ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX = ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND /**< maximum value */
} ecma_lexical_environment_type_t;
#if ENABLED (JERRY_ES2015)
@@ -686,29 +686,29 @@ typedef enum
/**
* Offset for JERRY_CONTEXT (status_flags) top 8 bits.
*/
#define ECMA_SUPER_EVAL_OPTS_OFFSET (32 - 8)
#define ECMA_LOCAL_PARSE_OPTS_OFFSET ((sizeof (uint32_t) - sizeof (uint8_t)) * JERRY_BITSINBYTE)
/**
* Set JERRY_CONTEXT (status_flags) top 8 bits to the specified 'opts'.
*/
#define ECMA_SET_SUPER_EVAL_PARSER_OPTS(opts) \
#define ECMA_SET_LOCAL_PARSE_OPTS(opts) \
do \
{ \
JERRY_CONTEXT (status_flags) |= ((uint32_t) opts << ECMA_SUPER_EVAL_OPTS_OFFSET) | ECMA_STATUS_DIRECT_EVAL; \
JERRY_CONTEXT (status_flags) |= ((uint32_t) opts << ECMA_LOCAL_PARSE_OPTS_OFFSET) | ECMA_STATUS_DIRECT_EVAL; \
} while (0)
/**
* Get JERRY_CONTEXT (status_flags) top 8 bits.
*/
#define ECMA_GET_SUPER_EVAL_PARSER_OPTS() (JERRY_CONTEXT (status_flags) >> ECMA_SUPER_EVAL_OPTS_OFFSET)
#define ECMA_GET_LOCAL_PARSE_OPTS() (JERRY_CONTEXT (status_flags) >> ECMA_LOCAL_PARSE_OPTS_OFFSET)
/**
* Clear JERRY_CONTEXT (status_flags) top 8 bits.
*/
#define ECMA_CLEAR_SUPER_EVAL_PARSER_OPTS() \
#define ECMA_CLEAR_LOCAL_PARSE_OPTS() \
do \
{ \
JERRY_CONTEXT (status_flags) &= ((1 << ECMA_SUPER_EVAL_OPTS_OFFSET) - 1); \
JERRY_CONTEXT (status_flags) &= ((1 << ECMA_LOCAL_PARSE_OPTS_OFFSET) - 1); \
} while (0)
/**
@@ -778,8 +778,9 @@ typedef struct
union
{
jmem_cpointer_t property_list_cp; /**< compressed pointer to object's
* or declerative lexical environments's property list */
* or declerative lexical environments's property list */
jmem_cpointer_t bound_object_cp; /**< compressed pointer to lexical environments's the bound object */
jmem_cpointer_t home_object_cp; /**< compressed pointer to lexical environments's the home object */
} u1;
/** object prototype or outer reference */
@@ -961,6 +962,7 @@ typedef struct
{
ecma_extended_object_t header; /**< extended object header */
ecma_value_t this_binding; /**< value of 'this' binding */
ecma_value_t new_target; /**< value of new.target */
} ecma_arrow_function_t;
#if ENABLED (JERRY_SNAPSHOT_EXEC)
@@ -144,6 +144,45 @@ ecma_collection_push_back (ecma_collection_t *collection_p, /**< value collectio
collection_p->buffer_p = buffer_p;
} /* ecma_collection_push_back */
/**
* Reserve space for the given amount of ecma_values in the collection
*/
void
ecma_collection_reserve (ecma_collection_t *collection_p, /**< value collection */
uint32_t count) /**< number of ecma values to reserve */
{
JERRY_ASSERT (collection_p != NULL);
JERRY_ASSERT (UINT32_MAX - count > collection_p->capacity);
const uint32_t new_capacity = collection_p->capacity + count;
const uint32_t old_size = ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity);
const uint32_t new_size = ECMA_COLLECTION_ALLOCATED_SIZE (new_capacity);
ecma_value_t *buffer_p = collection_p->buffer_p;
buffer_p = jmem_heap_realloc_block (buffer_p, old_size, new_size);
collection_p->capacity = new_capacity;
collection_p->buffer_p = buffer_p;
} /* ecma_collection_reserve */
/**
* Append a list of values to the end of the collection
*/
void
ecma_collection_append (ecma_collection_t *collection_p, /**< value collection */
const ecma_value_t *buffer_p, /**< values to append */
uint32_t count) /**< number of ecma values to append */
{
JERRY_ASSERT (collection_p != NULL);
if (collection_p->capacity - collection_p->item_count > count)
{
ecma_collection_reserve (collection_p, count);
}
memcpy (collection_p->buffer_p + collection_p->item_count, buffer_p, count * sizeof (ecma_value_t));
collection_p->item_count += count;
} /* ecma_collection_append */
/**
* @}
* @}
+2 -2
View File
@@ -141,7 +141,7 @@ ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< out
{
#if ENABLED (JERRY_ES2015)
JERRY_ASSERT (type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND
|| type == ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND);
|| type == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
#else /* !ENABLED (JERRY_ES2015) */
JERRY_ASSERT (type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
#endif /* ENABLED (JERRY_ES2015) */
@@ -288,7 +288,7 @@ ecma_get_lex_env_binding_object (const ecma_object_t *object_p) /**< object-boun
JERRY_ASSERT (ecma_is_lexical_environment (object_p));
#if ENABLED (JERRY_ES2015)
JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND
|| ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND);
|| ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
#else /* !ENABLED (JERRY_ES2015) */
JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
#endif /* ENABLED (JERRY_ES2015) */
+10 -2
View File
@@ -192,13 +192,20 @@ typedef enum
#define ECMA_ASSERT_VALUE_IS_SYMBOL(value) (false)
#endif /* ENABLED (JERRY_ES2015) */
/**
* Check whether the given type is ECMA_OBJECT_TYPE_PROXY
*
* @param type object type
*/
#define ECMA_OBJECT_TYPE_IS_PROXY(type) (JERRY_UNLIKELY ((type) == ECMA_OBJECT_TYPE_PROXY))
/**
* Check whether the given object has [[ProxyHandler]] and [[ProxyTarger]] internal slots
*
* @param obj_p ecma-object
*/
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
#define ECMA_OBJECT_IS_PROXY(obj_p) (JERRY_UNLIKELY (ecma_get_object_type ((obj_p)) == ECMA_OBJECT_TYPE_PROXY))
#define ECMA_OBJECT_IS_PROXY(obj_p) (ECMA_OBJECT_TYPE_IS_PROXY (ecma_get_object_type ((obj_p))))
#else /* !ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
#define ECMA_OBJECT_IS_PROXY(obj_p) (false)
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
@@ -402,6 +409,8 @@ lit_utf8_size_t ecma_number_to_binary_floating_point_number (ecma_number_t num,
/* ecma-helpers-collection.c */
ecma_collection_t *ecma_new_collection (void);
void ecma_collection_push_back (ecma_collection_t *collection_p, ecma_value_t value);
void ecma_collection_reserve (ecma_collection_t *collection_p, uint32_t count);
void ecma_collection_append (ecma_collection_t *collection_p, const ecma_value_t *buffer_p, uint32_t count);
void ecma_collection_destroy (ecma_collection_t *collection_p);
void ecma_collection_free (ecma_collection_t *collection_p);
void ecma_collection_free_if_not_object (ecma_collection_t *collection_p);
@@ -419,7 +428,6 @@ bool JERRY_ATTR_PURE ecma_get_object_is_builtin (const ecma_object_t *object_p);
void ecma_set_object_is_builtin (ecma_object_t *object_p);
uint8_t ecma_get_object_builtin_id (ecma_object_t *object_p);
ecma_lexical_environment_type_t JERRY_ATTR_PURE ecma_get_lex_env_type (const ecma_object_t *object_p);
ecma_object_t JERRY_ATTR_PURE *ecma_get_lex_env_outer_reference (const ecma_object_t *object_p);
ecma_object_t JERRY_ATTR_PURE *ecma_get_lex_env_binding_object (const ecma_object_t *object_p);
ecma_object_t *ecma_clone_decl_lexical_environment (ecma_object_t *lex_env_p, bool copy_values);
@@ -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);
@@ -73,7 +73,7 @@ ecma_op_new_array_object (ecma_length_t length) /**< length of the new array */
ecma_object_t *array_prototype_object_p = ecma_builtin_get (ECMA_BUILTIN_ID_ARRAY_PROTOTYPE);
#else /* !ENABLED (JERRY_BUILTIN_ARRAY) */
ecma_object_t *array_prototype_object_p = ecma_builtin_get (ECMA_BUILTIN_ID_OBJECT_PROTOTYPE);
#endif /* (ENABLED (JERRY_BUILTIN_ARRAY)) */
#endif /* ENABLED (JERRY_BUILTIN_ARRAY) */
ecma_object_t *object_p = ecma_create_object (array_prototype_object_p,
sizeof (ecma_extended_object_t),
@@ -733,7 +733,7 @@ ecma_op_array_species_create (ecma_object_t *original_array_p, /**< The object f
ecma_value_t len_val = ecma_make_uint32_value (length);
ecma_object_t *ctor_object_p = ecma_get_object_from_value (constructor);
ecma_value_t ret_val = ecma_op_function_construct (ctor_object_p,
ECMA_VALUE_UNDEFINED,
ctor_object_p,
&len_val,
1);
+1 -1
View File
@@ -98,7 +98,7 @@ ecma_op_eval_chars_buffer (const lit_utf8_byte_t *code_p, /**< code characters b
#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ERROR_MESSAGES) */
#if ENABLED (JERRY_ES2015)
ECMA_CLEAR_SUPER_EVAL_PARSER_OPTS ();
ECMA_CLEAR_LOCAL_PARSE_OPTS ();
/* If a direct eval is used inside the function the info should be propagated. */
if (JERRY_CONTEXT (current_new_target) != JERRY_CONTEXT_INVALID_NEW_TARGET
File diff suppressed because it is too large Load Diff
@@ -51,29 +51,8 @@ ecma_op_create_dynamic_function (const ecma_value_t *arguments_list_p,
ecma_parse_opts_t opts);
#if ENABLED (JERRY_ES2015)
void
ecma_op_set_super_called (ecma_object_t *lex_env_p);
bool
ecma_op_is_super_called (ecma_object_t *lex_env_p);
void
ecma_op_set_class_this_binding (ecma_object_t *lex_env_p, ecma_value_t this_binding);
ecma_value_t
ecma_op_get_class_this_binding (ecma_object_t *lex_env_p);
ecma_value_t
ecma_op_function_implicit_constructor_handler_cb (const ecma_value_t function_obj,
const ecma_value_t this_val,
const ecma_value_t args_p[],
const ecma_length_t args_count);
void
ecma_op_set_class_prototype (ecma_value_t completion_value, ecma_value_t this_arg);
ecma_object_t *
ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, ecma_builtin_id_t default_proto_id);
ecma_op_function_get_super_constructor (ecma_object_t *func_obj_p);
ecma_object_t *
ecma_op_create_generator_function_object (ecma_object_t *scope_p, const ecma_compiled_code_t *bytecode_data_p);
@@ -81,9 +60,13 @@ ecma_op_create_generator_function_object (ecma_object_t *scope_p, const ecma_com
ecma_object_t *
ecma_op_create_arrow_function_object (ecma_object_t *scope_p, const ecma_compiled_code_t *bytecode_data_p,
ecma_value_t this_binding);
bool
ecma_op_function_is_generator (ecma_object_t *func_obj_p);
#endif /* ENABLED (JERRY_ES2015) */
ecma_object_t *
ecma_op_get_prototype_from_constructor (ecma_object_t *ctor_obj_p, ecma_builtin_id_t default_proto_id);
ecma_value_t
ecma_op_function_has_instance (ecma_object_t *func_obj_p, ecma_value_t value);
@@ -92,7 +75,7 @@ ecma_op_function_call (ecma_object_t *func_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_op_function_construct (ecma_object_t *func_obj_p, ecma_value_t this_arg_value,
ecma_op_function_construct (ecma_object_t *func_obj_p, ecma_object_t *new_target_p,
const ecma_value_t *arguments_list_p, ecma_length_t arguments_list_len);
ecma_property_t *
@@ -77,7 +77,7 @@ ecma_op_get_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environme
break;
}
#if ENABLED (JERRY_ES2015)
case ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND:
case ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND:
{
break;
}
@@ -266,7 +266,7 @@ ecma_op_put_value_lex_env_base (ecma_object_t *lex_env_p, /**< lexical environme
break;
}
#if ENABLED (JERRY_ES2015)
case ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND:
case ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND:
{
break;
}
+138
View File
@@ -427,6 +427,144 @@ ecma_op_create_immutable_binding (ecma_object_t *lex_env_p, /**< lexical environ
prop_value_p->value = ecma_copy_value_if_not_object (value);
} /* ecma_op_create_immutable_binding */
#if ENABLED (JERRY_ES2015)
/**
* InitializeBinding operation.
*
* See also: ECMA-262 v6, 8.1.1.1.4
*/
void
ecma_op_initialize_binding (ecma_object_t *lex_env_p, /**< lexical environment */
ecma_string_t *name_p, /**< argument N */
ecma_value_t value) /**< argument V */
{
JERRY_ASSERT (lex_env_p != NULL
&& ecma_is_lexical_environment (lex_env_p));
JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE);
ecma_property_t *prop_p = ecma_find_named_property (lex_env_p, name_p);
JERRY_ASSERT (prop_p != NULL);
JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*prop_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
ecma_property_value_t *prop_value_p = ECMA_PROPERTY_VALUE_PTR (prop_p);
JERRY_ASSERT (prop_value_p->value == ECMA_VALUE_UNINITIALIZED);
prop_value_p->value = ecma_copy_value_if_not_object (value);
} /* ecma_op_initialize_binding */
/**
* BindThisValue operation for an empty lexical environment
*
* See also: ECMA-262 v6, 8.1.1.3.1
*/
void
ecma_op_init_this_binding (ecma_object_t *lex_env_p, /**< lexical environment */
ecma_value_t this_binding) /**< this binding value */
{
JERRY_ASSERT (lex_env_p != NULL);
JERRY_ASSERT (ecma_is_value_object (this_binding) || this_binding == ECMA_VALUE_UNINITIALIZED);
ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_THIS_BINDING_VALUE);
ecma_property_value_t *prop_value_p = ecma_create_named_data_property (lex_env_p,
prop_name_p,
ECMA_PROPERTY_FIXED,
NULL);
prop_value_p->value = this_binding;
} /* ecma_op_init_this_binding */
/**
* GetThisEnvironment operation.
*
* See also: ECMA-262 v6, 8.3.2
*
* @return property pointer for the internal [[ThisBindingValue]] property
*/
ecma_property_t *
ecma_op_get_this_property (ecma_object_t *lex_env_p) /**< lexical environment */
{
JERRY_ASSERT (lex_env_p != NULL);
ecma_string_t *prop_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_THIS_BINDING_VALUE);
while (true)
{
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
{
ecma_property_t *prop_p = ecma_find_named_property (lex_env_p, prop_name_p);
if (prop_p != NULL)
{
return prop_p;
}
}
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
}
} /* ecma_op_get_this_property */
/**
* GetThisBinding operation.
*
* See also: ECMA-262 v6, 8.1.1.3.4
*
* @return ECMA_VALUE_ERROR - if the operation fails
* ecma-object - otherwise
*/
ecma_value_t
ecma_op_get_this_binding (ecma_object_t *lex_env_p) /**< lexical environment */
{
JERRY_ASSERT (lex_env_p != NULL);
ecma_property_t *prop_p = ecma_op_get_this_property (lex_env_p);
JERRY_ASSERT (prop_p != NULL);
ecma_value_t this_value = ECMA_PROPERTY_VALUE_PTR (prop_p)->value;
if (this_value == ECMA_VALUE_UNINITIALIZED)
{
return ecma_raise_reference_error (ECMA_ERR_MSG ("Must call super constructor in derived class before "
"accessing 'this' or returning from it."));
}
ecma_ref_object (ecma_get_object_from_value (this_value));
return this_value;
} /* ecma_op_get_this_binding */
/**
* BindThisValue operation.
*
* See also: ECMA-262 v6, 8.1.1.3.1
*/
void
ecma_op_bind_this_value (ecma_property_t *prop_p, /**< [[ThisBindingValue]] internal property */
ecma_value_t this_binding) /**< this binding value */
{
JERRY_ASSERT (prop_p != NULL);
JERRY_ASSERT (ecma_is_value_object (this_binding));
JERRY_ASSERT (!ecma_op_this_binding_is_initialized (prop_p));
ECMA_PROPERTY_VALUE_PTR (prop_p)->value = this_binding;
} /* ecma_op_bind_this_value */
/**
* Get the environment record [[ThisBindingStatus]] internal property.
*
* See also: ECMA-262 v6, 8.1.1.3
*
* @return true - if the status is "initialzed"
* false - otherwise
*/
bool
ecma_op_this_binding_is_initialized (ecma_property_t *prop_p) /**< [[ThisBindingValue]] internal property */
{
JERRY_ASSERT (prop_p != NULL);
return ECMA_PROPERTY_VALUE_PTR (prop_p)->value != ECMA_VALUE_UNINITIALIZED;
} /* ecma_op_this_binding_is_initialized */
#endif /* ENABLED (JERRY_ES2015) */
/**
* @}
* @}
+19
View File
@@ -66,6 +66,25 @@ ecma_value_t ecma_op_implicit_this_value (ecma_object_t *lex_env_p);
/* ECMA-262 v5, Table 18. Additional methods of Declarative Environment Records */
void ecma_op_create_immutable_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p, ecma_value_t value);
#if ENABLED (JERRY_ES2015)
void ecma_op_initialize_binding (ecma_object_t *lex_env_p, ecma_string_t *name_p, ecma_value_t value);
void
ecma_op_init_this_binding (ecma_object_t *lex_env_p, ecma_value_t this_binding);
ecma_property_t *
ecma_op_get_this_property (ecma_object_t *lex_env_p);
bool
ecma_op_this_binding_is_initialized (ecma_property_t *prop_p);
ecma_value_t
ecma_op_get_this_binding (ecma_object_t *lex_env_p);
void
ecma_op_bind_this_value (ecma_property_t *prop_p, ecma_value_t this_binding);
#endif /* ENABLED (JERRY_ES2015) */
/**
* @}
* @}
@@ -679,7 +679,7 @@ ecma_promise_new_capability (ecma_value_t constructor)
/* 6. */
ecma_value_t promise = ecma_op_function_construct (constructor_obj_p,
ECMA_VALUE_UNDEFINED,
constructor_obj_p,
&executor,
1);
ecma_deref_object (executor_p);
@@ -849,12 +849,12 @@ ecma_proxy_object_call (ecma_object_t *obj_p, /**< proxy object */
*/
ecma_value_t
ecma_proxy_object_construct (ecma_object_t *obj_p, /**< proxy object */
ecma_object_t *new_target_p, /**< new target */
const ecma_value_t *args_p, /**< argument list */
ecma_length_t argc, /**< number of arguments */
ecma_value_t new_target) /**< this argument to invoke the function */
ecma_length_t argc) /**< number of arguments */
{
JERRY_ASSERT (ECMA_OBJECT_IS_PROXY (obj_p));
JERRY_UNUSED_4 (obj_p, args_p, argc, new_target);
JERRY_UNUSED_4 (obj_p, new_target_p, args_p, argc);
return ecma_raise_type_error (ECMA_ERR_MSG ("UNIMPLEMENTED: Proxy.[[Construct]]"));
} /* ecma_proxy_object_construct */
@@ -106,9 +106,9 @@ ecma_proxy_object_call (ecma_object_t *obj_p,
ecma_value_t
ecma_proxy_object_construct (ecma_object_t *obj_p,
ecma_object_t *new_target_p,
const ecma_value_t *args_p,
ecma_length_t argc,
ecma_value_t new_target);
ecma_length_t argc);
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
+41 -12
View File
@@ -21,6 +21,7 @@
#include "ecma-lcache.h"
#include "ecma-lex-env.h"
#include "ecma-objects.h"
#include "ecma-proxy-object.h"
#include "ecma-reference.h"
#include "jrt.h"
@@ -47,7 +48,7 @@ ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, /**< starting lexical
while (true)
{
#if ENABLED (JERRY_ES2015)
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND)
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND)
{
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
@@ -79,27 +80,55 @@ ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, /**< starting lexical
#if ENABLED (JERRY_ES2015)
/**
* Resolve super reference.
* Perform GetThisEnvironment and GetSuperBase operations
*
* @return value of the reference
* See also: ECMAScript v6, 8.1.1.3.5
*
* @return ECMA_VALUE_ERROR - if the operation fails
* ECMA_VALUE_UNDEFINED - if the home object is null
* value of the [[HomeObject]].[[Prototype]] internal slot - otherwise
*/
ecma_object_t *
ecma_op_resolve_super_reference_value (ecma_object_t *lex_env_p) /**< starting lexical environment */
ecma_value_t
ecma_op_resolve_super_base (ecma_object_t *lex_env_p) /**< starting lexical environment */
{
JERRY_ASSERT (lex_env_p != NULL);
while (true)
{
JERRY_ASSERT (lex_env_p != NULL);
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND)
if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND)
{
return ecma_get_lex_env_binding_object (lex_env_p);
ecma_object_t *home_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u1.home_object_cp);
#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
if (ECMA_OBJECT_IS_PROXY (home_p))
{
return ecma_proxy_object_get_prototype_of (home_p);
}
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
jmem_cpointer_t proto_cp = ecma_op_ordinary_object_get_prototype_of (home_p);
if (proto_cp == JMEM_CP_NULL)
{
return ECMA_VALUE_NULL;
}
ecma_object_t *proto_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, proto_cp);
ecma_ref_object (proto_p);
return ecma_make_object_value (proto_p);
}
JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
if (lex_env_p->u2.outer_reference_cp == JMEM_CP_NULL)
{
break;
}
lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
}
} /* ecma_op_resolve_super_reference_value */
return ECMA_VALUE_UNDEFINED;
} /* ecma_op_resolve_super_base */
/**
* Helper method for HasBindig operation
@@ -262,7 +291,7 @@ ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, /**< starting lexical
else
{
#if ENABLED (JERRY_ES2015)
JERRY_ASSERT (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND);
JERRY_ASSERT (lex_env_type == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
#else /* !ENABLED (JERRY_ES2015) */
JERRY_UNREACHABLE ();
#endif /* ENABLED (JERRY_ES2015) */
+1 -1
View File
@@ -29,7 +29,7 @@
ecma_object_t *ecma_op_resolve_reference_base (ecma_object_t *lex_env_p, ecma_string_t *name_p);
ecma_value_t ecma_op_resolve_reference_value (ecma_object_t *lex_env_p, ecma_string_t *name_p);
#if ENABLED (JERRY_ES2015)
ecma_object_t *ecma_op_resolve_super_reference_value (ecma_object_t *lex_env_p);
ecma_value_t ecma_op_resolve_super_base (ecma_object_t *lex_env_p);
ecma_value_t ecma_op_is_prop_unscopable (ecma_object_t *lex_env_p, ecma_string_t *prop_name_p);
#endif /* ENABLED (JERRY_ES2015) */
@@ -1696,7 +1696,7 @@ ecma_regexp_split_helper (ecma_value_t this_arg, /**< this value */
/* 13-14. */
ecma_value_t arguments[] = { this_arg, ecma_make_string_value (flags_str_p) };
ecma_value_t splitter = ecma_op_function_construct (constructor_obj_p, ECMA_VALUE_UNDEFINED, arguments, 2);
ecma_value_t splitter = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, arguments, 2);
ecma_deref_ecma_string (flags_str_p);
ecma_deref_object (constructor_obj_p);
@@ -536,7 +536,7 @@ ecma_typedarray_create_object_with_length (ecma_length_t array_length, /**< leng
ecma_value_t byte_length_val = ecma_make_uint32_value (byte_length);
ecma_value_t new_arraybuffer = ecma_op_function_construct (ctor_proto_p,
ECMA_VALUE_UNDEFINED,
ctor_proto_p,
&byte_length_val,
1);
ecma_deref_object (ctor_proto_p);