• 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-helpers.h"
17 #include "jcontext.h"
18 #include "js-parser-internal.h"
19 #include "js-scanner-internal.h"
20 #include "lit-char-helpers.h"
21 
22 #if ENABLED (JERRY_PARSER)
23 
24 /** \addtogroup parser Parser
25  * @{
26  *
27  * \addtogroup jsparser JavaScript
28  * @{
29  *
30  * \addtogroup jsparser_scanner Scanner
31  * @{
32  */
33 
34 JERRY_STATIC_ASSERT (PARSER_MAXIMUM_NUMBER_OF_LITERALS + PARSER_MAXIMUM_NUMBER_OF_REGISTERS < PARSER_REGISTER_START,
35                      maximum_number_of_literals_plus_registers_must_be_less_than_register_start);
36 
37 #if ENABLED (JERRY_ES2015)
38 
39 JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG & SCANNER_LITERAL_IS_LOCAL) == 0,
40                      is_arrow_arg_binding_flag_must_not_use_local_flags);
41 
42 JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_LET & SCANNER_LITERAL_IS_LOCAL) != 0,
43                      is_let_flag_must_use_local_flags);
44 
45 JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_CONST & SCANNER_LITERAL_IS_LOCAL) != 0,
46                      is_const_flag_must_use_local_flags);
47 
48 JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_FUNC_DECLARATION & SCANNER_LITERAL_IS_LOCAL) != 0,
49                      is_func_declaration_flag_must_use_local_flags);
50 
51 JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_DESTRUCTURED_ARG & SCANNER_LITERAL_IS_LOCAL) != 0,
52                      is_arg_binding_flag_must_use_local_flags);
53 
54 JERRY_STATIC_ASSERT (SCANNER_LITERAL_IS_FUNC_DECLARATION != SCANNER_LITERAL_IS_DESTRUCTURED_ARG,
55                      is_func_declaration_must_be_different_from_is_arg_binding);
56 
57 JERRY_STATIC_ASSERT (PARSER_SCOPE_STACK_IS_CONST_REG == PARSER_SCOPE_STACK_IS_LOCAL_CREATED,
58                      scope_stack_is_const_reg_and_scope_stack_is_local_created_must_be_the_same);
59 
60 #endif /* ENABLED (JERRY_ES2015) */
61 
62 /**
63  * Raise a scanner error.
64  */
65 void
scanner_raise_error(parser_context_t * context_p)66 scanner_raise_error (parser_context_t *context_p) /**< context */
67 {
68   PARSER_THROW (context_p->try_buffer);
69   /* Should never been reached. */
70   JERRY_ASSERT (0);
71 } /* scanner_raise_error */
72 
73 #if ENABLED (JERRY_ES2015)
74 
75 /**
76  * Raise a variable redeclaration error.
77  */
78 void
scanner_raise_redeclaration_error(parser_context_t * context_p)79 scanner_raise_redeclaration_error (parser_context_t *context_p) /**< context */
80 {
81   scanner_info_t *info_p = scanner_insert_info (context_p, context_p->source_p, sizeof (scanner_info_t));
82   info_p->type = SCANNER_TYPE_ERR_REDECLARED;
83 
84   scanner_raise_error (context_p);
85 } /* scanner_raise_redeclaration_error */
86 
87 #endif /* ENABLED (JERRY_ES2015) */
88 
89 /**
90  * Allocate memory for scanner.
91  *
92  * @return allocated memory
93  */
94 void *
scanner_malloc(parser_context_t * context_p,size_t size)95 scanner_malloc (parser_context_t *context_p, /**< context */
96                 size_t size) /**< size of the memory block */
97 {
98   void *result;
99 
100   JERRY_ASSERT (size > 0);
101   result = jmem_heap_alloc_block_null_on_error (size);
102 
103   if (result == NULL)
104   {
105     scanner_cleanup (context_p);
106 
107     /* This is the only error which specify its reason. */
108     context_p->error = PARSER_ERR_OUT_OF_MEMORY;
109     PARSER_THROW (context_p->try_buffer);
110   }
111   return result;
112 } /* scanner_malloc */
113 
114 /**
115  * Free memory allocated by scanner_malloc.
116  */
117 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_free(void * ptr,size_t size)118 scanner_free (void *ptr, /**< pointer to free */
119               size_t size) /**< size of the memory block */
120 {
121   jmem_heap_free_block (ptr, size);
122 } /* scanner_free */
123 
124 /**
125  * Count the size of a stream after an info block.
126  *
127  * @return the size in bytes
128  */
129 size_t
scanner_get_stream_size(scanner_info_t * info_p,size_t size)130 scanner_get_stream_size (scanner_info_t *info_p, /**< scanner info block */
131                          size_t size) /**< size excluding the stream */
132 {
133   const uint8_t *data_p = ((const uint8_t *) info_p) + size;
134   const uint8_t *data_p_start = data_p;
135 
136   while (data_p[0] != SCANNER_STREAM_TYPE_END)
137   {
138     switch (data_p[0] & SCANNER_STREAM_TYPE_MASK)
139     {
140       case SCANNER_STREAM_TYPE_VAR:
141 #if ENABLED (JERRY_ES2015)
142       case SCANNER_STREAM_TYPE_LET:
143       case SCANNER_STREAM_TYPE_CONST:
144       case SCANNER_STREAM_TYPE_LOCAL:
145 #endif /* ENABLED (JERRY_ES2015) */
146 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
147       case SCANNER_STREAM_TYPE_IMPORT:
148 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
149       case SCANNER_STREAM_TYPE_ARG:
150 #if ENABLED (JERRY_ES2015)
151       case SCANNER_STREAM_TYPE_ARG_VAR:
152       case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
153       case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
154 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
155       case SCANNER_STREAM_TYPE_ARG_FUNC:
156 #if ENABLED (JERRY_ES2015)
157       case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
158 #endif /* ENABLED (JERRY_ES2015) */
159       case SCANNER_STREAM_TYPE_FUNC:
160       {
161         break;
162       }
163       default:
164       {
165         JERRY_ASSERT ((data_p[0] & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_HOLE);
166         data_p++;
167         continue;
168       }
169     }
170 
171     data_p += 3;
172 
173     if (data_p[-3] & SCANNER_STREAM_UINT16_DIFF)
174     {
175       data_p++;
176     }
177     else if (data_p[-1] == 0)
178     {
179       data_p += sizeof (const uint8_t *);
180     }
181   }
182 
183   return size + 1 + (size_t) (data_p - data_p_start);
184 } /* scanner_get_stream_size */
185 
186 /**
187  * Insert a scanner info block into the scanner info chain.
188  *
189  * @return newly allocated scanner info
190  */
191 scanner_info_t *
scanner_insert_info(parser_context_t * context_p,const uint8_t * source_p,size_t size)192 scanner_insert_info (parser_context_t *context_p, /**< context */
193                      const uint8_t *source_p, /**< triggering position */
194                      size_t size) /**< size of the memory block */
195 {
196   scanner_info_t *new_scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, size);
197   scanner_info_t *scanner_info_p = context_p->next_scanner_info_p;
198   scanner_info_t *prev_scanner_info_p = NULL;
199 
200   JERRY_ASSERT (scanner_info_p != NULL);
201   JERRY_ASSERT (source_p != NULL);
202 
203   new_scanner_info_p->source_p = source_p;
204 
205   while (source_p < scanner_info_p->source_p)
206   {
207     prev_scanner_info_p = scanner_info_p;
208     scanner_info_p = scanner_info_p->next_p;
209 
210     JERRY_ASSERT (scanner_info_p != NULL);
211   }
212 
213   /* Multiple scanner info blocks cannot be assigned to the same position. */
214   JERRY_ASSERT (source_p != scanner_info_p->source_p);
215 
216   new_scanner_info_p->next_p = scanner_info_p;
217 
218   if (JERRY_LIKELY (prev_scanner_info_p == NULL))
219   {
220     context_p->next_scanner_info_p = new_scanner_info_p;
221   }
222   else
223   {
224     prev_scanner_info_p->next_p = new_scanner_info_p;
225   }
226 
227   return new_scanner_info_p;
228 } /* scanner_insert_info */
229 
230 /**
231  * Insert a scanner info block into the scanner info chain before a given info block.
232  *
233  * @return newly allocated scanner info
234  */
235 scanner_info_t *
scanner_insert_info_before(parser_context_t * context_p,const uint8_t * source_p,scanner_info_t * start_info_p,size_t size)236 scanner_insert_info_before (parser_context_t *context_p, /**< context */
237                             const uint8_t *source_p, /**< triggering position */
238                             scanner_info_t *start_info_p, /**< first info position */
239                             size_t size) /**< size of the memory block */
240 {
241   JERRY_ASSERT (start_info_p != NULL);
242 
243   scanner_info_t *new_scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, size);
244   scanner_info_t *scanner_info_p = start_info_p->next_p;
245   scanner_info_t *prev_scanner_info_p = start_info_p;
246 
247   new_scanner_info_p->source_p = source_p;
248 
249   while (source_p < scanner_info_p->source_p)
250   {
251     prev_scanner_info_p = scanner_info_p;
252     scanner_info_p = scanner_info_p->next_p;
253 
254     JERRY_ASSERT (scanner_info_p != NULL);
255   }
256 
257   /* Multiple scanner info blocks cannot be assigned to the same position. */
258   JERRY_ASSERT (source_p != scanner_info_p->source_p);
259 
260   new_scanner_info_p->next_p = scanner_info_p;
261 
262   prev_scanner_info_p->next_p = new_scanner_info_p;
263   return new_scanner_info_p;
264 } /* scanner_insert_info_before */
265 
266 /**
267  * Release the next scanner info.
268  */
269 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_release_next(parser_context_t * context_p,size_t size)270 scanner_release_next (parser_context_t *context_p, /**< context */
271                       size_t size) /**< size of the memory block */
272 {
273   scanner_info_t *next_p = context_p->next_scanner_info_p->next_p;
274 
275   jmem_heap_free_block (context_p->next_scanner_info_p, size);
276   context_p->next_scanner_info_p = next_p;
277 } /* scanner_release_next */
278 
279 /**
280  * Set the active scanner info to the next scanner info.
281  */
282 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_set_active(parser_context_t * context_p)283 scanner_set_active (parser_context_t *context_p) /**< context */
284 {
285   scanner_info_t *scanner_info_p = context_p->next_scanner_info_p;
286 
287   context_p->next_scanner_info_p = scanner_info_p->next_p;
288   scanner_info_p->next_p = context_p->active_scanner_info_p;
289   context_p->active_scanner_info_p = scanner_info_p;
290 } /* scanner_set_active */
291 
292 /**
293  * Set the next scanner info to the active scanner info.
294  */
295 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_revert_active(parser_context_t * context_p)296 scanner_revert_active (parser_context_t *context_p) /**< context */
297 {
298   scanner_info_t *scanner_info_p = context_p->active_scanner_info_p;
299 
300   context_p->active_scanner_info_p = scanner_info_p->next_p;
301   scanner_info_p->next_p = context_p->next_scanner_info_p;
302   context_p->next_scanner_info_p = scanner_info_p;
303 } /* scanner_revert_active */
304 
305 /**
306  * Release the active scanner info.
307  */
308 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_release_active(parser_context_t * context_p,size_t size)309 scanner_release_active (parser_context_t *context_p, /**< context */
310                         size_t size) /**< size of the memory block */
311 {
312   scanner_info_t *next_p = context_p->active_scanner_info_p->next_p;
313 
314   jmem_heap_free_block (context_p->active_scanner_info_p, size);
315   context_p->active_scanner_info_p = next_p;
316 } /* scanner_release_active */
317 
318 /**
319  * Release switch cases.
320  */
321 void
scanner_release_switch_cases(scanner_case_info_t * case_p)322 scanner_release_switch_cases (scanner_case_info_t *case_p) /**< case list */
323 {
324   while (case_p != NULL)
325   {
326     scanner_case_info_t *next_p = case_p->next_p;
327 
328     jmem_heap_free_block (case_p, sizeof (scanner_case_info_t));
329     case_p = next_p;
330   }
331 } /* scanner_release_switch_cases */
332 
333 /**
334  * Seek to correct position in the scanner info list.
335  */
336 void
scanner_seek(parser_context_t * context_p)337 scanner_seek (parser_context_t *context_p) /**< context */
338 {
339   const uint8_t *source_p = context_p->source_p;
340   scanner_info_t *prev_p;
341 
342   if (context_p->skipped_scanner_info_p != NULL)
343   {
344     JERRY_ASSERT (context_p->skipped_scanner_info_p->source_p != NULL);
345 
346     context_p->skipped_scanner_info_end_p->next_p = context_p->next_scanner_info_p;
347 
348     if (context_p->skipped_scanner_info_end_p->source_p <= source_p)
349     {
350       prev_p = context_p->skipped_scanner_info_end_p;
351     }
352     else
353     {
354       prev_p = context_p->skipped_scanner_info_p;
355 
356       if (prev_p->source_p > source_p)
357       {
358         context_p->next_scanner_info_p = prev_p;
359         context_p->skipped_scanner_info_p = NULL;
360         return;
361       }
362 
363       context_p->skipped_scanner_info_p = prev_p;
364     }
365   }
366   else
367   {
368     prev_p = context_p->next_scanner_info_p;
369 
370     if (prev_p->source_p == NULL || prev_p->source_p > source_p)
371     {
372       return;
373     }
374 
375     context_p->skipped_scanner_info_p = prev_p;
376   }
377 
378   while (prev_p->next_p->source_p != NULL && prev_p->next_p->source_p <= source_p)
379   {
380     prev_p = prev_p->next_p;
381   }
382 
383   context_p->skipped_scanner_info_end_p = prev_p;
384   context_p->next_scanner_info_p = prev_p->next_p;
385 } /* scanner_seek */
386 
387 /**
388  * Push a new literal pool.
389  *
390  * @return the newly created literal pool
391  */
392 scanner_literal_pool_t *
scanner_push_literal_pool(parser_context_t * context_p,scanner_context_t * scanner_context_p,uint16_t status_flags)393 scanner_push_literal_pool (parser_context_t *context_p, /**< context */
394                            scanner_context_t *scanner_context_p, /**< scanner context */
395                            uint16_t status_flags) /**< combination of scanner_literal_pool_flags_t flags */
396 {
397   scanner_literal_pool_t *prev_literal_pool_p = scanner_context_p->active_literal_pool_p;
398   scanner_literal_pool_t *literal_pool_p;
399 
400   literal_pool_p = (scanner_literal_pool_t *) scanner_malloc (context_p, sizeof (scanner_literal_pool_t));
401 
402   if (!(status_flags & SCANNER_LITERAL_POOL_FUNCTION))
403   {
404     JERRY_ASSERT (prev_literal_pool_p != NULL);
405     status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS;
406 
407 #if ENABLED (JERRY_ES2015)
408     const uint16_t copied_flags = (SCANNER_LITERAL_POOL_IN_WITH
409                                    | SCANNER_LITERAL_POOL_GENERATOR
410                                    | SCANNER_LITERAL_POOL_ASYNC);
411 #else /* !ENABLED (JERRY_ES2015) */
412     const uint16_t copied_flags = SCANNER_LITERAL_POOL_IN_WITH;
413 #endif /* ENABLED (JERRY_ES2015) */
414 
415     status_flags |= (uint16_t) (prev_literal_pool_p->status_flags & copied_flags);
416   }
417 #if ENABLED (JERRY_ES2015)
418   else
419   {
420     context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION);
421 
422     if (status_flags & SCANNER_LITERAL_POOL_GENERATOR)
423     {
424       context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
425     }
426 
427     if (status_flags & SCANNER_LITERAL_POOL_ASYNC)
428     {
429       context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
430     }
431   }
432 #endif /* ENABLED (JERRY_ES2015) */
433 
434   if (prev_literal_pool_p != NULL)
435   {
436     const uint16_t copied_flags = SCANNER_LITERAL_POOL_IS_STRICT;
437     status_flags |= (uint16_t) (prev_literal_pool_p->status_flags & copied_flags);
438 
439     /* The logical value of these flags must be the same. */
440     JERRY_ASSERT (!(status_flags & SCANNER_LITERAL_POOL_IS_STRICT) == !(context_p->status_flags & PARSER_IS_STRICT));
441   }
442 
443   parser_list_init (&literal_pool_p->literal_pool,
444                     sizeof (lexer_lit_location_t),
445                     (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_lit_location_t)));
446   literal_pool_p->source_p = NULL;
447   literal_pool_p->status_flags = status_flags;
448   literal_pool_p->no_declarations = 0;
449 
450   literal_pool_p->prev_p = prev_literal_pool_p;
451   scanner_context_p->active_literal_pool_p = literal_pool_p;
452 
453   return literal_pool_p;
454 } /* scanner_push_literal_pool */
455 
456 JERRY_STATIC_ASSERT (PARSER_MAXIMUM_IDENT_LENGTH <= UINT8_MAX,
457                      maximum_ident_length_must_fit_in_a_byte);
458 
459 /**
460  * Checks whether a literal is equal to "arguments".
461  */
462 static inline bool JERRY_ATTR_ALWAYS_INLINE
scanner_literal_is_arguments(lexer_lit_location_t * literal_p)463 scanner_literal_is_arguments (lexer_lit_location_t *literal_p) /**< literal */
464 {
465   return lexer_compare_identifier_to_string (literal_p, (const uint8_t *) "arguments", 9);
466 } /* scanner_literal_is_arguments */
467 
468 /**
469  * Pop the last literal pool from the end.
470  */
471 void
scanner_pop_literal_pool(parser_context_t * context_p,scanner_context_t * scanner_context_p)472 scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
473                           scanner_context_t *scanner_context_p) /**< scanner context */
474 {
475   scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
476   scanner_literal_pool_t *prev_literal_pool_p = literal_pool_p->prev_p;
477 
478   if (literal_pool_p->source_p == NULL)
479   {
480     JERRY_ASSERT (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION);
481     JERRY_ASSERT (literal_pool_p->literal_pool.data.first_p == NULL
482                   && literal_pool_p->literal_pool.data.last_p == NULL);
483 
484     scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p;
485     scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
486     return;
487   }
488 
489   parser_list_iterator_t literal_iterator;
490   lexer_lit_location_t *literal_p;
491   uint16_t status_flags = literal_pool_p->status_flags;
492   bool arguments_required = ((status_flags & (SCANNER_LITERAL_POOL_CAN_EVAL | SCANNER_LITERAL_POOL_NO_ARGUMENTS))
493                              == SCANNER_LITERAL_POOL_CAN_EVAL);
494 
495   uint8_t can_eval_types = 0;
496 #if ENABLED (JERRY_ES2015)
497   if (prev_literal_pool_p == NULL && !(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL))
498   {
499     can_eval_types |= SCANNER_LITERAL_IS_FUNC;
500   }
501 #endif /* ENABLED (JERRY_ES2015) */
502 
503   if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && prev_literal_pool_p != NULL)
504   {
505     prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
506   }
507 
508 #if ENABLED (JERRY_DEBUGGER)
509   if (scanner_context_p->status_flags & SCANNER_CONTEXT_DEBUGGER_ENABLED)
510   {
511     /* When debugger is enabled, identifiers are not stored in registers. However,
512      * this does not affect 'eval' detection, so 'arguments' object is not created. */
513     status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
514   }
515 #endif /* ENABLED (JERRY_DEBUGGER) */
516 
517   parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
518 
519   const uint8_t *prev_source_p = literal_pool_p->source_p - 1;
520   size_t compressed_size = 1;
521   uint32_t no_declarations = literal_pool_p->no_declarations;
522 
523   while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
524   {
525     uint8_t type = literal_p->type;
526 
527     if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK))
528     {
529       continue;
530     }
531 
532     if (!(status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) && scanner_literal_is_arguments (literal_p))
533     {
534       status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS;
535 
536       if (type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LOCAL))
537       {
538         arguments_required = false;
539       }
540       else
541       {
542         literal_p->type = 0;
543         arguments_required = true;
544         continue;
545       }
546     }
547 
548 #if ENABLED (JERRY_ES2015)
549     if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION)
550         && (type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION)) == SCANNER_LITERAL_IS_FUNC)
551     {
552       if (prev_literal_pool_p == NULL
553           && (context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)
554           && scanner_scope_find_let_declaration (context_p, literal_p))
555       {
556         literal_p->type = 0;
557         continue;
558       }
559 
560       if (!(type & SCANNER_LITERAL_IS_ARG))
561       {
562         type |= SCANNER_LITERAL_IS_VAR;
563       }
564 
565       type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC;
566       literal_p->type = type;
567     }
568 #endif /* ENABLED (JERRY_ES2015) */
569 
570     if ((type & SCANNER_LITERAL_IS_LOCAL)
571         || ((type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG))
572             && (status_flags & SCANNER_LITERAL_POOL_FUNCTION)))
573     {
574       JERRY_ASSERT ((status_flags & SCANNER_LITERAL_POOL_FUNCTION)
575                     || !(literal_p->type & SCANNER_LITERAL_IS_ARG));
576 
577       if (literal_p->length == 0)
578       {
579         compressed_size += 1;
580         continue;
581       }
582 
583       no_declarations++;
584 
585       if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) || (type & can_eval_types))
586       {
587         type |= SCANNER_LITERAL_NO_REG;
588         literal_p->type = type;
589       }
590 
591       if (type & SCANNER_LITERAL_IS_FUNC)
592       {
593         no_declarations++;
594 
595 #if ENABLED (JERRY_ES2015)
596         if ((type & (SCANNER_LITERAL_IS_CONST | SCANNER_LITERAL_IS_ARG)) == SCANNER_LITERAL_IS_CONST)
597         {
598           JERRY_ASSERT (type & SCANNER_LITERAL_IS_LET);
599 
600           /* Catch parameters cannot be functions. */
601           literal_p->type = (uint8_t) (type & ~SCANNER_LITERAL_IS_FUNC);
602           no_declarations--;
603         }
604 #else /* !ENABLED (JERRY_ES2015) */
605         if (type & SCANNER_LITERAL_IS_LOCAL)
606         {
607           /* Catch parameters cannot be functions. */
608           literal_p->type = (uint8_t) (type & ~SCANNER_LITERAL_IS_FUNC);
609           no_declarations--;
610         }
611 #endif /* ENABLED (JERRY_ES2015) */
612       }
613 
614       intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p);
615 
616       if (diff >= 1 && diff <= UINT8_MAX)
617       {
618         compressed_size += 2 + 1;
619       }
620       else if (diff >= -UINT8_MAX && diff <= UINT16_MAX)
621       {
622         compressed_size += 2 + 2;
623       }
624       else
625       {
626         compressed_size += 2 + 1 + sizeof (const uint8_t *);
627       }
628 
629       prev_source_p = literal_p->char_p + literal_p->length;
630 
631       if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION)
632 #if ENABLED (JERRY_ES2015)
633           || ((type & SCANNER_LITERAL_IS_FUNC) && (status_flags & SCANNER_LITERAL_POOL_IS_STRICT))
634 #endif /* ENABLED (JERRY_ES2015) */
635           || !(type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC)))
636       {
637         continue;
638       }
639     }
640 
641     if (prev_literal_pool_p != NULL && literal_p->length > 0)
642     {
643       /* Propagate literal to upper level. */
644       lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p,
645                                                                              prev_literal_pool_p,
646                                                                              literal_p);
647       uint8_t extended_type = literal_location_p->type;
648 
649       if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) || (type & SCANNER_LITERAL_NO_REG))
650       {
651         extended_type |= SCANNER_LITERAL_NO_REG;
652       }
653 
654 #if ENABLED (JERRY_ES2015)
655       extended_type |= SCANNER_LITERAL_IS_USED;
656 
657       if (status_flags & SCANNER_LITERAL_POOL_FUNCTION_STATEMENT)
658       {
659         extended_type |= SCANNER_LITERAL_EARLY_CREATE;
660       }
661 
662       const uint8_t mask = (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_LOCAL);
663 
664       if ((type & SCANNER_LITERAL_IS_ARG)
665           || (literal_location_p->type & mask) == SCANNER_LITERAL_IS_LET
666           || (literal_location_p->type & mask) == SCANNER_LITERAL_IS_CONST)
667       {
668         /* Clears the SCANNER_LITERAL_IS_VAR and SCANNER_LITERAL_IS_FUNC flags
669          * for speculative arrow parameters and local (non-var) functions. */
670         type = 0;
671       }
672 #endif /* ENABLED (JERRY_ES2015) */
673 
674       type = (uint8_t) (type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC));
675       JERRY_ASSERT (type == 0 || !(status_flags & SCANNER_LITERAL_POOL_FUNCTION));
676 
677       literal_location_p->type = (uint8_t) (extended_type | type);
678     }
679   }
680 
681   if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) || (compressed_size > 1))
682   {
683     compressed_size += sizeof (scanner_info_t);
684 
685     scanner_info_t *info_p;
686 
687     if (prev_literal_pool_p != NULL || scanner_context_p->end_arguments_p == NULL)
688     {
689       info_p = scanner_insert_info (context_p, literal_pool_p->source_p, compressed_size);
690     }
691     else
692     {
693       scanner_info_t *start_info_p = scanner_context_p->end_arguments_p;
694       info_p = scanner_insert_info_before (context_p, literal_pool_p->source_p, start_info_p, compressed_size);
695     }
696 
697     if (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
698     {
699       no_declarations = PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK;
700     }
701 
702     uint8_t *data_p = (uint8_t *) (info_p + 1);
703 
704     if (status_flags & SCANNER_LITERAL_POOL_FUNCTION)
705     {
706       info_p->type = SCANNER_TYPE_FUNCTION;
707 
708       uint8_t u8_arg = 0;
709 
710       if (arguments_required)
711       {
712         u8_arg |= SCANNER_FUNCTION_ARGUMENTS_NEEDED;
713 
714         if (no_declarations < PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
715         {
716           no_declarations++;
717         }
718 
719 #if ENABLED (JERRY_ES2015)
720         const uint16_t is_unmapped = SCANNER_LITERAL_POOL_IS_STRICT | SCANNER_LITERAL_POOL_ARGUMENTS_UNMAPPED;
721 #else /* !ENABLED (JERRY_ES2015) */
722         const uint16_t is_unmapped = SCANNER_LITERAL_POOL_IS_STRICT;
723 #endif /* ENABLED (JERRY_ES2015) */
724 
725         if (status_flags & is_unmapped)
726         {
727           arguments_required = false;
728         }
729         else
730         {
731           u8_arg |= SCANNER_FUNCTION_MAPPED_ARGUMENTS;
732         }
733       }
734 
735 #if ENABLED (JERRY_ES2015)
736       if (status_flags & SCANNER_LITERAL_POOL_ASYNC)
737       {
738         u8_arg |= SCANNER_FUNCTION_ASYNC;
739 
740         if (status_flags & SCANNER_LITERAL_POOL_FUNCTION_STATEMENT)
741         {
742           u8_arg |= SCANNER_FUNCTION_STATEMENT;
743         }
744       }
745 
746       if (status_flags & SCANNER_LITERAL_POOL_CAN_EVAL)
747       {
748         u8_arg |= SCANNER_FUNCTION_LEXICAL_ENV_NEEDED;
749       }
750 #endif /* ENABLED (JERRY_ES2015) */
751 
752       info_p->u8_arg = u8_arg;
753       info_p->u16_arg = (uint16_t) no_declarations;
754     }
755     else
756     {
757       info_p->type = SCANNER_TYPE_BLOCK;
758 
759       JERRY_ASSERT (prev_literal_pool_p != NULL);
760     }
761 
762     parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
763     prev_source_p = literal_pool_p->source_p - 1;
764     no_declarations = literal_pool_p->no_declarations;
765 
766     while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
767     {
768       if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
769           || (!(literal_p->type & SCANNER_LITERAL_IS_LOCAL)
770               && (!(literal_p->type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG))
771                   || !(status_flags & SCANNER_LITERAL_POOL_FUNCTION))))
772       {
773         continue;
774       }
775 
776       if (literal_p->length == 0)
777       {
778         *data_p++ = SCANNER_STREAM_TYPE_HOLE;
779         continue;
780       }
781 
782       no_declarations++;
783 
784       uint8_t type = SCANNER_STREAM_TYPE_VAR;
785 
786       if (literal_p->type & SCANNER_LITERAL_IS_FUNC)
787       {
788         no_declarations++;
789         type = SCANNER_STREAM_TYPE_FUNC;
790 
791         if (literal_p->type & SCANNER_LITERAL_IS_ARG)
792         {
793           type = SCANNER_STREAM_TYPE_ARG_FUNC;
794 
795 #if ENABLED (JERRY_ES2015)
796           if (literal_p->type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
797           {
798             type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC;
799           }
800 #endif /* ENABLED (JERRY_ES2015) */
801         }
802       }
803       else if (literal_p->type & SCANNER_LITERAL_IS_ARG)
804       {
805         type = SCANNER_STREAM_TYPE_ARG;
806 
807 #if ENABLED (JERRY_ES2015)
808         if (literal_p->type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
809         {
810           type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG;
811         }
812 
813         if (literal_p->type & SCANNER_LITERAL_IS_VAR)
814         {
815           type = (uint8_t) (type + 1);
816 
817           JERRY_ASSERT (type == SCANNER_STREAM_TYPE_ARG_VAR
818                         || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR);
819         }
820 #endif /* ENABLED (JERRY_ES2015) */
821       }
822 #if ENABLED (JERRY_ES2015)
823       else if (literal_p->type & SCANNER_LITERAL_IS_LET)
824       {
825         if (!(literal_p->type & SCANNER_LITERAL_IS_CONST))
826         {
827           type = SCANNER_STREAM_TYPE_LET;
828 
829           if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && (literal_p->type & SCANNER_LITERAL_NO_REG))
830           {
831             literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
832           }
833         }
834 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
835         else if (prev_literal_pool_p == NULL)
836         {
837           type = SCANNER_STREAM_TYPE_IMPORT;
838         }
839 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
840         else
841         {
842           type = SCANNER_STREAM_TYPE_LOCAL;
843         }
844       }
845       else if (literal_p->type & SCANNER_LITERAL_IS_CONST)
846       {
847         type = SCANNER_STREAM_TYPE_CONST;
848 
849         if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && (literal_p->type & SCANNER_LITERAL_NO_REG))
850         {
851           literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
852         }
853       }
854 
855       if (literal_p->type & SCANNER_LITERAL_EARLY_CREATE)
856       {
857         type |= SCANNER_STREAM_NO_REG | SCANNER_STREAM_EARLY_CREATE;
858       }
859 #endif /* ENABLED (JERRY_ES2015) */
860 
861       if (literal_p->has_escape)
862       {
863         type |= SCANNER_STREAM_HAS_ESCAPE;
864       }
865 
866       if ((literal_p->type & SCANNER_LITERAL_NO_REG)
867           || (arguments_required && (literal_p->type & SCANNER_LITERAL_IS_ARG)))
868       {
869         type |= SCANNER_STREAM_NO_REG;
870       }
871 
872       data_p[0] = type;
873       data_p[1] = (uint8_t) literal_p->length;
874       data_p += 3;
875 
876       intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p);
877 
878       if (diff >= 1 && diff <= UINT8_MAX)
879       {
880         data_p[-1] = (uint8_t) diff;
881       }
882       else if (diff >= -UINT8_MAX && diff <= UINT16_MAX)
883       {
884         if (diff < 0)
885         {
886           diff = -diff;
887         }
888 
889         data_p[-3] |= SCANNER_STREAM_UINT16_DIFF;
890         data_p[-1] = (uint8_t) diff;
891         data_p[0] = (uint8_t) (diff >> 8);
892         data_p += 1;
893       }
894       else
895       {
896         data_p[-1] = 0;
897         memcpy (data_p, &literal_p->char_p, sizeof (const uint8_t *));
898         data_p += sizeof (const uint8_t *);
899       }
900 
901       prev_source_p = literal_p->char_p + literal_p->length;
902     }
903 
904     data_p[0] = SCANNER_STREAM_TYPE_END;
905 
906     JERRY_ASSERT (((uint8_t *) info_p) + compressed_size == data_p + 1);
907   }
908 
909   if (!(status_flags & SCANNER_LITERAL_POOL_FUNCTION)
910       && prev_literal_pool_p->no_declarations < no_declarations)
911   {
912     prev_literal_pool_p->no_declarations = (uint16_t) no_declarations;
913   }
914 
915   if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) && prev_literal_pool_p != NULL)
916   {
917     if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IS_STRICT)
918     {
919       context_p->status_flags |= PARSER_IS_STRICT;
920     }
921     else
922     {
923       context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT;
924     }
925 
926 #if ENABLED (JERRY_ES2015)
927     if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_GENERATOR)
928     {
929       context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
930     }
931     else
932     {
933       context_p->status_flags &= (uint32_t) ~PARSER_IS_GENERATOR_FUNCTION;
934     }
935 
936     if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_ASYNC)
937     {
938       context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
939     }
940     else
941     {
942       context_p->status_flags &= (uint32_t) ~PARSER_IS_ASYNC_FUNCTION;
943     }
944 #endif /* ENABLED (JERRY_ES2015) */
945   }
946 
947   scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p;
948 
949   parser_list_free (&literal_pool_p->literal_pool);
950   scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
951 } /* scanner_pop_literal_pool */
952 
953 /**
954  * Filter out the arguments from a literal pool.
955  */
956 void
scanner_filter_arguments(parser_context_t * context_p,scanner_context_t * scanner_context_p)957 scanner_filter_arguments (parser_context_t *context_p, /**< context */
958                           scanner_context_t *scanner_context_p) /**< scanner context */
959 {
960   /* Fast case: check whether all literals are arguments. */
961   scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
962   scanner_literal_pool_t *prev_literal_pool_p = literal_pool_p->prev_p;
963   parser_list_iterator_t literal_iterator;
964   lexer_lit_location_t *literal_p;
965   bool can_eval = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) != 0;
966   bool has_arguments = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0;
967 
968   if (can_eval && prev_literal_pool_p != NULL)
969   {
970     prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
971   }
972 
973   literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_CAN_EVAL;
974 
975   parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
976 
977   while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
978   {
979 #if ENABLED (JERRY_ES2015)
980     if (can_eval || (literal_p->type & SCANNER_LITERAL_EARLY_CREATE))
981     {
982       literal_p->type |= SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE;
983     }
984 #else /* !ENABLED (JERRY_ES2015) */
985     if (can_eval)
986     {
987       literal_p->type |= SCANNER_LITERAL_NO_REG;
988     }
989 #endif /* ENABLED (JERRY_ES2015) */
990 
991     uint8_t type = literal_p->type;
992 
993     if (!(type & SCANNER_LITERAL_IS_ARG) && !(has_arguments && scanner_literal_is_arguments (literal_p)))
994     {
995       break;
996     }
997 
998 #if ENABLED (JERRY_ES2015)
999     if (type & (SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG))
1000     {
1001       break;
1002     }
1003 #endif /* ENABLED (JERRY_ES2015) */
1004   }
1005 
1006   if (literal_p == NULL)
1007   {
1008     return;
1009   }
1010 
1011   scanner_literal_pool_t *new_literal_pool_p;
1012 
1013   new_literal_pool_p = (scanner_literal_pool_t *) scanner_malloc (context_p, sizeof (scanner_literal_pool_t));
1014 
1015   new_literal_pool_p->prev_p = literal_pool_p;
1016   scanner_context_p->active_literal_pool_p = new_literal_pool_p;
1017 
1018   *new_literal_pool_p = *literal_pool_p;
1019   parser_list_init (&new_literal_pool_p->literal_pool,
1020                     sizeof (lexer_lit_location_t),
1021                     (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_lit_location_t)));
1022 
1023   parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1024 
1025 #if ENABLED (JERRY_ES2015)
1026   /* Destructured args are placed after the other arguments because of register assignments. */
1027   bool has_destructured_arg = false;
1028 #endif /* ENABLED (JERRY_ES2015) */
1029 
1030   while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1031   {
1032     uint8_t type = literal_p->type;
1033 
1034     if ((type & SCANNER_LITERAL_IS_ARG) || (has_arguments && scanner_literal_is_arguments (literal_p)))
1035     {
1036 #if ENABLED (JERRY_ES2015)
1037       if (can_eval || (literal_p->type & SCANNER_LITERAL_EARLY_CREATE))
1038       {
1039         type |= SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE;
1040         literal_p->type = type;
1041       }
1042 
1043       if (type & (SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG))
1044       {
1045         has_destructured_arg = true;
1046 
1047         if (type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
1048         {
1049           continue;
1050         }
1051 
1052         type &= (uint8_t) ~SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG;
1053         type |= SCANNER_LITERAL_IS_DESTRUCTURED_ARG;
1054 
1055         literal_p->type = type;
1056         continue;
1057       }
1058 #else /* !ENABLED (JERRY_ES2015) */
1059       if (can_eval)
1060       {
1061         literal_p->type |= SCANNER_LITERAL_NO_REG;
1062       }
1063 #endif /* ENABLED (JERRY_ES2015) */
1064 
1065       lexer_lit_location_t *new_literal_p;
1066       new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool);
1067       *new_literal_p = *literal_p;
1068     }
1069     else if (prev_literal_pool_p != NULL)
1070     {
1071       /* Propagate literal to upper level. */
1072       lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p,
1073                                                                              prev_literal_pool_p,
1074                                                                              literal_p);
1075       type |= SCANNER_LITERAL_NO_REG;
1076 
1077 #if ENABLED (JERRY_ES2015)
1078       type |= SCANNER_LITERAL_IS_USED;
1079 #endif /* ENABLED (JERRY_ES2015) */
1080 
1081       literal_location_p->type |= type;
1082     }
1083   }
1084 
1085 #if ENABLED (JERRY_ES2015)
1086   if (has_destructured_arg)
1087   {
1088     parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1089 
1090     while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1091     {
1092       const uint8_t expected_flags = SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG;
1093 
1094       if ((literal_p->type & expected_flags) == expected_flags)
1095       {
1096         lexer_lit_location_t *new_literal_p;
1097         new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool);
1098         *new_literal_p = *literal_p;
1099       }
1100     }
1101   }
1102 #endif /* ENABLED (JERRY_ES2015) */
1103 
1104   new_literal_pool_p->prev_p = prev_literal_pool_p;
1105 
1106   parser_list_free (&literal_pool_p->literal_pool);
1107   scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
1108 } /* scanner_filter_arguments */
1109 
1110 /**
1111  * Add any literal to the specified literal pool.
1112  *
1113  * @return pointer to the literal
1114  */
1115 lexer_lit_location_t *
scanner_add_custom_literal(parser_context_t * context_p,scanner_literal_pool_t * literal_pool_p,const lexer_lit_location_t * literal_location_p)1116 scanner_add_custom_literal (parser_context_t *context_p, /**< context */
1117                             scanner_literal_pool_t *literal_pool_p, /**< literal pool */
1118                             const lexer_lit_location_t *literal_location_p) /**< literal */
1119 {
1120   parser_list_iterator_t literal_iterator;
1121   parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1122   lexer_lit_location_t *literal_p;
1123 
1124   const uint8_t *char_p = literal_location_p->char_p;
1125   prop_length_t length = literal_location_p->length;
1126 
1127   if (JERRY_LIKELY (!literal_location_p->has_escape))
1128   {
1129     while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1130     {
1131       if (literal_p->length == length)
1132       {
1133         if (JERRY_LIKELY (!literal_p->has_escape))
1134         {
1135           if (memcmp (literal_p->char_p, char_p, length) == 0)
1136           {
1137             return literal_p;
1138           }
1139         }
1140         else if (lexer_compare_identifier_to_string (literal_p, char_p, length))
1141         {
1142           /* The non-escaped version is preferred. */
1143           literal_p->char_p = char_p;
1144           literal_p->has_escape = 0;
1145           return literal_p;
1146         }
1147       }
1148     }
1149   }
1150   else
1151   {
1152     while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1153     {
1154       if (lexer_compare_identifiers (context_p, literal_p, literal_location_p))
1155       {
1156         return literal_p;
1157       }
1158     }
1159   }
1160 
1161   literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool);
1162   *literal_p = *literal_location_p;
1163 
1164   literal_p->type = 0;
1165 
1166   return literal_p;
1167 } /* scanner_add_custom_literal */
1168 
1169 /**
1170  * Add the current literal token to the current literal pool.
1171  *
1172  * @return pointer to the literal
1173  */
1174 inline lexer_lit_location_t * JERRY_ATTR_ALWAYS_INLINE
scanner_add_literal(parser_context_t * context_p,scanner_context_t * scanner_context_p)1175 scanner_add_literal (parser_context_t *context_p, /**< context */
1176                      scanner_context_t *scanner_context_p) /**< scanner context */
1177 {
1178   return scanner_add_custom_literal (context_p,
1179                                      scanner_context_p->active_literal_pool_p,
1180                                      &context_p->token.lit_location);
1181 } /* scanner_add_literal */
1182 
1183 /**
1184  * Add the current literal token to the current literal pool and
1185  * set SCANNER_LITERAL_NO_REG if it is inside a with statement.
1186  *
1187  * @return pointer to the literal
1188  */
1189 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_add_reference(parser_context_t * context_p,scanner_context_t * scanner_context_p)1190 scanner_add_reference (parser_context_t *context_p, /**< context */
1191                        scanner_context_t *scanner_context_p) /**< scanner context */
1192 {
1193   lexer_lit_location_t *lit_location_p = scanner_add_custom_literal (context_p,
1194                                                                      scanner_context_p->active_literal_pool_p,
1195                                                                      &context_p->token.lit_location);
1196 #if ENABLED (JERRY_ES2015)
1197   lit_location_p->type |= SCANNER_LITERAL_IS_USED;
1198 #endif /* ENABLED (JERRY_ES2015) */
1199 
1200   if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
1201   {
1202     lit_location_p->type |= SCANNER_LITERAL_NO_REG;
1203   }
1204 
1205   scanner_detect_eval_call (context_p, scanner_context_p);
1206 } /* scanner_add_reference */
1207 
1208 /**
1209  * Append an argument to the literal pool. If the argument is already present, make it a "hole".
1210  *
1211  * @return newly created literal
1212  */
1213 lexer_lit_location_t *
scanner_append_argument(parser_context_t * context_p,scanner_context_t * scanner_context_p)1214 scanner_append_argument (parser_context_t *context_p, /**< context */
1215                          scanner_context_t *scanner_context_p) /**< scanner context */
1216 {
1217   scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
1218   parser_list_iterator_t literal_iterator;
1219   parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1220   lexer_lit_location_t *literal_location_p = &context_p->token.lit_location;
1221   lexer_lit_location_t *literal_p;
1222 
1223   const uint8_t *char_p = literal_location_p->char_p;
1224   prop_length_t length = literal_location_p->length;
1225 
1226   if (JERRY_LIKELY (!context_p->token.lit_location.has_escape))
1227   {
1228     while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1229     {
1230       if (literal_p->length == length)
1231       {
1232         if (JERRY_LIKELY (!literal_p->has_escape))
1233         {
1234           if (memcmp (literal_p->char_p, char_p, length) == 0)
1235           {
1236             break;
1237           }
1238         }
1239         else if (lexer_compare_identifier_to_string (literal_p, char_p, length))
1240         {
1241           break;
1242         }
1243       }
1244     }
1245   }
1246   else
1247   {
1248     while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1249     {
1250       if (lexer_compare_identifiers (context_p, literal_p, literal_location_p))
1251       {
1252         break;
1253       }
1254     }
1255   }
1256 
1257   uint8_t literal_type = SCANNER_LITERAL_IS_ARG;
1258 
1259   if (literal_p != NULL)
1260   {
1261     literal_p->length = 0;
1262 
1263 #if ENABLED (JERRY_ES2015)
1264     if (literal_p->type & SCANNER_LITERAL_IS_USED)
1265     {
1266       literal_type = SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_EARLY_CREATE;
1267     }
1268 #endif /* ENABLED (JERRY_ES2015) */
1269   }
1270 
1271   literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool);
1272 
1273   *literal_p = context_p->token.lit_location;
1274   literal_p->type = literal_type;
1275 
1276   return literal_p;
1277 } /* scanner_append_argument */
1278 
1279 /**
1280  * Check whether an eval call is performed and update the status flags accordingly.
1281  */
1282 void
scanner_detect_eval_call(parser_context_t * context_p,scanner_context_t * scanner_context_p)1283 scanner_detect_eval_call (parser_context_t *context_p, /**< context */
1284                           scanner_context_t *scanner_context_p) /**< scanner context */
1285 {
1286   if (context_p->token.keyword_type == LEXER_KEYW_EVAL
1287       && lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN))
1288   {
1289     scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
1290   }
1291 } /* scanner_detect_eval_call */
1292 
1293 #if ENABLED (JERRY_ES2015)
1294 
1295 /**
1296  * Find a let/const declaration of a given literal.
1297  *
1298  * @return true - if the literal is found, false - otherwise
1299  */
1300 bool
scanner_scope_find_let_declaration(parser_context_t * context_p,lexer_lit_location_t * literal_p)1301 scanner_scope_find_let_declaration (parser_context_t *context_p, /**< context */
1302                                     lexer_lit_location_t *literal_p) /**< literal */
1303 {
1304   ecma_string_t *name_p;
1305 
1306   if (JERRY_LIKELY (!literal_p->has_escape))
1307   {
1308     name_p = ecma_new_ecma_string_from_utf8 (literal_p->char_p, literal_p->length);
1309   }
1310   else
1311   {
1312     uint8_t *destination_p = (uint8_t *) scanner_malloc (context_p, literal_p->length);
1313 
1314     lexer_convert_ident_to_cesu8 (destination_p, literal_p->char_p, literal_p->length);
1315 
1316     name_p = ecma_new_ecma_string_from_utf8 (destination_p, literal_p->length);
1317     scanner_free (destination_p, literal_p->length);
1318   }
1319 
1320   ecma_object_t *lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p;
1321 
1322   while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK)
1323   {
1324     if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
1325     {
1326       ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
1327 
1328       if (property_p != NULL && ecma_is_property_enumerable (*property_p))
1329       {
1330         ecma_deref_ecma_string (name_p);
1331         return true;
1332       }
1333     }
1334 
1335     JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
1336     lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
1337   }
1338 
1339   if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
1340   {
1341     ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
1342 
1343     if (property_p != NULL && ecma_is_property_enumerable (*property_p))
1344     {
1345       ecma_deref_ecma_string (name_p);
1346       return true;
1347     }
1348   }
1349 
1350   ecma_deref_ecma_string (name_p);
1351   return false;
1352 } /* scanner_scope_find_let_declaration */
1353 
1354 /**
1355  * Throws an error for invalid var statements.
1356  */
1357 void
scanner_detect_invalid_var(parser_context_t * context_p,scanner_context_t * scanner_context_p,lexer_lit_location_t * var_literal_p)1358 scanner_detect_invalid_var (parser_context_t *context_p, /**< context */
1359                             scanner_context_t *scanner_context_p, /**< scanner context */
1360                             lexer_lit_location_t *var_literal_p) /**< var literal */
1361 {
1362   if (var_literal_p->type & SCANNER_LITERAL_IS_LOCAL
1363       && !(var_literal_p->type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_ARG))
1364       && (var_literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL)
1365   {
1366     scanner_raise_redeclaration_error (context_p);
1367   }
1368 
1369   scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
1370   const uint8_t *char_p = var_literal_p->char_p;
1371   prop_length_t length = var_literal_p->length;
1372 
1373   while (!(literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION))
1374   {
1375     literal_pool_p = literal_pool_p->prev_p;
1376 
1377     parser_list_iterator_t literal_iterator;
1378     parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1379     lexer_lit_location_t *literal_p;
1380 
1381     if (JERRY_LIKELY (!context_p->token.lit_location.has_escape))
1382     {
1383       while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1384       {
1385         if (literal_p->type & SCANNER_LITERAL_IS_LOCAL
1386             && !(literal_p->type & SCANNER_LITERAL_IS_ARG)
1387             && (literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL
1388             && literal_p->length == length)
1389         {
1390           if (JERRY_LIKELY (!literal_p->has_escape))
1391           {
1392             if (memcmp (literal_p->char_p, char_p, length) == 0)
1393             {
1394               scanner_raise_redeclaration_error (context_p);
1395               return;
1396             }
1397           }
1398           else if (lexer_compare_identifier_to_string (literal_p, char_p, length))
1399           {
1400             scanner_raise_redeclaration_error (context_p);
1401             return;
1402           }
1403         }
1404       }
1405     }
1406     else
1407     {
1408       while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1409       {
1410         if (literal_p->type & SCANNER_LITERAL_IS_LOCAL
1411             && !(literal_p->type & SCANNER_LITERAL_IS_ARG)
1412             && (literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL
1413             && lexer_compare_identifiers (context_p, literal_p, var_literal_p))
1414         {
1415           scanner_raise_redeclaration_error (context_p);
1416           return;
1417         }
1418       }
1419     }
1420   }
1421 
1422   if ((context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)
1423       && scanner_scope_find_let_declaration (context_p, var_literal_p))
1424   {
1425     scanner_raise_redeclaration_error (context_p);
1426   }
1427 } /* scanner_detect_invalid_var */
1428 
1429 /**
1430  * Throws an error for invalid let statements.
1431  */
1432 void
scanner_detect_invalid_let(parser_context_t * context_p,lexer_lit_location_t * let_literal_p)1433 scanner_detect_invalid_let (parser_context_t *context_p, /**< context */
1434                             lexer_lit_location_t *let_literal_p) /**< let literal */
1435 {
1436   if (let_literal_p->type & (SCANNER_LITERAL_IS_ARG
1437                              | SCANNER_LITERAL_IS_VAR
1438                              | SCANNER_LITERAL_IS_LOCAL))
1439   {
1440     scanner_raise_redeclaration_error (context_p);
1441   }
1442 
1443   if (let_literal_p->type & SCANNER_LITERAL_IS_FUNC)
1444   {
1445     let_literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC;
1446   }
1447 } /* scanner_detect_invalid_let */
1448 
1449 /**
1450  * Push the values required for class declaration parsing.
1451  */
1452 void
scanner_push_class_declaration(parser_context_t * context_p,scanner_context_t * scanner_context_p,uint8_t stack_mode)1453 scanner_push_class_declaration (parser_context_t *context_p, /**< context */
1454                                 scanner_context_t *scanner_context_p, /* scanner context */
1455                                 uint8_t stack_mode) /**< stack mode */
1456 {
1457   JERRY_ASSERT (context_p->token.type == LEXER_KEYW_CLASS);
1458 
1459   parser_stack_push_uint8 (context_p, stack_mode);
1460   scanner_source_start_t source_start;
1461   source_start.source_p = context_p->source_p;
1462 
1463   parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t));
1464   parser_stack_push_uint8 (context_p, SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR);
1465   scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
1466 
1467   lexer_next_token (context_p);
1468 } /* scanner_push_class_declaration */
1469 
1470 /**
1471  * Push the values required for destructuring assignment or binding parsing.
1472  */
1473 void
scanner_push_destructuring_pattern(parser_context_t * context_p,scanner_context_t * scanner_context_p,uint8_t binding_type,bool is_nested)1474 scanner_push_destructuring_pattern (parser_context_t *context_p, /**< context */
1475                                     scanner_context_t *scanner_context_p, /**< scanner context */
1476                                     uint8_t binding_type, /**< type of destructuring binding pattern */
1477                                     bool is_nested) /**< nested declaration */
1478 {
1479   JERRY_ASSERT (binding_type != SCANNER_BINDING_NONE || !is_nested);
1480 
1481   scanner_source_start_t source_start;
1482   source_start.source_p = context_p->source_p;
1483 
1484   parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t));
1485   parser_stack_push_uint8 (context_p, scanner_context_p->binding_type);
1486   scanner_context_p->binding_type = binding_type;
1487 
1488   if (SCANNER_NEEDS_BINDING_LIST (binding_type))
1489   {
1490     scanner_binding_list_t *binding_list_p;
1491     binding_list_p = (scanner_binding_list_t *) scanner_malloc (context_p, sizeof (scanner_binding_list_t));
1492 
1493     binding_list_p->prev_p = scanner_context_p->active_binding_list_p;
1494     binding_list_p->items_p = NULL;
1495     binding_list_p->is_nested = is_nested;
1496 
1497     scanner_context_p->active_binding_list_p = binding_list_p;
1498   }
1499 } /* scanner_push_destructuring_pattern */
1500 
1501 /**
1502  * Pop binding list.
1503  */
1504 void
scanner_pop_binding_list(scanner_context_t * scanner_context_p)1505 scanner_pop_binding_list (scanner_context_t *scanner_context_p) /**< scanner context */
1506 {
1507   scanner_binding_list_t *binding_list_p = scanner_context_p->active_binding_list_p;
1508   scanner_binding_item_t *item_p = binding_list_p->items_p;
1509   scanner_binding_list_t *prev_binding_list_p = binding_list_p->prev_p;
1510   bool is_nested = binding_list_p->is_nested;
1511 
1512   scanner_free (binding_list_p, sizeof (scanner_binding_list_t));
1513   scanner_context_p->active_binding_list_p = prev_binding_list_p;
1514 
1515   JERRY_ASSERT (binding_list_p != NULL);
1516 
1517   if (!is_nested)
1518   {
1519     while (item_p != NULL)
1520     {
1521       scanner_binding_item_t *next_p = item_p->next_p;
1522 
1523       JERRY_ASSERT (item_p->literal_p->type & (SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_IS_ARG));
1524 
1525       scanner_free (item_p, sizeof (scanner_binding_item_t));
1526       item_p = next_p;
1527     }
1528     return;
1529   }
1530 
1531   JERRY_ASSERT (prev_binding_list_p != NULL);
1532 
1533   while (item_p != NULL)
1534   {
1535     scanner_binding_item_t *next_p = item_p->next_p;
1536 
1537     item_p->next_p = prev_binding_list_p->items_p;
1538     prev_binding_list_p->items_p = item_p;
1539 
1540     item_p = next_p;
1541   }
1542 } /* scanner_pop_binding_list */
1543 
1544 /**
1545  * Append a hole into the literal pool.
1546  */
1547 void
scanner_append_hole(parser_context_t * context_p,scanner_context_t * scanner_context_p)1548 scanner_append_hole (parser_context_t *context_p, scanner_context_t *scanner_context_p)
1549 {
1550   scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
1551 
1552   lexer_lit_location_t *literal_p;
1553   literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool);
1554 
1555   literal_p->char_p = NULL;
1556   literal_p->length = 0;
1557   literal_p->type = SCANNER_LITERAL_IS_ARG;
1558   literal_p->has_escape = 0;
1559 } /* scanner_append_hole */
1560 
1561 #endif /* ENABLED (JERRY_ES2015) */
1562 
1563 /**
1564  * Reverse the scanner info chain after the scanning is completed.
1565  */
1566 void
scanner_reverse_info_list(parser_context_t * context_p)1567 scanner_reverse_info_list (parser_context_t *context_p) /**< context */
1568 {
1569   scanner_info_t *scanner_info_p = context_p->next_scanner_info_p;
1570   scanner_info_t *last_scanner_info_p = NULL;
1571 
1572   if (scanner_info_p->type == SCANNER_TYPE_END)
1573   {
1574     return;
1575   }
1576 
1577   do
1578   {
1579     scanner_info_t *next_scanner_info_p = scanner_info_p->next_p;
1580     scanner_info_p->next_p = last_scanner_info_p;
1581 
1582     last_scanner_info_p = scanner_info_p;
1583     scanner_info_p = next_scanner_info_p;
1584   }
1585   while (scanner_info_p->type != SCANNER_TYPE_END);
1586 
1587   context_p->next_scanner_info_p->next_p = scanner_info_p;
1588   context_p->next_scanner_info_p = last_scanner_info_p;
1589 } /* scanner_reverse_info_list */
1590 
1591 /**
1592  * Release unused scanner info blocks.
1593  * This should happen only if an error is occured.
1594  */
1595 void
scanner_cleanup(parser_context_t * context_p)1596 scanner_cleanup (parser_context_t *context_p) /**< context */
1597 {
1598   if (context_p->skipped_scanner_info_p != NULL)
1599   {
1600     context_p->skipped_scanner_info_end_p->next_p = context_p->next_scanner_info_p;
1601     context_p->next_scanner_info_p = context_p->skipped_scanner_info_p;
1602     context_p->skipped_scanner_info_p = NULL;
1603   }
1604 
1605   scanner_info_t *scanner_info_p = context_p->next_scanner_info_p;
1606 
1607   while (scanner_info_p != NULL)
1608   {
1609     scanner_info_t *next_scanner_info_p = scanner_info_p->next_p;
1610 
1611     size_t size = sizeof (scanner_info_t);
1612 
1613     switch (scanner_info_p->type)
1614     {
1615       case SCANNER_TYPE_END:
1616       {
1617         scanner_info_p = context_p->active_scanner_info_p;
1618         continue;
1619       }
1620       case SCANNER_TYPE_FUNCTION:
1621       case SCANNER_TYPE_BLOCK:
1622       {
1623         size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_info_t));
1624         break;
1625       }
1626       case SCANNER_TYPE_WHILE:
1627       case SCANNER_TYPE_FOR_IN:
1628 #if ENABLED (JERRY_ES2015)
1629       case SCANNER_TYPE_FOR_OF:
1630 #endif /* ENABLED (JERRY_ES2015) */
1631       case SCANNER_TYPE_CASE:
1632 #if ENABLED (JERRY_ES2015)
1633       case SCANNER_TYPE_INITIALIZER:
1634 #endif /* ENABLED (JERRY_ES2015) */
1635       {
1636         size = sizeof (scanner_location_info_t);
1637         break;
1638       }
1639       case SCANNER_TYPE_FOR:
1640       {
1641         size = sizeof (scanner_for_info_t);
1642         break;
1643       }
1644       case SCANNER_TYPE_SWITCH:
1645       {
1646         scanner_release_switch_cases (((scanner_switch_info_t *) scanner_info_p)->case_p);
1647         size = sizeof (scanner_switch_info_t);
1648         break;
1649       }
1650       default:
1651       {
1652 #if ENABLED (JERRY_ES2015)
1653         JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS
1654                       || scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION
1655                       || scanner_info_p->type == SCANNER_TYPE_CLASS_CONSTRUCTOR
1656                       || scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED
1657                       || scanner_info_p->type == SCANNER_TYPE_ERR_ASYNC_FUNCTION);
1658 #else /* !ENABLED (JERRY_ES2015) */
1659         JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS);
1660 #endif /* ENABLED (JERRY_ES2015) */
1661         break;
1662       }
1663     }
1664 
1665     scanner_free (scanner_info_p, size);
1666     scanner_info_p = next_scanner_info_p;
1667   }
1668 
1669   context_p->next_scanner_info_p = NULL;
1670   context_p->active_scanner_info_p = NULL;
1671 } /* scanner_cleanup */
1672 
1673 /**
1674  * Checks whether a context needs to be created for a block.
1675  *
1676  * @return true - if context is needed,
1677  *         false - otherwise
1678  */
1679 bool
scanner_is_context_needed(parser_context_t * context_p,parser_check_context_type_t check_type)1680 scanner_is_context_needed (parser_context_t *context_p, /**< context */
1681                            parser_check_context_type_t check_type) /**< context type */
1682 {
1683   scanner_info_t *info_p = context_p->next_scanner_info_p;
1684   const uint8_t *data_p = (const uint8_t *) (info_p + 1);
1685 
1686   JERRY_UNUSED (check_type);
1687 
1688 #if ENABLED (JERRY_ES2015)
1689   JERRY_ASSERT ((check_type == PARSER_CHECK_BLOCK_CONTEXT ? info_p->type == SCANNER_TYPE_BLOCK
1690                                                           : info_p->type == SCANNER_TYPE_FUNCTION));
1691 
1692   uint32_t scope_stack_reg_top = (check_type != PARSER_CHECK_GLOBAL_CONTEXT ? context_p->scope_stack_reg_top
1693                                                                             : 0);
1694 #else /* !ENABLED (JERRY_ES2015) */
1695   JERRY_ASSERT (check_type == PARSER_CHECK_BLOCK_CONTEXT);
1696   JERRY_ASSERT (info_p->type == SCANNER_TYPE_BLOCK);
1697 
1698   uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top;
1699 #endif /* !JERRY_NDEBUG */
1700 
1701   while (data_p[0] != SCANNER_STREAM_TYPE_END)
1702   {
1703     uint8_t data = data_p[0];
1704 
1705 #if ENABLED (JERRY_ES2015)
1706     uint32_t type = data & SCANNER_STREAM_TYPE_MASK;
1707 
1708     if (JERRY_UNLIKELY (type == SCANNER_STREAM_TYPE_HOLE))
1709     {
1710       JERRY_ASSERT (check_type == PARSER_CHECK_FUNCTION_CONTEXT);
1711       data_p++;
1712       continue;
1713     }
1714 
1715 #ifndef JERRY_NDEBUG
1716     if (check_type == PARSER_CHECK_BLOCK_CONTEXT)
1717     {
1718       JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR
1719                     || type == SCANNER_STREAM_TYPE_LET
1720                     || type == SCANNER_STREAM_TYPE_CONST
1721                     || type == SCANNER_STREAM_TYPE_LOCAL
1722                     || type == SCANNER_STREAM_TYPE_FUNC);
1723     }
1724     else if (check_type == PARSER_CHECK_GLOBAL_CONTEXT)
1725     {
1726       /* FIXME: a private declarative lexical environment should always be present
1727        * for modules. Remove SCANNER_STREAM_TYPE_IMPORT after it is implemented. */
1728       JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR
1729                     || type == SCANNER_STREAM_TYPE_LET
1730                     || type == SCANNER_STREAM_TYPE_CONST
1731                     || type == SCANNER_STREAM_TYPE_FUNC
1732                     || type == SCANNER_STREAM_TYPE_IMPORT);
1733 
1734       /* Only let/const can be stored in registers */
1735       JERRY_ASSERT ((data & SCANNER_STREAM_NO_REG)
1736                     || (type == SCANNER_STREAM_TYPE_FUNC && (context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL))
1737                     || type == SCANNER_STREAM_TYPE_LET
1738                     || type == SCANNER_STREAM_TYPE_CONST);
1739     }
1740     else
1741     {
1742       JERRY_ASSERT (check_type == PARSER_CHECK_FUNCTION_CONTEXT);
1743 
1744       JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR
1745                     || type == SCANNER_STREAM_TYPE_LET
1746                     || type == SCANNER_STREAM_TYPE_CONST
1747                     || type == SCANNER_STREAM_TYPE_LOCAL
1748                     || type == SCANNER_STREAM_TYPE_ARG
1749                     || type == SCANNER_STREAM_TYPE_ARG_VAR
1750                     || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG
1751                     || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR
1752                     || type == SCANNER_STREAM_TYPE_ARG_FUNC
1753                     || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC
1754                     || type == SCANNER_STREAM_TYPE_FUNC);
1755     }
1756 #endif /* !JERRY_NDEBUG */
1757 
1758 #else /* !ENABLED (JERRY_ES2015) */
1759     JERRY_ASSERT ((data & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_VAR);
1760 #endif /* ENABLED (JERRY_ES2015) */
1761 
1762     if (!(data & SCANNER_STREAM_UINT16_DIFF))
1763     {
1764       if (data_p[2] != 0)
1765       {
1766         data_p += 2 + 1;
1767       }
1768       else
1769       {
1770         data_p += 2 + 1 + sizeof (const uint8_t *);
1771       }
1772     }
1773     else
1774     {
1775       data_p += 2 + 2;
1776     }
1777 
1778 #if ENABLED (JERRY_ES2015)
1779     if (JERRY_UNLIKELY (check_type == PARSER_CHECK_GLOBAL_CONTEXT)
1780         && (type == SCANNER_STREAM_TYPE_VAR
1781             || (type == SCANNER_STREAM_TYPE_FUNC && !(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL))
1782             || type == SCANNER_STREAM_TYPE_IMPORT))
1783     {
1784       continue;
1785     }
1786 
1787     if (JERRY_UNLIKELY (check_type == PARSER_CHECK_FUNCTION_CONTEXT))
1788     {
1789       if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)
1790           || type == SCANNER_STREAM_TYPE_ARG_VAR
1791           || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR)
1792       {
1793         /* The return value is true, if the variable is stored in the lexical environment
1794          * or all registers have already been used for function arguments. This can be
1795          * inprecise in the latter case, but this is a very rare corner case. A more
1796          * sophisticated check would require to decode the literal. */
1797         if ((data & SCANNER_STREAM_NO_REG)
1798             || scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
1799         {
1800           return true;
1801         }
1802         continue;
1803       }
1804 
1805       if (SCANNER_STREAM_TYPE_IS_ARG (type))
1806       {
1807         continue;
1808       }
1809     }
1810 #endif /* ENABLED (JERRY_ES2015) */
1811 
1812     if ((data & SCANNER_STREAM_NO_REG)
1813         || scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
1814     {
1815       return true;
1816     }
1817 
1818     scope_stack_reg_top++;
1819   }
1820 
1821   return false;
1822 } /* scanner_is_context_needed */
1823 
1824 #if ENABLED (JERRY_ES2015)
1825 
1826 /**
1827  * Try to scan/parse the ".target" part in the "new.target" expression.
1828  *
1829  * Upon exiting with "true" the current token will point to the "target"
1830  * literal.
1831  *
1832  * If the "target" literal is not after the "new." then a scanner/parser
1833  * error will be raised.
1834  *
1835  * @returns true if the ".target" part was found
1836  *          false if there is no "." after the new.
1837  */
1838 bool
scanner_try_scan_new_target(parser_context_t * context_p)1839 scanner_try_scan_new_target (parser_context_t *context_p) /**< parser/scanner context */
1840 {
1841   JERRY_ASSERT (context_p->token.type == LEXER_KEYW_NEW);
1842 
1843   if (lexer_check_next_character (context_p, LIT_CHAR_DOT))
1844   {
1845     lexer_next_token (context_p);
1846     if (context_p->token.type != LEXER_DOT)
1847     {
1848       parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER);
1849     }
1850 
1851     lexer_next_token (context_p);
1852     if (!lexer_token_is_identifier (context_p, "target", 6))
1853     {
1854       parser_raise_error (context_p, PARSER_ERR_NEW_TARGET_EXPECTED);
1855     }
1856 
1857     return true;
1858   }
1859   return false;
1860 } /* scanner_try_scan_new_target */
1861 
1862 #endif /* ENABLED (JERRY_ES2015) */
1863 
1864 /**
1865  * Description of "arguments" literal string.
1866  */
1867 const lexer_lit_location_t lexer_arguments_literal =
1868 {
1869   (const uint8_t *) "arguments", 9, LEXER_IDENT_LITERAL, false
1870 };
1871 
1872 /**
1873  * Create an unused literal.
1874  */
1875 static void
scanner_create_unused_literal(parser_context_t * context_p,uint8_t status_flags)1876 scanner_create_unused_literal (parser_context_t *context_p, /**< context */
1877                                uint8_t status_flags) /**< initial status flags */
1878 {
1879   if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS))
1880   {
1881     parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
1882   }
1883 
1884   lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
1885 
1886   literal_p->type = LEXER_UNUSED_LITERAL;
1887   literal_p->status_flags = status_flags;
1888 
1889   context_p->literal_count++;
1890 } /* scanner_create_unused_literal */
1891 
1892 #if ENABLED (JERRY_ES2015)
1893 /**
1894  * Emit checks for redeclared bindings in the global lexical scope.
1895  */
1896 void
scanner_check_variables(parser_context_t * context_p)1897 scanner_check_variables (parser_context_t *context_p) /**< context */
1898 {
1899   scanner_info_t *info_p = context_p->next_scanner_info_p;
1900   const uint8_t *next_data_p = (const uint8_t *) (info_p + 1);
1901   lexer_lit_location_t literal;
1902 
1903   JERRY_ASSERT (info_p->type == SCANNER_TYPE_FUNCTION);
1904 
1905   literal.char_p = info_p->source_p - 1;
1906 
1907   while (next_data_p[0] != SCANNER_STREAM_TYPE_END)
1908   {
1909     uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK;
1910     const uint8_t *data_p = next_data_p;
1911 
1912     JERRY_ASSERT (type != SCANNER_STREAM_TYPE_HOLE
1913                   && !SCANNER_STREAM_TYPE_IS_ARG (type)
1914                   && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type));
1915     JERRY_ASSERT (data_p[0] & SCANNER_STREAM_NO_REG);
1916 
1917     if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
1918     {
1919       if (data_p[2] != 0)
1920       {
1921         literal.char_p += data_p[2];
1922         next_data_p += 2 + 1;
1923       }
1924       else
1925       {
1926         memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *));
1927         next_data_p += 2 + 1 + sizeof (const uint8_t *);
1928       }
1929     }
1930     else
1931     {
1932       int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
1933 
1934       if (diff <= UINT8_MAX)
1935       {
1936         diff = -diff;
1937       }
1938 
1939       literal.char_p += diff;
1940       next_data_p += 2 + 2;
1941     }
1942 
1943     literal.length = data_p[1];
1944     literal.type = LEXER_IDENT_LITERAL;
1945     literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
1946 
1947     lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
1948     literal.char_p += data_p[1];
1949 
1950 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
1951     if (type == SCANNER_STREAM_TYPE_IMPORT)
1952     {
1953       continue;
1954     }
1955 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
1956 
1957     context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED;
1958 
1959     uint16_t opcode;
1960     if (type == SCANNER_STREAM_TYPE_VAR || type == SCANNER_STREAM_TYPE_FUNC)
1961     {
1962       opcode = CBC_CHECK_VAR;
1963     }
1964     else
1965     {
1966       opcode = CBC_CHECK_LET;
1967     }
1968 
1969     parser_emit_cbc_literal (context_p, opcode, context_p->lit_object.index);
1970   }
1971 
1972   parser_flush_cbc (context_p);
1973 } /* scanner_check_variables */
1974 #endif /* ENABLED (JERRY_ES2015) */
1975 
1976 /**
1977  * Create and/or initialize var/let/const/function/etc. variables.
1978  */
1979 void
scanner_create_variables(parser_context_t * context_p,uint32_t option_flags)1980 scanner_create_variables (parser_context_t *context_p, /**< context */
1981                           uint32_t option_flags) /**< combination of scanner_create_variables_flags_t bits */
1982 {
1983   scanner_info_t *info_p = context_p->next_scanner_info_p;
1984   const uint8_t *next_data_p = (const uint8_t *) (info_p + 1);
1985   uint8_t info_type = info_p->type;
1986   uint8_t info_u8_arg = info_p->u8_arg;
1987   lexer_lit_location_t literal;
1988   parser_scope_stack_t *scope_stack_p;
1989   parser_scope_stack_t *scope_stack_end_p;
1990 
1991   JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION || info_type == SCANNER_TYPE_BLOCK);
1992   JERRY_ASSERT (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)
1993                 || !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY));
1994   JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION
1995                 || !(option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_ARGS | SCANNER_CREATE_VARS_IS_FUNCTION_BODY)));
1996 
1997   if (info_type == SCANNER_TYPE_FUNCTION && !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY))
1998   {
1999     JERRY_ASSERT (context_p->scope_stack_p == NULL);
2000 
2001     size_t stack_size = info_p->u16_arg * sizeof (parser_scope_stack_t);
2002     context_p->scope_stack_size = info_p->u16_arg;
2003 
2004     scope_stack_p = NULL;
2005 
2006     if (stack_size > 0)
2007     {
2008       scope_stack_p = (parser_scope_stack_t *) parser_malloc (context_p, stack_size);
2009     }
2010 
2011     context_p->scope_stack_p = scope_stack_p;
2012     scope_stack_end_p = scope_stack_p + context_p->scope_stack_size;
2013   }
2014   else
2015   {
2016     JERRY_ASSERT (context_p->scope_stack_p != NULL || context_p->scope_stack_size == 0);
2017 
2018     scope_stack_p = context_p->scope_stack_p;
2019     scope_stack_end_p = scope_stack_p + context_p->scope_stack_size;
2020     scope_stack_p += context_p->scope_stack_top;
2021   }
2022 
2023   uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top;
2024 
2025   literal.char_p = info_p->source_p - 1;
2026 
2027   while (next_data_p[0] != SCANNER_STREAM_TYPE_END)
2028   {
2029     uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK;
2030     const uint8_t *data_p = next_data_p;
2031 
2032     JERRY_ASSERT ((option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_BODY | SCANNER_CREATE_VARS_IS_FUNCTION_ARGS))
2033                   || (type != SCANNER_STREAM_TYPE_HOLE
2034                       && !SCANNER_STREAM_TYPE_IS_ARG (type)
2035                       && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)));
2036 
2037 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2038     JERRY_ASSERT (type != SCANNER_STREAM_TYPE_IMPORT || (data_p[0] & SCANNER_STREAM_NO_REG));
2039 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2040 
2041     if (type == SCANNER_STREAM_TYPE_HOLE)
2042     {
2043       next_data_p++;
2044 
2045       if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
2046       {
2047         continue;
2048       }
2049 
2050       if (info_u8_arg & SCANNER_FUNCTION_MAPPED_ARGUMENTS)
2051       {
2052         scanner_create_unused_literal (context_p, LEXER_FLAG_FUNCTION_ARGUMENT);
2053       }
2054 
2055       if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
2056       {
2057         scope_stack_reg_top++;
2058       }
2059       continue;
2060     }
2061 
2062     JERRY_ASSERT (context_p->scope_stack_size != 0);
2063 
2064     if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
2065     {
2066       if (data_p[2] != 0)
2067       {
2068         literal.char_p += data_p[2];
2069         next_data_p += 2 + 1;
2070       }
2071       else
2072       {
2073         memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *));
2074         next_data_p += 2 + 1 + sizeof (const uint8_t *);
2075       }
2076     }
2077     else
2078     {
2079       int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
2080 
2081       if (diff <= UINT8_MAX)
2082       {
2083         diff = -diff;
2084       }
2085 
2086       literal.char_p += diff;
2087       next_data_p += 2 + 2;
2088     }
2089 
2090     if (SCANNER_STREAM_TYPE_IS_ARG (type))
2091     {
2092       if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
2093       {
2094 #if ENABLED (JERRY_ES2015)
2095         if ((context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)
2096             && (type == SCANNER_STREAM_TYPE_ARG_VAR || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR))
2097         {
2098           literal.length = data_p[1];
2099           literal.type = LEXER_IDENT_LITERAL;
2100           literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
2101 
2102           /* Literal must be exists. */
2103           lexer_construct_literal_object (context_p, &literal, LEXER_IDENT_LITERAL);
2104 
2105           if (context_p->lit_object.index < PARSER_REGISTER_START)
2106           {
2107             parser_emit_cbc_ext_literal_from_token (context_p, CBC_EXT_COPY_FROM_ARG);
2108           }
2109         }
2110 #endif /* ENABLED (JERRY_ES2015) */
2111 
2112         literal.char_p += data_p[1];
2113         continue;
2114       }
2115     }
2116     else if ((option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)
2117              && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type))
2118     {
2119       /* Function arguments must come first. */
2120       break;
2121     }
2122 
2123     literal.length = data_p[1];
2124     literal.type = LEXER_IDENT_LITERAL;
2125     literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
2126 
2127     lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
2128     literal.char_p += data_p[1];
2129 
2130     if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type) && (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY))
2131     {
2132       JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p + 2);
2133       JERRY_ASSERT (context_p->status_flags & PARSER_IS_FUNCTION);
2134 #if ENABLED (JERRY_ES2015)
2135       JERRY_ASSERT (!(context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS));
2136 #endif /* ENABLED (JERRY_ES2015) */
2137 
2138       parser_scope_stack_t *function_map_p = scope_stack_p - 2;
2139       uint16_t literal_index = context_p->lit_object.index;
2140 
2141       while (literal_index != function_map_p->map_from)
2142       {
2143         function_map_p--;
2144 
2145         JERRY_ASSERT (function_map_p >= context_p->scope_stack_p);
2146       }
2147 
2148       JERRY_ASSERT (function_map_p[1].map_from == PARSER_SCOPE_STACK_FUNC);
2149 
2150       cbc_opcode_t opcode = CBC_SET_VAR_FUNC;
2151 
2152 #if ENABLED (JERRY_ES2015)
2153       if (JERRY_UNLIKELY (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)
2154           && (function_map_p[0].map_to & PARSER_SCOPE_STACK_REGISTER_MASK) == 0)
2155       {
2156         opcode = CBC_INIT_ARG_OR_FUNC;
2157       }
2158 #endif /* ENABLED (JERRY_ES2015) */
2159 
2160       parser_emit_cbc_literal_value (context_p,
2161                                      (uint16_t) opcode,
2162                                      function_map_p[1].map_to,
2163                                      scanner_decode_map_to (function_map_p));
2164       continue;
2165     }
2166 
2167     if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
2168     {
2169       JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
2170       parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
2171     }
2172 
2173     scope_stack_p->map_from = context_p->lit_object.index;
2174 
2175 #if ENABLED (JERRY_ES2015)
2176     if (info_type == SCANNER_TYPE_FUNCTION)
2177     {
2178       if (type != SCANNER_STREAM_TYPE_LET
2179 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2180           && type != SCANNER_STREAM_TYPE_IMPORT
2181 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2182           && type != SCANNER_STREAM_TYPE_CONST)
2183       {
2184         context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_GLOBAL;
2185       }
2186     }
2187 #endif /* ENABLED (JERRY_ES2015) */
2188 
2189     uint16_t map_to;
2190     uint16_t func_init_opcode = CBC_INIT_ARG_OR_FUNC;
2191 
2192     if (!(data_p[0] & SCANNER_STREAM_NO_REG)
2193         && scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
2194     {
2195       map_to = (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top);
2196 
2197 #if ENABLED (JERRY_ES2015)
2198       scope_stack_p->map_to = (uint16_t) (scope_stack_reg_top + 1);
2199 #else /* !ENABLED (JERRY_ES2015) */
2200       scope_stack_p->map_to = map_to;
2201 #endif /* ENABLED (JERRY_ES2015) */
2202 
2203       scope_stack_reg_top++;
2204 #if ENABLED (JERRY_ES2015)
2205       switch (type)
2206       {
2207         case SCANNER_STREAM_TYPE_CONST:
2208         {
2209           scope_stack_p->map_to |= PARSER_SCOPE_STACK_IS_CONST_REG;
2210           /* FALLTHRU */
2211         }
2212         case SCANNER_STREAM_TYPE_LET:
2213         case SCANNER_STREAM_TYPE_ARG:
2214         case SCANNER_STREAM_TYPE_ARG_VAR:
2215         case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
2216         case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
2217         case SCANNER_STREAM_TYPE_ARG_FUNC:
2218         case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
2219         {
2220           scope_stack_p->map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY;
2221           break;
2222         }
2223       }
2224 
2225       func_init_opcode = CBC_SET_VAR_FUNC;
2226 #endif /* ENABLED (JERRY_ES2015) */
2227     }
2228     else
2229     {
2230       context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED;
2231       map_to = context_p->lit_object.index;
2232 
2233 #if ENABLED (JERRY_ES2015)
2234       uint16_t scope_stack_map_to = 0;
2235 #else /* !ENABLED (JERRY_ES2015) */
2236       scope_stack_p->map_to = map_to;
2237 #endif /* ENABLED (JERRY_ES2015) */
2238 
2239       if (info_type == SCANNER_TYPE_FUNCTION)
2240       {
2241         context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
2242       }
2243 
2244       switch (type)
2245       {
2246 #if ENABLED (JERRY_ES2015)
2247         case SCANNER_STREAM_TYPE_LET:
2248         case SCANNER_STREAM_TYPE_CONST:
2249         case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
2250         case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
2251         case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
2252         {
2253           scope_stack_map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY;
2254 
2255           if (!(data_p[0] & SCANNER_STREAM_EARLY_CREATE))
2256           {
2257             break;
2258           }
2259           scope_stack_map_to |= PARSER_SCOPE_STACK_IS_LOCAL_CREATED;
2260           /* FALLTHRU */
2261         }
2262         case SCANNER_STREAM_TYPE_LOCAL:
2263 #endif /* ENABLED (JERRY_ES2015) */
2264         case SCANNER_STREAM_TYPE_VAR:
2265         {
2266 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2267           context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
2268 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2269 
2270 #if ENABLED (JERRY_ES2015)
2271           uint16_t opcode;
2272 
2273           switch (type)
2274           {
2275             case SCANNER_STREAM_TYPE_LET:
2276             {
2277               opcode = CBC_CREATE_LET;
2278               break;
2279             }
2280             case SCANNER_STREAM_TYPE_CONST:
2281             {
2282               opcode = CBC_CREATE_CONST;
2283               break;
2284             }
2285             case SCANNER_STREAM_TYPE_VAR:
2286             {
2287               opcode = CBC_CREATE_VAR;
2288 
2289               if (option_flags & SCANNER_CREATE_VARS_IS_SCRIPT)
2290               {
2291                 opcode = CBC_CREATE_VAR_EVAL;
2292 
2293                 if (context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT)
2294                 {
2295                   opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_CREATE_VAR_EVAL);
2296                 }
2297               }
2298               break;
2299             }
2300             default:
2301             {
2302               JERRY_ASSERT (type == SCANNER_STREAM_TYPE_LOCAL
2303                             || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG
2304                             || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR
2305                             || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC);
2306 
2307               opcode = CBC_CREATE_LOCAL;
2308               break;
2309             }
2310           }
2311 #else /* !ENABLED (JERRY_ES2015) */
2312           uint16_t opcode = ((option_flags & SCANNER_CREATE_VARS_IS_SCRIPT) ? CBC_CREATE_VAR_EVAL
2313                                                                             : CBC_CREATE_VAR);
2314 #endif /* ENABLED (JERRY_ES2015) */
2315 
2316           parser_emit_cbc_literal (context_p, opcode, map_to);
2317           break;
2318         }
2319         case SCANNER_STREAM_TYPE_ARG:
2320 #if ENABLED (JERRY_ES2015)
2321         case SCANNER_STREAM_TYPE_ARG_VAR:
2322 #endif /* ENABLED (JERRY_ES2015) */
2323         case SCANNER_STREAM_TYPE_ARG_FUNC:
2324         {
2325 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2326           context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
2327 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2328 
2329 #if ENABLED (JERRY_ES2015)
2330           scope_stack_map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY;
2331 
2332           /* Argument initializers of functions with mapped arguments (e.g. function f(a,b,a) {}) are
2333            * generated here. The other initializers are handled by parser_parse_function_arguments(). */
2334           if (info_u8_arg & SCANNER_FUNCTION_MAPPED_ARGUMENTS)
2335           {
2336 #endif /* ENABLED (JERRY_ES2015) */
2337             parser_emit_cbc_literal_value (context_p,
2338                                            CBC_INIT_ARG_OR_FUNC,
2339                                            (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top),
2340                                            map_to);
2341 #if ENABLED (JERRY_ES2015)
2342           }
2343           else if (data_p[0] & SCANNER_STREAM_EARLY_CREATE)
2344           {
2345             parser_emit_cbc_literal (context_p, CBC_CREATE_LOCAL, map_to);
2346             scope_stack_map_to |= PARSER_SCOPE_STACK_IS_LOCAL_CREATED;
2347           }
2348 #endif /* ENABLED (JERRY_ES2015) */
2349 
2350           if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
2351           {
2352             scope_stack_reg_top++;
2353           }
2354           break;
2355         }
2356       }
2357 
2358 #if ENABLED (JERRY_ES2015)
2359       scope_stack_p->map_to = scope_stack_map_to;
2360 #endif /* ENABLED (JERRY_ES2015) */
2361     }
2362 
2363     scope_stack_p++;
2364 
2365     if (!SCANNER_STREAM_TYPE_IS_FUNCTION (type))
2366     {
2367       continue;
2368     }
2369 
2370     if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
2371     {
2372       JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
2373       parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
2374     }
2375 
2376 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2377     context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
2378 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2379 
2380     if (!SCANNER_STREAM_TYPE_IS_ARG_FUNC (type))
2381     {
2382       if (func_init_opcode == CBC_INIT_ARG_OR_FUNC && (option_flags & SCANNER_CREATE_VARS_IS_SCRIPT))
2383       {
2384 #if ENABLED (JERRY_ES2015)
2385         literal.char_p -= data_p[1];
2386         if (!(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)
2387             || !scanner_scope_find_let_declaration (context_p, &literal))
2388         {
2389           func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL;
2390 
2391           if (context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT)
2392           {
2393             func_init_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL);
2394           }
2395         }
2396         literal.char_p += data_p[1];
2397 #else /* !ENABLED (JERRY_ES2015) */
2398         func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL;
2399 #endif /* ENABLED (JERRY_ES2015) */
2400       }
2401 
2402       parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to);
2403     }
2404 
2405     scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC;
2406     scope_stack_p->map_to = context_p->literal_count;
2407     scope_stack_p++;
2408 
2409     scanner_create_unused_literal (context_p, 0);
2410   }
2411 
2412   if (info_type == SCANNER_TYPE_FUNCTION
2413       && !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
2414       && (info_u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED))
2415   {
2416     JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION);
2417 
2418     if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
2419     {
2420       JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
2421       parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
2422     }
2423 
2424     context_p->status_flags |= PARSER_ARGUMENTS_NEEDED | PARSER_LEXICAL_ENV_NEEDED;
2425 
2426     lexer_construct_literal_object (context_p, &lexer_arguments_literal, lexer_arguments_literal.type);
2427 
2428     scope_stack_p->map_from = context_p->lit_object.index;
2429 #if ENABLED (JERRY_ES2015)
2430     scope_stack_p->map_to = 0;
2431 #else /* !ENABLED (JERRY_ES2015) */
2432     scope_stack_p->map_to = context_p->lit_object.index;
2433 #endif /* ENABLED (JERRY_ES2015) */
2434     scope_stack_p++;
2435   }
2436 
2437   context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
2438   context_p->scope_stack_reg_top = (uint16_t) scope_stack_reg_top;
2439 
2440 #if ENABLED (JERRY_ES2015)
2441   if (info_type == SCANNER_TYPE_FUNCTION)
2442   {
2443     context_p->scope_stack_global_end = context_p->scope_stack_top;
2444   }
2445 #endif /* ENABLED (JERRY_ES2015) */
2446 
2447   if (context_p->register_count < scope_stack_reg_top)
2448   {
2449     context_p->register_count = (uint16_t) scope_stack_reg_top;
2450   }
2451 
2452   if (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS))
2453   {
2454     scanner_release_next (context_p, (size_t) (next_data_p + 1 - ((const uint8_t *) info_p)));
2455   }
2456   parser_flush_cbc (context_p);
2457 } /* scanner_create_variables */
2458 
2459 /**
2460  * Get location from context.
2461  */
2462 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_get_location(scanner_location_t * location_p,parser_context_t * context_p)2463 scanner_get_location (scanner_location_t *location_p, /**< location */
2464                       parser_context_t *context_p) /**< context */
2465 {
2466   location_p->source_p = context_p->source_p;
2467   location_p->line = context_p->line;
2468   location_p->column = context_p->column;
2469 } /* scanner_get_location */
2470 
2471 /**
2472  * Set context location.
2473  */
2474 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_set_location(parser_context_t * context_p,scanner_location_t * location_p)2475 scanner_set_location (parser_context_t *context_p, /**< context */
2476                       scanner_location_t *location_p) /**< location */
2477 {
2478   context_p->source_p = location_p->source_p;
2479   context_p->line = location_p->line;
2480   context_p->column = location_p->column;
2481 } /* scanner_set_location */
2482 
2483 /**
2484  * Get the real map_to value.
2485  */
2486 inline uint16_t JERRY_ATTR_ALWAYS_INLINE
scanner_decode_map_to(parser_scope_stack_t * stack_item_p)2487 scanner_decode_map_to (parser_scope_stack_t *stack_item_p) /**< scope stack item */
2488 {
2489   JERRY_ASSERT (stack_item_p->map_from != PARSER_SCOPE_STACK_FUNC);
2490 
2491 #if ENABLED (JERRY_ES2015)
2492   uint16_t value = (stack_item_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK);
2493   return (value == 0) ? stack_item_p->map_from : (uint16_t) (value + (PARSER_REGISTER_START - 1));
2494 #else /* !ENABLED (JERRY_ES2015) */
2495   return stack_item_p->map_to;
2496 #endif /* ENABLED (JERRY_ES2015) */
2497 } /* scanner_decode_map_to */
2498 
2499 #if ENABLED (JERRY_ES2015)
2500 
2501 /**
2502  * Checks whether the literal is a const in the current scope.
2503  *
2504  * @return true if the literal is a const, false otherwise
2505  */
2506 bool
scanner_literal_is_const_reg(parser_context_t * context_p,uint16_t literal_index)2507 scanner_literal_is_const_reg (parser_context_t *context_p, /**< context */
2508                               uint16_t literal_index) /**< literal index */
2509 {
2510   if (literal_index < PARSER_REGISTER_START)
2511   {
2512     /* Re-assignment of non-register const bindings are detected elsewhere. */
2513     return false;
2514   }
2515 
2516   parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top;
2517 
2518   literal_index = (uint16_t) (literal_index - (PARSER_REGISTER_START - 1));
2519 
2520   do
2521   {
2522     /* Registers must be found in the scope stack. */
2523     JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p);
2524     scope_stack_p--;
2525   }
2526   while (literal_index != (scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK));
2527 
2528   return (scope_stack_p->map_to & PARSER_SCOPE_STACK_IS_CONST_REG) != 0;
2529 } /* scanner_literal_is_const_reg */
2530 
2531 /**
2532  * Checks whether the literal is created before.
2533  *
2534  * @return true if the literal is created before, false otherwise
2535  */
2536 bool
scanner_literal_is_created(parser_context_t * context_p,uint16_t literal_index)2537 scanner_literal_is_created (parser_context_t *context_p, /**< context */
2538                             uint16_t literal_index) /**< literal index */
2539 {
2540   JERRY_ASSERT (literal_index < PARSER_REGISTER_START);
2541 
2542   parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top;
2543 
2544   do
2545   {
2546     /* These literals must be found in the scope stack. */
2547     JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p);
2548     scope_stack_p--;
2549   }
2550   while (literal_index != scope_stack_p->map_from);
2551 
2552   JERRY_ASSERT ((scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK) == 0);
2553 
2554   return (scope_stack_p->map_to & PARSER_SCOPE_STACK_IS_LOCAL_CREATED) != 0;
2555 } /* scanner_literal_is_created */
2556 
2557 #endif /* ENABLED (JERRY_ES2015) */
2558 
2559 /**
2560  * @}
2561  * @}
2562  * @}
2563  */
2564 
2565 #endif /* ENABLED (JERRY_PARSER) */
2566