Skip to content

Commit c8a34a7

Browse files
committed
Rework the core of class parsing/runtime semantic
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 property set new.target JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]
1 parent 76bbb08 commit c8a34a7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1490
-1294
lines changed

jerry-core/api/jerry.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2769,7 +2769,7 @@ jerry_invoke_function (bool is_invoke_as_constructor, /**< true - invoke functio
27692769
JERRY_ASSERT (jerry_value_is_constructor (func_obj_val));
27702770

27712771
return jerry_return (ecma_op_function_construct (ecma_get_object_from_value (func_obj_val),
2772-
ECMA_VALUE_UNDEFINED,
2772+
ecma_get_object_from_value (func_obj_val),
27732773
args_p,
27742774
args_count));
27752775
}

jerry-core/ecma/base/ecma-globals.h

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,13 @@ typedef enum
111111
ECMA_PARSE_EVAL = (1u << 2), /**< eval is called */
112112
ECMA_PARSE_DIRECT_EVAL = (1u << 3), /**< eval is called directly (ECMA-262 v5, 15.1.2.1.1) */
113113

114-
/* These four status flags must be in this order. See PARSER_CLASS_PARSE_OPTS_OFFSET. */
114+
/* These two status flags must be in this order. See PARSER_CLASS_PARSE_OPTS_OFFSET. */
115115
ECMA_PARSE_CLASS_CONSTRUCTOR = (1u << 4), /**< a class constructor is being parsed (this value must be kept in
116116
* in sync with PARSER_CLASS_CONSTRUCTOR) */
117-
ECMA_PARSE_HAS_SUPER = (1u << 5), /**< the current context has super reference */
118-
ECMA_PARSE_HAS_IMPL_SUPER = (1u << 6), /**< the current context has implicit parent class */
119-
ECMA_PARSE_HAS_STATIC_SUPER = (1u << 7), /**< the current context is a static class method */
117+
ECMA_PARSE_CLASS_HERITAGE = (1u << 5), /**< the current method is in a heritage context */
120118

121-
ECMA_PARSE_CALLED_FROM_FUNCTION = (1u << 8), /**< a function body is parsed or the code is inside a function */
122-
ECMA_PARSE_GENERATOR_FUNCTION = (1u << 9), /**< generator function is parsed */
119+
ECMA_PARSE_CALLED_FROM_FUNCTION = (1u << 6), /**< a function body is parsed or the code is inside a function */
120+
ECMA_PARSE_GENERATOR_FUNCTION = (1u << 7), /**< generator function is parsed */
123121

124122
/* These flags are internally used by the parser. */
125123
} ecma_parse_opts_t;
@@ -195,7 +193,7 @@ enum
195193
* ecma_op_object_find */
196194
ECMA_VALUE_REGISTER_REF = ECMA_MAKE_VALUE (8), /**< register reference,
197195
* a special "base" value for vm */
198-
ECMA_VALUE_IMPLICIT_CONSTRUCTOR = ECMA_MAKE_VALUE (9), /**< special value for bound class constructors */
196+
ECMA_VALUE_CLASS_ENVIRONMENT = ECMA_MAKE_VALUE (9), /**< a special value for class encironment record on the stack */
199197
ECMA_VALUE_UNINITIALIZED = ECMA_MAKE_VALUE (10), /**< a special value for uninitialized let/const declarations */
200198
ECMA_VALUE_SPREAD_ELEMENT = ECMA_MAKE_VALUE (11), /**< a special value for spread elements in array initialization
201199
* or function call argument list */
@@ -661,12 +659,12 @@ typedef enum
661659
ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE = 13, /**< declarative lexical environment */
662660
ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND = 14, /**< object-bound lexical environment
663661
* with provideThis flag */
664-
ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND = 15, /**< object-bound lexical environment
665-
* with provided super reference */
662+
ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND = 15, /**< object-bound lexical environment
663+
* with provided home object reference */
666664

667665
ECMA_LEXICAL_ENVIRONMENT_TYPE_START = ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE, /**< first lexical
668666
* environment type */
669-
ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX = ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND /**< maximum value */
667+
ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX = ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND /**< maximum value */
670668
} ecma_lexical_environment_type_t;
671669

672670
#if ENABLED (JERRY_ES2015)
@@ -778,8 +776,9 @@ typedef struct
778776
union
779777
{
780778
jmem_cpointer_t property_list_cp; /**< compressed pointer to object's
781-
* or declerative lexical environments's property list */
779+
* or declerative lexical environments's property list */
782780
jmem_cpointer_t bound_object_cp; /**< compressed pointer to lexical environments's the bound object */
781+
jmem_cpointer_t home_object_cp; /**< compressed pointer to lexical environments's the home object */
783782
} u1;
784783

785784
/** object prototype or outer reference */
@@ -953,13 +952,12 @@ typedef struct
953952
#endif /* ENABLED (JERRY_SNAPSHOT_EXEC) */
954953

955954
#if ENABLED (JERRY_ES2015)
956-
957955
/**
958956
* Description of arrow function objects.
959957
*/
960958
typedef struct
961959
{
962-
ecma_extended_object_t header; /**< extended object header */
960+
ecma_extended_object_t header; /**< object header */
963961
ecma_value_t this_binding; /**< value of 'this' binding */
964962
} ecma_arrow_function_t;
965963

@@ -1862,6 +1860,32 @@ typedef struct
18621860
ecma_extended_object_t header; /**< header part */
18631861
ecma_value_t proxy; /**< [[RevocableProxy]] internal slot */
18641862
} ecma_revocable_proxy_object_t;
1863+
1864+
/**
1865+
* Set "derived" [[ConstructorKind]] flag for the [[Construct]] method.
1866+
*
1867+
* Whenever this flag is set the new_target_p parameter contains the current [[ThisBindingValue]]
1868+
*
1869+
* @param new_target_p new.target to invoke the [[Construct]] with
1870+
*/
1871+
#define ECMA_SET_DERIVED_FLAG(new_target_p) \
1872+
((ecma_object_t *) (((uintptr_t) (new_target_p)) | (uintptr_t) 0x01))
1873+
1874+
/**
1875+
* Check whether the "derived" [[ConstructorKind]] flag is set
1876+
*
1877+
* @param new_target_p new.target which the [[Construct]] was invoked
1878+
*/
1879+
#define ECMA_HAS_DERIVED_FLAG(new_target_p) (((uintptr_t) (new_target_p)) & (uintptr_t) 0x1)
1880+
1881+
/**
1882+
* Clear the "derived" [[ConstructorKind]] flag from the parameter
1883+
*
1884+
* @param new_target_p new.target which the [[Construct]] was invoked
1885+
*/
1886+
#define ECMA_CLEAR_DERIVED_FLAG(new_target_p) \
1887+
((ecma_object_t *) (((uintptr_t) (new_target_p)) & ((uintptr_t) ~0x01)))
1888+
18651889
#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
18661890

18671891
/**

jerry-core/ecma/base/ecma-helpers-collection.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,45 @@ ecma_collection_push_back (ecma_collection_t *collection_p, /**< value collectio
144144
collection_p->buffer_p = buffer_p;
145145
} /* ecma_collection_push_back */
146146

147+
/**
148+
* Reserve space for the given amount of ecma_values in the collection
149+
*/
150+
void
151+
ecma_collection_reserve (ecma_collection_t *collection_p, /**< value collection */
152+
uint32_t count) /**< number of ecma values to reserve */
153+
{
154+
JERRY_ASSERT (collection_p != NULL);
155+
JERRY_ASSERT (UINT32_MAX - count > collection_p->capacity);
156+
157+
const uint32_t new_capacity = collection_p->capacity + count;
158+
const uint32_t old_size = ECMA_COLLECTION_ALLOCATED_SIZE (collection_p->capacity);
159+
const uint32_t new_size = ECMA_COLLECTION_ALLOCATED_SIZE (new_capacity);
160+
161+
ecma_value_t *buffer_p = collection_p->buffer_p;
162+
buffer_p = jmem_heap_realloc_block (buffer_p, old_size, new_size);
163+
164+
collection_p->capacity = new_capacity;
165+
collection_p->buffer_p = buffer_p;
166+
} /* ecma_collection_reserve */
167+
168+
/**
169+
* Append a list of values to the end of the collection
170+
*/
171+
void
172+
ecma_collection_append (ecma_collection_t *collection_p, /**< value collection */
173+
const ecma_value_t *buffer_p, /**< values to append */
174+
uint32_t count) /**< number of ecma values to append */
175+
{
176+
JERRY_ASSERT (collection_p != NULL);
177+
if (collection_p->capacity - collection_p->item_count > count)
178+
{
179+
ecma_collection_reserve (collection_p, count);
180+
}
181+
182+
memcpy (collection_p->buffer_p + collection_p->item_count, buffer_p, count * sizeof (ecma_value_t));
183+
collection_p->item_count += count;
184+
} /* ecma_collection_append */
185+
147186
/**
148187
* @}
149188
* @}

jerry-core/ecma/base/ecma-helpers.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< out
141141
{
142142
#if ENABLED (JERRY_ES2015)
143143
JERRY_ASSERT (type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND
144-
|| type == ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND);
144+
|| type == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
145145
#else /* !ENABLED (JERRY_ES2015) */
146146
JERRY_ASSERT (type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
147147
#endif /* ENABLED (JERRY_ES2015) */
@@ -288,7 +288,7 @@ ecma_get_lex_env_binding_object (const ecma_object_t *object_p) /**< object-boun
288288
JERRY_ASSERT (ecma_is_lexical_environment (object_p));
289289
#if ENABLED (JERRY_ES2015)
290290
JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND
291-
|| ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_SUPER_OBJECT_BOUND);
291+
|| ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
292292
#else /* !ENABLED (JERRY_ES2015) */
293293
JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
294294
#endif /* ENABLED (JERRY_ES2015) */

jerry-core/ecma/base/ecma-helpers.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,8 @@ lit_utf8_size_t ecma_number_to_binary_floating_point_number (ecma_number_t num,
402402
/* ecma-helpers-collection.c */
403403
ecma_collection_t *ecma_new_collection (void);
404404
void ecma_collection_push_back (ecma_collection_t *collection_p, ecma_value_t value);
405+
void ecma_collection_reserve (ecma_collection_t *collection_p, uint32_t count);
406+
void ecma_collection_append (ecma_collection_t *collection_p, const ecma_value_t *buffer_p, uint32_t count);
405407
void ecma_collection_destroy (ecma_collection_t *collection_p);
406408
void ecma_collection_free (ecma_collection_t *collection_p);
407409
void ecma_collection_free_if_not_object (ecma_collection_t *collection_p);
@@ -419,7 +421,6 @@ bool JERRY_ATTR_PURE ecma_get_object_is_builtin (const ecma_object_t *object_p);
419421
void ecma_set_object_is_builtin (ecma_object_t *object_p);
420422
uint8_t ecma_get_object_builtin_id (ecma_object_t *object_p);
421423
ecma_lexical_environment_type_t JERRY_ATTR_PURE ecma_get_lex_env_type (const ecma_object_t *object_p);
422-
ecma_object_t JERRY_ATTR_PURE *ecma_get_lex_env_outer_reference (const ecma_object_t *object_p);
423424
ecma_object_t JERRY_ATTR_PURE *ecma_get_lex_env_binding_object (const ecma_object_t *object_p);
424425
ecma_object_t *ecma_clone_decl_lexical_environment (ecma_object_t *lex_env_p, bool copy_values);
425426

jerry-core/ecma/builtin-objects/ecma-builtin-array.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */
128128
{
129129
ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor);
130130

131-
array = ecma_op_function_construct (constructor_obj_p, ECMA_VALUE_UNDEFINED, NULL, 0);
131+
array = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, NULL, 0);
132132

133133
if (ecma_is_value_undefined (array) || ecma_is_value_null (array))
134134
{
@@ -289,7 +289,7 @@ ecma_builtin_array_object_from (ecma_value_t this_arg, /**< 'this' argument */
289289
{
290290
ecma_object_t *constructor_obj_p = ecma_get_object_from_value (constructor);
291291

292-
array = ecma_op_function_construct (constructor_obj_p, ECMA_VALUE_UNDEFINED, &len_value, 1);
292+
array = ecma_op_function_construct (constructor_obj_p, constructor_obj_p, &len_value, 1);
293293

294294
if (ecma_is_value_undefined (array) || ecma_is_value_null (array))
295295
{
@@ -414,7 +414,7 @@ ecma_builtin_array_object_of (ecma_value_t this_arg, /**< 'this' argument */
414414
ecma_value_t len = ecma_make_uint32_value (arguments_list_len);
415415

416416
ecma_value_t ret_val = ecma_op_function_construct (ecma_get_object_from_value (this_arg),
417-
ECMA_VALUE_UNDEFINED,
417+
ecma_get_object_from_value (this_arg),
418418
&len,
419419
1);
420420

jerry-core/ecma/builtin-objects/ecma-builtin-reflect.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,8 @@ ecma_builtin_reflect_dispatch_routine (uint16_t builtin_routine_id, /**< built-i
205205
return ECMA_VALUE_ERROR;
206206
}
207207

208-
// TODO: add new_target_p to construct when it'll be supported
209-
JERRY_UNUSED (new_target_p);
210208
ecma_value_t ret_value = ecma_op_function_construct (target_p,
211-
ECMA_VALUE_UNDEFINED,
209+
new_target_p,
212210
coll_p->buffer_p,
213211
coll_p->item_count);
214212

jerry-core/ecma/operations/ecma-array-object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,7 @@ ecma_op_array_species_create (ecma_object_t *original_array_p, /**< The object f
733733
ecma_value_t len_val = ecma_make_uint32_value (length);
734734
ecma_object_t *ctor_object_p = ecma_get_object_from_value (constructor);
735735
ecma_value_t ret_val = ecma_op_function_construct (ctor_object_p,
736-
ECMA_VALUE_UNDEFINED,
736+
ctor_object_p,
737737
&len_val,
738738
1);
739739

0 commit comments

Comments
 (0)