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 */
43 ecma_value_t
do_number_arithmetic(number_arithmetic_op op,ecma_value_t left_value,ecma_value_t right_value)44 do_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 */
102 ecma_value_t
opfunc_addition(ecma_value_t left_value,ecma_value_t right_value)103 opfunc_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 */
210 ecma_value_t
opfunc_unary_operation(ecma_value_t left_value,bool is_plus)211 opfunc_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