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-array-object.h"
18 #include "ecma-gc.h"
19 #include "ecma-globals.h"
20 #include "ecma-helpers.h"
21 #include "ecma-lcache.h"
22 #include "ecma-property-hashmap.h"
23 #include "jcontext.h"
24 #include "jrt-bit-fields.h"
25 #include "byte-code.h"
26 #include "re-compiler.h"
27 #include "ecma-builtins.h"
28 
29 #if ENABLED (JERRY_DEBUGGER)
30 #include "debugger.h"
31 #endif /* ENABLED (JERRY_DEBUGGER) */
32 
33 /** \addtogroup ecma ECMA
34  * @{
35  *
36  * \addtogroup ecmahelpers Helpers for operations with ECMA data types
37  * @{
38  */
39 
40 JERRY_STATIC_ASSERT (ECMA_PROPERTY_TYPE_MASK >= ECMA_PROPERTY_TYPE__MAX,
41                      ecma_property_types_must_be_lower_than_the_container_mask);
42 
43 JERRY_STATIC_ASSERT (ECMA_OBJECT_TYPE_MASK >= ECMA_OBJECT_TYPE__MAX - 1,
44                      ecma_object_types_must_be_lower_than_the_container_mask);
45 
46 JERRY_STATIC_ASSERT (ECMA_OBJECT_TYPE_MASK >= ECMA_LEXICAL_ENVIRONMENT_TYPE__MAX,
47                      ecma_lexical_environment_types_must_be_lower_than_the_container_mask);
48 
49 JERRY_STATIC_ASSERT (ECMA_OBJECT_TYPE_MASK + 1 == ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV,
50                      ecma_built_in_flag_must_follow_the_object_type);
51 
52 JERRY_STATIC_ASSERT (ECMA_OBJECT_FLAG_EXTENSIBLE == (ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV << 1),
53                      ecma_extensible_flag_must_follow_the_built_in_flag);
54 
55 JERRY_STATIC_ASSERT (ECMA_OBJECT_REF_ONE == (ECMA_OBJECT_FLAG_EXTENSIBLE << 1),
56                      ecma_object_ref_one_must_follow_the_extensible_flag);
57 
58 JERRY_STATIC_ASSERT (((ECMA_OBJECT_MAX_REF + ECMA_OBJECT_REF_ONE) | (ECMA_OBJECT_REF_ONE - 1)) == UINT16_MAX,
59                       ecma_object_max_ref_does_not_fill_the_remaining_bits);
60 
61 JERRY_STATIC_ASSERT (ECMA_PROPERTY_TYPE_DELETED == (ECMA_DIRECT_STRING_MAGIC << ECMA_PROPERTY_NAME_TYPE_SHIFT),
62                      ecma_property_type_deleted_must_have_magic_string_name_type);
63 
64 /**
65  * Create an object with specified prototype object
66  * (or NULL prototype if there is not prototype for the object)
67  * and value of 'Extensible' attribute.
68  *
69  * Reference counter's value will be set to one.
70  *
71  * @return pointer to the object's descriptor
72  */
73 ecma_object_t *
ecma_create_object(ecma_object_t *prototype_object_p, size_t ext_object_size, ecma_object_type_t type)74 ecma_create_object (ecma_object_t *prototype_object_p, /**< pointer to prototybe of the object (or NULL) */
75                     size_t ext_object_size, /**< size of extended objects */
76                     ecma_object_type_t type) /**< object type */
77 {
78   ecma_object_t *new_object_p;
79 
80   if (ext_object_size > 0)
81   {
82     new_object_p = (ecma_object_t *) ecma_alloc_extended_object (ext_object_size);
83   }
84   else
85   {
86     new_object_p = ecma_alloc_object ();
87   }
88 
89   new_object_p->type_flags_refs = (uint16_t) (type | ECMA_OBJECT_FLAG_EXTENSIBLE);
90 
91   ecma_init_gc_info (new_object_p);
92 
93   new_object_p->u1.property_list_cp = JMEM_CP_NULL;
94 
95   ECMA_SET_POINTER (new_object_p->u2.prototype_cp, prototype_object_p);
96 
97   return new_object_p;
98 } /* ecma_create_object */
99 
100 /**
101  * Create a declarative lexical environment with specified outer lexical environment
102  * (or NULL if the environment is not nested).
103  *
104  * See also: ECMA-262 v5, 10.2.1.1
105  *
106  * Reference counter's value will be set to one.
107  *
108  * @return pointer to the descriptor of lexical environment
109  */
110 ecma_object_t *
ecma_create_decl_lex_env(ecma_object_t *outer_lexical_environment_p)111 ecma_create_decl_lex_env (ecma_object_t *outer_lexical_environment_p) /**< outer lexical environment */
112 {
113   ecma_object_t *new_lexical_environment_p = ecma_alloc_object ();
114 
115   uint16_t type = ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV | ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE;
116   new_lexical_environment_p->type_flags_refs = type;
117 
118   ecma_init_gc_info (new_lexical_environment_p);
119 
120   new_lexical_environment_p->u1.property_list_cp = JMEM_CP_NULL;
121 
122   ECMA_SET_POINTER (new_lexical_environment_p->u2.outer_reference_cp, outer_lexical_environment_p);
123 
124   return new_lexical_environment_p;
125 } /* ecma_create_decl_lex_env */
126 
127 /**
128  * Create a object lexical environment with specified outer lexical environment
129  * (or NULL if the environment is not nested), binding object and provided type flag.
130  *
131  * See also: ECMA-262 v5, 10.2.1.2
132  *
133  * Reference counter's value will be set to one.
134  *
135  * @return pointer to the descriptor of lexical environment
136  */
137 ecma_object_t *
ecma_create_object_lex_env(ecma_object_t *outer_lexical_environment_p, ecma_object_t *binding_obj_p, ecma_lexical_environment_type_t type)138 ecma_create_object_lex_env (ecma_object_t *outer_lexical_environment_p, /**< outer lexical environment */
139                             ecma_object_t *binding_obj_p, /**< binding object */
140                             ecma_lexical_environment_type_t type) /**< type of the new lexical environment */
141 {
142 #if ENABLED (JERRY_ES2015)
143   JERRY_ASSERT (type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND
144                 || type == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
145 #else /* !ENABLED (JERRY_ES2015) */
146   JERRY_ASSERT (type == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
147 #endif /* ENABLED (JERRY_ES2015) */
148 
149   JERRY_ASSERT (binding_obj_p != NULL
150                 && !ecma_is_lexical_environment (binding_obj_p));
151 
152   ecma_object_t *new_lexical_environment_p = ecma_alloc_object ();
153 
154   new_lexical_environment_p->type_flags_refs = (uint16_t) (ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV | type);
155 
156   ecma_init_gc_info (new_lexical_environment_p);
157 
158   ECMA_SET_NON_NULL_POINTER (new_lexical_environment_p->u1.bound_object_cp,
159                              binding_obj_p);
160 
161   ECMA_SET_POINTER (new_lexical_environment_p->u2.outer_reference_cp, outer_lexical_environment_p);
162 
163   return new_lexical_environment_p;
164 } /* ecma_create_object_lex_env */
165 
166 /**
167  * Check if the object is lexical environment.
168  *
169  * @return true  - if object is a lexical environment
170  *         false - otherwise
171  */
172 inline bool JERRY_ATTR_PURE
ecma_is_lexical_environment(const ecma_object_t *object_p)173 ecma_is_lexical_environment (const ecma_object_t *object_p) /**< object or lexical environment */
174 {
175   JERRY_ASSERT (object_p != NULL);
176 
177   uint32_t full_type = object_p->type_flags_refs & (ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV | ECMA_OBJECT_TYPE_MASK);
178 
179   return full_type >= (ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV | ECMA_LEXICAL_ENVIRONMENT_TYPE_START);
180 } /* ecma_is_lexical_environment */
181 
182 /**
183  * Set value of [[Extensible]] object's internal property.
184  */
185 inline void
ecma_op_ordinary_object_set_extensible(ecma_object_t *object_p)186 ecma_op_ordinary_object_set_extensible (ecma_object_t *object_p) /**< object */
187 {
188   JERRY_ASSERT (object_p != NULL);
189   JERRY_ASSERT (!ecma_is_lexical_environment (object_p));
190 
191   object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs | ECMA_OBJECT_FLAG_EXTENSIBLE);
192 } /* ecma_op_ordinary_object_set_extensible */
193 
194 /**
195  * Get object's internal implementation-defined type.
196  *
197  * @return type of the object (ecma_object_type_t)
198  */
199 inline ecma_object_type_t JERRY_ATTR_PURE
ecma_get_object_type(const ecma_object_t *object_p)200 ecma_get_object_type (const ecma_object_t *object_p) /**< object */
201 {
202   JERRY_ASSERT (object_p != NULL);
203   JERRY_ASSERT (!ecma_is_lexical_environment (object_p));
204 
205   return (ecma_object_type_t) (object_p->type_flags_refs & ECMA_OBJECT_TYPE_MASK);
206 } /* ecma_get_object_type */
207 
208 /**
209  * Check if the object is a built-in object
210  *
211  * @return true  - if object is a built-in object
212  *         false - otherwise
213  */
214 inline bool JERRY_ATTR_PURE
ecma_get_object_is_builtin(const ecma_object_t *object_p)215 ecma_get_object_is_builtin (const ecma_object_t *object_p) /**< object */
216 {
217   JERRY_ASSERT (object_p != NULL);
218   JERRY_ASSERT (!ecma_is_lexical_environment (object_p));
219 
220   return (object_p->type_flags_refs & ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV) != 0;
221 } /* ecma_get_object_is_builtin */
222 
223 /**
224  * Set flag indicating whether the object is a built-in object
225  */
226 inline void
ecma_set_object_is_builtin(ecma_object_t *object_p)227 ecma_set_object_is_builtin (ecma_object_t *object_p) /**< object */
228 {
229   JERRY_ASSERT (object_p != NULL);
230   JERRY_ASSERT (!(object_p->type_flags_refs & ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV));
231   JERRY_ASSERT ((object_p->type_flags_refs & ECMA_OBJECT_TYPE_MASK) < ECMA_LEXICAL_ENVIRONMENT_TYPE_START);
232 
233   object_p->type_flags_refs = (uint16_t) (object_p->type_flags_refs | ECMA_OBJECT_FLAG_BUILT_IN_OR_LEXICAL_ENV);
234 } /* ecma_set_object_is_builtin */
235 
236 /**
237  * Get the built-in ID of the object.
238  * If the object is not builtin, return ECMA_BUILTIN_ID__COUNT
239  *
240  * @return the ID of the built-in
241  */
242 inline uint8_t
ecma_get_object_builtin_id(ecma_object_t *object_p)243 ecma_get_object_builtin_id (ecma_object_t *object_p) /**< object */
244 {
245   if (!ecma_get_object_is_builtin (object_p))
246   {
247     return ECMA_BUILTIN_ID__COUNT;
248   }
249 
250   ecma_built_in_props_t *built_in_props_p;
251   ecma_object_type_t object_type = ecma_get_object_type (object_p);
252 
253   if (object_type == ECMA_OBJECT_TYPE_CLASS || object_type == ECMA_OBJECT_TYPE_ARRAY)
254   {
255     built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in;
256   }
257   else
258   {
259     built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in;
260   }
261 
262   return built_in_props_p->id;
263 } /* ecma_get_object_builtin_id */
264 
265 /**
266  * Get type of lexical environment.
267  *
268  * @return type of the lexical environment (ecma_lexical_environment_type_t)
269  */
270 inline ecma_lexical_environment_type_t JERRY_ATTR_PURE
ecma_get_lex_env_type(const ecma_object_t *object_p)271 ecma_get_lex_env_type (const ecma_object_t *object_p) /**< lexical environment */
272 {
273   JERRY_ASSERT (object_p != NULL);
274   JERRY_ASSERT (ecma_is_lexical_environment (object_p));
275 
276   if (object_p == NULL)
277   {
278     jerry_fatal(ERR_FAILED_INTERNAL_ASSERTION);
279   }
280 
281   return (ecma_lexical_environment_type_t) (object_p->type_flags_refs & ECMA_OBJECT_TYPE_MASK);
282 } /* ecma_get_lex_env_type */
283 
284 /**
285  * Get lexical environment's bound object.
286  *
287  * @return pointer to ecma object
288  */
289 inline ecma_object_t *JERRY_ATTR_PURE
ecma_get_lex_env_binding_object(const ecma_object_t *object_p)290 ecma_get_lex_env_binding_object (const ecma_object_t *object_p) /**< object-bound lexical environment */
291 {
292   JERRY_ASSERT (object_p != NULL);
293   JERRY_ASSERT (ecma_is_lexical_environment (object_p));
294 #if ENABLED (JERRY_ES2015)
295   JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND
296                 || ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_HOME_OBJECT_BOUND);
297 #else /* !ENABLED (JERRY_ES2015) */
298   JERRY_ASSERT (ecma_get_lex_env_type (object_p) == ECMA_LEXICAL_ENVIRONMENT_THIS_OBJECT_BOUND);
299 #endif /* ENABLED (JERRY_ES2015) */
300 
301   return ECMA_GET_NON_NULL_POINTER (ecma_object_t, object_p->u1.bound_object_cp);
302 } /* ecma_get_lex_env_binding_object */
303 
304 /**
305  * Create a new lexical environment with the same property list as the passed lexical environment
306  *
307  * @return pointer to the newly created lexical environment
308  */
309 ecma_object_t *
ecma_clone_decl_lexical_environment(ecma_object_t *lex_env_p, bool copy_values)310 ecma_clone_decl_lexical_environment (ecma_object_t *lex_env_p, /**< declarative lexical environment */
311                                      bool copy_values) /**< copy property values as well */
312 {
313   JERRY_ASSERT (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE);
314   JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
315 
316   ecma_object_t *outer_lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
317   ecma_object_t *new_lex_env_p = ecma_create_decl_lex_env (outer_lex_env_p);
318 
319   jmem_cpointer_t prop_iter_cp = lex_env_p->u1.property_list_cp;
320   JERRY_ASSERT (prop_iter_cp != JMEM_CP_NULL);
321 
322   ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t,
323                                                                    prop_iter_cp);
324   if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
325   {
326     prop_iter_cp = prop_iter_p->next_property_cp;
327   }
328 
329   JERRY_ASSERT (prop_iter_cp != JMEM_CP_NULL);
330 
331   do
332   {
333     prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
334 
335     JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
336 
337     ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
338 
339     for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
340     {
341       if (prop_iter_p->types[i] != ECMA_PROPERTY_TYPE_DELETED)
342       {
343         JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_iter_p->types[i]) == ECMA_PROPERTY_TYPE_NAMEDDATA);
344 
345         uint8_t prop_attributes = (uint8_t) (prop_iter_p->types[i] & ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE);
346         ecma_string_t *name_p = ecma_string_from_property_name (prop_iter_p->types[i], prop_pair_p->names_cp[i]);
347 
348         ecma_property_value_t *property_value_p;
349         property_value_p = ecma_create_named_data_property (new_lex_env_p, name_p, prop_attributes, NULL);
350 
351         ecma_deref_ecma_string (name_p);
352 
353         JERRY_ASSERT (property_value_p->value == ECMA_VALUE_UNDEFINED);
354 
355         if (copy_values)
356         {
357           property_value_p->value = ecma_copy_value_if_not_object (prop_pair_p->values[i].value);
358         }
359         else
360         {
361           property_value_p->value = ECMA_VALUE_UNINITIALIZED;
362         }
363       }
364     }
365 
366     prop_iter_cp = prop_iter_p->next_property_cp;
367   }
368   while (prop_iter_cp != JMEM_CP_NULL);
369 
370   ecma_deref_object (lex_env_p);
371   return new_lex_env_p;
372 } /* ecma_clone_decl_lexical_environment */
373 
374 /**
375  * Create a property in an object and link it into
376  * the object's properties' linked-list (at start of the list).
377  *
378  * @return pointer to the newly created property value
379  */
380 static ecma_property_value_t *
ecma_create_property(ecma_object_t *object_p, ecma_string_t *name_p, uint8_t type_and_flags, ecma_property_value_t value, ecma_property_t **out_prop_p)381 ecma_create_property (ecma_object_t *object_p, /**< the object */
382                       ecma_string_t *name_p, /**< property name */
383                       uint8_t type_and_flags, /**< type and flags, see ecma_property_info_t */
384                       ecma_property_value_t value, /**< property value */
385                       ecma_property_t **out_prop_p) /**< [out] the property is also returned
386                                                      *         if this field is non-NULL */
387 {
388   JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2);
389   JERRY_ASSERT (name_p != NULL);
390   JERRY_ASSERT (object_p != NULL);
391 
392   jmem_cpointer_t *property_list_head_p = &object_p->u1.property_list_cp;
393 
394   if (*property_list_head_p != ECMA_NULL_POINTER)
395   {
396     /* If the first entry is free (deleted), it is reused. */
397     ecma_property_header_t *first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t,
398                                                                           *property_list_head_p);
399 
400 #if ENABLED (JERRY_PROPRETY_HASHMAP)
401     bool has_hashmap = false;
402 
403     if (first_property_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
404     {
405       property_list_head_p = &first_property_p->next_property_cp;
406       first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t,
407                                                     *property_list_head_p);
408       has_hashmap = true;
409     }
410 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
411 
412     JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (first_property_p));
413 
414     if (first_property_p->types[0] == ECMA_PROPERTY_TYPE_DELETED)
415     {
416       ecma_property_pair_t *first_property_pair_p = (ecma_property_pair_t *) first_property_p;
417 
418       ecma_property_t name_type;
419       first_property_pair_p->names_cp[0] = ecma_string_to_property_name (name_p,
420                                                                          &name_type);
421       first_property_p->types[0] = (ecma_property_t) (type_and_flags | name_type);
422 
423       ecma_property_t *property_p = first_property_p->types + 0;
424 
425       JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 0);
426 
427       if (out_prop_p != NULL)
428       {
429         *out_prop_p = property_p;
430       }
431 
432       first_property_pair_p->values[0] = value;
433 
434 #if ENABLED (JERRY_PROPRETY_HASHMAP)
435       /* The property must be fully initialized before ecma_property_hashmap_insert
436        * is called, because the insert operation may reallocate the hashmap, and
437        * that triggers garbage collection which scans all properties of all objects.
438        * A not fully initialized but queued property may cause a crash. */
439 
440       if (has_hashmap)
441       {
442         ecma_property_hashmap_insert (object_p,
443                                       name_p,
444                                       first_property_pair_p,
445                                       0);
446       }
447 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
448 
449       return first_property_pair_p->values + 0;
450     }
451   }
452 
453   /* Otherwise we create a new property pair and use its second value. */
454   ecma_property_pair_t *first_property_pair_p = ecma_alloc_property_pair ();
455 
456   /* Need to query property_list_head_p again and recheck the existennce
457    * of property hasmap, because ecma_alloc_property_pair may delete them. */
458   property_list_head_p = &object_p->u1.property_list_cp;
459 #if ENABLED (JERRY_PROPRETY_HASHMAP)
460   bool has_hashmap = false;
461 
462   if (*property_list_head_p != ECMA_NULL_POINTER)
463   {
464     ecma_property_header_t *first_property_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t,
465                                                                           *property_list_head_p);
466 
467     if (first_property_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
468     {
469       property_list_head_p = &first_property_p->next_property_cp;
470       has_hashmap = true;
471     }
472   }
473 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
474 
475   /* Just copy the previous value (no need to decompress, compress). */
476   first_property_pair_p->header.next_property_cp = *property_list_head_p;
477   first_property_pair_p->header.types[0] = ECMA_PROPERTY_TYPE_DELETED;
478   first_property_pair_p->names_cp[0] = LIT_INTERNAL_MAGIC_STRING_DELETED;
479 
480   ecma_property_t name_type;
481   first_property_pair_p->names_cp[1] = ecma_string_to_property_name (name_p,
482                                                                      &name_type);
483 
484   first_property_pair_p->header.types[1] = (ecma_property_t) (type_and_flags | name_type);
485 
486   ECMA_SET_NON_NULL_POINTER (*property_list_head_p, &first_property_pair_p->header);
487 
488   ecma_property_t *property_p = first_property_pair_p->header.types + 1;
489 
490   JERRY_ASSERT (ECMA_PROPERTY_VALUE_PTR (property_p) == first_property_pair_p->values + 1);
491 
492   if (out_prop_p != NULL)
493   {
494     *out_prop_p = property_p;
495   }
496 
497   first_property_pair_p->values[1] = value;
498 
499 #if ENABLED (JERRY_PROPRETY_HASHMAP)
500   /* See the comment before the other ecma_property_hashmap_insert above. */
501 
502   if (has_hashmap)
503   {
504     ecma_property_hashmap_insert (object_p,
505                                   name_p,
506                                   first_property_pair_p,
507                                   1);
508   }
509 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
510 
511   return first_property_pair_p->values + 1;
512 } /* ecma_create_property */
513 
514 /**
515  * Create named data property with given name, attributes and undefined value
516  * in the specified object.
517  *
518  * @return pointer to the newly created property value
519  */
520 ecma_property_value_t *
ecma_create_named_data_property(ecma_object_t *object_p, ecma_string_t *name_p, uint8_t prop_attributes, ecma_property_t **out_prop_p)521 ecma_create_named_data_property (ecma_object_t *object_p, /**< object */
522                                  ecma_string_t *name_p, /**< property name */
523                                  uint8_t prop_attributes, /**< property attributes (See: ecma_property_flags_t) */
524                                  ecma_property_t **out_prop_p) /**< [out] the property is also returned
525                                                                 *         if this field is non-NULL */
526 {
527   JERRY_ASSERT (object_p != NULL && name_p != NULL);
528   JERRY_ASSERT (ecma_is_lexical_environment (object_p)
529                 || !ecma_op_object_is_fast_array (object_p));
530   JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL);
531   JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE_WRITABLE) == 0);
532 
533   uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDDATA | prop_attributes;
534 
535   ecma_property_value_t value;
536   value.value = ECMA_VALUE_UNDEFINED;
537 
538   return ecma_create_property (object_p, name_p, type_and_flags, value, out_prop_p);
539 } /* ecma_create_named_data_property */
540 
541 /**
542  * Create named accessor property with given name, attributes, getter and setter.
543  *
544  * @return pointer to the newly created property value
545  */
546 ecma_property_value_t *
ecma_create_named_accessor_property(ecma_object_t *object_p, ecma_string_t *name_p, ecma_object_t *get_p, ecma_object_t *set_p, uint8_t prop_attributes, ecma_property_t **out_prop_p)547 ecma_create_named_accessor_property (ecma_object_t *object_p, /**< object */
548                                      ecma_string_t *name_p, /**< property name */
549                                      ecma_object_t *get_p, /**< getter */
550                                      ecma_object_t *set_p, /**< setter */
551                                      uint8_t prop_attributes, /**< property attributes */
552                                      ecma_property_t **out_prop_p) /**< [out] the property is also returned
553                                                                     *         if this field is non-NULL */
554 {
555   JERRY_ASSERT (object_p != NULL && name_p != NULL);
556   JERRY_ASSERT (ecma_is_lexical_environment (object_p)
557                 || !ecma_op_object_is_fast_array (object_p));
558   JERRY_ASSERT (ecma_find_named_property (object_p, name_p) == NULL);
559   JERRY_ASSERT ((prop_attributes & ~ECMA_PROPERTY_CONFIGURABLE_ENUMERABLE) == 0);
560 
561   uint8_t type_and_flags = ECMA_PROPERTY_TYPE_NAMEDACCESSOR | prop_attributes;
562 
563   ecma_property_value_t value;
564 #if ENABLED (JERRY_CPOINTER_32_BIT)
565   ecma_getter_setter_pointers_t *getter_setter_pair_p;
566   getter_setter_pair_p = jmem_pools_alloc (sizeof (ecma_getter_setter_pointers_t));
567   ECMA_SET_POINTER (getter_setter_pair_p->getter_cp, get_p);
568   ECMA_SET_POINTER (getter_setter_pair_p->setter_cp, set_p);
569   ECMA_SET_NON_NULL_POINTER (value.getter_setter_pair_cp, getter_setter_pair_p);
570 #else /* !ENABLED (JERRY_CPOINTER_32_BIT) */
571   ECMA_SET_POINTER (value.getter_setter_pair.getter_cp, get_p);
572   ECMA_SET_POINTER (value.getter_setter_pair.setter_cp, set_p);
573 #endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
574 
575   return ecma_create_property (object_p, name_p, type_and_flags, value, out_prop_p);
576 } /* ecma_create_named_accessor_property */
577 
578 /**
579  * Find named data property or named access property in specified object.
580  *
581  * @return pointer to the property, if it is found,
582  *         NULL - otherwise.
583  */
584 ecma_property_t *
ecma_find_named_property(ecma_object_t *obj_p, ecma_string_t *name_p)585 ecma_find_named_property (ecma_object_t *obj_p, /**< object to find property in */
586                           ecma_string_t *name_p) /**< property's name */
587 {
588   JERRY_ASSERT (obj_p != NULL);
589   JERRY_ASSERT (name_p != NULL);
590   JERRY_ASSERT (ecma_is_lexical_environment (obj_p)
591                 || !ecma_op_object_is_fast_array (obj_p));
592 
593   ecma_property_t *property_p = NULL;
594 
595 #if ENABLED (JERRY_LCACHE)
596   property_p = ecma_lcache_lookup (obj_p, name_p);
597   if (property_p != NULL)
598   {
599     return property_p;
600   }
601 #endif /* ENABLED (JERRY_LCACHE) */
602 
603   jmem_cpointer_t prop_iter_cp = obj_p->u1.property_list_cp;
604 
605 #if ENABLED (JERRY_PROPRETY_HASHMAP)
606   if (prop_iter_cp != JMEM_CP_NULL)
607   {
608     ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t,
609                                                                      prop_iter_cp);
610     if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
611     {
612       jmem_cpointer_t property_real_name_cp;
613       property_p = ecma_property_hashmap_find ((ecma_property_hashmap_t *) prop_iter_p,
614                                                name_p,
615                                                &property_real_name_cp);
616 #if ENABLED (JERRY_LCACHE)
617       if (property_p != NULL
618           && !ecma_is_property_lcached (property_p))
619       {
620         ecma_lcache_insert (obj_p, property_real_name_cp, property_p);
621       }
622 #endif /* ENABLED (JERRY_LCACHE) */
623       return property_p;
624     }
625   }
626 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
627 
628 #if ENABLED (JERRY_PROPRETY_HASHMAP)
629   uint32_t steps = 0;
630 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
631   jmem_cpointer_t property_name_cp = ECMA_NULL_POINTER;
632 
633   if (ECMA_IS_DIRECT_STRING (name_p))
634   {
635     ecma_property_t prop_name_type = (ecma_property_t) ECMA_GET_DIRECT_STRING_TYPE (name_p);
636     property_name_cp = (jmem_cpointer_t) ECMA_GET_DIRECT_STRING_VALUE (name_p);
637 
638     JERRY_ASSERT (prop_name_type > 0);
639 
640     while (prop_iter_cp != JMEM_CP_NULL)
641     {
642       ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t,
643                                                                        prop_iter_cp);
644 
645       JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
646 
647       ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
648 
649       if (prop_pair_p->names_cp[0] == property_name_cp
650           && ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[0]) == prop_name_type)
651       {
652         JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[0]));
653 
654         property_p = prop_iter_p->types + 0;
655         break;
656       }
657 
658       if (prop_pair_p->names_cp[1] == property_name_cp
659           && ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[1]) == prop_name_type)
660       {
661         JERRY_ASSERT (ECMA_PROPERTY_IS_NAMED_PROPERTY (prop_iter_p->types[1]));
662 
663         property_p = prop_iter_p->types + 1;
664         break;
665       }
666 
667 #if ENABLED (JERRY_PROPRETY_HASHMAP)
668       steps++;
669 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
670       prop_iter_cp = prop_iter_p->next_property_cp;
671     }
672   }
673   else
674   {
675     while (prop_iter_cp != JMEM_CP_NULL)
676     {
677       ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t,
678                                                                        prop_iter_cp);
679 
680       JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
681 
682       ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
683 
684       if (ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[0]) == ECMA_DIRECT_STRING_PTR)
685       {
686         property_name_cp = prop_pair_p->names_cp[0];
687         ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_name_cp);
688 
689         if (ecma_compare_ecma_non_direct_strings (name_p, prop_name_p))
690         {
691           property_p = prop_iter_p->types + 0;
692           break;
693         }
694       }
695 
696       if (ECMA_PROPERTY_GET_NAME_TYPE (prop_iter_p->types[1]) == ECMA_DIRECT_STRING_PTR)
697       {
698         property_name_cp = prop_pair_p->names_cp[1];
699         ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, property_name_cp);
700 
701         if (ecma_compare_ecma_non_direct_strings (name_p, prop_name_p))
702         {
703           property_p = prop_iter_p->types + 1;
704           break;
705         }
706       }
707 
708 #if ENABLED (JERRY_PROPRETY_HASHMAP)
709       steps++;
710 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
711       prop_iter_cp = prop_iter_p->next_property_cp;
712     }
713   }
714 
715 #if ENABLED (JERRY_PROPRETY_HASHMAP)
716   if (steps >= (ECMA_PROPERTY_HASMAP_MINIMUM_SIZE / 2))
717   {
718     ecma_property_hashmap_create (obj_p);
719   }
720 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
721 
722 #if ENABLED (JERRY_LCACHE)
723   if (property_p != NULL
724       && !ecma_is_property_lcached (property_p))
725   {
726     ecma_lcache_insert (obj_p, property_name_cp, property_p);
727   }
728 #endif /* ENABLED (JERRY_LCACHE) */
729 
730   return property_p;
731 } /* ecma_find_named_property */
732 
733 /**
734  * Get named data property or named access property in specified object.
735  *
736  * Warning:
737  *         the property must exist
738  *
739  * @return pointer to the property, if it is found,
740  *         NULL - otherwise.
741  */
742 ecma_property_value_t *
ecma_get_named_data_property(ecma_object_t *obj_p, ecma_string_t *name_p)743 ecma_get_named_data_property (ecma_object_t *obj_p, /**< object to find property in */
744                               ecma_string_t *name_p) /**< property's name */
745 {
746   JERRY_ASSERT (obj_p != NULL);
747   JERRY_ASSERT (name_p != NULL);
748   JERRY_ASSERT (ecma_is_lexical_environment (obj_p)
749                 || !ecma_op_object_is_fast_array (obj_p));
750 
751   ecma_property_t *property_p = ecma_find_named_property (obj_p, name_p);
752 
753   JERRY_ASSERT (property_p != NULL
754                 && ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
755 
756   return ECMA_PROPERTY_VALUE_PTR (property_p);
757 } /* ecma_get_named_data_property */
758 
759 /**
760  * Free property values and change their type to deleted.
761  */
762 void
ecma_free_property(ecma_object_t *object_p, jmem_cpointer_t name_cp, ecma_property_t *property_p)763 ecma_free_property (ecma_object_t *object_p, /**< object the property belongs to */
764                     jmem_cpointer_t name_cp, /**< name of the property or ECMA_NULL_POINTER */
765                     ecma_property_t *property_p) /**< property */
766 {
767   JERRY_ASSERT (object_p != NULL && property_p != NULL);
768 
769   switch (ECMA_PROPERTY_GET_TYPE (*property_p))
770   {
771     case ECMA_PROPERTY_TYPE_NAMEDDATA:
772     {
773       ecma_free_value_if_not_object (ECMA_PROPERTY_VALUE_PTR (property_p)->value);
774       break;
775     }
776     case ECMA_PROPERTY_TYPE_NAMEDACCESSOR:
777     {
778 #if ENABLED (JERRY_CPOINTER_32_BIT)
779       ecma_getter_setter_pointers_t *getter_setter_pair_p;
780       getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t,
781                                                         ECMA_PROPERTY_VALUE_PTR (property_p)->getter_setter_pair_cp);
782       jmem_pools_free (getter_setter_pair_p, sizeof (ecma_getter_setter_pointers_t));
783 #endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
784       break;
785     }
786     default:
787     {
788       JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_INTERNAL);
789 
790       /* Must be a native pointer. */
791       JERRY_ASSERT (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_MAGIC
792                     && name_cp >= LIT_FIRST_INTERNAL_MAGIC_STRING);
793       break;
794     }
795   }
796 
797 #if ENABLED (JERRY_LCACHE)
798   if (ecma_is_property_lcached (property_p))
799   {
800     ecma_lcache_invalidate (object_p, name_cp, property_p);
801   }
802 #endif /* ENABLED (JERRY_LCACHE) */
803 
804   if (ECMA_PROPERTY_GET_NAME_TYPE (*property_p) == ECMA_DIRECT_STRING_PTR)
805   {
806     ecma_string_t *prop_name_p = ECMA_GET_NON_NULL_POINTER (ecma_string_t, name_cp);
807     ecma_deref_ecma_string (prop_name_p);
808   }
809 } /* ecma_free_property */
810 
811 /**
812  * Delete the object's property referenced by its value pointer.
813  *
814  * Note: specified property must be owned by specified object.
815  */
816 void
ecma_delete_property(ecma_object_t *object_p, ecma_property_value_t *prop_value_p)817 ecma_delete_property (ecma_object_t *object_p, /**< object */
818                       ecma_property_value_t *prop_value_p) /**< property value reference */
819 {
820   jmem_cpointer_t cur_prop_cp = object_p->u1.property_list_cp;
821 
822   ecma_property_header_t *prev_prop_p = NULL;
823 
824 #if ENABLED (JERRY_PROPRETY_HASHMAP)
825   ecma_property_hashmap_delete_status hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_NO_HASHMAP;
826 
827   if (cur_prop_cp != JMEM_CP_NULL)
828   {
829     ecma_property_header_t *cur_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t,
830                                                                     cur_prop_cp);
831 
832     if (cur_prop_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
833     {
834       prev_prop_p = cur_prop_p;
835       cur_prop_cp = cur_prop_p->next_property_cp;
836       hashmap_status = ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP;
837     }
838   }
839 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
840 
841   while (cur_prop_cp != JMEM_CP_NULL)
842   {
843     ecma_property_header_t *cur_prop_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t,
844                                                                     cur_prop_cp);
845 
846     JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (cur_prop_p));
847 
848     ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) cur_prop_p;
849 
850     for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
851     {
852       if ((prop_pair_p->values + i) == prop_value_p)
853       {
854         JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (cur_prop_p->types[i]) != ECMA_PROPERTY_TYPE_SPECIAL);
855 
856 #if ENABLED (JERRY_PROPRETY_HASHMAP)
857         if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_HAS_HASHMAP)
858         {
859           hashmap_status = ecma_property_hashmap_delete (object_p,
860                                                          prop_pair_p->names_cp[i],
861                                                          cur_prop_p->types + i);
862         }
863 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
864 
865         ecma_free_property (object_p, prop_pair_p->names_cp[i], cur_prop_p->types + i);
866         cur_prop_p->types[i] = ECMA_PROPERTY_TYPE_DELETED;
867         prop_pair_p->names_cp[i] = LIT_INTERNAL_MAGIC_STRING_DELETED;
868 
869         JERRY_ASSERT (ECMA_PROPERTY_PAIR_ITEM_COUNT == 2);
870 
871         if (cur_prop_p->types[1 - i] != ECMA_PROPERTY_TYPE_DELETED)
872         {
873 #if ENABLED (JERRY_PROPRETY_HASHMAP)
874           /* The other property is still valid. */
875           if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP)
876           {
877             ecma_property_hashmap_free (object_p);
878             ecma_property_hashmap_create (object_p);
879           }
880 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
881           return;
882         }
883 
884         JERRY_ASSERT (cur_prop_p->types[i] == ECMA_PROPERTY_TYPE_DELETED);
885 
886         if (prev_prop_p == NULL)
887         {
888           object_p->u1.property_list_cp = cur_prop_p->next_property_cp;
889         }
890         else
891         {
892           prev_prop_p->next_property_cp = cur_prop_p->next_property_cp;
893         }
894 
895         ecma_dealloc_property_pair ((ecma_property_pair_t *) cur_prop_p);
896 
897 #if ENABLED (JERRY_PROPRETY_HASHMAP)
898         if (hashmap_status == ECMA_PROPERTY_HASHMAP_DELETE_RECREATE_HASHMAP)
899         {
900           ecma_property_hashmap_free (object_p);
901           ecma_property_hashmap_create (object_p);
902         }
903 #endif /* ENABLED (JERRY_PROPRETY_HASHMAP) */
904         return;
905       }
906     }
907 
908     prev_prop_p = cur_prop_p;
909     cur_prop_cp = cur_prop_p->next_property_cp;
910   }
911 } /* ecma_delete_property */
912 
913 /**
914  * Check whether the object contains a property
915  */
916 static void
ecma_assert_object_contains_the_property(const ecma_object_t *object_p, const ecma_property_value_t *prop_value_p, ecma_property_types_t type)917 ecma_assert_object_contains_the_property (const ecma_object_t *object_p, /**< ecma-object */
918                                           const ecma_property_value_t *prop_value_p, /**< property value */
919                                           ecma_property_types_t type) /**< expected property type */
920 {
921 #ifndef JERRY_NDEBUG
922   jmem_cpointer_t prop_iter_cp = object_p->u1.property_list_cp;
923   JERRY_ASSERT (prop_iter_cp != JMEM_CP_NULL);
924 
925   ecma_property_header_t *prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
926 
927   if (prop_iter_p->types[0] == ECMA_PROPERTY_TYPE_HASHMAP)
928   {
929     prop_iter_cp = prop_iter_p->next_property_cp;
930   }
931 
932   while (prop_iter_cp != JMEM_CP_NULL)
933   {
934     prop_iter_p = ECMA_GET_NON_NULL_POINTER (ecma_property_header_t, prop_iter_cp);
935 
936     JERRY_ASSERT (ECMA_PROPERTY_IS_PROPERTY_PAIR (prop_iter_p));
937 
938     ecma_property_pair_t *prop_pair_p = (ecma_property_pair_t *) prop_iter_p;
939 
940     for (int i = 0; i < ECMA_PROPERTY_PAIR_ITEM_COUNT; i++)
941     {
942       if ((prop_pair_p->values + i) == prop_value_p)
943       {
944         JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (prop_pair_p->header.types[i]) == type);
945         return;
946       }
947     }
948 
949     prop_iter_cp = prop_iter_p->next_property_cp;
950   }
951 #else /* JERRY_NDEBUG */
952   JERRY_UNUSED (object_p);
953   JERRY_UNUSED (prop_value_p);
954   JERRY_UNUSED (type);
955 #endif /* !JERRY_NDEBUG */
956 } /* ecma_assert_object_contains_the_property */
957 
958 /**
959  * Assign value to named data property
960  *
961  * Note:
962  *      value previously stored in the property is freed
963  */
964 inline void JERRY_ATTR_ALWAYS_INLINE
ecma_named_data_property_assign_value(ecma_object_t *obj_p, ecma_property_value_t *prop_value_p, ecma_value_t value)965 ecma_named_data_property_assign_value (ecma_object_t *obj_p, /**< object */
966                                        ecma_property_value_t *prop_value_p, /**< property value reference */
967                                        ecma_value_t value) /**< value to assign */
968 {
969   ecma_assert_object_contains_the_property (obj_p, prop_value_p, ECMA_PROPERTY_TYPE_NAMEDDATA);
970 
971   ecma_value_assign_value (&prop_value_p->value, value);
972 } /* ecma_named_data_property_assign_value */
973 
974 /**
975  * Get named accessor property getter-setter-pair
976  *
977  * @return pointer to object's getter-setter pair
978  */
979 ecma_getter_setter_pointers_t *
ecma_get_named_accessor_property(const ecma_property_value_t *prop_value_p)980 ecma_get_named_accessor_property (const ecma_property_value_t *prop_value_p) /**< property value reference */
981 {
982 #if ENABLED (JERRY_CPOINTER_32_BIT)
983   return ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t, prop_value_p->getter_setter_pair_cp);
984 #else /* !ENABLED (JERRY_CPOINTER_32_BIT) */
985   return (ecma_getter_setter_pointers_t *) &prop_value_p->getter_setter_pair;
986 #endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
987 } /* ecma_get_named_accessor_property */
988 
989 /**
990  * Set getter of named accessor property
991  */
992 void
ecma_set_named_accessor_property_getter(ecma_object_t *object_p, ecma_property_value_t *prop_value_p, ecma_object_t *getter_p)993 ecma_set_named_accessor_property_getter (ecma_object_t *object_p, /**< the property's container */
994                                          ecma_property_value_t *prop_value_p, /**< property value reference */
995                                          ecma_object_t *getter_p) /**< getter object */
996 {
997   ecma_assert_object_contains_the_property (object_p, prop_value_p, ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
998 
999 #if ENABLED (JERRY_CPOINTER_32_BIT)
1000   ecma_getter_setter_pointers_t *getter_setter_pair_p;
1001   getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t,
1002                                                     prop_value_p->getter_setter_pair_cp);
1003   ECMA_SET_POINTER (getter_setter_pair_p->getter_cp, getter_p);
1004 #else /* !ENABLED (JERRY_CPOINTER_32_BIT) */
1005   ECMA_SET_POINTER (prop_value_p->getter_setter_pair.getter_cp, getter_p);
1006 #endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
1007 } /* ecma_set_named_accessor_property_getter */
1008 
1009 /**
1010  * Set setter of named accessor property
1011  */
1012 void
ecma_set_named_accessor_property_setter(ecma_object_t *object_p, ecma_property_value_t *prop_value_p, ecma_object_t *setter_p)1013 ecma_set_named_accessor_property_setter (ecma_object_t *object_p, /**< the property's container */
1014                                          ecma_property_value_t *prop_value_p, /**< property value reference */
1015                                          ecma_object_t *setter_p) /**< setter object */
1016 {
1017   ecma_assert_object_contains_the_property (object_p, prop_value_p, ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
1018 
1019 #if ENABLED (JERRY_CPOINTER_32_BIT)
1020   ecma_getter_setter_pointers_t *getter_setter_pair_p;
1021   getter_setter_pair_p = ECMA_GET_NON_NULL_POINTER (ecma_getter_setter_pointers_t,
1022                                                     prop_value_p->getter_setter_pair_cp);
1023   ECMA_SET_POINTER (getter_setter_pair_p->setter_cp, setter_p);
1024 #else /* !ENABLED (JERRY_CPOINTER_32_BIT) */
1025   ECMA_SET_POINTER (prop_value_p->getter_setter_pair.setter_cp, setter_p);
1026 #endif /* ENABLED (JERRY_CPOINTER_32_BIT) */
1027 } /* ecma_set_named_accessor_property_setter */
1028 
1029 /**
1030  * Get property's 'Writable' attribute value
1031  *
1032  * @return true - property is writable,
1033  *         false - otherwise
1034  */
1035 inline bool JERRY_ATTR_ALWAYS_INLINE
ecma_is_property_writable(ecma_property_t property)1036 ecma_is_property_writable (ecma_property_t property) /**< property */
1037 {
1038   JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA
1039                 || ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_VIRTUAL);
1040 
1041   return (property & ECMA_PROPERTY_FLAG_WRITABLE) != 0;
1042 } /* ecma_is_property_writable */
1043 
1044 /**
1045  * Set property's 'Writable' attribute value
1046  */
1047 void
ecma_set_property_writable_attr(ecma_property_t *property_p, bool is_writable)1048 ecma_set_property_writable_attr (ecma_property_t *property_p, /**< [in,out] property */
1049                                  bool is_writable) /**< new value for writable flag */
1050 {
1051   JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA);
1052 
1053   if (is_writable)
1054   {
1055     *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_WRITABLE);
1056   }
1057   else
1058   {
1059     *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_WRITABLE);
1060   }
1061 } /* ecma_set_property_writable_attr */
1062 
1063 /**
1064  * Get property's 'Enumerable' attribute value
1065  *
1066  * @return true - property is enumerable,
1067  *         false - otherwise
1068  */
1069 inline bool JERRY_ATTR_ALWAYS_INLINE
ecma_is_property_enumerable(ecma_property_t property)1070 ecma_is_property_enumerable (ecma_property_t property) /**< property */
1071 {
1072   JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA
1073                 || ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR
1074                 || ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_VIRTUAL);
1075 
1076   return (property & ECMA_PROPERTY_FLAG_ENUMERABLE) != 0;
1077 } /* ecma_is_property_enumerable */
1078 
1079 /**
1080  * Set property's 'Enumerable' attribute value
1081  */
1082 void
ecma_set_property_enumerable_attr(ecma_property_t *property_p, bool is_enumerable)1083 ecma_set_property_enumerable_attr (ecma_property_t *property_p, /**< [in,out] property */
1084                                    bool is_enumerable) /**< new value for enumerable flag */
1085 {
1086   JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
1087                 || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
1088 
1089   if (is_enumerable)
1090   {
1091     *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_ENUMERABLE);
1092   }
1093   else
1094   {
1095     *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_ENUMERABLE);
1096   }
1097 } /* ecma_set_property_enumerable_attr */
1098 
1099 /**
1100  * Get property's 'Configurable' attribute value
1101  *
1102  * @return true - property is configurable,
1103  *         false - otherwise
1104  */
1105 inline bool JERRY_ATTR_ALWAYS_INLINE
ecma_is_property_configurable(ecma_property_t property)1106 ecma_is_property_configurable (ecma_property_t property) /**< property */
1107 {
1108   JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDDATA
1109                 || ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR
1110                 || ECMA_PROPERTY_GET_TYPE (property) == ECMA_PROPERTY_TYPE_VIRTUAL);
1111 
1112   return (property & ECMA_PROPERTY_FLAG_CONFIGURABLE) != 0;
1113 } /* ecma_is_property_configurable */
1114 
1115 /**
1116  * Set property's 'Configurable' attribute value
1117  */
1118 void
ecma_set_property_configurable_attr(ecma_property_t *property_p, bool is_configurable)1119 ecma_set_property_configurable_attr (ecma_property_t *property_p, /**< [in,out] property */
1120                                      bool is_configurable) /**< new value for configurable flag */
1121 {
1122   JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
1123                 || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR);
1124 
1125   if (is_configurable)
1126   {
1127     *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_CONFIGURABLE);
1128   }
1129   else
1130   {
1131     *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_CONFIGURABLE);
1132   }
1133 } /* ecma_set_property_configurable_attr */
1134 
1135 #if ENABLED (JERRY_LCACHE)
1136 
1137 /**
1138  * Check whether the property is registered in LCache
1139  *
1140  * @return true / false
1141  */
1142 inline bool JERRY_ATTR_ALWAYS_INLINE
ecma_is_property_lcached(ecma_property_t *property_p)1143 ecma_is_property_lcached (ecma_property_t *property_p) /**< property */
1144 {
1145   JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
1146                 || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR
1147                 || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_INTERNAL);
1148 
1149   return (*property_p & ECMA_PROPERTY_FLAG_LCACHED) != 0;
1150 } /* ecma_is_property_lcached */
1151 
1152 /**
1153  * Set value of flag indicating whether the property is registered in LCache
1154  */
1155 inline void JERRY_ATTR_ALWAYS_INLINE
ecma_set_property_lcached(ecma_property_t *property_p, bool is_lcached)1156 ecma_set_property_lcached (ecma_property_t *property_p, /**< property */
1157                            bool is_lcached) /**< new value for lcached flag */
1158 {
1159   JERRY_ASSERT (ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDDATA
1160                 || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_NAMEDACCESSOR
1161                 || ECMA_PROPERTY_GET_TYPE (*property_p) == ECMA_PROPERTY_TYPE_INTERNAL);
1162 
1163   if (is_lcached)
1164   {
1165     *property_p = (uint8_t) (*property_p | ECMA_PROPERTY_FLAG_LCACHED);
1166   }
1167   else
1168   {
1169     *property_p = (uint8_t) (*property_p & ~ECMA_PROPERTY_FLAG_LCACHED);
1170   }
1171 } /* ecma_set_property_lcached */
1172 
1173 #endif /* ENABLED (JERRY_LCACHE) */
1174 
1175 /**
1176  * Construct empty property descriptor, i.e.:
1177  *  property descriptor with all is_defined flags set to false and the rest - to default value.
1178  *
1179  * @return empty property descriptor
1180  */
1181 ecma_property_descriptor_t
ecma_make_empty_property_descriptor(void)1182 ecma_make_empty_property_descriptor (void)
1183 {
1184   ecma_property_descriptor_t prop_desc;
1185 
1186   prop_desc.flags = 0;
1187   prop_desc.value = ECMA_VALUE_UNDEFINED;
1188   prop_desc.get_p = NULL;
1189   prop_desc.set_p = NULL;
1190 
1191   return prop_desc;
1192 } /* ecma_make_empty_property_descriptor */
1193 
1194 /**
1195  * Free values contained in the property descriptor
1196  * and make it empty property descriptor
1197  */
1198 void
ecma_free_property_descriptor(ecma_property_descriptor_t *prop_desc_p)1199 ecma_free_property_descriptor (ecma_property_descriptor_t *prop_desc_p) /**< property descriptor */
1200 {
1201   if (prop_desc_p->flags & ECMA_PROP_IS_VALUE_DEFINED)
1202   {
1203     ecma_free_value (prop_desc_p->value);
1204   }
1205 
1206   if ((prop_desc_p->flags & ECMA_PROP_IS_GET_DEFINED)
1207       && prop_desc_p->get_p != NULL)
1208   {
1209     ecma_deref_object (prop_desc_p->get_p);
1210   }
1211 
1212   if ((prop_desc_p->flags & ECMA_PROP_IS_SET_DEFINED)
1213       && prop_desc_p->set_p != NULL)
1214   {
1215     ecma_deref_object (prop_desc_p->set_p);
1216   }
1217 
1218   *prop_desc_p = ecma_make_empty_property_descriptor ();
1219 } /* ecma_free_property_descriptor */
1220 
1221 /**
1222  * The size of error reference must be 8 bytes to use jmem_pools_alloc().
1223  */
1224 JERRY_STATIC_ASSERT (sizeof (ecma_error_reference_t) == 8,
1225                      ecma_error_reference_size_must_be_8_bytes);
1226 
1227 /**
1228  * Create an error reference from a given value.
1229  *
1230  * Note:
1231  *   Reference of the value is taken.
1232  *
1233  * @return error reference value
1234  */
1235 ecma_value_t
ecma_create_error_reference(ecma_value_t value, bool is_exception)1236 ecma_create_error_reference (ecma_value_t value, /**< referenced value */
1237                              bool is_exception) /**< error reference is an exception */
1238 {
1239   ecma_error_reference_t *error_ref_p = (ecma_error_reference_t *) jmem_pools_alloc (sizeof (ecma_error_reference_t));
1240 
1241   error_ref_p->refs_and_flags = ECMA_ERROR_REF_ONE | (is_exception ? 0 : ECMA_ERROR_REF_ABORT);
1242   error_ref_p->value = value;
1243   return ecma_make_error_reference_value (error_ref_p);
1244 } /* ecma_create_error_reference */
1245 
1246 /**
1247  * Create an error reference from the currently thrown error value.
1248  *
1249  * @return error reference value
1250  */
1251 ecma_value_t
ecma_create_error_reference_from_context(void)1252 ecma_create_error_reference_from_context (void)
1253 {
1254   bool is_abort = jcontext_has_pending_abort ();
1255 
1256   if (is_abort)
1257   {
1258     jcontext_set_abort_flag (false);
1259   }
1260   return ecma_create_error_reference (jcontext_take_exception (), !is_abort);
1261 } /* ecma_create_error_reference_from_context */
1262 
1263 /**
1264  * Create an error reference from a given object.
1265  *
1266  * Note:
1267  *   Reference of the value is taken.
1268  *
1269  * @return error reference value
1270  */
1271 inline ecma_value_t JERRY_ATTR_ALWAYS_INLINE
ecma_create_error_object_reference(ecma_object_t *object_p)1272 ecma_create_error_object_reference (ecma_object_t *object_p) /**< referenced object */
1273 {
1274   return ecma_create_error_reference (ecma_make_object_value (object_p), true);
1275 } /* ecma_create_error_object_reference */
1276 
1277 /**
1278  * Increase ref count of an error reference.
1279  */
1280 void
ecma_ref_error_reference(ecma_error_reference_t *error_ref_p)1281 ecma_ref_error_reference (ecma_error_reference_t *error_ref_p) /**< error reference */
1282 {
1283   if (JERRY_LIKELY (error_ref_p->refs_and_flags < ECMA_ERROR_MAX_REF))
1284   {
1285     error_ref_p->refs_and_flags += ECMA_ERROR_REF_ONE;
1286   }
1287   else
1288   {
1289     jerry_fatal (ERR_REF_COUNT_LIMIT);
1290   }
1291 } /* ecma_ref_error_reference */
1292 
1293 /**
1294  * Decrease ref count of an error reference.
1295  */
1296 void
ecma_deref_error_reference(ecma_error_reference_t *error_ref_p)1297 ecma_deref_error_reference (ecma_error_reference_t *error_ref_p) /**< error reference */
1298 {
1299   JERRY_ASSERT (error_ref_p->refs_and_flags >= ECMA_ERROR_REF_ONE);
1300 
1301   error_ref_p->refs_and_flags -= ECMA_ERROR_REF_ONE;
1302 
1303   if (error_ref_p->refs_and_flags < ECMA_ERROR_REF_ONE)
1304   {
1305     ecma_free_value (error_ref_p->value);
1306     jmem_pools_free (error_ref_p, sizeof (ecma_error_reference_t));
1307   }
1308 } /* ecma_deref_error_reference */
1309 
1310 /**
1311  * Raise error from the given error reference.
1312  *
1313  * Note: the error reference's ref count is also decreased
1314  */
1315 void
ecma_raise_error_from_error_reference(ecma_value_t value)1316 ecma_raise_error_from_error_reference (ecma_value_t value) /**< error reference */
1317 {
1318   JERRY_ASSERT (!jcontext_has_pending_exception () && !jcontext_has_pending_abort ());
1319   ecma_error_reference_t *error_ref_p = ecma_get_error_reference_from_value (value);
1320 
1321   JERRY_ASSERT (error_ref_p->refs_and_flags >= ECMA_ERROR_REF_ONE);
1322 
1323   ecma_value_t referenced_value = error_ref_p->value;
1324 
1325   jcontext_set_exception_flag (true);
1326   jcontext_set_abort_flag (error_ref_p->refs_and_flags & ECMA_ERROR_REF_ABORT);
1327 
1328   if (error_ref_p->refs_and_flags >= 2 * ECMA_ERROR_REF_ONE)
1329   {
1330     error_ref_p->refs_and_flags -= ECMA_ERROR_REF_ONE;
1331     referenced_value = ecma_copy_value (referenced_value);
1332   }
1333   else
1334   {
1335     jmem_pools_free (error_ref_p, sizeof (ecma_error_reference_t));
1336   }
1337 
1338   JERRY_CONTEXT (error_value) = referenced_value;
1339 } /* ecma_raise_error_from_error_reference */
1340 
1341 /**
1342  * Increase reference counter of Compact
1343  * Byte Code or regexp byte code.
1344  */
1345 void
ecma_bytecode_ref(ecma_compiled_code_t *bytecode_p)1346 ecma_bytecode_ref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
1347 {
1348   /* Abort program if maximum reference number is reached. */
1349   if (bytecode_p->refs >= UINT16_MAX)
1350   {
1351     jerry_fatal (ERR_REF_COUNT_LIMIT);
1352   }
1353 
1354   bytecode_p->refs++;
1355 } /* ecma_bytecode_ref */
1356 
1357 /**
1358  * Decrease reference counter of Compact
1359  * Byte Code or regexp byte code.
1360  */
1361 void
ecma_bytecode_deref(ecma_compiled_code_t *bytecode_p)1362 ecma_bytecode_deref (ecma_compiled_code_t *bytecode_p) /**< byte code pointer */
1363 {
1364   JERRY_ASSERT (bytecode_p->refs > 0);
1365   JERRY_ASSERT (!(bytecode_p->status_flags & CBC_CODE_FLAGS_STATIC_FUNCTION));
1366 
1367   bytecode_p->refs--;
1368 
1369   if (bytecode_p->refs > 0)
1370   {
1371     /* Non-zero reference counter. */
1372     return;
1373   }
1374 
1375   if (bytecode_p->status_flags & CBC_CODE_FLAGS_FUNCTION)
1376   {
1377     ecma_value_t *literal_start_p = NULL;
1378     uint32_t literal_end;
1379     uint32_t const_literal_end;
1380 
1381     if (bytecode_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
1382     {
1383       cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) bytecode_p;
1384       literal_end = args_p->literal_end;
1385       const_literal_end = args_p->const_literal_end;
1386 
1387       literal_start_p = (ecma_value_t *) ((uint8_t *) bytecode_p + sizeof (cbc_uint16_arguments_t));
1388       literal_start_p -= args_p->register_end;
1389     }
1390     else
1391     {
1392       cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) bytecode_p;
1393       literal_end = args_p->literal_end;
1394       const_literal_end = args_p->const_literal_end;
1395 
1396       literal_start_p = (ecma_value_t *) ((uint8_t *) bytecode_p + sizeof (cbc_uint8_arguments_t));
1397       literal_start_p -= args_p->register_end;
1398     }
1399 
1400     for (uint32_t i = const_literal_end; i < literal_end; i++)
1401     {
1402       ecma_compiled_code_t *bytecode_literal_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_compiled_code_t,
1403                                                                                   literal_start_p[i]);
1404 
1405       /* Self references are ignored. */
1406       if (bytecode_literal_p != bytecode_p)
1407       {
1408         ecma_bytecode_deref (bytecode_literal_p);
1409       }
1410     }
1411 
1412 #if ENABLED (JERRY_DEBUGGER)
1413     if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
1414         && !(bytecode_p->status_flags & CBC_CODE_FLAGS_DEBUGGER_IGNORE)
1415         && jerry_debugger_send_function_cp (JERRY_DEBUGGER_RELEASE_BYTE_CODE_CP, bytecode_p))
1416     {
1417       /* Delay the byte code free until the debugger client is notified.
1418        * If the connection is aborted the pointer is still freed by
1419        * jerry_debugger_close_connection(). */
1420       jerry_debugger_byte_code_free_t *byte_code_free_p = (jerry_debugger_byte_code_free_t *) bytecode_p;
1421       jmem_cpointer_t byte_code_free_head = JERRY_CONTEXT (debugger_byte_code_free_head);
1422 
1423       byte_code_free_p->prev_cp = ECMA_NULL_POINTER;
1424 
1425       jmem_cpointer_t byte_code_free_cp;
1426       JMEM_CP_SET_NON_NULL_POINTER (byte_code_free_cp, byte_code_free_p);
1427 
1428       if (byte_code_free_head == ECMA_NULL_POINTER)
1429       {
1430         JERRY_CONTEXT (debugger_byte_code_free_tail) = byte_code_free_cp;
1431       }
1432       else
1433       {
1434         jerry_debugger_byte_code_free_t *first_byte_code_free_p;
1435 
1436         first_byte_code_free_p = JMEM_CP_GET_NON_NULL_POINTER (jerry_debugger_byte_code_free_t,
1437                                                                byte_code_free_head);
1438         first_byte_code_free_p->prev_cp = byte_code_free_cp;
1439       }
1440 
1441       JERRY_CONTEXT (debugger_byte_code_free_head) = byte_code_free_cp;
1442       return;
1443     }
1444 #endif /* ENABLED (JERRY_DEBUGGER) */
1445 
1446 #if ENABLED (JERRY_ES2015)
1447     if (bytecode_p->status_flags & CBC_CODE_FLAG_HAS_TAGGED_LITERALS)
1448     {
1449       ecma_collection_t *collection_p = ecma_compiled_code_get_tagged_template_collection (bytecode_p);
1450 
1451       /* Since the objects in the tagged template collection are not strong referenced anymore by the compiled code
1452          we can treat them as 'new' objects. */
1453       JERRY_CONTEXT (ecma_gc_new_objects) += collection_p->item_count;
1454       ecma_collection_free (collection_p);
1455     }
1456 #endif /* ENABLED (JERRY_ES2015) */
1457 
1458 #if ENABLED (JERRY_MEM_STATS)
1459     jmem_stats_free_byte_code_bytes (((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG);
1460 #endif /* ENABLED (JERRY_MEM_STATS) */
1461   }
1462   else
1463   {
1464 #if ENABLED (JERRY_BUILTIN_REGEXP)
1465     re_compiled_code_t *re_bytecode_p = (re_compiled_code_t *) bytecode_p;
1466 
1467     ecma_deref_ecma_string (ecma_get_string_from_value (re_bytecode_p->source));
1468 #endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
1469   }
1470 
1471   jmem_heap_free_block (bytecode_p,
1472                         ((size_t) bytecode_p->size) << JMEM_ALIGNMENT_LOG);
1473 } /* ecma_bytecode_deref */
1474 
1475 #if ENABLED (JERRY_ES2015)
1476 /**
1477  * Get the tagged template collection of the compiled code
1478  *
1479  * @return pointer to the tagged template collection
1480  */
1481 ecma_collection_t *
ecma_compiled_code_get_tagged_template_collection(const ecma_compiled_code_t *bytecode_header_p)1482 ecma_compiled_code_get_tagged_template_collection (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */
1483 {
1484   JERRY_ASSERT (bytecode_header_p != NULL);
1485   JERRY_ASSERT (bytecode_header_p->status_flags & CBC_CODE_FLAG_HAS_TAGGED_LITERALS);
1486 
1487   uint8_t *byte_p = (uint8_t *) bytecode_header_p;
1488   byte_p += ((size_t) bytecode_header_p->size) << JMEM_ALIGNMENT_LOG;
1489 
1490   ecma_value_t *tagged_base_p = (ecma_value_t *) byte_p;
1491   tagged_base_p -= ecma_compiled_code_get_formal_params (bytecode_header_p);
1492 
1493   return ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t, tagged_base_p[-1]);
1494 } /* ecma_compiled_code_get_tagged_template_collection */
1495 #endif /* ENABLED (JERRY_ES2015) */
1496 
1497 #if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) || ENABLED (JERRY_ES2015)
1498 /**
1499  * Get the number of formal parameters of the compiled code
1500  *
1501  * @return number of formal parameters
1502  */
1503 ecma_length_t
ecma_compiled_code_get_formal_params(const ecma_compiled_code_t *bytecode_header_p)1504 ecma_compiled_code_get_formal_params (const ecma_compiled_code_t *bytecode_header_p) /**< compiled code */
1505 {
1506   if (!(bytecode_header_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED))
1507   {
1508     return 0;
1509   }
1510 
1511   if (bytecode_header_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
1512   {
1513     return ((cbc_uint16_arguments_t *) bytecode_header_p)->argument_end;
1514   }
1515 
1516   return ((cbc_uint8_arguments_t *) bytecode_header_p)->argument_end;
1517 } /* ecma_compiled_code_get_formal_params */
1518 #endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) || ENABLED (JERRY_ES2015) */
1519 
1520 #if (JERRY_STACK_LIMIT != 0)
1521 /**
1522  * Check the current stack usage by calculating the difference from the initial stack base.
1523  *
1524  * @return current stack usage in bytes
1525  */
1526 uintptr_t JERRY_ATTR_NOINLINE
ecma_get_current_stack_usage(void)1527 ecma_get_current_stack_usage (void)
1528 {
1529   volatile int __sp;
1530   return (uintptr_t) (JERRY_CONTEXT (stack_base) - (uintptr_t) &__sp);
1531 } /* ecma_get_current_stack_usage */
1532 
1533 #endif /* (JERRY_STACK_LIMIT != 0) */
1534 
1535 /**
1536  * @}
1537  * @}
1538  */
1539