• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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