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