1/* Copyright JS Foundation and other contributors, http://js.foundation 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecma-alloc.h" 17#include "ecma-conversion.h" 18#include "ecma-helpers.h" 19#include "ecma-number-arithmetic.h" 20#include "ecma-objects.h" 21#include "ecma-try-catch-macro.h" 22#include "opcodes.h" 23#include "jrt-libc-includes.h" 24 25/** \addtogroup vm Virtual machine 26 * @{ 27 * 28 * \addtogroup vm_opcodes Opcodes 29 * @{ 30 */ 31 32/** 33 * Perform ECMA number arithmetic operation. 34 * 35 * The algorithm of the operation is following: 36 * leftNum = ToNumber (leftValue); 37 * rightNum = ToNumber (rightValue); 38 * result = leftNum ArithmeticOp rightNum; 39 * 40 * @return ecma value 41 * Returned value must be freed with ecma_free_value 42 */ 43ecma_value_t 44do_number_arithmetic (number_arithmetic_op op, /**< number arithmetic operation */ 45 ecma_value_t left_value, /**< left value */ 46 ecma_value_t right_value) /**< right value */ 47{ 48 ecma_value_t ret_value = ECMA_VALUE_EMPTY; 49 50 ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value); 51 ECMA_OP_TO_NUMBER_TRY_CATCH (num_right, right_value, ret_value); 52 53 ecma_number_t result = ECMA_NUMBER_ZERO; 54 55 switch (op) 56 { 57 case NUMBER_ARITHMETIC_SUBTRACTION: 58 { 59 result = num_left - num_right; 60 break; 61 } 62 case NUMBER_ARITHMETIC_MULTIPLICATION: 63 { 64 result = num_left * num_right; 65 break; 66 } 67 case NUMBER_ARITHMETIC_DIVISION: 68 { 69 result = num_left / num_right; 70 break; 71 } 72 case NUMBER_ARITHMETIC_REMAINDER: 73 { 74 result = ecma_op_number_remainder (num_left, num_right); 75 break; 76 } 77#if ENABLED (JERRY_ES2015) 78 case NUMBER_ARITHMETIC_EXPONENTIATION: 79 { 80 result = ecma_number_pow (num_left, num_right); 81 break; 82 } 83#endif /* ENABLED (JERRY_ES2015) */ 84 } 85 86 ret_value = ecma_make_number_value (result); 87 88 ECMA_OP_TO_NUMBER_FINALIZE (num_right); 89 ECMA_OP_TO_NUMBER_FINALIZE (num_left); 90 91 return ret_value; 92} /* do_number_arithmetic */ 93 94/** 95 * 'Addition' opcode handler. 96 * 97 * See also: ECMA-262 v5, 11.6.1 98 * 99 * @return ecma value 100 * Returned value must be freed with ecma_free_value 101 */ 102ecma_value_t 103opfunc_addition (ecma_value_t left_value, /**< left value */ 104 ecma_value_t right_value) /**< right value */ 105{ 106 bool free_left_value = false; 107 bool free_right_value = false; 108 109 if (ecma_is_value_object (left_value)) 110 { 111 ecma_object_t *obj_p = ecma_get_object_from_value (left_value); 112 left_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NO); 113 free_left_value = true; 114 115 if (ECMA_IS_VALUE_ERROR (left_value)) 116 { 117 return left_value; 118 } 119 } 120 121 if (ecma_is_value_object (right_value)) 122 { 123 ecma_object_t *obj_p = ecma_get_object_from_value (right_value); 124 right_value = ecma_op_object_default_value (obj_p, ECMA_PREFERRED_TYPE_NO); 125 free_right_value = true; 126 127 if (ECMA_IS_VALUE_ERROR (right_value)) 128 { 129 if (free_left_value) 130 { 131 ecma_free_value (left_value); 132 } 133 return right_value; 134 } 135 } 136 137 ecma_value_t ret_value = ECMA_VALUE_EMPTY; 138 139 if (ecma_is_value_string (left_value) 140 || ecma_is_value_string (right_value)) 141 { 142 ecma_string_t *string1_p = ecma_op_to_string (left_value); 143 144 if (JERRY_UNLIKELY (string1_p == NULL)) 145 { 146 if (free_left_value) 147 { 148 ecma_free_value (left_value); 149 } 150 if (free_right_value) 151 { 152 ecma_free_value (right_value); 153 } 154 return ECMA_VALUE_ERROR; 155 } 156 157 ecma_string_t *string2_p = ecma_op_to_string (right_value); 158 159 if (JERRY_UNLIKELY (string2_p == NULL)) 160 { 161 if (free_right_value) 162 { 163 ecma_free_value (right_value); 164 } 165 if (free_left_value) 166 { 167 ecma_free_value (left_value); 168 } 169 ecma_deref_ecma_string (string1_p); 170 return ECMA_VALUE_ERROR; 171 } 172 173 string1_p = ecma_concat_ecma_strings (string1_p, string2_p); 174 ret_value = ecma_make_string_value (string1_p); 175 176 ecma_deref_ecma_string (string2_p); 177 } 178 else 179 { 180 ECMA_OP_TO_NUMBER_TRY_CATCH (num_left, left_value, ret_value); 181 ECMA_OP_TO_NUMBER_TRY_CATCH (num_right, right_value, ret_value); 182 183 ret_value = ecma_make_number_value (num_left + num_right); 184 185 ECMA_OP_TO_NUMBER_FINALIZE (num_right); 186 ECMA_OP_TO_NUMBER_FINALIZE (num_left); 187 } 188 189 if (free_left_value) 190 { 191 ecma_free_value (left_value); 192 } 193 194 if (free_right_value) 195 { 196 ecma_free_value (right_value); 197 } 198 199 return ret_value; 200} /* opfunc_addition */ 201 202/** 203 * Unary operation opcode handler. 204 * 205 * See also: ECMA-262 v5, 11.4, 11.4.6, 11.4.7 206 * 207 * @return ecma value 208 * Returned value must be freed with ecma_free_value 209 */ 210ecma_value_t 211opfunc_unary_operation (ecma_value_t left_value, /**< left value */ 212 bool is_plus) /**< unary plus flag */ 213{ 214 ecma_value_t ret_value = ECMA_VALUE_EMPTY; 215 216 ECMA_OP_TO_NUMBER_TRY_CATCH (num_var_value, 217 left_value, 218 ret_value); 219 220 ret_value = ecma_make_number_value (is_plus ? num_var_value : -num_var_value); 221 222 ECMA_OP_TO_NUMBER_FINALIZE (num_var_value); 223 224 return ret_value; 225} /* opfunc_unary_operation */ 226 227/** 228 * @} 229 * @} 230 */ 231