From f08c242156342a70b9256959c9020e713a8514e0 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Wed, 27 Aug 2014 20:43:31 +0400 Subject: [PATCH] Implementing 'obj_decl' opcode; replacing 'prop', 'prop_get_decl', 'prop_set_decl' with 'meta' opcodes of corresponding types. --- src/libcoreint/opcodes-ecma-support.h | 1 + src/libcoreint/opcodes.c | 158 +++++++++++++++++++++++++- src/libcoreint/opcodes.h | 10 +- src/libjsparser/parser.c | 18 ++- src/liboptimizer/pretty-printer.c | 3 - 5 files changed, 175 insertions(+), 15 deletions(-) diff --git a/src/libcoreint/opcodes-ecma-support.h b/src/libcoreint/opcodes-ecma-support.h index 495a27019..48ed859f1 100644 --- a/src/libcoreint/opcodes-ecma-support.h +++ b/src/libcoreint/opcodes-ecma-support.h @@ -29,6 +29,7 @@ #include "ecma-operations.h" #include "ecma-try-catch-macro.h" #include "ecma-objects.h" +#include "ecma-objects-general.h" bool is_reg_variable (int_data_t *int_data, idx_t var_idx); ecma_completion_value_t get_variable_value (int_data_t *, idx_t, bool); diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index ede4ed8b2..cf8f58ced 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -45,10 +45,6 @@ */ #define OP_UNIMPLEMENTED_LIST(op) \ - op (prop) \ - op (prop_get_decl) \ - op (prop_set_decl) \ - op (obj_decl) \ op (with) \ op (end_with) \ static char __unused unimplemented_list_end @@ -941,6 +937,157 @@ opfunc_array_decl (opcode_t opdata, /**< operation data */ return ret_value; } /* opfunc_array_decl */ +/** + * 'Object initializer' opcode handler. + * + * See also: ECMA-262 v5, 11.1.5 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value. + */ +ecma_completion_value_t +opfunc_obj_decl (opcode_t opdata, /**< operation data */ + int_data_t *int_data) /**< interpreter context */ +{ + const idx_t lhs_var_idx = opdata.data.obj_decl.lhs; + const idx_t args_number = opdata.data.obj_decl.list; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ecma_completion_value_t completion = ecma_make_empty_completion_value (); + ecma_object_t *obj_p = ecma_op_create_object_object_noarg (); + + for (uint32_t prop_index = 0; + prop_index < args_number; + prop_index++) + { + ecma_completion_value_t evaluate_prop_completion = run_int_loop (int_data); + + if (evaluate_prop_completion.type == ECMA_COMPLETION_TYPE_META) + { + opcode_t next_opcode = read_opcode (int_data->pos); + JERRY_ASSERT (next_opcode.op_idx == __op__idx_meta); + + const opcode_meta_type type = next_opcode.data.meta.type; + JERRY_ASSERT (type == OPCODE_META_TYPE_VARG_PROP_DATA + || type == OPCODE_META_TYPE_VARG_PROP_GETTER + || type == OPCODE_META_TYPE_VARG_PROP_SETTER); + + const idx_t prop_name_lit_idx = next_opcode.data.meta.data_1; + const idx_t value_for_prop_desc_var_idx = next_opcode.data.meta.data_2; + + ecma_completion_value_t value_for_prop_desc = get_variable_value (int_data, + value_for_prop_desc_var_idx, + false); + + if (ecma_is_completion_value_normal (value_for_prop_desc)) + { + bool is_throw_syntax_error = false; + + ecma_string_t *prop_name_string_p = ecma_new_ecma_string_from_lit_index (prop_name_lit_idx); + ecma_property_t *previous_p = ecma_op_object_get_own_property (obj_p, prop_name_string_p); + + const bool is_previous_data_desc = (previous_p->type == ECMA_PROPERTY_NAMEDDATA); + const bool is_previous_accessor_desc = (previous_p->type == ECMA_PROPERTY_NAMEDACCESSOR); + JERRY_ASSERT (is_previous_data_desc || is_previous_accessor_desc); + + ecma_property_descriptor_t prop_desc = ecma_make_empty_property_descriptor (); + { + prop_desc.is_enumerable_defined = true; + prop_desc.enumerable = ECMA_PROPERTY_ENUMERABLE; + + prop_desc.is_configurable_defined = true; + prop_desc.configurable = ECMA_PROPERTY_CONFIGURABLE; + } + + if (type == OPCODE_META_TYPE_VARG_PROP_DATA) + { + prop_desc.is_value_defined = true; + prop_desc.value = value_for_prop_desc.value; + + prop_desc.is_writable_defined = true; + prop_desc.writable = ECMA_PROPERTY_WRITABLE; + + if ((is_previous_data_desc + && int_data->is_strict) + || is_previous_accessor_desc) + { + is_throw_syntax_error = true; + } + } + else if (type == OPCODE_META_TYPE_VARG_PROP_GETTER) + { + JERRY_ASSERT (value_for_prop_desc.value.value_type == ECMA_TYPE_OBJECT); + + prop_desc.is_get_defined = true; + prop_desc.get_p = ECMA_GET_POINTER (value_for_prop_desc.value.value); + + if (is_previous_data_desc) + { + is_throw_syntax_error = true; + } + } + else + { + JERRY_ASSERT (value_for_prop_desc.value.value_type == ECMA_TYPE_OBJECT); + + prop_desc.is_set_defined = true; + prop_desc.set_p = ECMA_GET_POINTER (value_for_prop_desc.value.value); + + if (is_previous_data_desc) + { + is_throw_syntax_error = true; + } + } + + /* The SyntaxError should be treated as an early error */ + JERRY_ASSERT (!is_throw_syntax_error); + + ecma_completion_value_t define_prop_completion = ecma_op_object_define_own_property (obj_p, + prop_name_string_p, + prop_desc, + false); + JERRY_ASSERT (ecma_is_completion_value_normal_true (define_prop_completion) + || ecma_is_completion_value_normal_false (define_prop_completion)); + + ecma_deref_ecma_string (prop_name_string_p); + + ecma_free_completion_value (value_for_prop_desc); + } + else + { + completion = value_for_prop_desc; + + break; + } + + int_data->pos++; + } + else + { + JERRY_ASSERT (!ecma_is_completion_value_normal (evaluate_prop_completion)); + + completion = evaluate_prop_completion; + + break; + } + } + + if (ecma_is_empty_completion_value (completion)) + { + ret_value = set_variable_value (int_data, lhs_var_idx, ecma_make_object_value (obj_p)); + } + else + { + ret_value = completion; + } + + ecma_deref_object (obj_p); + + return ret_value; +} /* opfunc_obj_decl */ /** * 'Return with no expression' opcode handler. * @@ -1541,6 +1688,9 @@ opfunc_meta (opcode_t opdata, /**< operation data */ ECMA_TARGET_ID_RESERVED); } case OPCODE_META_TYPE_THIS_ARG: + case OPCODE_META_TYPE_VARG_PROP_DATA: + case OPCODE_META_TYPE_VARG_PROP_GETTER: + case OPCODE_META_TYPE_VARG_PROP_SETTER: { JERRY_UNREACHABLE (); } diff --git a/src/libcoreint/opcodes.h b/src/libcoreint/opcodes.h index aa2ddc7a4..62f0412ee 100644 --- a/src/libcoreint/opcodes.h +++ b/src/libcoreint/opcodes.h @@ -52,8 +52,11 @@ typedef enum */ typedef enum { - OPCODE_META_TYPE_THIS_ARG, /**< value of this used during call */ - OPCODE_META_TYPE_VARG /**< element of arguments' list */ + OPCODE_META_TYPE_THIS_ARG, /**< value (var_idx) of this used during call */ + OPCODE_META_TYPE_VARG, /**< element (var_idx) of arguments' list */ + OPCODE_META_TYPE_VARG_PROP_DATA, /**< name (lit_idx) and value (var_idx) for a data property descriptor */ + OPCODE_META_TYPE_VARG_PROP_GETTER, /**< name (lit_idx) and getter (var_idx) for an accessor property descriptor */ + OPCODE_META_TYPE_VARG_PROP_SETTER /**< name (lit_idx) and setter (var_idx) for an accessor property descriptor */ } opcode_meta_type; typedef struct @@ -85,11 +88,8 @@ typedef struct #define OP_INITS(p, a) \ p##_2 (a, array_decl, lhs, list) \ - p##_3 (a, prop, lhs, name, value) \ p##_3 (a, prop_getter, lhs, obj, prop) \ p##_3 (a, prop_setter, obj, prop, rhs) \ - p##_2 (a, prop_get_decl, lhs, prop) \ - p##_3 (a, prop_set_decl, lhs, prop, arg) \ p##_2 (a, obj_decl, lhs, list) \ p##_1 (a, this, lhs) \ p##_2 (a, delete_var, lhs, name) \ diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index ed4735c8c..d22bd8115 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -460,7 +460,11 @@ parse_property_name_and_value (void) token_after_newlines_must_be (TOK_COLON); NEXT (value, assignment_expression); - DUMP_OPCODE_3 (prop, lhs, name, value); + TODO (Change to dumping meta opcode); + // DUMP_OPCODE_3 (prop, lhs, name, value); + // to + // DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_VARG_PROP_DATA, name, value); + JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (name, value); return lhs; } @@ -487,7 +491,11 @@ parse_property_assignment (void) token_after_newlines_must_be (TOK_CLOSE_PAREN); token_after_newlines_must_be (TOK_OPEN_BRACE); - DUMP_OPCODE_2 (prop_get_decl, lhs, name); + TODO (Change to dumping meta opcode); + // DUMP_OPCODE_2 (prop_get_decl, lhs, name); + // to + // DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_VARG_PROP_GETTER, name, result_of_func_expression); + JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (name); skip_newlines (); parse_source_element_list (); @@ -507,7 +515,11 @@ parse_property_assignment (void) token_after_newlines_must_be (TOK_CLOSE_PAREN); token_after_newlines_must_be (TOK_OPEN_BRACE); - DUMP_OPCODE_3 (prop_set_decl, lhs, name, arg); + TODO (Change to dumping meta opcode); + // DUMP_OPCODE_3 (prop_set_decl, lhs, name, arg); + // to + // DUMP_OPCODE_3 (meta, OPCODE_META_TYPE_VARG_PROP_SETTER, name, result_of_func_expression); + JERRY_UNIMPLEMENTED_REF_UNUSED_VARS (name, arg); skip_newlines (); parse_source_element_list (); diff --git a/src/liboptimizer/pretty-printer.c b/src/liboptimizer/pretty-printer.c index f90672544..97b840e15 100644 --- a/src/liboptimizer/pretty-printer.c +++ b/src/liboptimizer/pretty-printer.c @@ -421,10 +421,7 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite) CASE_VARG_1_LHS (array_decl, lhs, "=", "[", list, "]") TODO (Refine to match new opcodes) CASE_VARG_0_LHS (obj_decl, lhs, "=", "{", "}") - CASE_TRIPLE_ADDRESS (prop, lhs, "=", name, ":", value) CASE_VARG_1_NAME_LHS (prop_getter, lhs, "=", "", obj, "[", prop, "]") - CASE_VARG_0_NAME_LHS (prop_get_decl, lhs, "=", "get", prop, "[", "]") - CASE_VARG_1_NAME_LHS (prop_set_decl, lhs, "=", "set", prop, "[", arg, "]") CASE_THIS (this, lhs, "=", "this") CASE_DOUBLE_ADDRESS (delete_var, lhs, "=", "delete", name) CASE_TRIPLE_ADDRESS (delete_prop, lhs, "= delete", base, ".", name)