Splitting 'delete' opcode to 'delete_var' and 'delete_prop'. Implementing corresponding opcode handlers.

This commit is contained in:
Ruben Ayrapetyan
2014-08-27 17:12:59 +04:00
parent 05185bb2e9
commit 76121926d1
5 changed files with 131 additions and 5 deletions
+119 -1
View File
@@ -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.
*
+2 -1
View File
@@ -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)
+2 -1
View File
@@ -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));
}
+6 -1
View File
@@ -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))
+2 -1
View File
@@ -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, "", "")