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-exceptions.h"
18#include "ecma-gc.h"
19#include "ecma-globals.h"
20#include "ecma-helpers.h"
21#include "jrt.h"
22#include "jrt-bit-fields.h"
23#include "vm-defines.h"
24
25#include "ecma-function-object.h"
26
27JERRY_STATIC_ASSERT (ECMA_TYPE___MAX <= ECMA_VALUE_TYPE_MASK,
28                     ecma_types_must_be_less_than_mask);
29
30JERRY_STATIC_ASSERT ((ECMA_VALUE_TYPE_MASK + 1) == (1 << ECMA_VALUE_SHIFT),
31                     ecma_value_part_must_start_after_flags);
32
33JERRY_STATIC_ASSERT (ECMA_VALUE_SHIFT <= JMEM_ALIGNMENT_LOG,
34                     ecma_value_shift_must_be_less_than_or_equal_than_mem_alignment_log);
35
36JERRY_STATIC_ASSERT (sizeof (jmem_cpointer_t) <= sizeof (ecma_value_t),
37                     size_of_jmem_cpointer_t_must_be_less_or_equal_to_the_size_of_ecma_value_t);
38
39JERRY_STATIC_ASSERT (sizeof (jmem_cpointer_t) <= sizeof (jmem_cpointer_tag_t),
40                     size_of_jmem_cpointer_t_must_be_less_or_equal_to_the_size_of_jmem_cpointer_tag_t);
41
42#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
43
44/* cppcheck-suppress zerodiv */
45JERRY_STATIC_ASSERT (sizeof (uintptr_t) <= sizeof (ecma_value_t),
46                     uintptr_t_must_fit_in_ecma_value_t);
47
48#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
49
50JERRY_STATIC_ASSERT (sizeof (uintptr_t) > sizeof (ecma_value_t),
51                     uintptr_t_must_not_fit_in_ecma_value_t);
52
53#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
54
55JERRY_STATIC_ASSERT ((ECMA_VALUE_FALSE | (1 << ECMA_DIRECT_SHIFT)) == ECMA_VALUE_TRUE
56                     && ECMA_VALUE_FALSE != ECMA_VALUE_TRUE,
57                     only_the_lowest_bit_must_be_different_for_simple_value_true_and_false);
58
59/** \addtogroup ecma ECMA
60 * @{
61 *
62 * \addtogroup ecmahelpers Helpers for operations with ECMA data types
63 * @{
64 */
65
66/**
67 * Get type field of ecma value
68 *
69 * @return type field
70 */
71extern inline ecma_type_t JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
72ecma_get_value_type_field (ecma_value_t value) /**< ecma value */
73{
74  return value & ECMA_VALUE_TYPE_MASK;
75} /* ecma_get_value_type_field */
76
77/**
78 * Convert a pointer into an ecma value.
79 *
80 * @return ecma value
81 */
82static inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
83ecma_pointer_to_ecma_value (const void *ptr) /**< pointer */
84{
85#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
86
87  JERRY_ASSERT (ptr != NULL);
88  uintptr_t uint_ptr = (uintptr_t) ptr;
89  JERRY_ASSERT ((uint_ptr & ECMA_VALUE_TYPE_MASK) == 0);
90  return (ecma_value_t) uint_ptr;
91
92#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
93
94  jmem_cpointer_t ptr_cp;
95  ECMA_SET_NON_NULL_POINTER (ptr_cp, ptr);
96  return ((ecma_value_t) ptr_cp) << ECMA_VALUE_SHIFT;
97
98#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
99} /* ecma_pointer_to_ecma_value */
100
101/**
102 * Get a pointer from an ecma value
103 *
104 * @return pointer
105 */
106static inline void * JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
107ecma_get_pointer_from_ecma_value (ecma_value_t value) /**< value */
108{
109#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
110  void *ptr = (void *) (uintptr_t) ((value) & ~ECMA_VALUE_TYPE_MASK);
111  JERRY_ASSERT (ptr != NULL);
112  return ptr;
113#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
114  return ECMA_GET_NON_NULL_POINTER (void, value >> ECMA_VALUE_SHIFT);
115#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
116} /* ecma_get_pointer_from_ecma_value */
117
118/**
119 * Check if the value is direct ecma-value.
120 *
121 * @return true - if the value is a direct value,
122 *         false - otherwise
123 */
124inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
125ecma_is_value_direct (ecma_value_t value) /**< ecma value */
126{
127  return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT);
128} /* ecma_is_value_direct */
129
130/**
131 * Check if the value is simple ecma-value.
132 *
133 * @return true - if the value is a simple value,
134 *         false - otherwise
135 */
136inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
137ecma_is_value_simple (ecma_value_t value) /**< ecma value */
138{
139  return (value & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_SIMPLE_VALUE;
140} /* ecma_is_value_simple */
141
142/**
143 * Check whether the value is a given simple value.
144 *
145 * @return true - if the value is equal to the given simple value,
146 *         false - otherwise
147 */
148static inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
149ecma_is_value_equal_to_simple_value (ecma_value_t value, /**< ecma value */
150                                     ecma_value_t simple_value) /**< simple value */
151{
152  return value == simple_value;
153} /* ecma_is_value_equal_to_simple_value */
154
155/**
156 * Check if the value is empty.
157 *
158 * @return true - if the value contains implementation-defined empty simple value,
159 *         false - otherwise
160 */
161inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
162ecma_is_value_empty (ecma_value_t value) /**< ecma value */
163{
164  return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_EMPTY);
165} /* ecma_is_value_empty */
166
167/**
168 * Check if the value is undefined.
169 *
170 * @return true - if the value contains ecma-undefined simple value,
171 *         false - otherwise
172 */
173inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
174ecma_is_value_undefined (ecma_value_t value) /**< ecma value */
175{
176  return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_UNDEFINED);
177} /* ecma_is_value_undefined */
178
179/**
180 * Check if the value is null.
181 *
182 * @return true - if the value contains ecma-null simple value,
183 *         false - otherwise
184 */
185inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
186ecma_is_value_null (ecma_value_t value) /**< ecma value */
187{
188  return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_NULL);
189} /* ecma_is_value_null */
190
191/**
192 * Check if the value is boolean.
193 *
194 * @return true - if the value contains ecma-true or ecma-false simple values,
195 *         false - otherwise
196 */
197inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
198ecma_is_value_boolean (ecma_value_t value) /**< ecma value */
199{
200  return ecma_is_value_true (value | (1 << ECMA_DIRECT_SHIFT));
201} /* ecma_is_value_boolean */
202
203/**
204 * Check if the value is true.
205 *
206 * @return true - if the value contains ecma-true simple value,
207 *         false - otherwise
208 */
209inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
210ecma_is_value_true (ecma_value_t value) /**< ecma value */
211{
212  return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_TRUE);
213} /* ecma_is_value_true */
214
215/**
216 * Check if the value is false.
217 *
218 * @return true - if the value contains ecma-false simple value,
219 *         false - otherwise
220 */
221inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
222ecma_is_value_false (ecma_value_t value) /**< ecma value */
223{
224  return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_FALSE);
225} /* ecma_is_value_false */
226
227/**
228 * Check if the value is not found.
229 *
230 * @return true - if the value contains ecma-not-found simple value,
231 *         false - otherwise
232 */
233inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
234ecma_is_value_found (ecma_value_t value) /**< ecma value */
235{
236  return value != ECMA_VALUE_NOT_FOUND;
237} /* ecma_is_value_found */
238
239/**
240 * Check if the value is array hole.
241 *
242 * @return true - if the value contains ecma-array-hole simple value,
243 *         false - otherwise
244 */
245inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
246ecma_is_value_array_hole (ecma_value_t value) /**< ecma value */
247{
248  return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_ARRAY_HOLE);
249} /* ecma_is_value_array_hole */
250
251/**
252 * Check if the value is integer ecma-number.
253 *
254 * @return true - if the value contains an integer ecma-number value,
255 *         false - otherwise
256 */
257inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
258ecma_is_value_integer_number (ecma_value_t value) /**< ecma value */
259{
260  return (value & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_INTEGER_VALUE;
261} /* ecma_is_value_integer_number */
262
263/**
264 * Check if both values are integer ecma-numbers.
265 *
266 * @return true - if both values contain integer ecma-number values,
267 *         false - otherwise
268 */
269inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
270ecma_are_values_integer_numbers (ecma_value_t first_value, /**< first ecma value */
271                                 ecma_value_t second_value) /**< second ecma value */
272{
273  JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_INTEGER_VALUE == 0,
274                       ecma_direct_type_integer_value_must_be_zero);
275
276  return ((first_value | second_value) & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_INTEGER_VALUE;
277} /* ecma_are_values_integer_numbers */
278
279/**
280 * Check if the value is floating-point ecma-number.
281 *
282 * @return true - if the value contains a floating-point ecma-number value,
283 *         false - otherwise
284 */
285inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
286ecma_is_value_float_number (ecma_value_t value) /**< ecma value */
287{
288  return (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT);
289} /* ecma_is_value_float_number */
290
291/**
292 * Check if the value is ecma-number.
293 *
294 * @return true - if the value contains ecma-number value,
295 *         false - otherwise
296 */
297extern inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
298ecma_is_value_number (ecma_value_t value) /**< ecma value */
299{
300  return (ecma_is_value_integer_number (value)
301          || ecma_is_value_float_number (value));
302} /* ecma_is_value_number */
303
304JERRY_STATIC_ASSERT ((ECMA_TYPE_STRING | 0x4) == ECMA_TYPE_DIRECT_STRING,
305                     ecma_type_string_and_direct_string_must_have_one_bit_difference);
306
307/**
308 * Check if the value is ecma-string.
309 *
310 * @return true - if the value contains ecma-string value,
311 *         false - otherwise
312 */
313extern inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
314ecma_is_value_string (ecma_value_t value) /**< ecma value */
315{
316  return ((value & (ECMA_VALUE_TYPE_MASK - 0x4)) == ECMA_TYPE_STRING);
317} /* ecma_is_value_string */
318
319#if ENABLED (JERRY_ES2015)
320/**
321 * Check if the value is symbol.
322 *
323 * @return true - if the value contains symbol value,
324 *         false - otherwise
325 */
326inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
327ecma_is_value_symbol (ecma_value_t value) /**< ecma value */
328{
329  return (ecma_get_value_type_field (value) == ECMA_TYPE_SYMBOL);
330} /* ecma_is_value_symbol */
331#endif /* ENABLED (JERRY_ES2015) */
332
333/**
334 * Check if the value can be property name.
335 *
336 * @return true - if the value can be property name value,
337 *         false - otherwise
338 */
339inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
340ecma_is_value_prop_name (ecma_value_t value) /**< ecma value */
341{
342#if ENABLED (JERRY_ES2015)
343  return ecma_is_value_string (value) || ecma_is_value_symbol (value);
344#else /* !ENABLED (JERRY_ES2015) */
345  return ecma_is_value_string (value);
346#endif /* ENABLED (JERRY_ES2015) */
347} /* ecma_is_value_prop_name */
348
349/**
350 * Check if the value is direct ecma-string.
351 *
352 * @return true - if the value contains direct ecma-string value,
353 *         false - otherwise
354 */
355inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
356ecma_is_value_direct_string (ecma_value_t value) /**< ecma value */
357{
358  return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING);
359} /* ecma_is_value_direct_string */
360
361/**
362 * Check if the value is non-direct ecma-string.
363 *
364 * @return true - if the value contains non-direct ecma-string value,
365 *         false - otherwise
366 */
367inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
368ecma_is_value_non_direct_string (ecma_value_t value) /**< ecma value */
369{
370  return (ecma_get_value_type_field (value) == ECMA_TYPE_STRING);
371} /* ecma_is_value_non_direct_string */
372
373/**
374 * Check if the value is object.
375 *
376 * @return true - if the value contains object value,
377 *         false - otherwise
378 */
379inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
380ecma_is_value_object (ecma_value_t value) /**< ecma value */
381{
382  return (ecma_get_value_type_field (value) == ECMA_TYPE_OBJECT);
383} /* ecma_is_value_object */
384
385/**
386 * Check if the value is error reference.
387 *
388 * @return true - if the value contains an error reference,
389 *         false - otherwise
390 */
391inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
392ecma_is_value_error_reference (ecma_value_t value) /**< ecma value */
393{
394  return (ecma_get_value_type_field (value) == ECMA_TYPE_ERROR);
395} /* ecma_is_value_error_reference */
396
397/**
398 * Debug assertion that specified value's type is one of ECMA-defined
399 * script-visible types, i.e.: undefined, null, boolean, number, string, object.
400 */
401void
402ecma_check_value_type_is_spec_defined (ecma_value_t value) /**< ecma value */
403{
404  JERRY_ASSERT (ecma_is_value_undefined (value)
405                || ecma_is_value_null (value)
406                || ecma_is_value_boolean (value)
407                || ecma_is_value_number (value)
408                || ecma_is_value_string (value)
409                || ECMA_ASSERT_VALUE_IS_SYMBOL (value)
410                || ecma_is_value_object (value));
411} /* ecma_check_value_type_is_spec_defined */
412
413/**
414 * Checks if the given argument is an array or not.
415 *
416 * @return ECMA_VALUE_ERROR- if the operation fails
417 *         ECMA_VALUE_{TRUE/FALSE} - depends on whether 'arg' is an array object
418 */
419ecma_value_t
420ecma_is_value_array (ecma_value_t arg) /**< argument */
421{
422  if (!ecma_is_value_object (arg))
423  {
424    return ECMA_VALUE_FALSE;
425  }
426
427  ecma_object_t *arg_obj_p = ecma_get_object_from_value (arg);
428
429  if (ecma_get_object_type (arg_obj_p) == ECMA_OBJECT_TYPE_ARRAY)
430  {
431    return ECMA_VALUE_TRUE;
432  }
433
434#if ENABLED (JERRY_ES2015_BUILTIN_PROXY)
435  if (ECMA_OBJECT_IS_PROXY (arg_obj_p))
436  {
437    ecma_proxy_object_t *proxy_obj_p = (ecma_proxy_object_t *) arg_obj_p;
438
439    if (proxy_obj_p->handler == ECMA_VALUE_NULL)
440    {
441      return ecma_raise_type_error (ECMA_ERR_MSG ("Cannot perform 'IsArray' on the given proxy "
442                                                  "because handler is null"));
443    }
444
445    return ecma_is_value_array (proxy_obj_p->target);
446  }
447#endif /* ENABLED (JERRY_ES2015_BUILTIN_PROXY) */
448
449  return ECMA_VALUE_FALSE;
450} /* ecma_is_value_array */
451
452/**
453 * Creates an ecma value from the given raw boolean.
454 *
455 * @return boolean ecma_value
456 */
457inline ecma_value_t JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
458ecma_make_boolean_value (bool boolean_value) /**< raw bool value from which the ecma value will be created */
459{
460  return boolean_value ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE;
461} /* ecma_make_boolean_value */
462
463/**
464 * Encode an integer number into an ecma-value without allocating memory
465 *
466 * Note:
467 *   The value must fit into the range of allowed ecma integer values
468 *
469 * @return ecma-value
470 */
471inline ecma_value_t JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
472ecma_make_integer_value (ecma_integer_value_t integer_value) /**< integer number to be encoded */
473{
474  JERRY_ASSERT (ECMA_IS_INTEGER_NUMBER (integer_value));
475
476  return (((ecma_value_t) integer_value) << ECMA_DIRECT_SHIFT) | ECMA_DIRECT_TYPE_INTEGER_VALUE;
477} /* ecma_make_integer_value */
478
479/**
480 * Allocate and initialize a new float number without checks.
481 *
482 * @return ecma-value
483 */
484static ecma_value_t
485ecma_create_float_number (ecma_number_t ecma_number) /**< value of the float number */
486{
487  ecma_number_t *ecma_num_p = ecma_alloc_number ();
488
489  *ecma_num_p = ecma_number;
490
491  return ecma_pointer_to_ecma_value (ecma_num_p) | ECMA_TYPE_FLOAT;
492} /* ecma_create_float_number */
493
494/**
495 * Encode float number without checks.
496 *
497 * @return ecma-value
498 */
499ecma_value_t
500ecma_make_float_value (ecma_number_t *ecma_num_p) /**< pointer to the float number */
501{
502  return ecma_pointer_to_ecma_value (ecma_num_p) | ECMA_TYPE_FLOAT;
503} /* ecma_make_float_value */
504
505/**
506 * Create a new NaN value.
507 *
508 * @return ecma-value
509 */
510extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
511ecma_make_nan_value (void)
512{
513  return ecma_create_float_number (ecma_number_make_nan ());
514} /* ecma_make_nan_value */
515
516/**
517 * Checks whether the passed number is +0.0
518 *
519 * @return true, if it is +0.0, false otherwise
520 */
521static inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
522ecma_is_number_equal_to_positive_zero (ecma_number_t ecma_number) /**< number */
523{
524  ecma_number_accessor_t u;
525  u.as_ecma_number_t = ecma_number;
526#if !ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
527  return u.as_uint32_t == 0;
528#else /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
529  return u.as_uint64_t == 0;
530#endif /* !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
531} /* ecma_is_number_equal_to_positive_zero */
532
533/**
534 * Encode a number into an ecma-value
535 *
536 * @return ecma-value
537 */
538ecma_value_t
539ecma_make_number_value (ecma_number_t ecma_number) /**< number to be encoded */
540{
541  ecma_integer_value_t integer_value = (ecma_integer_value_t) ecma_number;
542
543  if ((ecma_number_t) integer_value == ecma_number
544      && ((integer_value == 0) ? ecma_is_number_equal_to_positive_zero (ecma_number)
545                               : ECMA_IS_INTEGER_NUMBER (integer_value)))
546  {
547    return ecma_make_integer_value (integer_value);
548  }
549
550  return ecma_create_float_number (ecma_number);
551} /* ecma_make_number_value */
552
553/**
554 * Encode an int32 number into an ecma-value
555 *
556 * @return ecma-value
557 */
558ecma_value_t
559ecma_make_int32_value (int32_t int32_number) /**< int32 number to be encoded */
560{
561  if (ECMA_IS_INTEGER_NUMBER (int32_number))
562  {
563    return ecma_make_integer_value ((ecma_integer_value_t) int32_number);
564  }
565
566  return ecma_create_float_number ((ecma_number_t) int32_number);
567} /* ecma_make_int32_value */
568
569/**
570 * Encode an unsigned int32 number into an ecma-value
571 *
572 * @return ecma-value
573 */
574ecma_value_t
575ecma_make_uint32_value (uint32_t uint32_number) /**< uint32 number to be encoded */
576{
577  if (uint32_number <= ECMA_INTEGER_NUMBER_MAX)
578  {
579    return ecma_make_integer_value ((ecma_integer_value_t) uint32_number);
580  }
581
582  return ecma_create_float_number ((ecma_number_t) uint32_number);
583} /* ecma_make_uint32_value */
584
585/**
586 * String value constructor
587 *
588 * @return ecma-value representation of the string argument
589 */
590inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
591ecma_make_string_value (const ecma_string_t *ecma_string_p) /**< string to reference in value */
592{
593  JERRY_ASSERT (ecma_string_p != NULL);
594#if ENABLED (JERRY_ES2015)
595  JERRY_ASSERT (!ecma_prop_name_is_symbol ((ecma_string_t *) ecma_string_p));
596#endif /* ENABLED (JERRY_ES2015) */
597
598  if ((((uintptr_t) ecma_string_p) & ECMA_VALUE_TYPE_MASK) != 0)
599  {
600    return (ecma_value_t) (uintptr_t) ecma_string_p;
601  }
602
603  return ecma_pointer_to_ecma_value (ecma_string_p) | ECMA_TYPE_STRING;
604} /* ecma_make_string_value */
605
606#if ENABLED (JERRY_ES2015)
607/**
608 * Symbol value constructor
609 *
610 * @return ecma-value representation of the string argument
611 */
612inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
613ecma_make_symbol_value (const ecma_string_t *ecma_symbol_p) /**< symbol to reference in value */
614{
615  JERRY_ASSERT (ecma_symbol_p != NULL);
616  JERRY_ASSERT (ecma_prop_name_is_symbol ((ecma_string_t *) ecma_symbol_p));
617
618  return ecma_pointer_to_ecma_value (ecma_symbol_p) | ECMA_TYPE_SYMBOL;
619} /* ecma_make_symbol_value */
620#endif /* ENABLED (JERRY_ES2015) */
621
622/**
623 * Property-name value constructor
624 *
625 * @return ecma-value representation of a property name argument
626 */
627inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
628ecma_make_prop_name_value (const ecma_string_t *ecma_prop_name_p) /**< property name to reference in value */
629{
630  JERRY_ASSERT (ecma_prop_name_p != NULL);
631
632#if ENABLED (JERRY_ES2015)
633  if (ecma_prop_name_is_symbol ((ecma_string_t *) ecma_prop_name_p))
634  {
635    return ecma_make_symbol_value (ecma_prop_name_p);
636  }
637#endif /* ENABLED (JERRY_ES2015) */
638
639  return ecma_make_string_value (ecma_prop_name_p);
640} /* ecma_make_prop_name_value */
641
642/**
643 * String value constructor
644 *
645 * @return ecma-value representation of the string argument
646 */
647inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
648ecma_make_magic_string_value (lit_magic_string_id_t id) /**< magic string id */
649{
650  return (ecma_value_t) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_MAGIC, (uintptr_t) id);
651} /* ecma_make_magic_string_value */
652
653/**
654 * Object value constructor
655 *
656 * @return ecma-value representation of the object argument
657 */
658inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
659ecma_make_object_value (const ecma_object_t *object_p) /**< object to reference in value */
660{
661  JERRY_ASSERT (object_p != NULL);
662
663  return ecma_pointer_to_ecma_value (object_p) | ECMA_TYPE_OBJECT;
664} /* ecma_make_object_value */
665
666/**
667 * Error reference constructor
668 *
669 * @return ecma-value representation of the Error reference
670 */
671inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
672ecma_make_error_reference_value (const ecma_error_reference_t *error_ref_p) /**< error reference */
673{
674  JERRY_ASSERT (error_ref_p != NULL);
675
676  return ecma_pointer_to_ecma_value (error_ref_p) | ECMA_TYPE_ERROR;
677} /* ecma_make_error_reference_value */
678
679/**
680 * Get integer value from an integer ecma value
681 *
682 * @return integer value
683 */
684inline ecma_integer_value_t JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
685ecma_get_integer_from_value (ecma_value_t value) /**< ecma value */
686{
687  JERRY_ASSERT (ecma_is_value_integer_number (value));
688
689  return ((ecma_integer_value_t) value) >> ECMA_DIRECT_SHIFT;
690} /* ecma_get_integer_from_value */
691
692/**
693 * Get floating point value from an ecma value
694 *
695 * @return floating point value
696 */
697inline ecma_number_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
698ecma_get_float_from_value (ecma_value_t value) /**< ecma value */
699{
700  JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT);
701
702  return *(ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
703} /* ecma_get_float_from_value */
704
705/**
706 * Get floating point value pointer from an ecma value
707 *
708 * @return floating point value
709 */
710inline ecma_number_t * JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
711ecma_get_pointer_from_float_value (ecma_value_t value) /**< ecma value */
712{
713  JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT);
714
715  return (ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
716} /* ecma_get_pointer_from_float_value */
717
718/**
719 * Get floating point value from an ecma value
720 *
721 * @return floating point value
722 */
723ecma_number_t JERRY_ATTR_PURE
724ecma_get_number_from_value (ecma_value_t value) /**< ecma value */
725{
726  if (ecma_is_value_integer_number (value))
727  {
728    return (ecma_number_t) ecma_get_integer_from_value (value);
729  }
730
731  return ecma_get_float_from_value (value);
732} /* ecma_get_number_from_value */
733
734/**
735 * Get pointer to ecma-string from ecma value
736 *
737 * @return the string pointer
738 */
739inline ecma_string_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
740ecma_get_string_from_value (ecma_value_t value) /**< ecma value */
741{
742  JERRY_ASSERT (ecma_is_value_string (value));
743
744  if ((value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_DIRECT_STRING)
745  {
746    return (ecma_string_t *) (uintptr_t) value;
747  }
748
749  return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value);
750} /* ecma_get_string_from_value */
751
752#if ENABLED (JERRY_ES2015)
753/**
754 * Get pointer to ecma-string from ecma value
755 *
756 * @return the string pointer
757 */
758inline ecma_string_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
759ecma_get_symbol_from_value (ecma_value_t value) /**< ecma value */
760{
761  JERRY_ASSERT (ecma_is_value_symbol (value));
762
763  return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value);
764} /* ecma_get_symbol_from_value */
765#endif /* ENABLED (JERRY_ES2015) */
766
767/**
768 * Get pointer to a property name from ecma value
769 *
770 * @return the string pointer
771 */
772inline ecma_string_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
773ecma_get_prop_name_from_value (ecma_value_t value) /**< ecma value */
774{
775  JERRY_ASSERT (ecma_is_value_prop_name (value));
776
777  if ((value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_DIRECT_STRING)
778  {
779    return (ecma_string_t *) (uintptr_t) value;
780  }
781
782  return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value);
783} /* ecma_get_prop_name_from_value */
784
785/**
786 * Get pointer to ecma-object from ecma value
787 *
788 * @return the pointer
789 */
790inline ecma_object_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
791ecma_get_object_from_value (ecma_value_t value) /**< ecma value */
792{
793  JERRY_ASSERT (ecma_is_value_object (value));
794
795  return (ecma_object_t *) ecma_get_pointer_from_ecma_value (value);
796} /* ecma_get_object_from_value */
797
798/**
799 * Get pointer to error reference from ecma value
800 *
801 * @return the pointer
802 */
803inline ecma_error_reference_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
804ecma_get_error_reference_from_value (ecma_value_t value) /**< ecma value */
805{
806  JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_ERROR);
807
808  return (ecma_error_reference_t *) ecma_get_pointer_from_ecma_value (value);
809} /* ecma_get_error_reference_from_value */
810
811/**
812 * Invert a boolean value
813 *
814 * @return ecma value
815 */
816inline ecma_value_t JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
817ecma_invert_boolean_value (ecma_value_t value) /**< ecma value */
818{
819  JERRY_ASSERT (ecma_is_value_boolean (value));
820
821  return (value ^ (1 << ECMA_DIRECT_SHIFT));
822} /* ecma_invert_boolean_value */
823
824/**
825 * Copy ecma value.
826 *
827 * @return copy of the given value
828 */
829ecma_value_t
830ecma_copy_value (ecma_value_t value)  /**< value description */
831{
832  switch (ecma_get_value_type_field (value))
833  {
834    case ECMA_TYPE_FLOAT:
835    {
836      ecma_number_t *num_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
837
838      return ecma_create_float_number (*num_p);
839    }
840    case ECMA_TYPE_STRING:
841    {
842      ecma_ref_ecma_string (ecma_get_string_from_value (value));
843      return value;
844    }
845#if ENABLED (JERRY_ES2015)
846    case ECMA_TYPE_SYMBOL:
847    {
848      ecma_ref_ecma_string (ecma_get_symbol_from_value (value));
849      return value;
850    }
851#endif /* ENABLED (JERRY_ES2015) */
852    case ECMA_TYPE_OBJECT:
853    {
854      ecma_ref_object (ecma_get_object_from_value (value));
855      return value;
856    }
857    default:
858    {
859      JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT
860                    || ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING);
861
862      return value;
863    }
864  }
865} /* ecma_copy_value */
866
867/**
868 * Copy ecma value.
869 *
870 * Note:
871 *   this function is similar to ecma_copy_value, but it is
872 *   faster for direct values since no function call is performed.
873 *   It also increases the binary size so it is recommended for
874 *   critical code paths only.
875 *
876 * @return copy of the given value
877 */
878inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
879ecma_fast_copy_value (ecma_value_t value)  /**< value description */
880{
881  return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT) ? value : ecma_copy_value (value);
882} /* ecma_fast_copy_value */
883
884/**
885 * Copy the ecma value if not an object
886 *
887 * @return copy of the given value
888 */
889inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
890ecma_copy_value_if_not_object (ecma_value_t value) /**< value description */
891{
892  if (!ecma_is_value_object (value))
893  {
894    return ecma_copy_value (value);
895  }
896
897  return value;
898} /* ecma_copy_value_if_not_object */
899
900/**
901 * Increase reference counter of a value if it is an object.
902 */
903inline void JERRY_ATTR_ALWAYS_INLINE
904ecma_ref_if_object (ecma_value_t value) /**< value description */
905{
906  if (ecma_is_value_object (value))
907  {
908    ecma_ref_object (ecma_get_object_from_value (value));
909  }
910} /* ecma_ref_if_object */
911
912/**
913 * Decrease reference counter of a value if it is an object.
914 */
915inline void JERRY_ATTR_ALWAYS_INLINE
916ecma_deref_if_object (ecma_value_t value) /**< value description */
917{
918  if (ecma_is_value_object (value))
919  {
920    ecma_deref_object (ecma_get_object_from_value (value));
921  }
922} /* ecma_deref_if_object */
923
924/**
925 * Assign a new value to an ecma-value
926 *
927 * Note:
928 *      value previously stored in the property is freed
929 */
930void
931ecma_value_assign_value (ecma_value_t *value_p, /**< [in, out] ecma value */
932                         ecma_value_t ecma_value) /**< value to assign */
933{
934  JERRY_STATIC_ASSERT (ECMA_TYPE_DIRECT == 0,
935                       ecma_type_direct_must_be_zero_for_the_next_check);
936
937  if (*value_p == ecma_value)
938  {
939    return;
940  }
941
942  if (ecma_get_value_type_field (ecma_value || *value_p) == ECMA_TYPE_DIRECT)
943  {
944    *value_p = ecma_value;
945  }
946  else if (ecma_is_value_float_number (ecma_value)
947           && ecma_is_value_float_number (*value_p))
948  {
949    const ecma_number_t *num_src_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (ecma_value);
950    ecma_number_t *num_dst_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (*value_p);
951
952    *num_dst_p = *num_src_p;
953  }
954  else
955  {
956    ecma_free_value_if_not_object (*value_p);
957    *value_p = ecma_copy_value_if_not_object (ecma_value);
958  }
959} /* ecma_value_assign_value */
960
961/**
962 * Update the value of a float number to a new value
963 *
964 * Note:
965 *   The original value is destroyed.
966 *
967 * @return updated ecma value
968 */
969ecma_value_t
970ecma_update_float_number (ecma_value_t float_value, /**< original float value */
971                          ecma_number_t new_number) /**< updated number value */
972{
973  JERRY_ASSERT (ecma_is_value_float_number (float_value));
974
975  ecma_integer_value_t integer_number = (ecma_integer_value_t) new_number;
976  ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (float_value);
977
978  if ((ecma_number_t) integer_number == new_number
979      && ((integer_number == 0) ? ecma_is_number_equal_to_positive_zero (new_number)
980                                : ECMA_IS_INTEGER_NUMBER (integer_number)))
981  {
982    ecma_dealloc_number (number_p);
983    return ecma_make_integer_value (integer_number);
984  }
985
986  *number_p = new_number;
987  return float_value;
988} /* ecma_update_float_number */
989
990/**
991 * Assign a float number to an ecma-value
992 *
993 * Note:
994 *      value previously stored in the property is freed
995 */
996static void
997ecma_value_assign_float_number (ecma_value_t *value_p, /**< [in, out] ecma value */
998                                ecma_number_t ecma_number) /**< number to assign */
999{
1000  if (ecma_is_value_float_number (*value_p))
1001  {
1002    ecma_number_t *num_dst_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (*value_p);
1003
1004    *num_dst_p = ecma_number;
1005    return;
1006  }
1007
1008  if (ecma_get_value_type_field (*value_p) != ECMA_TYPE_DIRECT
1009      && ecma_get_value_type_field (*value_p) != ECMA_TYPE_OBJECT)
1010  {
1011    ecma_free_value (*value_p);
1012  }
1013
1014  *value_p = ecma_create_float_number (ecma_number);
1015} /* ecma_value_assign_float_number */
1016
1017/**
1018 * Assign a number to an ecma-value
1019 *
1020 * Note:
1021 *      value previously stored in the property is freed
1022 */
1023void
1024ecma_value_assign_number (ecma_value_t *value_p, /**< [in, out] ecma value */
1025                          ecma_number_t ecma_number) /**< number to assign */
1026{
1027  ecma_integer_value_t integer_value = (ecma_integer_value_t) ecma_number;
1028
1029  if ((ecma_number_t) integer_value == ecma_number
1030      && ((integer_value == 0) ? ecma_is_number_equal_to_positive_zero (ecma_number)
1031                               : ECMA_IS_INTEGER_NUMBER (integer_value)))
1032  {
1033    if (ecma_get_value_type_field (*value_p) != ECMA_TYPE_DIRECT
1034        && ecma_get_value_type_field (*value_p) != ECMA_TYPE_OBJECT)
1035    {
1036      ecma_free_value (*value_p);
1037    }
1038    *value_p = ecma_make_integer_value (integer_value);
1039    return;
1040  }
1041
1042  ecma_value_assign_float_number (value_p, ecma_number);
1043} /* ecma_value_assign_number */
1044
1045/**
1046 * Free the ecma value
1047 */
1048void
1049ecma_free_value (ecma_value_t value) /**< value description */
1050{
1051  switch (ecma_get_value_type_field (value))
1052  {
1053    case ECMA_TYPE_FLOAT:
1054    {
1055      ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
1056      ecma_dealloc_number (number_p);
1057      break;
1058    }
1059
1060    case ECMA_TYPE_STRING:
1061    {
1062      ecma_string_t *string_p = ecma_get_string_from_value (value);
1063      ecma_deref_ecma_string (string_p);
1064      break;
1065    }
1066#if ENABLED (JERRY_ES2015)
1067    case ECMA_TYPE_SYMBOL:
1068    {
1069      ecma_deref_ecma_string (ecma_get_symbol_from_value (value));
1070      break;
1071    }
1072#endif /* ENABLED (JERRY_ES2015) */
1073    case ECMA_TYPE_OBJECT:
1074    {
1075      ecma_deref_object (ecma_get_object_from_value (value));
1076      break;
1077    }
1078
1079    default:
1080    {
1081      JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT
1082                    || ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING);
1083
1084      /* no memory is allocated */
1085      break;
1086    }
1087  }
1088} /* ecma_free_value */
1089
1090/**
1091 * Free the ecma value
1092 *
1093 * Note:
1094 *   this function is similar to ecma_free_value, but it is
1095 *   faster for direct values since no function call is performed.
1096 *   It also increases the binary size so it is recommended for
1097 *   critical code paths only.
1098 */
1099inline void JERRY_ATTR_ALWAYS_INLINE
1100ecma_fast_free_value (ecma_value_t value) /**< value description */
1101{
1102  if (ecma_get_value_type_field (value) != ECMA_TYPE_DIRECT)
1103  {
1104    ecma_free_value (value);
1105  }
1106} /* ecma_fast_free_value */
1107
1108/**
1109 * Free the ecma value if not an object
1110 */
1111void
1112ecma_free_value_if_not_object (ecma_value_t value) /**< value description */
1113{
1114  if (ecma_get_value_type_field (value) != ECMA_TYPE_OBJECT)
1115  {
1116    ecma_free_value (value);
1117  }
1118} /* ecma_free_value_if_not_object */
1119
1120/**
1121 * Free an ecma-value number
1122 */
1123inline void JERRY_ATTR_ALWAYS_INLINE
1124ecma_free_number (ecma_value_t value) /**< value description */
1125{
1126  JERRY_ASSERT (ecma_is_value_number (value));
1127
1128  if (ecma_is_value_float_number (value))
1129  {
1130    ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
1131    ecma_dealloc_number (number_p);
1132  }
1133} /* ecma_free_number */
1134
1135/**
1136 * Get the literal id associated with the given ecma_value type.
1137 * This operation is equivalent to the JavaScript 'typeof' operator.
1138 *
1139 * @returns one of the following value:
1140 *          - LIT_MAGIC_STRING_UNDEFINED
1141 *          - LIT_MAGIC_STRING_OBJECT
1142 *          - LIT_MAGIC_STRING_BOOLEAN
1143 *          - LIT_MAGIC_STRING_NUMBER
1144 *          - LIT_MAGIC_STRING_STRING
1145 *          - LIT_MAGIC_STRING_FUNCTION
1146 */
1147lit_magic_string_id_t
1148ecma_get_typeof_lit_id (ecma_value_t value) /**< input ecma value */
1149{
1150  lit_magic_string_id_t ret_value = LIT_MAGIC_STRING__EMPTY;
1151
1152  if (ecma_is_value_undefined (value))
1153  {
1154    ret_value = LIT_MAGIC_STRING_UNDEFINED;
1155  }
1156  else if (ecma_is_value_null (value))
1157  {
1158    ret_value = LIT_MAGIC_STRING_OBJECT;
1159  }
1160  else if (ecma_is_value_boolean (value))
1161  {
1162    ret_value = LIT_MAGIC_STRING_BOOLEAN;
1163  }
1164  else if (ecma_is_value_number (value))
1165  {
1166    ret_value = LIT_MAGIC_STRING_NUMBER;
1167  }
1168  else if (ecma_is_value_string (value))
1169  {
1170    ret_value = LIT_MAGIC_STRING_STRING;
1171  }
1172#if ENABLED (JERRY_ES2015)
1173  else if (ecma_is_value_symbol (value))
1174  {
1175    ret_value = LIT_MAGIC_STRING_SYMBOL;
1176  }
1177#endif /* ENABLED (JERRY_ES2015) */
1178  else
1179  {
1180    JERRY_ASSERT (ecma_is_value_object (value));
1181
1182    ret_value = ecma_op_is_callable (value) ? LIT_MAGIC_STRING_FUNCTION : LIT_MAGIC_STRING_OBJECT;
1183  }
1184
1185  JERRY_ASSERT (ret_value != LIT_MAGIC_STRING__EMPTY);
1186
1187  return ret_value;
1188} /* ecma_get_typeof_lit_id */
1189
1190/**
1191 * @}
1192 * @}
1193 */
1194