From 9573b7234dadba165c4d9910f031c6a944ba0475 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Tue, 26 Aug 2014 17:30:23 +0400 Subject: [PATCH] Implementing 'func_decl_n' and 'func_call_n' opcodes' handlers. --- src/libcoreint/opcodes.c | 176 ++++++++++++++++++++++++++++++++++++++- src/libcoreint/opcodes.h | 8 ++ 2 files changed, 182 insertions(+), 2 deletions(-) diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index acd8c3942..0180e7170 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -117,9 +117,7 @@ free_string_literal_copy (string_literal_copy *str_lit_descr_p) /**< string lite } /* free_string_literal */ #define OP_UNIMPLEMENTED_LIST(op) \ - op (call_n) \ op (native_call) \ - op (func_decl_n) \ op (func_expr_n) \ op (varg_list) \ op (construct_n) \ @@ -733,6 +731,63 @@ opfunc_func_decl_2 (opcode_t opdata, /**< operation data */ return ret_value; } /* opfunc_func_decl_2 */ +/** + * 'Function declaration' opcode handler. + * + * @return completion value + * returned value must be freed with ecma_free_completion_value. + */ +ecma_completion_value_t +opfunc_func_decl_n (opcode_t opdata, /**< operation data */ + int_data_t *int_data) /**< interpreter context */ +{ + int_data->pos++; + + const idx_t function_name_idx = opdata.data.func_decl_n.name_lit_idx; + const ecma_length_t args_number = opdata.data.func_decl_n.arg_list; + + ecma_string_t *arg_names[args_number + 1]; + + ecma_length_t arg_index = 0; + opcode_t next_opcode = read_opcode (int_data->pos); + while (next_opcode.op_idx == __op__idx_varg_list) + { + const idx_t arg1_lit_idx = next_opcode.data.varg_list.arg1_lit_idx; + const idx_t arg2_lit_idx = next_opcode.data.varg_list.arg2_lit_idx; + const idx_t arg3_lit_idx = next_opcode.data.varg_list.arg3_lit_idx; + + arg_names[arg_index++] = ecma_new_ecma_string_from_lit_index (arg1_lit_idx); + if (arg_index < args_number) + { + arg_names[arg_index++] = ecma_new_ecma_string_from_lit_index (arg2_lit_idx); + } + if (arg_index < args_number) + { + arg_names[arg_index++] = ecma_new_ecma_string_from_lit_index (arg3_lit_idx); + } + + JERRY_ASSERT (arg_index <= args_number); + + int_data->pos++; + next_opcode = read_opcode (int_data->pos); + } + JERRY_ASSERT (arg_index == args_number); + + ecma_completion_value_t ret_value = function_declaration (int_data, + function_name_idx, + arg_names, + args_number); + + for (arg_index = 0; + arg_index < args_number; + arg_index++) + { + ecma_deref_ecma_string (arg_names[arg_index]); + } + + return ret_value; +} /* opfunc_func_decl_n */ + /** * Function call with no arguments' opcode handler. * @@ -778,6 +833,123 @@ opfunc_call_0 (opcode_t opdata, /**< operation data */ return ret_value; } /* opfunc_call_0 */ +/** + * Function call' opcode handler. + * + * See also: ECMA-262 v5, 11.2.3 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value. + */ +ecma_completion_value_t +opfunc_call_n (opcode_t opdata, /**< operation data */ + int_data_t *int_data) /**< interpreter context */ +{ + const idx_t lhs_var_idx = opdata.data.call_n.lhs; + const idx_t func_name_lit_idx = opdata.data.call_n.name_lit_idx; + const idx_t args_number = opdata.data.call_n.arg_list; + + int_data->pos++; + + ecma_completion_value_t ret_value; + ecma_completion_value_t get_arg_completion = ecma_make_empty_completion_value (); + + ecma_value_t arg_values[args_number + 1]; + + ecma_length_t arg_index = 0; + opcode_t next_opcode = read_opcode (int_data->pos); + while (next_opcode.op_idx == __op__idx_varg_list + && ecma_is_completion_value_normal (get_arg_completion)) + { + const idx_t arg_lits[3] = + { + next_opcode.data.varg_list.arg1_lit_idx, + next_opcode.data.varg_list.arg2_lit_idx, + next_opcode.data.varg_list.arg3_lit_idx + }; + + ecma_length_t local_arg_index = 0; + + while (local_arg_index < 3 + && arg_index < args_number) + { + get_arg_completion = get_variable_value (int_data, arg_lits[local_arg_index++], false); + + if (unlikely (ecma_is_completion_value_throw (get_arg_completion))) + { + break; + } + else + { + JERRY_ASSERT (ecma_is_completion_value_normal (get_arg_completion)); + arg_values[arg_index++] = get_arg_completion.value; + } + } + + JERRY_ASSERT (arg_index <= args_number); + + int_data->pos++; + next_opcode = read_opcode (int_data->pos); + } + + JERRY_ASSERT (arg_index == args_number); + + ecma_completion_value_t this_value; + + if (next_opcode.op_idx == __op__idx_meta + && next_opcode.data.meta.type == OPCODE_META_TYPE_THIS_ARG) + { + const idx_t this_arg_var_idx = next_opcode.data.meta.data_1; + + JERRY_ASSERT (is_reg_variable (int_data, this_arg_var_idx)); + this_value = get_variable_value (int_data, this_arg_var_idx, false); + } + else + { + this_value = ecma_op_implicit_this_value (int_data->lex_env_p); + JERRY_ASSERT (ecma_is_completion_value_normal (this_value)); + } + + if (ecma_is_completion_value_normal (get_arg_completion)) + { + ECMA_TRY_CATCH (func_value, get_variable_value (int_data, func_name_lit_idx, false), ret_value); + + if (!ecma_op_is_callable (func_value.value)) + { + ret_value = ecma_make_throw_value (ecma_new_standard_error (ECMA_ERROR_TYPE)); + } + else + { + ecma_object_t *func_obj_p = ECMA_GET_POINTER (func_value.value.value); + + ECMA_FUNCTION_CALL (call_completion, + ecma_op_function_call (func_obj_p, this_value.value, arg_values, args_number), + ret_value); + + ret_value = set_variable_value (int_data, lhs_var_idx, call_completion.value); + + ECMA_FINALIZE (call_completion); + + ecma_free_completion_value (this_value); + } + + ECMA_FINALIZE (func_value); + } + else + { + ret_value = get_arg_completion; + } + + for (ecma_length_t arg_index = 0; + arg_index < args_number; + arg_index++) + { + ecma_free_value (arg_values[arg_index], true); + } + + return ret_value; +} /* opfunc_call_n */ + /** * 'Return with no expression' opcode handler. * diff --git a/src/libcoreint/opcodes.h b/src/libcoreint/opcodes.h index a05081399..00808310d 100644 --- a/src/libcoreint/opcodes.h +++ b/src/libcoreint/opcodes.h @@ -47,6 +47,14 @@ typedef enum OPCODE_ARG_TYPE_VARIABLE /**< index of variable name */ } opcode_arg_type_operand; +/** + * Types of data in 'meta' opcode. + */ +typedef enum +{ + OPCODE_META_TYPE_THIS_ARG /**< value of this used during call */ +} opcode_meta_type; + typedef struct { opcode_counter_t pos; /**< current opcode to execute */