Properly implement static class fields. (#4221)

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2020-09-25 14:23:02 +02:00
committed by GitHub
parent e478640d80
commit bc64957d19
15 changed files with 344 additions and 162 deletions
+59 -14
View File
@@ -967,22 +967,21 @@ opfunc_async_create_and_await (vm_frame_ctx_t *frame_ctx_p, /**< frame context *
} /* opfunc_async_create_and_await */
/**
* Initialize implicit class fields.
* Initialize class fields.
*
* @return ECMA_VALUE_ERROR - initialization fails
* ECMA_VALUE_UNDEFINED - otherwise
*/
ecma_value_t
ecma_op_init_class_fields (ecma_value_t function_object, /**< the function itself */
ecma_value_t this_val) /**< this_arg of the function */
opfunc_init_class_fields (ecma_value_t class_object, /**< the function itself */
ecma_value_t this_val) /**< this_arg of the function */
{
JERRY_ASSERT (ecma_is_value_object (function_object));
JERRY_ASSERT (ecma_is_value_object (class_object));
JERRY_ASSERT (ecma_is_value_object (this_val));
ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT);
ecma_object_t *function_object_p = ecma_get_object_from_value (function_object);
ecma_property_t *property_p = ecma_find_named_property (function_object_p, name_p);
ecma_object_t *class_object_p = ecma_get_object_from_value (class_object);
ecma_property_t *property_p = ecma_find_named_property (class_object_p, name_p);
if (property_p == NULL)
{
@@ -994,7 +993,7 @@ ecma_op_init_class_fields (ecma_value_t function_object, /**< the function itsel
shared_class_fields.computed_class_fields_p = NULL;
name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED);
ecma_property_t *class_field_property_p = ecma_find_named_property (function_object_p, name_p);
ecma_property_t *class_field_property_p = ecma_find_named_property (class_object_p, name_p);
if (class_field_property_p != NULL)
{
@@ -1016,11 +1015,57 @@ ecma_op_init_class_fields (ecma_value_t function_object, /**< the function itsel
JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result) || result == ECMA_VALUE_UNDEFINED);
return result;
} /* ecma_op_init_class_fields */
} /* opfunc_init_class_fields */
/**
* Initialize static class fields.
*
* @return ECMA_VALUE_ERROR - initialization fails
* ECMA_VALUE_UNDEFINED - otherwise
*/
ecma_value_t
ecma_op_add_computed_field (ecma_value_t class_object, /**< class object */
ecma_value_t name) /**< name of the property */
opfunc_init_static_class_fields (ecma_value_t function_object, /**< the function itself */
ecma_value_t this_val) /**< this_arg of the function */
{
JERRY_ASSERT (ecma_op_is_callable (function_object));
JERRY_ASSERT (ecma_is_value_object (this_val));
vm_frame_ctx_shared_class_fields_t shared_class_fields;
shared_class_fields.header.status_flags = VM_FRAME_CTX_SHARED_HAS_CLASS_FIELDS;
shared_class_fields.computed_class_fields_p = NULL;
ecma_string_t *name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_COMPUTED);
ecma_object_t *function_object_p = ecma_get_object_from_value (function_object);
ecma_property_t *class_field_property_p = ecma_find_named_property (function_object_p, name_p);
if (class_field_property_p != NULL)
{
ecma_value_t value = ECMA_PROPERTY_VALUE_PTR (class_field_property_p)->value;
shared_class_fields.computed_class_fields_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_value_t, value);
}
ecma_extended_object_t *ext_function_p;
ext_function_p = (ecma_extended_object_t *) ecma_get_object_from_value (function_object);
shared_class_fields.header.bytecode_header_p = ecma_op_function_get_compiled_code (ext_function_p);
ecma_object_t *scope_p = ECMA_GET_NON_NULL_POINTER_FROM_POINTER_TAG (ecma_object_t,
ext_function_p->u.function.scope_cp);
ecma_value_t result = vm_run (&shared_class_fields.header, this_val, scope_p);
JERRY_ASSERT (ECMA_IS_VALUE_ERROR (result) || result == ECMA_VALUE_UNDEFINED);
return result;
} /* opfunc_init_static_class_fields */
/**
* Add the name of a computed field to a name list
*
* @return ECMA_VALUE_ERROR - name is not a valid property name
* ECMA_VALUE_UNDEFINED - otherwise
*/
ecma_value_t
opfunc_add_computed_field (ecma_value_t class_object, /**< class object */
ecma_value_t name) /**< name of the property */
{
ecma_string_t *prop_name_p = ecma_op_to_property_key (name);
@@ -1060,7 +1105,7 @@ ecma_op_add_computed_field (ecma_value_t class_object, /**< class object */
compact_collection_p = ecma_compact_collection_push_back (compact_collection_p, name);
ECMA_SET_INTERNAL_VALUE_POINTER (property_value_p->value, compact_collection_p);
return ECMA_VALUE_UNDEFINED;
} /* ecma_op_add_computed_field */
} /* opfunc_add_computed_field */
/**
* Implicit class constructor handler when the classHeritage is not present.
@@ -1083,7 +1128,7 @@ ecma_op_implicit_constructor_handler_cb (const ecma_value_t function_obj, /**< t
return ecma_raise_type_error (ECMA_ERR_MSG ("Class constructor cannot be invoked without 'new'."));
}
return ecma_op_init_class_fields (function_obj, this_val);
return opfunc_init_class_fields (function_obj, this_val);
} /* ecma_op_implicit_constructor_handler_cb */
/**
@@ -1139,7 +1184,7 @@ ecma_op_implicit_constructor_handler_heritage_cb (const ecma_value_t function_ob
ecma_get_object_from_value (proto_value));
}
ecma_value_t fields_value = ecma_op_init_class_fields (function_obj, result);
ecma_value_t fields_value = opfunc_init_class_fields (function_obj, result);
if (ECMA_IS_VALUE_ERROR (fields_value))
{
+5 -2
View File
@@ -147,10 +147,13 @@ ecma_value_t
opfunc_async_create_and_await (vm_frame_ctx_t *frame_ctx_p, ecma_value_t value, uint16_t extra_flags);
ecma_value_t
ecma_op_init_class_fields (ecma_value_t function_object, ecma_value_t this_val);
opfunc_init_class_fields (ecma_value_t class_object, ecma_value_t this_val);
ecma_value_t
ecma_op_add_computed_field (ecma_value_t class_object, ecma_value_t name);
opfunc_init_static_class_fields (ecma_value_t function_object, ecma_value_t this_val);
ecma_value_t
opfunc_add_computed_field (ecma_value_t class_object, ecma_value_t name);
ecma_value_t
opfunc_create_implicit_class_constructor (uint8_t opcode);
+51 -6
View File
@@ -625,7 +625,7 @@ vm_super_call (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
if (ecma_is_value_object (completion_value))
{
ecma_value_t current_function = ecma_make_object_value (vm_get_class_function (frame_ctx_p));
ecma_value_t fields_value = ecma_op_init_class_fields (current_function, completion_value);
ecma_value_t fields_value = opfunc_init_class_fields (current_function, completion_value);
if (ECMA_IS_VALUE_ERROR (fields_value))
{
@@ -1811,9 +1811,40 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
}
goto free_left_value;
}
case VM_OC_PUSH_STATIC_FIELD_FUNC:
{
JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE
&& (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_FIELD_FUNC
|| byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC));
bool push_computed = (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC);
ecma_value_t value = stack_top_p[-1];
if (!push_computed)
{
stack_top_p++;
}
memmove (stack_top_p - 3, stack_top_p - 4, 3 * sizeof (ecma_value_t));
stack_top_p[-4] = left_value;
if (!push_computed)
{
continue;
}
left_value = value;
/* FALLTHRU */
}
case VM_OC_ADD_COMPUTED_FIELD:
{
result = ecma_op_add_computed_field (stack_top_p[-2], left_value);
JERRY_ASSERT (byte_code_start_p[0] == CBC_EXT_OPCODE
&& (byte_code_start_p[1] == CBC_EXT_PUSH_STATIC_COMPUTED_FIELD_FUNC
|| byte_code_start_p[1] == CBC_EXT_ADD_COMPUTED_FIELD
|| byte_code_start_p[1] == CBC_EXT_ADD_STATIC_COMPUTED_FIELD));
int index = (byte_code_start_p[1] == CBC_EXT_ADD_COMPUTED_FIELD) ? -2 : -4;
result = opfunc_add_computed_field (stack_top_p[index], left_value);
if (ECMA_IS_VALUE_ERROR (result))
{
@@ -2025,7 +2056,7 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
opfunc_finalize_class (frame_ctx_p, &stack_top_p, left_value);
goto free_left_value;
}
case VM_OC_SET_CLASS_FIELD_INIT:
case VM_OC_SET_FIELD_INIT:
{
ecma_string_t *property_name_p = ecma_get_magic_string (LIT_INTERNAL_MAGIC_STRING_CLASS_FIELD_INIT);
ecma_object_t *object_p = ecma_get_object_from_value (stack_top_p[-2]);
@@ -2050,11 +2081,11 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
goto free_left_value;
}
case VM_OC_RUN_CLASS_FIELD_INIT:
case VM_OC_RUN_FIELD_INIT:
{
JERRY_ASSERT (frame_ctx_p->shared_p->status_flags & VM_FRAME_CTX_SHARED_NON_ARROW_FUNC);
result = ecma_op_init_class_fields (ecma_make_object_value (VM_FRAME_CTX_GET_FUNCTION_OBJECT (frame_ctx_p)),
frame_ctx_p->this_binding);
result = opfunc_init_class_fields (ecma_make_object_value (VM_FRAME_CTX_GET_FUNCTION_OBJECT (frame_ctx_p)),
frame_ctx_p->this_binding);
if (ECMA_IS_VALUE_ERROR (result))
{
@@ -2062,6 +2093,20 @@ vm_loop (vm_frame_ctx_t *frame_ctx_p) /**< frame context */
}
continue;
}
case VM_OC_RUN_STATIC_FIELD_INIT:
{
left_value = stack_top_p[-2];
stack_top_p[-2] = stack_top_p[-1];
stack_top_p--;
result = opfunc_init_static_class_fields (left_value, stack_top_p[-1]);
if (ECMA_IS_VALUE_ERROR (result))
{
goto error;
}
goto free_left_value;
}
case VM_OC_SET_NEXT_COMPUTED_FIELD:
{
ecma_integer_value_t next_index = ecma_get_integer_from_value (stack_top_p[-2]) + 1;
+10 -4
View File
@@ -260,8 +260,10 @@ typedef enum
VM_OC_PUSH_IMPLICIT_CTOR, /**< create implicit class constructor */
VM_OC_INIT_CLASS, /**< initialize class */
VM_OC_FINALIZE_CLASS, /**< finalize class */
VM_OC_SET_CLASS_FIELD_INIT, /**< store the class field initializer function */
VM_OC_RUN_CLASS_FIELD_INIT, /**< run the class field initializer function */
VM_OC_SET_FIELD_INIT, /**< store the class field initializer function */
VM_OC_SET_STATIC_FIELD_INIT, /**< store the static class field initializer function */
VM_OC_RUN_FIELD_INIT, /**< run the class field initializer function */
VM_OC_RUN_STATIC_FIELD_INIT, /**< run the static class field initializer function */
VM_OC_SET_NEXT_COMPUTED_FIELD, /**< set the next computed field of a class */
VM_OC_PUSH_SUPER_CONSTRUCTOR, /**< getSuperConstructor operation */
VM_OC_RESOLVE_LEXICAL_THIS, /**< resolve this_binding from from the lexical environment */
@@ -294,6 +296,7 @@ typedef enum
VM_OC_REQUIRE_OBJECT_COERCIBLE,/**< RequireObjectCoercible opretaion */
VM_OC_ASSIGN_SUPER, /**< assign super reference */
VM_OC_SET__PROTO__, /**< set prototype when __proto__: form is used */
VM_OC_PUSH_STATIC_FIELD_FUNC, /**< push static field initializer function */
VM_OC_ADD_COMPUTED_FIELD, /**< add computed field name */
#endif /* ENABLED (JERRY_ESNEXT) */
VM_OC_NONE, /**< a special opcode for unsupported byte codes */
@@ -342,8 +345,10 @@ typedef enum
VM_OC_PUSH_IMPLICIT_CTOR = VM_OC_NONE, /**< create implicit class constructor */
VM_OC_INIT_CLASS = VM_OC_NONE, /**< initialize class */
VM_OC_FINALIZE_CLASS = VM_OC_NONE, /**< finalize class */
VM_OC_SET_CLASS_FIELD_INIT = VM_OC_NONE, /**< store the class field initializer function */
VM_OC_RUN_CLASS_FIELD_INIT = VM_OC_NONE, /**< run the class field initializer function */
VM_OC_SET_FIELD_INIT = VM_OC_NONE, /**< store the class field initializer function */
VM_OC_SET_STATIC_FIELD_INIT = VM_OC_NONE, /**< store the static class field initializer function */
VM_OC_RUN_FIELD_INIT = VM_OC_NONE, /**< run the class field initializer function */
VM_OC_RUN_STATIC_FIELD_INIT = VM_OC_NONE, /**< run the static class field initializer function */
VM_OC_SET_NEXT_COMPUTED_FIELD = VM_OC_NONE, /**< set the next computed field of a class */
VM_OC_PUSH_SUPER_CONSTRUCTOR = VM_OC_NONE, /**< getSuperConstructor operation */
VM_OC_RESOLVE_LEXICAL_THIS = VM_OC_NONE, /**< resolve this_binding from from the lexical environment */
@@ -376,6 +381,7 @@ typedef enum
VM_OC_REQUIRE_OBJECT_COERCIBLE = VM_OC_NONE,/**< RequireObjectCoercible opretaion */
VM_OC_ASSIGN_SUPER = VM_OC_NONE, /**< assign super reference */
VM_OC_SET__PROTO__ = VM_OC_NONE, /**< set prototype when __proto__: form is used */
VM_OC_PUSH_STATIC_FIELD_FUNC = VM_OC_NONE, /**< push static field initializer function */
VM_OC_ADD_COMPUTED_FIELD = VM_OC_NONE, /**< add computed field name */
#endif /* !ENABLED (JERRY_ESNEXT) */