ecma-helpers-value.c 32.8 KB
Newer Older
1
/* Copyright JS Foundation and other contributors, http://js.foundation
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * 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.
 */

#include "ecma-alloc.h"
#include "ecma-gc.h"
#include "ecma-globals.h"
#include "ecma-helpers.h"
20
#include "jrt.h"
21
#include "jrt-bit-fields.h"
22
#include "vm-defines.h"
23

24 25
#include "ecma-function-object.h"

26 27 28
JERRY_STATIC_ASSERT (ECMA_TYPE___MAX <= ECMA_VALUE_TYPE_MASK,
                     ecma_types_must_be_less_than_mask);

29
JERRY_STATIC_ASSERT ((ECMA_VALUE_TYPE_MASK + 1) == (1 << ECMA_VALUE_SHIFT),
30 31
                     ecma_value_part_must_start_after_flags);

32
JERRY_STATIC_ASSERT (ECMA_VALUE_SHIFT <= JMEM_ALIGNMENT_LOG,
33 34
                     ecma_value_shift_must_be_less_than_or_equal_than_mem_alignment_log);

35 36
JERRY_STATIC_ASSERT (sizeof (jmem_cpointer_t) <= sizeof (ecma_value_t),
                     size_of_jmem_cpointer_t_must_be_less_or_equal_to_the_size_of_ecma_value_t);
37 38 39 40 41 42

#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY

JERRY_STATIC_ASSERT (sizeof (uintptr_t) <= sizeof (ecma_value_t),
                     uintptr_t_must_fit_in_ecma_value_t);

43
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
44 45 46 47 48 49

JERRY_STATIC_ASSERT (sizeof (uintptr_t) > sizeof (ecma_value_t),
                     uintptr_t_must_not_fit_in_ecma_value_t);

#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */

50 51
JERRY_STATIC_ASSERT ((ECMA_VALUE_FALSE | (1 << ECMA_DIRECT_SHIFT)) == ECMA_VALUE_TRUE
                     && ECMA_VALUE_FALSE != ECMA_VALUE_TRUE,
Z
Zoltan Herczeg 已提交
52 53
                     only_the_lowest_bit_must_be_different_for_simple_value_true_and_false);

54 55 56 57 58 59 60
/** \addtogroup ecma ECMA
 * @{
 *
 * \addtogroup ecmahelpers Helpers for operations with ECMA data types
 * @{
 */

61
/**
62
 * Get type field of ecma value
63 64 65
 *
 * @return type field
 */
66
static inline ecma_type_t JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
67
ecma_get_value_type_field (ecma_value_t value) /**< ecma value */
68
{
69
  return value & ECMA_VALUE_TYPE_MASK;
70 71 72
} /* ecma_get_value_type_field */

/**
73
 * Convert a pointer into an ecma value.
74
 *
75
 * @return ecma value
76
 */
77
static inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
78
ecma_pointer_to_ecma_value (const void *ptr) /**< pointer */
79
{
80 81
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY

Z
Zoltan Herczeg 已提交
82
  JERRY_ASSERT (ptr != NULL);
83
  uintptr_t uint_ptr = (uintptr_t) ptr;
84
  JERRY_ASSERT ((uint_ptr & ECMA_VALUE_TYPE_MASK) == 0);
85 86
  return (ecma_value_t) uint_ptr;

87
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
88

89
  jmem_cpointer_t ptr_cp;
90 91 92 93 94
  ECMA_SET_NON_NULL_POINTER (ptr_cp, ptr);
  return ((ecma_value_t) ptr_cp) << ECMA_VALUE_SHIFT;

#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
} /* ecma_pointer_to_ecma_value */
95 96

/**
97
 * Get a pointer from an ecma value
98
 *
99
 * @return pointer
100
 */
101
static inline void * JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
102
ecma_get_pointer_from_ecma_value (ecma_value_t value) /**< value */
103
{
104
#ifdef ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY
Z
Zoltan Herczeg 已提交
105 106 107
  void *ptr = (void *) (uintptr_t) ((value) & ~ECMA_VALUE_TYPE_MASK);
  JERRY_ASSERT (ptr != NULL);
  return ptr;
108
#else /* !ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
Z
Zoltan Herczeg 已提交
109
  return ECMA_GET_NON_NULL_POINTER (void, value >> ECMA_VALUE_SHIFT);
110 111
#endif /* ECMA_VALUE_CAN_STORE_UINTPTR_VALUE_DIRECTLY */
} /* ecma_get_pointer_from_ecma_value */
112

Z
Zoltan Herczeg 已提交
113 114 115 116
/**
 * Check if the value is direct ecma-value.
 *
 * @return true - if the value is a direct value,
117
 *         false - otherwise
Z
Zoltan Herczeg 已提交
118
 */
119
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
Z
Zoltan Herczeg 已提交
120 121 122 123 124
ecma_is_value_direct (ecma_value_t value) /**< ecma value */
{
  return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT);
} /* ecma_is_value_direct */

Z
Zoltan Herczeg 已提交
125 126 127 128
/**
 * Check if the value is simple ecma-value.
 *
 * @return true - if the value is a simple value,
129
 *         false - otherwise
Z
Zoltan Herczeg 已提交
130
 */
131
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
Z
Zoltan Herczeg 已提交
132 133 134 135 136
ecma_is_value_simple (ecma_value_t value) /**< ecma value */
{
  return (value & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_SIMPLE_VALUE;
} /* ecma_is_value_simple */

137
/**
138
 * Check whether the value is a given simple value.
139
 *
140
 * @return true - if the value is equal to the given simple value,
141
 *         false - otherwise
142
 */
143
static inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
144
ecma_is_value_equal_to_simple_value (ecma_value_t value, /**< ecma value */
145
                                     ecma_value_t simple_value) /**< simple value */
146
{
147
  return value == simple_value;
148
} /* ecma_is_value_equal_to_simple_value */
149 150 151 152 153

/**
 * Check if the value is empty.
 *
 * @return true - if the value contains implementation-defined empty simple value,
154
 *         false - otherwise
155
 */
156
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
157
ecma_is_value_empty (ecma_value_t value) /**< ecma value */
158
{
159
  return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_EMPTY);
160 161 162 163 164 165
} /* ecma_is_value_empty */

/**
 * Check if the value is undefined.
 *
 * @return true - if the value contains ecma-undefined simple value,
166
 *         false - otherwise
167
 */
168
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
169
ecma_is_value_undefined (ecma_value_t value) /**< ecma value */
170
{
171
  return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_UNDEFINED);
172 173 174 175 176 177
} /* ecma_is_value_undefined */

/**
 * Check if the value is null.
 *
 * @return true - if the value contains ecma-null simple value,
178
 *         false - otherwise
179
 */
180
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
181
ecma_is_value_null (ecma_value_t value) /**< ecma value */
182
{
183
  return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_NULL);
184 185 186 187 188 189
} /* ecma_is_value_null */

/**
 * Check if the value is boolean.
 *
 * @return true - if the value contains ecma-true or ecma-false simple values,
190
 *         false - otherwise
191
 */
192
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
193
ecma_is_value_boolean (ecma_value_t value) /**< ecma value */
194
{
Z
Zoltan Herczeg 已提交
195
  return ecma_is_value_true (value | (1 << ECMA_DIRECT_SHIFT));
196 197 198 199 200 201
} /* ecma_is_value_boolean */

/**
 * Check if the value is true.
 *
 * @return true - if the value contains ecma-true simple value,
202
 *         false - otherwise
203
 */
204
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
205
ecma_is_value_true (ecma_value_t value) /**< ecma value */
206
{
207
  return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_TRUE);
208 209
} /* ecma_is_value_true */

210 211 212 213
/**
 * Check if the value is false.
 *
 * @return true - if the value contains ecma-false simple value,
214
 *         false - otherwise
215
 */
216
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
217 218
ecma_is_value_false (ecma_value_t value) /**< ecma value */
{
219
  return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_FALSE);
220 221
} /* ecma_is_value_false */

222 223 224 225
/**
 * Check if the value is not found.
 *
 * @return true - if the value contains ecma-not-found simple value,
226
 *         false - otherwise
227
 */
228
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
229 230
ecma_is_value_found (ecma_value_t value) /**< ecma value */
{
231
  return value != ECMA_VALUE_NOT_FOUND;
232 233
} /* ecma_is_value_found */

234 235 236 237
/**
 * Check if the value is array hole.
 *
 * @return true - if the value contains ecma-array-hole simple value,
238
 *         false - otherwise
239
 */
240
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
241
ecma_is_value_array_hole (ecma_value_t value) /**< ecma value */
242
{
243
  return ecma_is_value_equal_to_simple_value (value, ECMA_VALUE_ARRAY_HOLE);
244 245
} /* ecma_is_value_array_hole */

246 247 248 249
/**
 * Check if the value is integer ecma-number.
 *
 * @return true - if the value contains an integer ecma-number value,
250
 *         false - otherwise
251
 */
252
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
253 254 255 256 257
ecma_is_value_integer_number (ecma_value_t value) /**< ecma value */
{
  return (value & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_INTEGER_VALUE;
} /* ecma_is_value_integer_number */

258 259 260 261
/**
 * Check if both values are integer ecma-numbers.
 *
 * @return true - if both values contain integer ecma-number values,
262
 *         false - otherwise
263
 */
264
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
265 266 267 268 269 270 271 272 273
ecma_are_values_integer_numbers (ecma_value_t first_value, /**< first ecma value */
                                 ecma_value_t second_value) /**< second ecma value */
{
  JERRY_STATIC_ASSERT (ECMA_DIRECT_TYPE_INTEGER_VALUE == 0,
                       ecma_direct_type_integer_value_must_be_zero);

  return ((first_value | second_value) & ECMA_DIRECT_TYPE_MASK) == ECMA_DIRECT_TYPE_INTEGER_VALUE;
} /* ecma_are_values_integer_numbers */

274 275 276 277
/**
 * Check if the value is floating-point ecma-number.
 *
 * @return true - if the value contains a floating-point ecma-number value,
278
 *         false - otherwise
279
 */
280
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
281 282 283 284 285
ecma_is_value_float_number (ecma_value_t value) /**< ecma value */
{
  return (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT);
} /* ecma_is_value_float_number */

286 287 288 289
/**
 * Check if the value is ecma-number.
 *
 * @return true - if the value contains ecma-number value,
290
 *         false - otherwise
291
 */
292
extern inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
293
ecma_is_value_number (ecma_value_t value) /**< ecma value */
294
{
295 296
  return (ecma_is_value_integer_number (value)
          || ecma_is_value_float_number (value));
297 298
} /* ecma_is_value_number */

299 300 301
JERRY_STATIC_ASSERT ((ECMA_TYPE_STRING | 0x4) == ECMA_TYPE_DIRECT_STRING,
                     ecma_type_string_and_direct_string_must_have_one_bit_difference);

302 303 304 305
/**
 * Check if the value is ecma-string.
 *
 * @return true - if the value contains ecma-string value,
306
 *         false - otherwise
307
 */
308
extern inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
309
ecma_is_value_string (ecma_value_t value) /**< ecma value */
310
{
311
  return ((value & (ECMA_VALUE_TYPE_MASK - 0x4)) == ECMA_TYPE_STRING);
312 313
} /* ecma_is_value_string */

314
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
315 316 317 318 319 320 321 322 323 324 325
/**
 * Check if the value is symbol.
 *
 * @return true - if the value contains symbol value,
 *         false - otherwise
 */
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
ecma_is_value_symbol (ecma_value_t value) /**< ecma value */
{
  return (ecma_get_value_type_field (value) == ECMA_TYPE_SYMBOL);
} /* ecma_is_value_symbol */
326
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
327 328 329 330 331 332 333 334 335 336

/**
 * Check if the value can be property name.
 *
 * @return true - if the value can be property name value,
 *         false - otherwise
 */
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
ecma_is_value_prop_name (ecma_value_t value) /**< ecma value */
{
337
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
338
  return ecma_is_value_string (value) || ecma_is_value_symbol (value);
339
#else /* !ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
340
  return ecma_is_value_string (value);
341
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
342 343
} /* ecma_is_value_prop_name */

344
/**
345
 * Check if the value is direct ecma-string.
346
 *
347
 * @return true - if the value contains direct ecma-string value,
348 349
 *         false - otherwise
 */
350
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
351 352 353 354 355
ecma_is_value_direct_string (ecma_value_t value) /**< ecma value */
{
  return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING);
} /* ecma_is_value_direct_string */

356 357 358 359 360 361 362 363 364 365 366 367
/**
 * Check if the value is non-direct ecma-string.
 *
 * @return true - if the value contains non-direct ecma-string value,
 *         false - otherwise
 */
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
ecma_is_value_non_direct_string (ecma_value_t value) /**< ecma value */
{
  return (ecma_get_value_type_field (value) == ECMA_TYPE_STRING);
} /* ecma_is_value_non_direct_string */

368 369 370 371
/**
 * Check if the value is object.
 *
 * @return true - if the value contains object value,
372
 *         false - otherwise
373
 */
374
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
375
ecma_is_value_object (ecma_value_t value) /**< ecma value */
376 377 378 379
{
  return (ecma_get_value_type_field (value) == ECMA_TYPE_OBJECT);
} /* ecma_is_value_object */

380 381 382
/**
 * Check if the value is error reference.
 *
Z
Zoltan Herczeg 已提交
383
 * @return true - if the value contains an error reference,
384 385
 *         false - otherwise
 */
386
inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
387 388 389 390 391
ecma_is_value_error_reference (ecma_value_t value) /**< ecma value */
{
  return (ecma_get_value_type_field (value) == ECMA_TYPE_ERROR);
} /* ecma_is_value_error_reference */

392 393 394 395 396
/**
 * Debug assertion that specified value's type is one of ECMA-defined
 * script-visible types, i.e.: undefined, null, boolean, number, string, object.
 */
void
397
ecma_check_value_type_is_spec_defined (ecma_value_t value) /**< ecma value */
398 399 400 401 402 403
{
  JERRY_ASSERT (ecma_is_value_undefined (value)
                || ecma_is_value_null (value)
                || ecma_is_value_boolean (value)
                || ecma_is_value_number (value)
                || ecma_is_value_string (value)
404
                || ECMA_ASSERT_VALUE_IS_SYMBOL (value)
405 406 407
                || ecma_is_value_object (value));
} /* ecma_check_value_type_is_spec_defined */

408 409 410 411 412
/**
 * Creates an ecma value from the given raw boolean.
 *
 * @return boolean ecma_value
 */
413
inline ecma_value_t JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
414 415
ecma_make_boolean_value (bool boolean_value) /**< raw bool value from which the ecma value will be created */
{
416
  return boolean_value ? ECMA_VALUE_TRUE : ECMA_VALUE_FALSE;
417 418
} /* ecma_make_boolean_value */

419
/**
420 421 422 423 424 425
 * Encode an integer number into an ecma-value without allocating memory
 *
 * Note:
 *   The value must fit into the range of allowed ecma integer values
 *
 * @return ecma-value
426
 */
427
inline ecma_value_t JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
428
ecma_make_integer_value (ecma_integer_value_t integer_value) /**< integer number to be encoded */
429
{
430 431
  JERRY_ASSERT (ECMA_IS_INTEGER_NUMBER (integer_value));

432
  return (((ecma_value_t) integer_value) << ECMA_DIRECT_SHIFT) | ECMA_DIRECT_TYPE_INTEGER_VALUE;
433 434 435 436 437 438 439
} /* ecma_make_integer_value */

/**
 * Allocate and initialize a new float number without checks.
 *
 * @return ecma-value
 */
440
static ecma_value_t
441 442 443 444 445 446 447 448
ecma_create_float_number (ecma_number_t ecma_number) /**< value of the float number */
{
  ecma_number_t *ecma_num_p = ecma_alloc_number ();

  *ecma_num_p = ecma_number;

  return ecma_pointer_to_ecma_value (ecma_num_p) | ECMA_TYPE_FLOAT;
} /* ecma_create_float_number */
449

450 451 452 453 454 455 456 457 458 459 460
/**
 * Encode float number without checks.
 *
 * @return ecma-value
 */
ecma_value_t
ecma_make_float_value (ecma_number_t *ecma_num_p) /**< pointer to the float number */
{
  return ecma_pointer_to_ecma_value (ecma_num_p) | ECMA_TYPE_FLOAT;
} /* ecma_make_float_value */

461 462 463 464 465
/**
 * Create a new NaN value.
 *
 * @return ecma-value
 */
466
extern inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
467 468 469 470 471 472 473 474 475 476
ecma_make_nan_value (void)
{
  return ecma_create_float_number (ecma_number_make_nan ());
} /* ecma_make_nan_value */

/**
 * Checks whether the passed number is +0.0
 *
 * @return true, if it is +0.0, false otherwise
 */
477
static inline bool JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
478 479
ecma_is_number_equal_to_positive_zero (ecma_number_t ecma_number) /**< number */
{
480 481
  ecma_number_accessor_t u;
  u.as_ecma_number_t = ecma_number;
482
#if !ENABLED (JERRY_NUMBER_TYPE_FLOAT64)
483
  return u.as_uint32_t == 0;
484
#else /* ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
485
  return u.as_uint64_t == 0;
486
#endif /* !ENABLED (JERRY_NUMBER_TYPE_FLOAT64) */
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
} /* ecma_is_number_equal_to_positive_zero */

/**
 * Encode a number into an ecma-value
 *
 * @return ecma-value
 */
ecma_value_t
ecma_make_number_value (ecma_number_t ecma_number) /**< number to be encoded */
{
  ecma_integer_value_t integer_value = (ecma_integer_value_t) ecma_number;

  if ((ecma_number_t) integer_value == ecma_number
      && ((integer_value == 0) ? ecma_is_number_equal_to_positive_zero (ecma_number)
                               : ECMA_IS_INTEGER_NUMBER (integer_value)))
  {
    return ecma_make_integer_value (integer_value);
  }

  return ecma_create_float_number (ecma_number);
507 508
} /* ecma_make_number_value */

509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
/**
 * Encode an int32 number into an ecma-value
 *
 * @return ecma-value
 */
ecma_value_t
ecma_make_int32_value (int32_t int32_number) /**< int32 number to be encoded */
{
  if (ECMA_IS_INTEGER_NUMBER (int32_number))
  {
    return ecma_make_integer_value ((ecma_integer_value_t) int32_number);
  }

  return ecma_create_float_number ((ecma_number_t) int32_number);
} /* ecma_make_int32_value */

/**
 * Encode an unsigned int32 number into an ecma-value
 *
 * @return ecma-value
 */
ecma_value_t
ecma_make_uint32_value (uint32_t uint32_number) /**< uint32 number to be encoded */
{
  if (uint32_number <= ECMA_INTEGER_NUMBER_MAX)
  {
    return ecma_make_integer_value ((ecma_integer_value_t) uint32_number);
  }

  return ecma_create_float_number ((ecma_number_t) uint32_number);
} /* ecma_make_uint32_value */

541 542
/**
 * String value constructor
543 544
 *
 * @return ecma-value representation of the string argument
545
 */
546
inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
547
ecma_make_string_value (const ecma_string_t *ecma_string_p) /**< string to reference in value */
548
{
549
  JERRY_ASSERT (ecma_string_p != NULL);
550
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
551
  JERRY_ASSERT (!ecma_prop_name_is_symbol ((ecma_string_t *) ecma_string_p));
552
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
553

554 555 556 557 558
  if ((((uintptr_t) ecma_string_p) & ECMA_VALUE_TYPE_MASK) != 0)
  {
    return (ecma_value_t) (uintptr_t) ecma_string_p;
  }

559
  return ecma_pointer_to_ecma_value (ecma_string_p) | ECMA_TYPE_STRING;
560 561
} /* ecma_make_string_value */

562
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
563 564 565 566 567 568 569 570 571 572 573 574 575
/**
 * Symbol value constructor
 *
 * @return ecma-value representation of the string argument
 */
inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
ecma_make_symbol_value (const ecma_string_t *ecma_symbol_p) /**< symbol to reference in value */
{
  JERRY_ASSERT (ecma_symbol_p != NULL);
  JERRY_ASSERT (ecma_prop_name_is_symbol ((ecma_string_t *) ecma_symbol_p));

  return ecma_pointer_to_ecma_value (ecma_symbol_p) | ECMA_TYPE_SYMBOL;
} /* ecma_make_symbol_value */
576
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
577 578 579 580 581 582 583 584 585 586 587

/**
 * Property-name value constructor
 *
 * @return ecma-value representation of a property name argument
 */
inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
ecma_make_prop_name_value (const ecma_string_t *ecma_prop_name_p) /**< property name to reference in value */
{
  JERRY_ASSERT (ecma_prop_name_p != NULL);

588
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
589 590 591 592
  if (ecma_prop_name_is_symbol ((ecma_string_t *) ecma_prop_name_p))
  {
    return ecma_make_symbol_value (ecma_prop_name_p);
  }
593
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
594 595 596 597

  return ecma_make_string_value (ecma_prop_name_p);
} /* ecma_make_prop_name_value */

598 599
/**
 * String value constructor
600 601
 *
 * @return ecma-value representation of the string argument
602
 */
603
inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
604 605 606 607 608
ecma_make_magic_string_value (lit_magic_string_id_t id) /**< magic string id */
{
  return (ecma_value_t) ECMA_CREATE_DIRECT_STRING (ECMA_DIRECT_STRING_MAGIC, (uintptr_t) id);
} /* ecma_make_magic_string_value */

609
/**
610
 * Object value constructor
611 612
 *
 * @return ecma-value representation of the object argument
613
 */
614
inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
615
ecma_make_object_value (const ecma_object_t *object_p) /**< object to reference in value */
616
{
617
  JERRY_ASSERT (object_p != NULL);
618

619
  return ecma_pointer_to_ecma_value (object_p) | ECMA_TYPE_OBJECT;
620 621 622
} /* ecma_make_object_value */

/**
623
 * Error reference constructor
624 625
 *
 * @return ecma-value representation of the Error reference
626
 */
627
inline ecma_value_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
628
ecma_make_error_reference_value (const ecma_error_reference_t *error_ref_p) /**< error reference */
629
{
630
  JERRY_ASSERT (error_ref_p != NULL);
631

632 633
  return ecma_pointer_to_ecma_value (error_ref_p) | ECMA_TYPE_ERROR;
} /* ecma_make_error_reference_value */
634

635 636 637
/**
 * Get integer value from an integer ecma value
 *
638
 * @return integer value
639
 */
640
inline ecma_integer_value_t JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
641 642 643 644 645 646 647
ecma_get_integer_from_value (ecma_value_t value) /**< ecma value */
{
  JERRY_ASSERT (ecma_is_value_integer_number (value));

  return ((ecma_integer_value_t) value) >> ECMA_DIRECT_SHIFT;
} /* ecma_get_integer_from_value */

648 649 650 651 652
/**
 * Get floating point value from an ecma value
 *
 * @return floating point value
 */
653
inline ecma_number_t JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
Z
Zoltan Herczeg 已提交
654 655 656 657 658 659 660
ecma_get_float_from_value (ecma_value_t value) /**< ecma value */
{
  JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT);

  return *(ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
} /* ecma_get_float_from_value */

661 662 663 664 665 666 667 668 669 670 671 672 673
/**
 * Get floating point value pointer from an ecma value
 *
 * @return floating point value
 */
inline ecma_number_t * JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
ecma_get_pointer_from_float_value (ecma_value_t value) /**< ecma value */
{
  JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_FLOAT);

  return (ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
} /* ecma_get_pointer_from_float_value */

674
/**
675
 * Get floating point value from an ecma value
676
 *
677
 * @return floating point value
678
 */
679
ecma_number_t JERRY_ATTR_PURE
680
ecma_get_number_from_value (ecma_value_t value) /**< ecma value */
681
{
682 683
  if (ecma_is_value_integer_number (value))
  {
684
    return (ecma_number_t) ecma_get_integer_from_value (value);
685
  }
686

Z
Zoltan Herczeg 已提交
687
  return ecma_get_float_from_value (value);
688 689 690
} /* ecma_get_number_from_value */

/**
691
 * Get pointer to ecma-string from ecma value
692
 *
693
 * @return the string pointer
694
 */
695
inline ecma_string_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
696
ecma_get_string_from_value (ecma_value_t value) /**< ecma value */
697
{
698 699 700 701 702 703
  JERRY_ASSERT (ecma_is_value_string (value));

  if ((value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_DIRECT_STRING)
  {
    return (ecma_string_t *) (uintptr_t) value;
  }
704

705
  return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value);
706 707
} /* ecma_get_string_from_value */

708
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
709 710 711 712 713 714 715 716 717 718 719 720
/**
 * Get pointer to ecma-string from ecma value
 *
 * @return the string pointer
 */
inline ecma_string_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
ecma_get_symbol_from_value (ecma_value_t value) /**< ecma value */
{
  JERRY_ASSERT (ecma_is_value_symbol (value));

  return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value);
} /* ecma_get_symbol_from_value */
721
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740

/**
 * Get pointer to a property name from ecma value
 *
 * @return the string pointer
 */
inline ecma_string_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
ecma_get_prop_name_from_value (ecma_value_t value) /**< ecma value */
{
  JERRY_ASSERT (ecma_is_value_prop_name (value));

  if ((value & ECMA_VALUE_TYPE_MASK) == ECMA_TYPE_DIRECT_STRING)
  {
    return (ecma_string_t *) (uintptr_t) value;
  }

  return (ecma_string_t *) ecma_get_pointer_from_ecma_value (value);
} /* ecma_get_prop_name_from_value */

741
/**
742
 * Get pointer to ecma-object from ecma value
743 744 745
 *
 * @return the pointer
 */
746
inline ecma_object_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
747
ecma_get_object_from_value (ecma_value_t value) /**< ecma value */
748
{
749
  JERRY_ASSERT (ecma_is_value_object (value));
750

751
  return (ecma_object_t *) ecma_get_pointer_from_ecma_value (value);
752 753
} /* ecma_get_object_from_value */

Z
Zoltan Herczeg 已提交
754
/**
755
 * Get pointer to error reference from ecma value
Z
Zoltan Herczeg 已提交
756
 *
757
 * @return the pointer
Z
Zoltan Herczeg 已提交
758
 */
759
inline ecma_error_reference_t *JERRY_ATTR_PURE JERRY_ATTR_ALWAYS_INLINE
760
ecma_get_error_reference_from_value (ecma_value_t value) /**< ecma value */
Z
Zoltan Herczeg 已提交
761
{
762
  JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_ERROR);
Z
Zoltan Herczeg 已提交
763

764 765
  return (ecma_error_reference_t *) ecma_get_pointer_from_ecma_value (value);
} /* ecma_get_error_reference_from_value */
Z
Zoltan Herczeg 已提交
766

767
/**
768
 * Invert a boolean value
769 770 771
 *
 * @return ecma value
 */
772
inline ecma_value_t JERRY_ATTR_CONST JERRY_ATTR_ALWAYS_INLINE
773
ecma_invert_boolean_value (ecma_value_t value) /**< ecma value */
774
{
775
  JERRY_ASSERT (ecma_is_value_boolean (value));
776

777 778
  return (value ^ (1 << ECMA_DIRECT_SHIFT));
} /* ecma_invert_boolean_value */
779 780 781

/**
 * Copy ecma value.
782
 *
L
László Langó 已提交
783
 * @return copy of the given value
784 785
 */
ecma_value_t
L
László Langó 已提交
786
ecma_copy_value (ecma_value_t value)  /**< value description */
787 788 789
{
  switch (ecma_get_value_type_field (value))
  {
790
    case ECMA_TYPE_FLOAT:
791
    {
792
      ecma_number_t *num_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
793

794
      return ecma_create_float_number (*num_p);
795 796 797
    }
    case ECMA_TYPE_STRING:
    {
798 799
      ecma_ref_ecma_string (ecma_get_string_from_value (value));
      return value;
800
    }
801
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
802 803 804 805 806
    case ECMA_TYPE_SYMBOL:
    {
      ecma_ref_ecma_string (ecma_get_symbol_from_value (value));
      return value;
    }
807
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
808 809
    case ECMA_TYPE_OBJECT:
    {
L
László Langó 已提交
810 811
      ecma_ref_object (ecma_get_object_from_value (value));
      return value;
812
    }
813 814
    default:
    {
815 816 817 818
      JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT
                    || ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING);

      return value;
819
    }
820 821 822
  }
} /* ecma_copy_value */

823 824 825 826 827 828 829 830 831 832 833
/**
 * Copy ecma value.
 *
 * Note:
 *   this function is similar to ecma_copy_value, but it is
 *   faster for direct values since no function call is performed.
 *   It also increases the binary size so it is recommended for
 *   critical code paths only.
 *
 * @return copy of the given value
 */
834
inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
835 836 837 838 839
ecma_fast_copy_value (ecma_value_t value)  /**< value description */
{
  return (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT) ? value : ecma_copy_value (value);
} /* ecma_fast_copy_value */

L
László Langó 已提交
840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
/**
 * Copy the ecma value if not an object
 *
 * @return copy of the given value
 */
ecma_value_t
ecma_copy_value_if_not_object (ecma_value_t value) /**< value description */
{
  if (ecma_get_value_type_field (value) != ECMA_TYPE_OBJECT)
  {
    return ecma_copy_value (value);
  }

  return value;
} /* ecma_copy_value_if_not_object */

856 857 858 859 860 861 862 863 864 865 866 867 868
/**
 * Assign a new value to an ecma-value
 *
 * Note:
 *      value previously stored in the property is freed
 */
void
ecma_value_assign_value (ecma_value_t *value_p, /**< [in, out] ecma value */
                         ecma_value_t ecma_value) /**< value to assign */
{
  JERRY_STATIC_ASSERT (ECMA_TYPE_DIRECT == 0,
                       ecma_type_direct_must_be_zero_for_the_next_check);

869 870 871 872 873
  if (*value_p == ecma_value)
  {
    return;
  }

874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892
  if (ecma_get_value_type_field (ecma_value || *value_p) == ECMA_TYPE_DIRECT)
  {
    *value_p = ecma_value;
  }
  else if (ecma_is_value_float_number (ecma_value)
           && ecma_is_value_float_number (*value_p))
  {
    const ecma_number_t *num_src_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (ecma_value);
    ecma_number_t *num_dst_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (*value_p);

    *num_dst_p = *num_src_p;
  }
  else
  {
    ecma_free_value_if_not_object (*value_p);
    *value_p = ecma_copy_value_if_not_object (ecma_value);
  }
} /* ecma_value_assign_value */

Z
Zoltan Herczeg 已提交
893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921
/**
 * Update the value of a float number to a new value
 *
 * Note:
 *   The original value is destroyed.
 *
 * @return updated ecma value
 */
ecma_value_t
ecma_update_float_number (ecma_value_t float_value, /**< original float value */
                          ecma_number_t new_number) /**< updated number value */
{
  JERRY_ASSERT (ecma_is_value_float_number (float_value));

  ecma_integer_value_t integer_number = (ecma_integer_value_t) new_number;
  ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (float_value);

  if ((ecma_number_t) integer_number == new_number
      && ((integer_number == 0) ? ecma_is_number_equal_to_positive_zero (new_number)
                                : ECMA_IS_INTEGER_NUMBER (integer_number)))
  {
    ecma_dealloc_number (number_p);
    return ecma_make_integer_value (integer_number);
  }

  *number_p = new_number;
  return float_value;
} /* ecma_update_float_number */

922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976
/**
 * Assign a float number to an ecma-value
 *
 * Note:
 *      value previously stored in the property is freed
 */
static void
ecma_value_assign_float_number (ecma_value_t *value_p, /**< [in, out] ecma value */
                                ecma_number_t ecma_number) /**< number to assign */
{
  if (ecma_is_value_float_number (*value_p))
  {
    ecma_number_t *num_dst_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (*value_p);

    *num_dst_p = ecma_number;
    return;
  }

  if (ecma_get_value_type_field (*value_p) != ECMA_TYPE_DIRECT
      && ecma_get_value_type_field (*value_p) != ECMA_TYPE_OBJECT)
  {
    ecma_free_value (*value_p);
  }

  *value_p = ecma_create_float_number (ecma_number);
} /* ecma_value_assign_float_number */

/**
 * Assign a number to an ecma-value
 *
 * Note:
 *      value previously stored in the property is freed
 */
void
ecma_value_assign_number (ecma_value_t *value_p, /**< [in, out] ecma value */
                          ecma_number_t ecma_number) /**< number to assign */
{
  ecma_integer_value_t integer_value = (ecma_integer_value_t) ecma_number;

  if ((ecma_number_t) integer_value == ecma_number
      && ((integer_value == 0) ? ecma_is_number_equal_to_positive_zero (ecma_number)
                               : ECMA_IS_INTEGER_NUMBER (integer_value)))
  {
    if (ecma_get_value_type_field (*value_p) != ECMA_TYPE_DIRECT
        && ecma_get_value_type_field (*value_p) != ECMA_TYPE_OBJECT)
    {
      ecma_free_value (*value_p);
    }
    *value_p = ecma_make_integer_value (integer_value);
    return;
  }

  ecma_value_assign_float_number (value_p, ecma_number);
} /* ecma_value_assign_number */

977
/**
978
 * Free the ecma value
979 980
 */
void
981
ecma_free_value (ecma_value_t value) /**< value description */
982 983 984
{
  switch (ecma_get_value_type_field (value))
  {
985
    case ECMA_TYPE_FLOAT:
986
    {
987
      ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
988 989 990 991 992 993 994 995 996 997
      ecma_dealloc_number (number_p);
      break;
    }

    case ECMA_TYPE_STRING:
    {
      ecma_string_t *string_p = ecma_get_string_from_value (value);
      ecma_deref_ecma_string (string_p);
      break;
    }
998
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
999 1000 1001 1002 1003
    case ECMA_TYPE_SYMBOL:
    {
      ecma_deref_ecma_string (ecma_get_symbol_from_value (value));
      break;
    }
1004
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
1005 1006
    case ECMA_TYPE_OBJECT:
    {
1007
      ecma_deref_object (ecma_get_object_from_value (value));
1008 1009
      break;
    }
1010 1011 1012

    default:
    {
1013 1014 1015 1016
      JERRY_ASSERT (ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT
                    || ecma_get_value_type_field (value) == ECMA_TYPE_DIRECT_STRING);

      /* no memory is allocated */
1017 1018
      break;
    }
1019 1020 1021
  }
} /* ecma_free_value */

1022 1023 1024 1025 1026 1027 1028 1029 1030
/**
 * Free the ecma value
 *
 * Note:
 *   this function is similar to ecma_free_value, but it is
 *   faster for direct values since no function call is performed.
 *   It also increases the binary size so it is recommended for
 *   critical code paths only.
 */
1031
inline void JERRY_ATTR_ALWAYS_INLINE
1032 1033 1034 1035 1036 1037 1038 1039
ecma_fast_free_value (ecma_value_t value) /**< value description */
{
  if (ecma_get_value_type_field (value) != ECMA_TYPE_DIRECT)
  {
    ecma_free_value (value);
  }
} /* ecma_fast_free_value */

1040
/**
1041
 * Free the ecma value if not an object
1042 1043
 */
void
1044
ecma_free_value_if_not_object (ecma_value_t value) /**< value description */
1045
{
1046
  if (ecma_get_value_type_field (value) != ECMA_TYPE_OBJECT)
1047
  {
1048
    ecma_free_value (value);
1049
  }
1050
} /* ecma_free_value_if_not_object */
1051

1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066
/**
 * Free an ecma-value number
 */
inline void JERRY_ATTR_ALWAYS_INLINE
ecma_free_number (ecma_value_t value) /**< value description */
{
  JERRY_ASSERT (ecma_is_value_number (value));

  if (ecma_is_value_float_number (value))
  {
    ecma_number_t *number_p = (ecma_number_t *) ecma_get_pointer_from_ecma_value (value);
    ecma_dealloc_number (number_p);
  }
} /* ecma_free_number */

1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
/**
 * Get the literal id associated with the given ecma_value type.
 * This operation is equivalent to the JavaScript 'typeof' operator.
 *
 * @returns one of the following value:
 *          - LIT_MAGIC_STRING_UNDEFINED
 *          - LIT_MAGIC_STRING_OBJECT
 *          - LIT_MAGIC_STRING_BOOLEAN
 *          - LIT_MAGIC_STRING_NUMBER
 *          - LIT_MAGIC_STRING_STRING
 *          - LIT_MAGIC_STRING_FUNCTION
 */
lit_magic_string_id_t
ecma_get_typeof_lit_id (ecma_value_t value) /**< input ecma value */
{
  lit_magic_string_id_t ret_value = LIT_MAGIC_STRING__EMPTY;

  if (ecma_is_value_undefined (value))
  {
    ret_value = LIT_MAGIC_STRING_UNDEFINED;
  }
  else if (ecma_is_value_null (value))
  {
    ret_value = LIT_MAGIC_STRING_OBJECT;
  }
  else if (ecma_is_value_boolean (value))
  {
    ret_value = LIT_MAGIC_STRING_BOOLEAN;
  }
  else if (ecma_is_value_number (value))
  {
    ret_value = LIT_MAGIC_STRING_NUMBER;
  }
  else if (ecma_is_value_string (value))
  {
    ret_value = LIT_MAGIC_STRING_STRING;
  }
1104
#if ENABLED (JERRY_ES2015_BUILTIN_SYMBOL)
1105 1106 1107 1108
  else if (ecma_is_value_symbol (value))
  {
    ret_value = LIT_MAGIC_STRING_SYMBOL;
  }
1109
#endif /* ENABLED (JERRY_ES2015_BUILTIN_SYMBOL) */
1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
  else
  {
    JERRY_ASSERT (ecma_is_value_object (value));

    ret_value = ecma_op_is_callable (value) ? LIT_MAGIC_STRING_FUNCTION : LIT_MAGIC_STRING_OBJECT;
  }

  JERRY_ASSERT (ret_value != LIT_MAGIC_STRING__EMPTY);

  return ret_value;
} /* ecma_get_typeof_lit_id */

1122 1123 1124 1125
/**
 * @}
 * @}
 */