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:
@@ -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) */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user