From 76121926d189a119ecf75eef8c9ade54334ccc99 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Wed, 27 Aug 2014 17:12:59 +0400 Subject: [PATCH] Splitting 'delete' opcode to 'delete_var' and 'delete_prop'. Implementing corresponding opcode handlers. --- src/libcoreint/opcodes.c | 120 +++++++++++++++++++++++- src/libcoreint/opcodes.h | 3 +- src/libecmaoperations/ecma-conversion.c | 3 +- src/libjsparser/parser.c | 7 +- src/liboptimizer/pretty-printer.c | 3 +- 5 files changed, 131 insertions(+), 5 deletions(-) diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index d5d1a90b1..a2e7fbfe6 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -50,7 +50,6 @@ op (prop_get_decl) \ op (prop_set_decl) \ op (obj_decl) \ - op (delete) \ op (with) \ op (end_with) \ static char __unused unimplemented_list_end @@ -1367,6 +1366,125 @@ opfunc_typeof (opcode_t opdata, /**< operation data */ return ret_value; } /* opfunc_typeof */ +/** + * 'delete' opcode handler. + * + * See also: ECMA-262 v5, 11.4.1 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_delete_var (opcode_t opdata, /**< operation data */ + int_data_t *int_data) /**< interpreter context */ +{ + const idx_t dst_var_idx = opdata.data.delete_var.lhs; + const idx_t name_var_idx = opdata.data.delete_var.name; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH (name_value, get_variable_value (int_data, name_var_idx, false), ret_value); + JERRY_ASSERT (name_value.value.value_type == ECMA_TYPE_STRING); + ecma_string_t *name_string_p = ECMA_GET_POINTER (name_value.value.value); + + ecma_reference_t ref = ecma_op_get_identifier_reference (int_data->lex_env_p, + name_string_p, + int_data->is_strict); + + if (ref.is_strict) + { + ret_value = ecma_make_throw_value (ecma_new_standard_error (ECMA_ERROR_SYNTAX)); + } + else if (ecma_is_value_undefined (ref.base)) + { + ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); + } + else + { + JERRY_ASSERT (ref.base.value_type == ECMA_TYPE_OBJECT); + ecma_object_t *bindings_p = ECMA_GET_POINTER (ref.base.value); + JERRY_ASSERT (bindings_p->is_lexical_environment); + + ecma_completion_value_t completion = ecma_op_delete_binding (bindings_p, ref.referenced_name_p); + + ret_value = set_variable_value (int_data, dst_var_idx, completion.value); + } + + ecma_free_reference (ref); + + ECMA_FINALIZE (name_value); + + return ret_value; +} /* opfunc_delete_var */ + + +/** + * 'delete' opcode handler. + * + * See also: ECMA-262 v5, 11.4.1 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_delete_prop (opcode_t opdata, /**< operation data */ + int_data_t *int_data) /**< interpreter context */ +{ + const idx_t dst_var_idx = opdata.data.delete_prop.lhs; + const idx_t base_var_idx = opdata.data.delete_prop.base; + const idx_t name_var_idx = opdata.data.delete_prop.name; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH (base_value, get_variable_value (int_data, base_var_idx, false), ret_value); + ECMA_TRY_CATCH (name_value, get_variable_value (int_data, name_var_idx, false), ret_value); + ECMA_TRY_CATCH (check_coercible_ret, ecma_op_check_object_coercible (base_value.value), ret_value); + ECMA_TRY_CATCH (str_name_value, ecma_op_to_string (name_value.value), ret_value); + + JERRY_ASSERT (name_value.value.value_type == ECMA_TYPE_STRING); + ecma_string_t *name_string_p = ECMA_GET_POINTER (name_value.value.value); + + if (ecma_is_value_undefined (base_value.value)) + { + if (int_data->is_strict) + { + ret_value = ecma_make_throw_value (ecma_new_standard_error (ECMA_ERROR_SYNTAX)); + } + else + { + ret_value = ecma_make_simple_completion_value (ECMA_SIMPLE_VALUE_TRUE); + } + } + else + { + ECMA_TRY_CATCH (obj_value, ecma_op_to_object (base_value.value), ret_value); + + JERRY_ASSERT (obj_value.value.value_type == ECMA_TYPE_OBJECT); + ecma_object_t *obj_p = ECMA_GET_POINTER (obj_value.value.value); + JERRY_ASSERT (!obj_p->is_lexical_environment); + + ECMA_TRY_CATCH (delete_op_completion, + ecma_op_object_delete (obj_p, name_string_p, int_data->is_strict), + ret_value); + + ret_value = set_variable_value (int_data, dst_var_idx, delete_op_completion.value); + + ECMA_FINALIZE (delete_op_completion); + ECMA_FINALIZE (obj_value); + } + + ECMA_FINALIZE (str_name_value); + ECMA_FINALIZE (check_coercible_ret); + ECMA_FINALIZE (name_value); + ECMA_FINALIZE (base_value); + + return ret_value; +} /* opfunc_delete_prop */ + /** * 'meta' opcode handler. * diff --git a/src/libcoreint/opcodes.h b/src/libcoreint/opcodes.h index 08077808b..bb6cef5b0 100644 --- a/src/libcoreint/opcodes.h +++ b/src/libcoreint/opcodes.h @@ -92,7 +92,8 @@ typedef struct 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, lhs, obj) \ + p##_2 (a, delete_var, lhs, name) \ + p##_3 (a, delete_prop, lhs, base, name) \ p##_2 (a, typeof, lhs, obj) \ p##_1 (a, with, expr) \ p##_0 (a, end_with) diff --git a/src/libecmaoperations/ecma-conversion.c b/src/libecmaoperations/ecma-conversion.c index 9105d9dde..229d8df3e 100644 --- a/src/libecmaoperations/ecma-conversion.c +++ b/src/libecmaoperations/ecma-conversion.c @@ -47,7 +47,8 @@ ecma_op_check_object_coercible (ecma_value_t value) /**< ecma-value */ { case ECMA_TYPE_SIMPLE: { - if (ecma_is_value_undefined (value)) + if (ecma_is_value_undefined (value) + || ecma_is_value_null (value)) { return ecma_make_throw_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); } diff --git a/src/libjsparser/parser.c b/src/libjsparser/parser.c index 011822061..ed4735c8c 100644 --- a/src/libjsparser/parser.c +++ b/src/libjsparser/parser.c @@ -1331,7 +1331,12 @@ parse_unary_expression (void) { lhs = next_temp_name (); NEXT (expr, unary_expression); - DUMP_OPCODE_2 (delete, lhs, expr); + TODO (/* lhs = delete_var for delete, applied to expression, that is evaluating to Identifier; + lhs = delete_prop for 'delete expr[expr]'; + lhs = true - otherwise; */); + + // DUMP_OPCODE_2 (delete, lhs, expr); + JERRY_UNIMPLEMENTED (); return lhs; } if (is_keyword (KW_VOID)) diff --git a/src/liboptimizer/pretty-printer.c b/src/liboptimizer/pretty-printer.c index 6fbf3da1c..70c5cc646 100644 --- a/src/liboptimizer/pretty-printer.c +++ b/src/liboptimizer/pretty-printer.c @@ -427,7 +427,8 @@ pp_opcode (opcode_counter_t oc, opcode_t opcode, bool is_rewrite) 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, lhs, "=", "delete", obj) + CASE_DOUBLE_ADDRESS (delete_var, lhs, "=", "delete", name) + CASE_TRIPLE_ADDRESS (delete_prop, lhs, "= delete", base, ".", name) CASE_DOUBLE_ADDRESS (typeof, lhs, "=", "typeof", obj) CASE_WITH (with, expr) CASE_VARG_0_NAME (var_decl, "var", variable_name, "", "")