From ff2609eb88968b01917c4d737149b02c42c5aaa4 Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Fri, 25 Jul 2014 18:07:18 +0400 Subject: [PATCH] Implementing {pre,post}_{incr,decr} opcodes. --- src/libcoreint/opcodes.c | 204 +++++++++++++++++++++++++++++- src/libecmaobjects/ecma-globals.h | 10 ++ 2 files changed, 210 insertions(+), 4 deletions(-) diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index e60762bf4..feedc7fd0 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -374,10 +374,6 @@ do_number_arithmetic(struct __int_data *int_data, /**< interpreter context */ op(b_not) \ op(instanceof) \ op(in) \ - op(post_incr) \ - op(post_decr) \ - op(pre_incr) \ - op(pre_decr) \ static char __unused unimplemented_list_end #define DEFINE_UNIMPLEMENTED_OP(op) \ @@ -876,6 +872,206 @@ opfunc_remainder(OPCODE opdata, /**< operation data */ return ret_value; } /* opfunc_remainder */ +/** + * 'Pre increment' opcode handler. + * + * See also: ECMA-262 v5, 11.4.4 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_pre_incr(OPCODE opdata, /**< operation data */ + struct __int_data *int_data) /**< interpreter context */ +{ + const T_IDX dst_var_idx = opdata.data.pre_incr.dst; + const T_IDX incr_var_idx = opdata.data.pre_incr.var_right; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + // 1., 2., 3. + ECMA_TRY_CATCH(old_value, get_variable_value( int_data, incr_var_idx, true), ret_value); + ECMA_TRY_CATCH(old_num_value, ecma_op_to_number( old_value.value), ret_value); + + // 4. + ecma_number_t* new_num_p = ecma_alloc_number(); + + ecma_number_t* old_num_p = (ecma_number_t*)ecma_get_pointer( old_num_value.value.value); + *new_num_p= ecma_op_number_add (*old_num_p, ECMA_NUMBER_ONE); + + ecma_value_t new_num_value = ecma_make_number_value( new_num_p); + + // 5. + ret_value = set_variable_value (int_data, + incr_var_idx, + new_num_value); + + // assignment of operator result to register variable + ecma_completion_value_t reg_assignment_res = set_variable_value (int_data, + dst_var_idx, + new_num_value); + JERRY_ASSERT( ecma_is_completion_value_normal_simple_value (reg_assignment_res, + ECMA_SIMPLE_VALUE_EMPTY) ); + + ecma_dealloc_number( new_num_p); + + ECMA_FINALIZE(old_num_value); + ECMA_FINALIZE(old_value); + + return ret_value; +} /* opfunc_pre_incr */ + +/** + * 'Pre decrement' opcode handler. + * + * See also: ECMA-262 v5, 11.4.4 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_pre_decr(OPCODE opdata, /**< operation data */ + struct __int_data *int_data) /**< interpreter context */ +{ + const T_IDX dst_var_idx = opdata.data.pre_decr.dst; + const T_IDX decr_var_idx = opdata.data.pre_decr.var_right; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + // 1., 2., 3. + ECMA_TRY_CATCH(old_value, get_variable_value( int_data, decr_var_idx, true), ret_value); + ECMA_TRY_CATCH(old_num_value, ecma_op_to_number( old_value.value), ret_value); + + // 4. + ecma_number_t* new_num_p = ecma_alloc_number(); + + ecma_number_t* old_num_p = (ecma_number_t*)ecma_get_pointer( old_num_value.value.value); + *new_num_p= ecma_op_number_substract (*old_num_p, ECMA_NUMBER_ONE); + + ecma_value_t new_num_value = ecma_make_number_value( new_num_p); + + // 5. + ret_value = set_variable_value (int_data, + decr_var_idx, + new_num_value); + + // assignment of operator result to register variable + ecma_completion_value_t reg_assignment_res = set_variable_value (int_data, + dst_var_idx, + new_num_value); + JERRY_ASSERT( ecma_is_completion_value_normal_simple_value (reg_assignment_res, + ECMA_SIMPLE_VALUE_EMPTY) ); + + ecma_dealloc_number( new_num_p); + + ECMA_FINALIZE(old_num_value); + ECMA_FINALIZE(old_value); + + return ret_value; +} /* opfunc_pre_decr */ + +/** + * 'Post increment' opcode handler. + * + * See also: ECMA-262 v5, 11.3.1 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_post_incr(OPCODE opdata, /**< operation data */ + struct __int_data *int_data) /**< interpreter context */ +{ + const T_IDX dst_var_idx = opdata.data.post_incr.dst; + const T_IDX incr_var_idx = opdata.data.post_incr.var_right; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + // 1., 2., 3. + ECMA_TRY_CATCH(old_value, get_variable_value( int_data, incr_var_idx, true), ret_value); + ECMA_TRY_CATCH(old_num_value, ecma_op_to_number( old_value.value), ret_value); + + // 4. + ecma_number_t* new_num_p = ecma_alloc_number(); + + ecma_number_t* old_num_p = (ecma_number_t*)ecma_get_pointer( old_num_value.value.value); + *new_num_p= ecma_op_number_add (*old_num_p, ECMA_NUMBER_ONE); + + // 5. + ret_value = set_variable_value (int_data, + incr_var_idx, + ecma_make_number_value( new_num_p)); + + ecma_dealloc_number( new_num_p); + + // assignment of operator result to register variable + ecma_completion_value_t reg_assignment_res = set_variable_value (int_data, + dst_var_idx, + old_value.value); + JERRY_ASSERT( ecma_is_completion_value_normal_simple_value (reg_assignment_res, + ECMA_SIMPLE_VALUE_EMPTY) ); + + ECMA_FINALIZE(old_num_value); + ECMA_FINALIZE(old_value); + + return ret_value; +} /* opfunc_post_incr */ + +/** + * 'Post decrement' opcode handler. + * + * See also: ECMA-262 v5, 11.3.2 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_post_decr(OPCODE opdata, /**< operation data */ + struct __int_data *int_data) /**< interpreter context */ +{ + const T_IDX dst_var_idx = opdata.data.post_decr.dst; + const T_IDX decr_var_idx = opdata.data.post_decr.var_right; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + // 1., 2., 3. + ECMA_TRY_CATCH(old_value, get_variable_value( int_data, decr_var_idx, true), ret_value); + ECMA_TRY_CATCH(old_num_value, ecma_op_to_number( old_value.value), ret_value); + + // 4. + ecma_number_t* new_num_p = ecma_alloc_number(); + + ecma_number_t* old_num_p = (ecma_number_t*)ecma_get_pointer( old_num_value.value.value); + *new_num_p= ecma_op_number_substract (*old_num_p, ECMA_NUMBER_ONE); + + // 5. + ret_value = set_variable_value (int_data, + decr_var_idx, + ecma_make_number_value( new_num_p)); + + ecma_dealloc_number( new_num_p); + + // assignment of operator result to register variable + ecma_completion_value_t reg_assignment_res = set_variable_value (int_data, + dst_var_idx, + old_value.value); + JERRY_ASSERT( ecma_is_completion_value_normal_simple_value (reg_assignment_res, + ECMA_SIMPLE_VALUE_EMPTY) ); + + ECMA_FINALIZE(old_num_value); + ECMA_FINALIZE(old_value); + + return ret_value; +} /* opfunc_post_decr */ + /** * 'Equals' opcode handler. * diff --git a/src/libecmaobjects/ecma-globals.h b/src/libecmaobjects/ecma-globals.h index 39611a2e3..5ac352f6c 100644 --- a/src/libecmaobjects/ecma-globals.h +++ b/src/libecmaobjects/ecma-globals.h @@ -334,6 +334,16 @@ typedef uint8_t ecma_char_t; */ typedef float ecma_number_t; +/** + * Value '0' of ecma_number_t + */ +#define ECMA_NUMBER_ZERO ((ecma_number_t) 0) + +/** + * Value '1' of ecma_number_t + */ +#define ECMA_NUMBER_ONE ((ecma_number_t) 1) + /** * Description of arrays'/strings' length */