Implementing 'func_decl_n' and 'func_call_n' opcodes' handlers.
This commit is contained in:
+174
-2
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user