From 7dea812364ac05002fa483c38e1ee7a550a94ea9 Mon Sep 17 00:00:00 2001 From: "e.gavrin" Date: Thu, 21 Aug 2014 21:38:50 +0400 Subject: [PATCH] Add shift opcodes handlers --- src/libcoreint/opcodes.c | 147 ++++++++++++++++-- src/libecmaobjects/ecma-helpers-conversion.c | 13 ++ src/libecmaobjects/ecma-helpers.h | 1 + ....function_return.js => function_return.js} | 0 tests/jerry/shift.js | 21 +++ 5 files changed, 169 insertions(+), 13 deletions(-) rename tests/jerry/{N.function_return.js => function_return.js} (100%) create mode 100644 tests/jerry/shift.js diff --git a/src/libcoreint/opcodes.c b/src/libcoreint/opcodes.c index c8d48ead1..9486fff51 100644 --- a/src/libcoreint/opcodes.c +++ b/src/libcoreint/opcodes.c @@ -288,6 +288,9 @@ typedef enum number_bitwise_logic_and, /**< bitwise AND calculation */ number_bitwise_logic_or, /**< bitwise OR calculation */ number_bitwise_logic_xor, /**< bitwise XOR calculation */ + number_bitwise_shift_left, /**< bitwise LEFT SHIFT calculation */ + number_bitwise_shift_right, /**< bitwise RIGHT_SHIFT calculation */ + number_bitwise_shift_uright, /**< bitwise UNSIGNED RIGHT SHIFT calculation */ } number_bitwise_logic_op; /** @@ -387,33 +390,48 @@ do_number_bitwise_logic (struct __int_data *int_data, /**< interpreter context * left_p = (ecma_number_t*) ECMA_GET_POINTER (num_left_value.value.value); right_p = (ecma_number_t*) ECMA_GET_POINTER (num_right_value.value.value); - uint32_t left_uint32, right_uint32, res = 0; + ecma_number_t* res_p = ecma_alloc_number (); - left_uint32 = ecma_number_to_uint32 (*left_p); - right_uint32 = ecma_number_to_uint32 (*right_p); + int32_t left_int32 = ecma_number_to_int32 (*left_p); + int32_t right_int32 = ecma_number_to_int32 (*right_p); + + uint32_t left_uint32 = ecma_number_to_uint32 (*left_p); + uint32_t right_uint32 = ecma_number_to_uint32 (*right_p); switch (op) { case number_bitwise_logic_and: { - res = left_uint32 & right_uint32; + *res_p = ecma_int32_to_number (left_int32 & right_int32); break; } case number_bitwise_logic_or: { - res = left_uint32 | right_uint32; + *res_p = ecma_int32_to_number (left_int32 | right_int32); break; } case number_bitwise_logic_xor: { - res = left_uint32 ^ right_uint32; + *res_p = ecma_int32_to_number (left_int32 ^ right_int32); + break; + } + case number_bitwise_shift_left: + { + *res_p = ecma_int32_to_number (left_int32 << (right_uint32 & 0x1F)); + break; + } + case number_bitwise_shift_right: + { + *res_p = ecma_int32_to_number (left_int32 >> (right_uint32 & 0x1F)); + break; + } + case number_bitwise_shift_uright: + { + *res_p = ecma_uint32_to_number (left_uint32 >> (right_uint32 & 0x1F)); break; } } - ecma_number_t* res_p = ecma_alloc_number (); - *res_p = ecma_uint32_to_number (res); - ret_value = set_variable_value (int_data, dst_var_idx, ecma_make_number_value (res_p)); @@ -446,9 +464,6 @@ do_number_bitwise_logic (struct __int_data *int_data, /**< interpreter context * op (logical_and) \ op (logical_or) \ op (b_not) \ - op (b_shift_left) \ - op (b_shift_right) \ - op (b_shift_uright) \ op (instanceof) \ op (in) \ op (meta) \ @@ -1114,6 +1129,111 @@ opfunc_b_xor (OPCODE opdata, /**< operation data */ return ret_value; } /* opfunc_b_xor */ +/** + * 'Left Shift Operator' opcode handler. + * + * See also: ECMA-262 v5, 11.7.1 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_b_shift_left (OPCODE opdata, /**< operation data */ + struct __int_data *int_data) /**< interpreter context */ +{ + const T_IDX dst_var_idx = opdata.data.b_shift_left.dst; + const T_IDX left_var_idx = opdata.data.b_shift_left.var_left; + const T_IDX right_var_idx = opdata.data.b_shift_left.var_right; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value); + ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value); + + ret_value = do_number_bitwise_logic (int_data, + dst_var_idx, + number_bitwise_shift_left, + left_value.value, + right_value.value); + + ECMA_FINALIZE (right_value); + ECMA_FINALIZE (left_value); + + return ret_value; +} /* opfunc_b_shift_left */ + +/** + * 'Right Shift Operator' opcode handler. + * + * See also: ECMA-262 v5, 11.7.2 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_b_shift_right (OPCODE opdata, /**< operation data */ + struct __int_data *int_data) /**< interpreter context */ +{ + const T_IDX dst_var_idx = opdata.data.b_shift_left.dst; + const T_IDX left_var_idx = opdata.data.b_shift_left.var_left; + const T_IDX right_var_idx = opdata.data.b_shift_left.var_right; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value); + ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value); + + ret_value = do_number_bitwise_logic (int_data, + dst_var_idx, + number_bitwise_shift_right, + left_value.value, + right_value.value); + + ECMA_FINALIZE (right_value); + ECMA_FINALIZE (left_value); + + return ret_value; +} /* opfunc_b_shift_right */ + +/** + * 'Unsigned Right Shift Operator' opcode handler. + * + * See also: ECMA-262 v5, 11.7.3 + * + * @return completion value + * Returned value must be freed with ecma_free_completion_value + */ +ecma_completion_value_t +opfunc_b_shift_uright (OPCODE opdata, /**< operation data */ + struct __int_data *int_data) /**< interpreter context */ +{ + const T_IDX dst_var_idx = opdata.data.b_shift_left.dst; + const T_IDX left_var_idx = opdata.data.b_shift_left.var_left; + const T_IDX right_var_idx = opdata.data.b_shift_left.var_right; + + int_data->pos++; + + ecma_completion_value_t ret_value; + + ECMA_TRY_CATCH (left_value, get_variable_value (int_data, left_var_idx, false), ret_value); + ECMA_TRY_CATCH (right_value, get_variable_value (int_data, right_var_idx, false), ret_value); + + ret_value = do_number_bitwise_logic (int_data, + dst_var_idx, + number_bitwise_shift_uright, + left_value.value, + right_value.value); + + ECMA_FINALIZE (right_value); + ECMA_FINALIZE (left_value); + + return ret_value; +} /* opfunc_b_shift_uright */ + /** * 'Pre increment' opcode handler. * @@ -1911,10 +2031,11 @@ opfunc_retval (OPCODE opdata __unused, /**< operation data */ ECMA_TRY_CATCH (expr_val, get_variable_value (int_data, opdata.data.retval.ret_value, false), ret_value); ret_value = ecma_make_completion_value (ECMA_COMPLETION_TYPE_RETURN, - expr_val.value, + ecma_copy_value (expr_val.value, true), ECMA_TARGET_ID_RESERVED); ECMA_FINALIZE (expr_val); + return ret_value; } /* opfunc_retval */ diff --git a/src/libecmaobjects/ecma-helpers-conversion.c b/src/libecmaobjects/ecma-helpers-conversion.c index f403c3792..214ad4955 100644 --- a/src/libecmaobjects/ecma-helpers-conversion.c +++ b/src/libecmaobjects/ecma-helpers-conversion.c @@ -97,6 +97,19 @@ ecma_uint32_to_number (uint32_t value) /**< unsigned 32-bit integer value */ return (ecma_number_t) value; } /* ecma_uint32_to_number */ +/** + * ECMA-defined conversion of Int32 value to Number value + * + * @return number - result of conversion. + */ +ecma_number_t +ecma_int32_to_number (int32_t value) /**< signed 32-bit integer value */ +{ + TODO(Implement according to ECMA); + + return (ecma_number_t) value; +} /* ecma_int32_to_number */ + /** * ECMA-defined conversion of Number value to Uint32 value * diff --git a/src/libecmaobjects/ecma-helpers.h b/src/libecmaobjects/ecma-helpers.h index 73b674589..7171b6722 100644 --- a/src/libecmaobjects/ecma-helpers.h +++ b/src/libecmaobjects/ecma-helpers.h @@ -189,6 +189,7 @@ extern ecma_number_t ecma_zt_string_to_number (const ecma_char_t *str_p); extern void ecma_uint32_to_string (uint32_t value, ecma_char_t *out_buffer_p, size_t buffer_size); extern uint32_t ecma_number_to_uint32 (ecma_number_t value); extern int32_t ecma_number_to_int32 (ecma_number_t value); +extern ecma_number_t ecma_int32_to_number (int32_t value); extern ecma_number_t ecma_uint32_to_number (uint32_t value); extern ecma_length_t ecma_number_to_zt_string (ecma_number_t num, ecma_char_t *buffer_p, ssize_t buffer_size); diff --git a/tests/jerry/N.function_return.js b/tests/jerry/function_return.js similarity index 100% rename from tests/jerry/N.function_return.js rename to tests/jerry/function_return.js diff --git a/tests/jerry/shift.js b/tests/jerry/shift.js new file mode 100644 index 000000000..3e3c2f0c4 --- /dev/null +++ b/tests/jerry/shift.js @@ -0,0 +1,21 @@ +// Copyright 2014 Samsung Electronics Co., Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +assert(9 << 2 === 36); +assert(14 << 2 === 56); + +assert(9 >> 2 === 2); +assert(-14 >> 2 === -4); + +assert(9 >>> 2 === 9 >> 2);