• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright JS Foundation and other contributors, http://js.foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecma-alloc.h"
17 #include "ecma-builtins.h"
18 #include "ecma-exceptions.h"
19 #include "ecma-gc.h"
20 #include "ecma-globals.h"
21 #include "ecma-helpers.h"
22 #include "ecma-objects.h"
23 #include "jcontext.h"
24 #include "jrt-bit-fields.h"
25 
26 #define ECMA_BUILTINS_INTERNAL
27 #include "ecma-builtins-internal.h"
28 
29 /** \addtogroup ecma ECMA
30  * @{
31  *
32  * \addtogroup ecmabuiltins
33  * @{
34  */
35 
36 static void ecma_instantiate_builtin (ecma_builtin_id_t id);
37 
38 /**
39  * Helper definition for ecma_builtin_property_list_references.
40  */
41 typedef const ecma_builtin_property_descriptor_t *ecma_builtin_property_list_reference_t;
42 
43 /**
44  * Definition of built-in dispatch routine function pointer.
45  */
46 typedef ecma_value_t (*ecma_builtin_dispatch_routine_t) (uint16_t builtin_routine_id,
47                                                          ecma_value_t this_arg,
48                                                          const ecma_value_t arguments_list[],
49                                                          ecma_length_t arguments_number);
50 /**
51  * Definition of built-in dispatch call function pointer.
52  */
53 typedef ecma_value_t (*ecma_builtin_dispatch_call_t) (const ecma_value_t arguments_list[],
54                                                       ecma_length_t arguments_number);
55 /**
56  * Definition of a builtin descriptor which contains the builtin object's:
57  * - prototype objects's id (13-bits)
58  * - type (3-bits)
59  *
60  * Layout:
61  *
62  * |----------------------|---------------|
63  *     prototype_id(13)      obj_type(3)
64  */
65 typedef uint16_t ecma_builtin_descriptor_t;
66 
67 /**
68  * Bitshift index for get the prototype object's id from a builtin descriptor
69  */
70 #define ECMA_BUILTIN_PROTOTYPE_ID_SHIFT 3
71 
72 /**
73  * Bitmask for get the object's type from a builtin descriptor
74  */
75 #define ECMA_BUILTIN_OBJECT_TYPE_MASK ((1 << ECMA_BUILTIN_PROTOTYPE_ID_SHIFT) - 1)
76 
77 /**
78  * Create a builtin descriptor value
79  */
80 #define ECMA_MAKE_BUILTIN_DESCRIPTOR(type, proto_id) \
81   (((proto_id) << ECMA_BUILTIN_PROTOTYPE_ID_SHIFT) | (type))
82 
83 /**
84  * List of the built-in descriptors.
85  */
86 static const ecma_builtin_descriptor_t ecma_builtin_descriptors[] =
87 {
88 /** @cond doxygen_suppress */
89 #define BUILTIN(a, b, c, d, e)
90 #define BUILTIN_ROUTINE(builtin_id, \
91                         object_type, \
92                         object_prototype_builtin_id, \
93                         is_extensible, \
94                         lowercase_name) \
95   ECMA_MAKE_BUILTIN_DESCRIPTOR (object_type, object_prototype_builtin_id),
96 #include "ecma-builtins.inc.h"
97 #undef BUILTIN
98 #undef BUILTIN_ROUTINE
99 #define BUILTIN_ROUTINE(a, b, c, d, e)
100 #define BUILTIN(builtin_id, \
101                 object_type, \
102                 object_prototype_builtin_id, \
103                 is_extensible, \
104                 lowercase_name) \
105   ECMA_MAKE_BUILTIN_DESCRIPTOR (object_type, object_prototype_builtin_id),
106 #include "ecma-builtins.inc.h"
107 #undef BUILTIN
108 #undef BUILTIN_ROUTINE
109 /** @endcond */
110 };
111 
112 #ifndef JERRY_NDEBUG
113 /** @cond doxygen_suppress */
114 enum
115 {
116   ECMA_BUILTIN_EXTENSIBLE_CHECK =
117 #define BUILTIN(a, b, c, d, e)
118 #define BUILTIN_ROUTINE(builtin_id, \
119                         object_type, \
120                         object_prototype_builtin_id, \
121                         is_extensible, \
122                         lowercase_name) \
123   (is_extensible != 0 || builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER) &&
124 #include "ecma-builtins.inc.h"
125 #undef BUILTIN
126 #undef BUILTIN_ROUTINE
127 #define BUILTIN_ROUTINE(a, b, c, d, e)
128 #define BUILTIN(builtin_id, \
129                 object_type, \
130                 object_prototype_builtin_id, \
131                 is_extensible, \
132                 lowercase_name) \
133   (is_extensible != 0 || builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER) &&
134 #include "ecma-builtins.inc.h"
135 #undef BUILTIN
136 #undef BUILTIN_ROUTINE
137   true
138 };
139 /** @endcond */
140 
141 /**
142  * All the builtin object must be extensible except the ThrowTypeError object.
143  */
144 JERRY_STATIC_ASSERT (ECMA_BUILTIN_EXTENSIBLE_CHECK == true,
145                      ecma_builtin_must_be_extensible_except_the_builtin_thorw_type_error_object);
146 #endif /* !JERRY_NDEBUG */
147 
148 /**
149  * List of the built-in routines.
150  */
151 static const ecma_builtin_dispatch_routine_t ecma_builtin_routines[] =
152 {
153 /** @cond doxygen_suppress */
154 #define BUILTIN(a, b, c, d, e)
155 #define BUILTIN_ROUTINE(builtin_id, \
156                         object_type, \
157                         object_prototype_builtin_id, \
158                         is_extensible, \
159                         lowercase_name) \
160   ecma_builtin_ ## lowercase_name ## _dispatch_routine,
161 #include "ecma-builtins.inc.h"
162 #undef BUILTIN
163 #undef BUILTIN_ROUTINE
164 #define BUILTIN_ROUTINE(a, b, c, d, e)
165 #define BUILTIN(builtin_id, \
166                 object_type, \
167                 object_prototype_builtin_id, \
168                 is_extensible, \
169                 lowercase_name) \
170   ecma_builtin_ ## lowercase_name ## _dispatch_routine,
171 #include "ecma-builtins.inc.h"
172 #undef BUILTIN
173 #undef BUILTIN_ROUTINE
174 /** @endcond */
175 };
176 
177 /**
178  * List of the built-in call functions.
179  */
180 static const ecma_builtin_dispatch_call_t ecma_builtin_call_functions[] =
181 {
182 /** @cond doxygen_suppress */
183 #define BUILTIN(a, b, c, d, e)
184 #define BUILTIN_ROUTINE(builtin_id, \
185                         object_type, \
186                         object_prototype_builtin_id, \
187                         is_extensible, \
188                         lowercase_name) \
189   ecma_builtin_ ## lowercase_name ## _dispatch_call,
190 #include "ecma-builtins.inc.h"
191 #undef BUILTIN_ROUTINE
192 #undef BUILTIN
193 /** @endcond */
194 };
195 
196 /**
197  * List of the built-in construct functions.
198  */
199 static const ecma_builtin_dispatch_call_t ecma_builtin_construct_functions[] =
200 {
201 /** @cond doxygen_suppress */
202 #define BUILTIN(a, b, c, d, e)
203 #define BUILTIN_ROUTINE(builtin_id, \
204                         object_type, \
205                         object_prototype_builtin_id, \
206                         is_extensible, \
207                         lowercase_name) \
208   ecma_builtin_ ## lowercase_name ## _dispatch_construct,
209 #include "ecma-builtins.inc.h"
210 #undef BUILTIN_ROUTINE
211 #undef BUILTIN
212 /** @endcond */
213 };
214 
215 /**
216  * Property descriptor lists for all built-ins.
217  */
218 static const ecma_builtin_property_list_reference_t ecma_builtin_property_list_references[] =
219 {
220 /** @cond doxygen_suppress */
221 #define BUILTIN(a, b, c, d, e)
222 #define BUILTIN_ROUTINE(builtin_id, \
223                         object_type, \
224                         object_prototype_builtin_id, \
225                         is_extensible, \
226                         lowercase_name) \
227   ecma_builtin_ ## lowercase_name ## _property_descriptor_list,
228 #include "ecma-builtins.inc.h"
229 #undef BUILTIN
230 #undef BUILTIN_ROUTINE
231 #define BUILTIN_ROUTINE(a, b, c, d, e)
232 #define BUILTIN(builtin_id, \
233                 object_type, \
234                 object_prototype_builtin_id, \
235                 is_extensible, \
236                 lowercase_name) \
237   ecma_builtin_ ## lowercase_name ## _property_descriptor_list,
238 #include "ecma-builtins.inc.h"
239 #undef BUILTIN_ROUTINE
240 #undef BUILTIN
241 /** @endcond */
242 };
243 
244 /**
245  * Get the number of properties of a built-in object.
246  *
247  * @return the number of properties
248  */
249 static size_t
ecma_builtin_get_property_count(ecma_builtin_id_t builtin_id)250 ecma_builtin_get_property_count (ecma_builtin_id_t builtin_id) /**< built-in ID */
251 {
252   JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT);
253   const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id];
254 
255   const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p;
256 
257   while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT)
258   {
259     curr_property_p++;
260   }
261 
262   return (size_t) (curr_property_p - property_list_p);
263 } /* ecma_builtin_get_property_count */
264 
265 /**
266  * Check if passed object is the instance of specified built-in.
267  *
268  * @return true  - if the object is instance of the specified built-in
269  *         false - otherwise
270  */
271 bool
ecma_builtin_is(ecma_object_t * obj_p,ecma_builtin_id_t builtin_id)272 ecma_builtin_is (ecma_object_t *obj_p, /**< pointer to an object */
273                  ecma_builtin_id_t builtin_id) /**< id of built-in to check on */
274 {
275   JERRY_ASSERT (obj_p != NULL && !ecma_is_lexical_environment (obj_p));
276   JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT);
277 
278   /* If a built-in object is not instantiated, its value is NULL,
279      hence it cannot be equal to a valid object. */
280   jmem_cpointer_t builtin_cp = JERRY_CONTEXT (ecma_builtin_objects)[builtin_id];
281 
282   return (builtin_cp != JMEM_CP_NULL && (obj_p == ECMA_GET_NON_NULL_POINTER (ecma_object_t, builtin_cp)));
283 } /* ecma_builtin_is */
284 
285 /**
286  * Get reference to specified built-in object
287  *
288  * Note:
289  *   Does not increase the reference counter.
290  *
291  * @return pointer to the object's instance
292  */
293 ecma_object_t *
ecma_builtin_get(ecma_builtin_id_t builtin_id)294 ecma_builtin_get (ecma_builtin_id_t builtin_id) /**< id of built-in to check on */
295 {
296   JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT);
297 
298   if (JERRY_UNLIKELY (JERRY_CONTEXT (ecma_builtin_objects)[builtin_id] == JMEM_CP_NULL))
299   {
300     ecma_instantiate_builtin (builtin_id);
301   }
302 
303   return ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_builtin_objects)[builtin_id]);
304 } /* ecma_builtin_get */
305 
306 /**
307  * Get reference to the global object
308  *
309  * Note:
310  *   Does not increase the reference counter.
311  *
312  * @return pointer to the global object
313  */
314 inline ecma_object_t * JERRY_ATTR_ALWAYS_INLINE
ecma_builtin_get_global(void)315 ecma_builtin_get_global (void)
316 {
317   JERRY_ASSERT (JERRY_CONTEXT (ecma_builtin_objects)[ECMA_BUILTIN_ID_GLOBAL] != JMEM_CP_NULL);
318 
319   return ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_builtin_objects)[ECMA_BUILTIN_ID_GLOBAL]);
320 } /* ecma_builtin_get_global */
321 
322 /**
323  * Checks whether the given function is a built-in routine
324  *
325  * @return true - if the function object is a built-in routine
326  *         false - otherwise
327  */
328 inline bool JERRY_ATTR_ALWAYS_INLINE
ecma_builtin_function_is_routine(ecma_object_t * func_obj_p)329 ecma_builtin_function_is_routine (ecma_object_t *func_obj_p) /**< function object */
330 {
331   JERRY_ASSERT (ecma_get_object_type (func_obj_p) == ECMA_OBJECT_TYPE_FUNCTION);
332   JERRY_ASSERT (ecma_get_object_is_builtin (func_obj_p));
333 
334   ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p;
335   return (ext_func_obj_p->u.built_in.routine_id >= ECMA_BUILTIN_ID__COUNT);
336 } /* ecma_builtin_function_is_routine */
337 
338 /**
339  * Instantiate specified ECMA built-in object
340  */
341 static void
ecma_instantiate_builtin(ecma_builtin_id_t obj_builtin_id)342 ecma_instantiate_builtin (ecma_builtin_id_t obj_builtin_id) /**< built-in id */
343 {
344   JERRY_ASSERT (obj_builtin_id < ECMA_BUILTIN_ID__COUNT);
345   JERRY_ASSERT (JERRY_CONTEXT (ecma_builtin_objects)[obj_builtin_id] == JMEM_CP_NULL);
346 
347   ecma_builtin_descriptor_t builtin_desc = ecma_builtin_descriptors[obj_builtin_id];
348   ecma_builtin_id_t object_prototype_builtin_id = (ecma_builtin_id_t) (builtin_desc >> ECMA_BUILTIN_PROTOTYPE_ID_SHIFT);
349 
350   ecma_object_t *prototype_obj_p;
351 
352   /* cppcheck-suppress arrayIndexOutOfBoundsCond */
353   if (JERRY_UNLIKELY (object_prototype_builtin_id == ECMA_BUILTIN_ID__COUNT))
354   {
355     prototype_obj_p = NULL;
356   }
357   else
358   {
359     if (JERRY_CONTEXT (ecma_builtin_objects)[object_prototype_builtin_id] == JMEM_CP_NULL)
360     {
361       ecma_instantiate_builtin (object_prototype_builtin_id);
362     }
363     prototype_obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t,
364                                                  JERRY_CONTEXT (ecma_builtin_objects)[object_prototype_builtin_id]);
365     JERRY_ASSERT (prototype_obj_p != NULL);
366   }
367 
368   ecma_object_type_t obj_type = (ecma_object_type_t) (builtin_desc & ECMA_BUILTIN_OBJECT_TYPE_MASK);
369 
370   bool is_extended_built_in = (obj_type == ECMA_OBJECT_TYPE_CLASS
371                                || obj_type == ECMA_OBJECT_TYPE_ARRAY);
372 
373   size_t ext_object_size = (is_extended_built_in ? sizeof (ecma_extended_built_in_object_t)
374                                                  : sizeof (ecma_extended_object_t));
375 
376   size_t property_count = ecma_builtin_get_property_count (obj_builtin_id);
377 
378   if (property_count > 32)
379   {
380     /* Only 64 extra properties supported at the moment.
381      * This can be extended to 256 later. */
382     JERRY_ASSERT (property_count <= (32 + 64));
383 
384     ext_object_size += sizeof (uint32_t) * 2;
385   }
386 
387   ecma_object_t *obj_p = ecma_create_object (prototype_obj_p, ext_object_size, obj_type);
388 
389   if (JERRY_UNLIKELY (obj_builtin_id == ECMA_BUILTIN_ID_TYPE_ERROR_THROWER))
390   {
391     ecma_op_ordinary_object_prevent_extensions (obj_p);
392   }
393   else
394   {
395     ecma_op_ordinary_object_set_extensible (obj_p);
396   }
397 
398   /*
399    * [[Class]] property of built-in object is not stored explicitly.
400    *
401    * See also: ecma_object_get_class_name
402    */
403 
404   ecma_set_object_is_builtin (obj_p);
405   ecma_built_in_props_t *built_in_props_p;
406 
407   if (is_extended_built_in)
408   {
409     built_in_props_p = &((ecma_extended_built_in_object_t *) obj_p)->built_in;
410   }
411   else
412   {
413     built_in_props_p = &((ecma_extended_object_t *) obj_p)->u.built_in;
414   }
415 
416   built_in_props_p->id = (uint8_t) obj_builtin_id;
417   built_in_props_p->routine_id = (uint16_t) obj_builtin_id;
418   built_in_props_p->u.instantiated_bitset[0] = 0;
419 
420   if (property_count > 32)
421   {
422     built_in_props_p->length_and_bitset_size = 1 << ECMA_BUILT_IN_BITSET_SHIFT;
423 
424     uint32_t *instantiated_bitset_p = built_in_props_p->u.instantiated_bitset;
425     instantiated_bitset_p[1] = 0;
426     instantiated_bitset_p[2] = 0;
427   }
428   else
429   {
430     built_in_props_p->length_and_bitset_size = 0;
431   }
432 
433   /** Initializing [[PrimitiveValue]] properties of built-in prototype objects */
434   switch (obj_builtin_id)
435   {
436 #if ENABLED (JERRY_BUILTIN_ARRAY)
437     case ECMA_BUILTIN_ID_ARRAY_PROTOTYPE:
438     {
439       JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_ARRAY);
440       ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
441 
442       ext_object_p->u.array.length = 0;
443       ext_object_p->u.array.u.length_prop = ECMA_PROPERTY_FLAG_WRITABLE | ECMA_PROPERTY_TYPE_VIRTUAL;
444       break;
445     }
446 #endif /* ENABLED (JERRY_BUILTIN_ARRAY) */
447 
448 #if !ENABLED (JERRY_ES2015)
449 #if ENABLED (JERRY_BUILTIN_STRING)
450     case ECMA_BUILTIN_ID_STRING_PROTOTYPE:
451     {
452       JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_CLASS);
453       ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
454 
455       ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_STRING_UL;
456       ext_object_p->u.class_prop.u.value = ecma_make_magic_string_value (LIT_MAGIC_STRING__EMPTY);
457       break;
458     }
459 #endif /* ENABLED (JERRY_BUILTIN_STRING) */
460 
461 #if ENABLED (JERRY_BUILTIN_NUMBER)
462     case ECMA_BUILTIN_ID_NUMBER_PROTOTYPE:
463     {
464       JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_CLASS);
465       ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
466 
467       ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_NUMBER_UL;
468       ext_object_p->u.class_prop.u.value = ecma_make_integer_value (0);
469       break;
470     }
471 #endif /* ENABLED (JERRY_BUILTIN_NUMBER) */
472 
473 #if ENABLED (JERRY_BUILTIN_BOOLEAN)
474     case ECMA_BUILTIN_ID_BOOLEAN_PROTOTYPE:
475     {
476       JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_CLASS);
477       ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
478 
479       ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_BOOLEAN_UL;
480       ext_object_p->u.class_prop.u.value = ECMA_VALUE_FALSE;
481       break;
482     }
483 #endif /* ENABLED (JERRY_BUILTIN_BOOLEAN) */
484 
485 #if ENABLED (JERRY_BUILTIN_DATE)
486     case ECMA_BUILTIN_ID_DATE_PROTOTYPE:
487     {
488       JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_CLASS);
489       ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
490 
491       ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_DATE_UL;
492 
493       ecma_number_t *prim_prop_num_value_p = ecma_alloc_number ();
494       *prim_prop_num_value_p = ecma_number_make_nan ();
495       ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.class_prop.u.value, prim_prop_num_value_p);
496       break;
497     }
498 #endif /* ENABLED (JERRY_BUILTIN_DATE) */
499 
500 #if ENABLED (JERRY_BUILTIN_REGEXP)
501     case ECMA_BUILTIN_ID_REGEXP_PROTOTYPE:
502     {
503       JERRY_ASSERT (obj_type == ECMA_OBJECT_TYPE_CLASS);
504       ecma_extended_object_t *ext_object_p = (ecma_extended_object_t *) obj_p;
505 
506       ext_object_p->u.class_prop.class_id = LIT_MAGIC_STRING_REGEXP_UL;
507 
508       re_compiled_code_t *bc_p = re_compile_bytecode (ecma_get_magic_string (LIT_MAGIC_STRING_EMPTY_NON_CAPTURE_GROUP),
509                                                       RE_FLAG_EMPTY);
510 
511       JERRY_ASSERT (bc_p != NULL);
512 
513       ECMA_SET_INTERNAL_VALUE_POINTER (ext_object_p->u.class_prop.u.value, bc_p);
514 
515       break;
516     }
517 #endif /* ENABLED (JERRY_BUILTIN_REGEXP) */
518 #endif /* !ENABLED (JERRY_ES2015) */
519     default:
520     {
521       JERRY_ASSERT (obj_type != ECMA_OBJECT_TYPE_CLASS);
522       break;
523     }
524   }
525 
526   ECMA_SET_NON_NULL_POINTER (JERRY_CONTEXT (ecma_builtin_objects)[obj_builtin_id], obj_p);
527 } /* ecma_instantiate_builtin */
528 
529 /**
530  * Finalize ECMA built-in objects
531  */
532 void
ecma_finalize_builtins(void)533 ecma_finalize_builtins (void)
534 {
535   for (ecma_builtin_id_t id = (ecma_builtin_id_t) 0;
536        id < ECMA_BUILTIN_ID__COUNT;
537        id = (ecma_builtin_id_t) (id + 1))
538   {
539     if (JERRY_CONTEXT (ecma_builtin_objects)[id] != JMEM_CP_NULL)
540     {
541       ecma_object_t *obj_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, JERRY_CONTEXT (ecma_builtin_objects)[id]);
542       ecma_deref_object (obj_p);
543 
544 #if ENABLED (JERRY_ES2015)
545       /* Note: In ES2015 a function object may contain tagged template literal collection. Whenever
546          this function is assigned to a builtin function or function routine during the GC it may cause unresolvable
547          circle since one part of the circle is a weak reference (marked by GC) and the other part is hard reference
548          (reference count). In this case when the function which contains the tagged template literal collection
549          is getting GC marked the arrays in the collection are still holding weak references to properties/prototypes
550          which prevents these objects from getting freed. Releasing the property list and the prototype reference
551          manually eliminates the existence of the unresolvable circle described above. */
552       ecma_gc_free_properties (obj_p);
553       obj_p->u1.property_list_cp = JMEM_CP_NULL;
554       obj_p->u2.prototype_cp = JMEM_CP_NULL;
555 #endif /* ENABLED (JERRY_ES2015) */
556 
557       JERRY_CONTEXT (ecma_builtin_objects)[id] = JMEM_CP_NULL;
558     }
559   }
560 } /* ecma_finalize_builtins */
561 
562 /**
563  * Construct a Function object for specified built-in routine
564  *
565  * See also: ECMA-262 v5, 15
566  *
567  * @return pointer to constructed Function object
568  */
569 static ecma_object_t *
ecma_builtin_make_function_object_for_routine(ecma_builtin_id_t builtin_id,uint16_t routine_id,uint16_t name_id,uint8_t length_prop_value)570 ecma_builtin_make_function_object_for_routine (ecma_builtin_id_t builtin_id, /**< identifier of built-in object */
571                                                uint16_t routine_id, /**< builtin-wide identifier of the built-in
572                                                                      *   object's routine property */
573                                                uint16_t name_id, /**< magic string id of 'name' property */
574                                                uint8_t length_prop_value) /**< value of 'length' property */
575 {
576   JERRY_ASSERT (length_prop_value < (1 << ECMA_BUILT_IN_BITSET_SHIFT));
577 
578   ecma_object_t *prototype_obj_p = ecma_builtin_get (ECMA_BUILTIN_ID_FUNCTION_PROTOTYPE);
579 
580   size_t ext_object_size = sizeof (ecma_extended_object_t);
581 
582   ecma_object_t *func_obj_p = ecma_create_object (prototype_obj_p,
583                                                   ext_object_size,
584                                                   ECMA_OBJECT_TYPE_FUNCTION);
585 
586   ecma_set_object_is_builtin (func_obj_p);
587 
588   JERRY_ASSERT (routine_id >= ECMA_BUILTIN_ID__COUNT);
589 
590   ecma_extended_object_t *ext_func_obj_p = (ecma_extended_object_t *) func_obj_p;
591   ext_func_obj_p->u.built_in.id = (uint8_t) builtin_id;
592   ext_func_obj_p->u.built_in.routine_id = routine_id;
593   ext_func_obj_p->u.built_in.u.builtin_routine.name = name_id;
594   ext_func_obj_p->u.built_in.u.builtin_routine.bitset = 0;
595 
596   ext_func_obj_p->u.built_in.length_and_bitset_size = length_prop_value;
597 
598   return func_obj_p;
599 } /* ecma_builtin_make_function_object_for_routine */
600 
601 /**
602  * Construct a Function object for specified built-in accessor getter
603  *
604  * @return pointer to constructed accessor getter Function object
605  */
606 static ecma_object_t *
ecma_builtin_make_function_object_for_getter_accessor(ecma_builtin_id_t builtin_id,uint16_t routine_id,uint16_t name_id)607 ecma_builtin_make_function_object_for_getter_accessor (ecma_builtin_id_t builtin_id, /**< id of built-in object */
608                                                        uint16_t routine_id, /**< builtin-wide id of the built-in
609                                                                             *   object's routine property */
610                                                        uint16_t name_id) /**< magic string id of 'name' property */
611 {
612   return ecma_builtin_make_function_object_for_routine (builtin_id, routine_id, name_id, 0);
613 } /* ecma_builtin_make_function_object_for_getter_accessor */
614 
615 /**
616  * Construct a Function object for specified built-in accessor setter
617  *
618  * @return pointer to constructed accessor getter Function object
619  */
620 static ecma_object_t *
ecma_builtin_make_function_object_for_setter_accessor(ecma_builtin_id_t builtin_id,uint16_t routine_id,uint16_t name_id)621 ecma_builtin_make_function_object_for_setter_accessor (ecma_builtin_id_t builtin_id, /**< id of built-in object */
622                                                        uint16_t routine_id, /**< builtin-wide id of the built-in
623                                                                             *   object's routine property */
624                                                        uint16_t name_id) /**< magic string id of 'name' property */
625 {
626   return ecma_builtin_make_function_object_for_routine (builtin_id, routine_id, name_id, 1);
627 } /* ecma_builtin_make_function_object_for_setter_accessor */
628 
629 /**
630  * Lazy instantiation of builtin routine property of builtin object
631  *
632  * If the property is not instantiated yet, instantiate the property and
633  * return pointer to the instantiated property.
634  *
635  * @return pointer property, if one was instantiated,
636  *         NULL - otherwise.
637  */
638 ecma_property_t *
ecma_builtin_routine_try_to_instantiate_property(ecma_object_t * object_p,ecma_string_t * string_p)639 ecma_builtin_routine_try_to_instantiate_property (ecma_object_t *object_p, /**< object */
640                                                   ecma_string_t *string_p) /**< property's name */
641 {
642   JERRY_ASSERT (ecma_get_object_is_builtin (object_p));
643   JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION);
644   JERRY_ASSERT (ecma_builtin_function_is_routine (object_p));
645 
646   if (ecma_string_is_length (string_p))
647   {
648     /*
649      * Lazy instantiation of 'length' property
650      */
651 
652     ecma_property_t *len_prop_p;
653     ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
654 #if ENABLED (JERRY_ES2015)
655     uint16_t *bitset_p = &ext_func_p->u.built_in.u.builtin_routine.bitset;
656     if (*bitset_p & (1u << 0))
657     {
658       /* length property was already instantiated */
659       return NULL;
660     }
661     /* We mark that the property was lazily instantiated,
662      * as it is configurable and so can be deleted (ECMA-262 v6, 19.2.4.1) */
663     *bitset_p |= (1u << 0);
664     ecma_property_value_t *len_prop_value_p = ecma_create_named_data_property (object_p,
665                                                                                string_p,
666                                                                                ECMA_PROPERTY_FLAG_CONFIGURABLE,
667                                                                                &len_prop_p);
668 #else /* !ENABLED (JERRY_ES2015) */
669     /* We don't need to mark that the property was already lazy instantiated,
670      * as it is non-configurable and so can't be deleted (ECMA-262 v5, 13.2.5) */
671     ecma_property_value_t *len_prop_value_p = ecma_create_named_data_property (object_p,
672                                                                                string_p,
673                                                                                ECMA_PROPERTY_FIXED,
674                                                                                &len_prop_p);
675 #endif /* ENABLED (JERRY_ES2015) */
676 
677     uint8_t length = ext_func_p->u.built_in.length_and_bitset_size;
678     JERRY_ASSERT (length < (1 << ECMA_BUILT_IN_BITSET_SHIFT));
679 
680     len_prop_value_p->value = ecma_make_integer_value (length);
681 
682     return len_prop_p;
683   }
684 
685   return NULL;
686 } /* ecma_builtin_routine_try_to_instantiate_property */
687 
688 /**
689  * If the property's name is one of built-in properties of the object
690  * that is not instantiated yet, instantiate the property and
691  * return pointer to the instantiated property.
692  *
693  * @return pointer property, if one was instantiated,
694  *         NULL - otherwise.
695  */
696 ecma_property_t *
ecma_builtin_try_to_instantiate_property(ecma_object_t * object_p,ecma_string_t * string_p)697 ecma_builtin_try_to_instantiate_property (ecma_object_t *object_p, /**< object */
698                                           ecma_string_t *string_p) /**< property's name */
699 {
700   JERRY_ASSERT (ecma_get_object_is_builtin (object_p));
701 
702   lit_magic_string_id_t magic_string_id = ecma_get_string_magic (string_p);
703 
704 #if ENABLED (JERRY_ES2015)
705   if (JERRY_UNLIKELY (ecma_prop_name_is_symbol (string_p)))
706   {
707     if (string_p->u.hash & ECMA_GLOBAL_SYMBOL_FLAG)
708     {
709       magic_string_id = (string_p->u.hash >> ECMA_GLOBAL_SYMBOL_SHIFT);
710     }
711   }
712 #endif /* ENABLED (JERRY_ES2015) */
713 
714   if (magic_string_id == LIT_MAGIC_STRING__COUNT)
715   {
716     return NULL;
717   }
718 
719   ecma_built_in_props_t *built_in_props_p;
720   ecma_object_type_t object_type = ecma_get_object_type (object_p);
721   JERRY_ASSERT (object_type != ECMA_OBJECT_TYPE_FUNCTION || !ecma_builtin_function_is_routine (object_p));
722 
723   if (object_type == ECMA_OBJECT_TYPE_CLASS || object_type == ECMA_OBJECT_TYPE_ARRAY)
724   {
725     built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in;
726   }
727   else
728   {
729     built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in;
730   }
731 
732   ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id;
733 
734   JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT);
735   JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id));
736 
737   const ecma_builtin_property_descriptor_t *property_list_p = ecma_builtin_property_list_references[builtin_id];
738 
739   const ecma_builtin_property_descriptor_t *curr_property_p = property_list_p;
740 
741   while (curr_property_p->magic_string_id != magic_string_id)
742   {
743     if (curr_property_p->magic_string_id == LIT_MAGIC_STRING__COUNT)
744     {
745       return NULL;
746     }
747     curr_property_p++;
748   }
749 
750   uint32_t index = (uint32_t) (curr_property_p - property_list_p);
751 
752   uint32_t *bitset_p = built_in_props_p->u.instantiated_bitset + (index >> 5);
753 
754   uint32_t bit_for_index = (uint32_t) (1u << (index & 0x1f));
755 
756   if (*bitset_p & bit_for_index)
757   {
758     /* This property was instantiated before. */
759     return NULL;
760   }
761 
762   *bitset_p |= bit_for_index;
763 
764   ecma_value_t value = ECMA_VALUE_EMPTY;
765   bool is_accessor = false;
766   ecma_object_t *getter_p = NULL;
767   ecma_object_t *setter_p = NULL;
768 
769   switch (curr_property_p->type)
770   {
771     case ECMA_BUILTIN_PROPERTY_SIMPLE:
772     {
773       value = curr_property_p->value;
774       break;
775     }
776     case ECMA_BUILTIN_PROPERTY_NUMBER:
777     {
778       ecma_number_t num = 0.0;
779 
780       if (curr_property_p->value < ECMA_BUILTIN_NUMBER_MAX)
781       {
782         num = curr_property_p->value;
783       }
784       else if (curr_property_p->value < ECMA_BUILTIN_NUMBER_NAN)
785       {
786         static const ecma_number_t builtin_number_list[] =
787         {
788           ECMA_NUMBER_MAX_VALUE,
789           ECMA_NUMBER_MIN_VALUE,
790 #if ENABLED (JERRY_ES2015)
791           ECMA_NUMBER_EPSILON,
792           ECMA_NUMBER_MAX_SAFE_INTEGER,
793           ECMA_NUMBER_MIN_SAFE_INTEGER,
794 #endif /* ENABLED (JERRY_ES2015) */
795           ECMA_NUMBER_E,
796           ECMA_NUMBER_PI,
797           ECMA_NUMBER_LN10,
798           ECMA_NUMBER_LN2,
799           ECMA_NUMBER_LOG2E,
800           ECMA_NUMBER_LOG10E,
801           ECMA_NUMBER_SQRT2,
802           ECMA_NUMBER_SQRT_1_2,
803         };
804 
805         num = builtin_number_list[curr_property_p->value - ECMA_BUILTIN_NUMBER_MAX];
806       }
807       else
808       {
809         switch (curr_property_p->value)
810         {
811           case ECMA_BUILTIN_NUMBER_POSITIVE_INFINITY:
812           {
813             num = ecma_number_make_infinity (false);
814             break;
815           }
816           case ECMA_BUILTIN_NUMBER_NEGATIVE_INFINITY:
817           {
818             num = ecma_number_make_infinity (true);
819             break;
820           }
821           default:
822           {
823             JERRY_ASSERT (curr_property_p->value == ECMA_BUILTIN_NUMBER_NAN);
824 
825             num = ecma_number_make_nan ();
826             break;
827           }
828         }
829       }
830 
831       value = ecma_make_number_value (num);
832       break;
833     }
834     case ECMA_BUILTIN_PROPERTY_STRING:
835     {
836       value = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->value);
837       break;
838     }
839 #if ENABLED (JERRY_ES2015)
840     case ECMA_BUILTIN_PROPERTY_SYMBOL:
841     {
842       ecma_stringbuilder_t builder = ecma_stringbuilder_create_raw ((lit_utf8_byte_t *) "Symbol.", 7);
843 
844       lit_magic_string_id_t symbol_desc_id = (lit_magic_string_id_t) curr_property_p->value;
845 
846       ecma_stringbuilder_append_magic (&builder, symbol_desc_id);
847 
848       ecma_value_t symbol_desc_value = ecma_make_string_value (ecma_stringbuilder_finalize (&builder));
849 
850       ecma_string_t *symbol_p = ecma_new_symbol_from_descriptor_string (symbol_desc_value);
851       lit_magic_string_id_t symbol_id = (lit_magic_string_id_t) curr_property_p->magic_string_id;
852       symbol_p->u.hash = (uint16_t) ((symbol_id << ECMA_GLOBAL_SYMBOL_SHIFT) | ECMA_GLOBAL_SYMBOL_FLAG);
853 
854       value = ecma_make_symbol_value (symbol_p);
855       break;
856     }
857     case ECMA_BUILTIN_PROPERTY_INTRINSIC_PROPERTY:
858     {
859       value = ecma_op_object_get_by_magic_id (ecma_builtin_get (ECMA_BUILTIN_ID_INTRINSIC_OBJECT),
860                                               (lit_magic_string_id_t) curr_property_p->value);
861       break;
862     }
863     case ECMA_BUILTIN_PROPERTY_ACCESSOR_BUILTIN_FUNCTION:
864     {
865       is_accessor = true;
866       uint16_t getter_id = ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID (curr_property_p->value);
867       uint16_t setter_id = ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID (curr_property_p->value);
868       getter_p = ecma_builtin_get (getter_id);
869       setter_p = ecma_builtin_get (setter_id);
870       ecma_ref_object (getter_p);
871       ecma_ref_object (setter_p);
872       break;
873     }
874 #endif /* ENABLED (JERRY_ES2015) */
875     case ECMA_BUILTIN_PROPERTY_OBJECT:
876     {
877       ecma_object_t *builtin_object_p = ecma_builtin_get ((ecma_builtin_id_t) curr_property_p->value);
878       ecma_ref_object (builtin_object_p);
879       value = ecma_make_object_value (builtin_object_p);
880       break;
881     }
882     case ECMA_BUILTIN_PROPERTY_ROUTINE:
883     {
884       ecma_object_t *func_obj_p;
885       func_obj_p = ecma_builtin_make_function_object_for_routine (builtin_id,
886                                                                   ECMA_GET_ROUTINE_ID (curr_property_p->value),
887                                                                   curr_property_p->magic_string_id,
888                                                                   ECMA_GET_ROUTINE_LENGTH (curr_property_p->value));
889       value = ecma_make_object_value (func_obj_p);
890       break;
891     }
892     case ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_WRITE:
893     {
894       is_accessor = true;
895       uint16_t getter_id = ECMA_ACCESSOR_READ_WRITE_GET_GETTER_ID (curr_property_p->value);
896       uint16_t setter_id = ECMA_ACCESSOR_READ_WRITE_GET_SETTER_ID (curr_property_p->value);
897       getter_p = ecma_builtin_make_function_object_for_getter_accessor (builtin_id,
898                                                                         getter_id,
899                                                                         curr_property_p->magic_string_id);
900       setter_p = ecma_builtin_make_function_object_for_setter_accessor (builtin_id,
901                                                                         setter_id,
902                                                                         curr_property_p->magic_string_id);
903       break;
904     }
905     default:
906     {
907       JERRY_ASSERT (curr_property_p->type == ECMA_BUILTIN_PROPERTY_ACCESSOR_READ_ONLY);
908 
909       is_accessor = true;
910       getter_p = ecma_builtin_make_function_object_for_getter_accessor (builtin_id,
911                                                                         curr_property_p->value,
912                                                                         curr_property_p->magic_string_id);
913       break;
914     }
915   }
916 
917   ecma_property_t *prop_p;
918 
919   if (is_accessor)
920   {
921     ecma_create_named_accessor_property (object_p,
922                                          string_p,
923                                          getter_p,
924                                          setter_p,
925                                          curr_property_p->attributes,
926                                          &prop_p);
927 
928     if (setter_p)
929     {
930       ecma_deref_object (setter_p);
931     }
932     if (getter_p)
933     {
934       ecma_deref_object (getter_p);
935     }
936   }
937   else
938   {
939     ecma_property_value_t *prop_value_p = ecma_create_named_data_property (object_p,
940                                                                            string_p,
941                                                                            curr_property_p->attributes,
942                                                                            &prop_p);
943     prop_value_p->value = value;
944 
945     /* Reference count of objects must be decreased. */
946     if (ecma_is_value_object (value))
947     {
948       ecma_free_value (value);
949     }
950   }
951 
952   return prop_p;
953 } /* ecma_builtin_try_to_instantiate_property */
954 
955 /**
956  * List names of a built-in function's lazy instantiated properties
957  *
958  * See also:
959  *          ecma_builtin_routine_try_to_instantiate_property
960  */
961 void
ecma_builtin_routine_list_lazy_property_names(ecma_object_t * object_p,uint32_t opts,ecma_collection_t * main_collection_p,ecma_collection_t * non_enum_collection_p)962 ecma_builtin_routine_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */
963                                                uint32_t opts, /**< listing options using flags
964                                                                *   from ecma_list_properties_options_t */
965                                                ecma_collection_t *main_collection_p, /**< 'main' collection */
966                                                ecma_collection_t *non_enum_collection_p) /**< skipped 'non-enumerable'
967                                                                                           *   collection */
968 {
969   JERRY_ASSERT (ecma_get_object_is_builtin (object_p));
970   JERRY_ASSERT (ecma_get_object_type (object_p) == ECMA_OBJECT_TYPE_FUNCTION);
971   JERRY_ASSERT (ecma_builtin_function_is_routine (object_p));
972 
973   const bool separate_enumerable = (opts & ECMA_LIST_ENUMERABLE) != 0;
974   const bool is_array_indices_only = (opts & ECMA_LIST_ARRAY_INDICES) != 0;
975 
976   ecma_collection_t *for_enumerable_p = main_collection_p;
977   JERRY_UNUSED (for_enumerable_p);
978 
979   ecma_collection_t *for_non_enumerable_p = separate_enumerable ? non_enum_collection_p : main_collection_p;
980 
981   if (!is_array_indices_only)
982   {
983 #if ENABLED (JERRY_ES2015)
984     ecma_extended_object_t *ext_func_p = (ecma_extended_object_t *) object_p;
985     if (!(ext_func_p->u.built_in.u.builtin_routine.bitset & (1u << 0)))
986     {
987       /* Unintialized 'length' property is non-enumerable (ECMA-262 v6, 19.2.4.1) */
988       ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH));
989     }
990 #else /* !ENABLED (JERRY_ES2015) */
991     /* 'length' property is non-enumerable (ECMA-262 v5, 15) */
992     ecma_collection_push_back (for_non_enumerable_p, ecma_make_magic_string_value (LIT_MAGIC_STRING_LENGTH));
993 #endif /* ENABLED (JERRY_ES2015) */
994   }
995 } /* ecma_builtin_routine_list_lazy_property_names */
996 
997 /**
998  * List names of a built-in object's lazy instantiated properties
999  *
1000  * See also:
1001  *          ecma_builtin_try_to_instantiate_property
1002  */
1003 void
ecma_builtin_list_lazy_property_names(ecma_object_t * object_p,uint32_t opts,ecma_collection_t * main_collection_p,ecma_collection_t * non_enum_collection_p)1004 ecma_builtin_list_lazy_property_names (ecma_object_t *object_p, /**< a built-in object */
1005                                        uint32_t opts, /**< listing options using flags
1006                                                        *   from ecma_list_properties_options_t */
1007                                        ecma_collection_t *main_collection_p, /**< 'main' collection */
1008                                        ecma_collection_t *non_enum_collection_p) /**< skipped 'non-enumerable'
1009                                                                                   *   collection */
1010 {
1011   JERRY_ASSERT (ecma_get_object_is_builtin (object_p));
1012   JERRY_ASSERT (ecma_get_object_type (object_p) != ECMA_OBJECT_TYPE_FUNCTION
1013                 || !ecma_builtin_function_is_routine (object_p));
1014 
1015   const bool separate_enumerable = (opts & ECMA_LIST_ENUMERABLE) != 0;
1016   const bool is_array_indices_only = (opts & ECMA_LIST_ARRAY_INDICES) != 0;
1017 
1018   ecma_built_in_props_t *built_in_props_p;
1019   ecma_object_type_t object_type = ecma_get_object_type (object_p);
1020 
1021   if (object_type == ECMA_OBJECT_TYPE_CLASS || object_type == ECMA_OBJECT_TYPE_ARRAY)
1022   {
1023     built_in_props_p = &((ecma_extended_built_in_object_t *) object_p)->built_in;
1024   }
1025   else
1026   {
1027     built_in_props_p = &((ecma_extended_object_t *) object_p)->u.built_in;
1028   }
1029 
1030   ecma_builtin_id_t builtin_id = (ecma_builtin_id_t) built_in_props_p->id;
1031 
1032   JERRY_ASSERT (builtin_id < ECMA_BUILTIN_ID__COUNT);
1033   JERRY_ASSERT (ecma_builtin_is (object_p, builtin_id));
1034 
1035   const ecma_builtin_property_descriptor_t *curr_property_p = ecma_builtin_property_list_references[builtin_id];
1036 
1037   ecma_length_t index = 0;
1038   uint32_t *bitset_p = built_in_props_p->u.instantiated_bitset;
1039 
1040   ecma_collection_t *for_non_enumerable_p = (separate_enumerable ? non_enum_collection_p
1041                                                                  : main_collection_p);
1042 
1043   while (curr_property_p->magic_string_id != LIT_MAGIC_STRING__COUNT)
1044   {
1045     if (index == 32)
1046     {
1047       bitset_p++;
1048       index = 0;
1049     }
1050 
1051 #if ENABLED (JERRY_ES2015)
1052     /* Builtin symbol properties are internal magic strings which must not be listed */
1053     if (curr_property_p->magic_string_id > LIT_NON_INTERNAL_MAGIC_STRING__COUNT)
1054     {
1055       curr_property_p++;
1056       continue;
1057     }
1058 #endif /* ENABLED (JERRY_ES2015) */
1059 
1060     ecma_string_t *name_p = ecma_get_magic_string ((lit_magic_string_id_t) curr_property_p->magic_string_id);
1061 
1062     if (is_array_indices_only && ecma_string_get_array_index (name_p) == ECMA_STRING_NOT_ARRAY_INDEX)
1063     {
1064       curr_property_p++;
1065       continue;
1066     }
1067 
1068     uint32_t bit_for_index = (uint32_t) 1u << index;
1069 
1070     if (!(*bitset_p & bit_for_index) || ecma_op_ordinary_object_has_own_property (object_p, name_p))
1071     {
1072       ecma_value_t name = ecma_make_magic_string_value ((lit_magic_string_id_t) curr_property_p->magic_string_id);
1073 
1074 #if ENABLED (JERRY_ES2015)
1075       if (curr_property_p->attributes & ECMA_PROPERTY_FLAG_ENUMERABLE)
1076       {
1077         ecma_collection_push_back (main_collection_p, name);
1078       }
1079       else
1080 #endif /* ENABLED (JERRY_ES2015) */
1081       {
1082         ecma_collection_push_back (for_non_enumerable_p, name);
1083       }
1084     }
1085 
1086     curr_property_p++;
1087     index++;
1088   }
1089 } /* ecma_builtin_list_lazy_property_names */
1090 
1091 /**
1092  * Dispatcher of built-in routines
1093  *
1094  * @return ecma value
1095  *         Returned value must be freed with ecma_free_value.
1096  */
1097 static ecma_value_t
ecma_builtin_dispatch_routine(ecma_extended_object_t * func_obj_p,ecma_value_t this_arg_value,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)1098 ecma_builtin_dispatch_routine (ecma_extended_object_t *func_obj_p, /**< builtin object */
1099                                ecma_value_t this_arg_value, /**< 'this' argument value */
1100                                const ecma_value_t *arguments_list_p, /**< list of arguments passed to routine */
1101                                ecma_length_t arguments_list_len) /**< length of arguments' list */
1102 {
1103   JERRY_ASSERT (ecma_builtin_function_is_routine ((ecma_object_t *) func_obj_p));
1104 
1105   ecma_value_t padded_arguments_list_p[3] = { ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED, ECMA_VALUE_UNDEFINED };
1106 
1107   if (arguments_list_len <= 2)
1108   {
1109     switch (arguments_list_len)
1110     {
1111       case 2:
1112       {
1113         padded_arguments_list_p[1] = arguments_list_p[1];
1114         /* FALLTHRU */
1115       }
1116       case 1:
1117       {
1118         padded_arguments_list_p[0] = arguments_list_p[0];
1119         break;
1120       }
1121       default:
1122       {
1123         JERRY_ASSERT (arguments_list_len == 0);
1124       }
1125     }
1126 
1127     arguments_list_p = padded_arguments_list_p;
1128   }
1129 
1130   return ecma_builtin_routines[func_obj_p->u.built_in.id] (func_obj_p->u.built_in.routine_id,
1131                                                            this_arg_value,
1132                                                            arguments_list_p,
1133                                                            arguments_list_len);
1134 } /* ecma_builtin_dispatch_routine */
1135 
1136 /**
1137  * Handle calling [[Call]] of built-in object
1138  *
1139  * @return ecma value
1140  */
1141 ecma_value_t
ecma_builtin_dispatch_call(ecma_object_t * obj_p,ecma_value_t this_arg_value,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)1142 ecma_builtin_dispatch_call (ecma_object_t *obj_p, /**< built-in object */
1143                             ecma_value_t this_arg_value, /**< 'this' argument value */
1144                             const ecma_value_t *arguments_list_p, /**< arguments list */
1145                             ecma_length_t arguments_list_len) /**< arguments list length */
1146 {
1147   JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION);
1148   JERRY_ASSERT (ecma_get_object_is_builtin (obj_p));
1149 
1150   ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
1151 
1152   if (ecma_builtin_function_is_routine (obj_p))
1153   {
1154     return ecma_builtin_dispatch_routine (ext_obj_p,
1155                                           this_arg_value,
1156                                           arguments_list_p,
1157                                           arguments_list_len);
1158   }
1159 
1160   ecma_builtin_id_t builtin_object_id = ext_obj_p->u.built_in.id;
1161   JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_call_functions) / sizeof (ecma_builtin_dispatch_call_t));
1162   return ecma_builtin_call_functions[builtin_object_id] (arguments_list_p, arguments_list_len);
1163 } /* ecma_builtin_dispatch_call */
1164 
1165 /**
1166  * Handle calling [[Construct]] of built-in object
1167  *
1168  * @return ecma value
1169  */
1170 ecma_value_t
ecma_builtin_dispatch_construct(ecma_object_t * obj_p,ecma_object_t * new_target_p,const ecma_value_t * arguments_list_p,ecma_length_t arguments_list_len)1171 ecma_builtin_dispatch_construct (ecma_object_t *obj_p, /**< built-in object */
1172                                  ecma_object_t *new_target_p, /**< new target */
1173                                  const ecma_value_t *arguments_list_p, /**< arguments list */
1174                                  ecma_length_t arguments_list_len) /**< arguments list length */
1175 {
1176   JERRY_ASSERT (ecma_get_object_type (obj_p) == ECMA_OBJECT_TYPE_FUNCTION);
1177   JERRY_ASSERT (ecma_get_object_is_builtin (obj_p));
1178 
1179   if (ecma_builtin_function_is_routine (obj_p))
1180   {
1181     return ecma_raise_type_error (ECMA_ERR_MSG ("Built-in routines have no constructor."));
1182   }
1183 
1184   ecma_extended_object_t *ext_obj_p = (ecma_extended_object_t *) obj_p;
1185   ecma_builtin_id_t builtin_object_id = ext_obj_p->u.built_in.id;
1186   JERRY_ASSERT (builtin_object_id < sizeof (ecma_builtin_construct_functions) / sizeof (ecma_builtin_dispatch_call_t));
1187 
1188 #if ENABLED (JERRY_ES2015)
1189   ecma_object_t *old_new_target = JERRY_CONTEXT (current_new_target);
1190   JERRY_CONTEXT (current_new_target) = new_target_p;
1191 #else /* !ENABLED (JERRY_ES2015) */
1192   JERRY_UNUSED (new_target_p);
1193 #endif /* ENABLED (JERRY_ES2015) */
1194 
1195   ecma_value_t ret_value = ecma_builtin_construct_functions[builtin_object_id] (arguments_list_p, arguments_list_len);
1196 
1197 #if ENABLED (JERRY_ES2015)
1198   JERRY_CONTEXT (current_new_target) = old_new_target;
1199 #endif /* ENABLED (JERRY_ES2015) */
1200 
1201   return ret_value;
1202 } /* ecma_builtin_dispatch_construct */
1203 
1204 /**
1205  * @}
1206  * @}
1207  */
1208