From 284e7fc91b147f3bce6f570d3d37d5c4071b21ce Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Wed, 20 Aug 2014 16:33:33 +0400 Subject: [PATCH] Renaming prop_access opcode to prop_getter; introducing prop_setter opcode; implementing property getter/setter opcode handlers. --- src/libcoreint/opcode-structures.h | 8 ++- src/libcoreint/opcodes.c | 80 +++++++++++++++++++++++++- src/libcoreint/opcodes.h | 3 +- src/libecmaoperations/ecma-reference.c | 2 +- src/libecmaoperations/ecma-reference.h | 2 +- src/libjsparser/parser.c | 6 +- src/liboptimizer/pretty-printer.c | 4 +- 7 files changed, 95 insertions(+), 10 deletions(-) diff --git a/src/libcoreint/opcode-structures.h b/src/libcoreint/opcode-structures.h index b94bc3fae..0e0b29905 100644 --- a/src/libcoreint/opcode-structures.h +++ b/src/libcoreint/opcode-structures.h @@ -422,11 +422,17 @@ OP_CODE_DECL (prop, T_IDX_IDX_IDX, value) /** a = b.c OR a = b[c] */ -OP_CODE_DECL (prop_access, T_IDX_IDX_IDX, +OP_CODE_DECL (prop_getter, T_IDX_IDX_IDX, lhs, obj, prop) +/** a.b = c OR a[b] = c */ +OP_CODE_DECL (prop_setter, T_IDX_IDX_IDX, + obj, + prop, + rhs) + /** a = get prop () */ OP_CODE_DECL (prop_get_decl, T_IDX_IDX, lhs, diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index 6659035e0..84ea00ee2 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -450,7 +450,6 @@ do_number_bitwise_logic (struct __int_data *int_data, /**< interpreter context * op (array_2) \ op (array_n) \ op (prop) \ - op (prop_access) \ op (prop_get_decl) \ op (prop_set_decl) \ op (obj_0) \ @@ -1907,6 +1906,82 @@ opfunc_ret (OPCODE opdata __unused, /**< operation data */ ECMA_TARGET_ID_RESERVED); } /* opfunc_ret */ +/** + * 'Property getter' opcode handler. + * + * See also: ECMA-262 v5, 11.2.1 + * + * @return completion value + * returned value must be freed with ecma_free_completion_value. + */ +ecma_completion_value_t +opfunc_prop_getter (OPCODE opdata __unused, /**< operation data */ + struct __int_data *int_data __unused) /**< interpreter context */ +{ + const T_IDX lhs_var_idx = opdata.data.prop_getter.lhs; + const T_IDX base_var_idx = opdata.data.prop_getter.obj; + const T_IDX prop_lit_idx = opdata.data.prop_getter.prop; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH (base_value, get_variable_value (int_data, base_var_idx, false), ret_value); + + ecma_string_t *prop_name_string_p = ecma_new_ecma_string_from_lit_index (prop_lit_idx); + ecma_reference_t ref = ecma_make_reference (base_value.value, + prop_name_string_p, + int_data->is_strict); + ecma_deref_ecma_string (prop_name_string_p); + + ECMA_TRY_CATCH (prop_value, ecma_op_get_value (ref), ret_value); + + ret_value = set_variable_value (int_data, lhs_var_idx, prop_value.value); + + ECMA_FINALIZE (prop_value); + + ecma_free_reference (ref); + + ECMA_FINALIZE (base_value); + + return ret_value; +} /* opfunc_prop_getter */ + +/** + * 'Property setter' opcode handler. + * + * See also: ECMA-262 v5, 11.2.1 + * + * @return completion value + * returned value must be freed with ecma_free_completion_value. + */ +ecma_completion_value_t +opfunc_prop_setter (OPCODE opdata __unused, /**< operation data */ + struct __int_data *int_data __unused) /**< interpreter context */ +{ + const T_IDX base_var_idx = opdata.data.prop_setter.obj; + const T_IDX prop_lit_idx = opdata.data.prop_setter.prop; + const T_IDX rhs_var_idx = opdata.data.prop_setter.rhs; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH (rhs_value, get_variable_value (int_data, rhs_var_idx, false), ret_value); + ECMA_TRY_CATCH (base_value, get_variable_value (int_data, base_var_idx, false), ret_value); + + ecma_string_t *prop_name_string_p = ecma_new_ecma_string_from_lit_index (prop_lit_idx); + ecma_reference_t ref = ecma_make_reference (base_value.value, + prop_name_string_p, + int_data->is_strict); + ecma_deref_ecma_string (prop_name_string_p); + + ret_value = ecma_op_put_value (ref, rhs_value.value); + + ecma_free_reference (ref); + + ECMA_FINALIZE (base_value); + ECMA_FINALIZE (rhs_value); + + return ret_value; +} /* opfunc_prop_setter */ + /** * Exit from script with specified status code: * 0 - for successful completion @@ -1998,7 +2073,8 @@ GETOP_IMPL_2 (array_1, lhs, elem1) GETOP_IMPL_3 (array_2, lhs, elem1, elem2) GETOP_IMPL_3 (array_n, lhs, elem1, elem2) GETOP_IMPL_3 (prop, lhs, name, value) -GETOP_IMPL_3 (prop_access, lhs, obj, prop) +GETOP_IMPL_3 (prop_getter, lhs, obj, prop) +GETOP_IMPL_3 (prop_setter, obj, prop, rhs) GETOP_IMPL_2 (prop_get_decl, lhs, prop) GETOP_IMPL_3 (prop_set_decl, lhs, prop, arg) GETOP_IMPL_1 (obj_0, lhs) diff --git a/src/libcoreint/opcodes.h b/src/libcoreint/opcodes.h index 7e86a9c63..0d621722d 100644 --- a/src/libcoreint/opcodes.h +++ b/src/libcoreint/opcodes.h @@ -64,7 +64,8 @@ ecma_completion_value_t (*opfunc) (OPCODE, struct __int_data *); op (array_2) \ op (array_n) \ op (prop) \ - op (prop_access) \ + op (prop_getter) \ + op (prop_setter) \ op (prop_get_decl) \ op (prop_set_decl) \ op (obj_0) \ diff --git a/src/libecmaoperations/ecma-reference.c b/src/libecmaoperations/ecma-reference.c index d70125e11..e8590ac5c 100644 --- a/src/libecmaoperations/ecma-reference.c +++ b/src/libecmaoperations/ecma-reference.c @@ -98,7 +98,7 @@ ecma_make_reference (ecma_value_t base, /**< base value */ * freeing invalidates all copies of the reference. */ void -ecma_free_reference (const ecma_reference_t ref) /**< reference */ +ecma_free_reference (ecma_reference_t ref) /**< reference */ { ecma_free_value (ref.base, true); ecma_deref_ecma_string (ref.referenced_name_p); diff --git a/src/libecmaoperations/ecma-reference.h b/src/libecmaoperations/ecma-reference.h index ff14526a0..a9fff9da0 100644 --- a/src/libecmaoperations/ecma-reference.h +++ b/src/libecmaoperations/ecma-reference.h @@ -34,7 +34,7 @@ extern ecma_reference_t ecma_op_get_identifier_reference (ecma_object_t *lex_env extern ecma_reference_t ecma_make_reference (ecma_value_t base, ecma_string_t *name_p, bool is_strict); -extern void ecma_free_reference (const ecma_reference_t ref); +extern void ecma_free_reference (ecma_reference_t ref); /** * @} diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index 13497806d..94d9c8720 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -1133,7 +1133,7 @@ parse_member_expression (void) JERRY_UNREACHABLE (); } - DUMP_OPCODE_3 (prop_access, lhs, obj, prop); + DUMP_OPCODE_3 (prop_getter, lhs, obj, prop); obj = lhs; skip_newlines (); } @@ -1190,7 +1190,7 @@ parse_call_expression (void) NEXT (prop, expression); next_token_must_be (TOK_CLOSE_SQUARE); - DUMP_OPCODE_3 (prop_access, lhs, obj, prop); + DUMP_OPCODE_3 (prop_getter, lhs, obj, prop); obj = lhs; skip_newlines (); break; @@ -1200,7 +1200,7 @@ parse_call_expression (void) token_after_newlines_must_be (TOK_NAME); prop = tok.data.uid; - DUMP_OPCODE_3 (prop_access, lhs, obj, prop); + DUMP_OPCODE_3 (prop_getter, lhs, obj, prop); obj = lhs; skip_newlines (); break; diff --git a/src/liboptimizer/pretty-printer.c b/src/liboptimizer/pretty-printer.c index e1ca1837e..f900651a1 100644 --- a/src/liboptimizer/pretty-printer.c +++ b/src/liboptimizer/pretty-printer.c @@ -371,6 +371,8 @@ pp_opcode (opcode_counter_t oc, OPCODE opcode, bool is_rewrite) __printf (" // "); + TODO (Pretty print for prop_setter); + switch (opcode_num) { CASE_CONDITIONAL_JUMP (is_true_jmp, "if (", value, ") goto", opcode) @@ -441,7 +443,7 @@ pp_opcode (opcode_counter_t oc, OPCODE opcode, bool is_rewrite) CASE_VARG_2_LHS (obj_2, lhs, "=", "{", arg1, arg2, "}") CASE_VARG_N_LHS (obj_n, lhs, "=", "{", arg1, arg2, "}") CASE_TRIPLE_ADDRESS (prop, lhs, "=", name, ":", value) - CASE_VARG_1_NAME_LHS (prop_access, lhs, "=", "", obj, "[", prop, "]") + 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")