• 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 "debugger.h"
17 #include "ecma-exceptions.h"
18 #include "ecma-helpers.h"
19 #include "ecma-literal-storage.h"
20 #include "ecma-module.h"
21 #include "jcontext.h"
22 #include "js-parser-internal.h"
23 
24 #if ENABLED (JERRY_PARSER)
25 
26 JERRY_STATIC_ASSERT ((int) ECMA_PARSE_STRICT_MODE == (int) PARSER_IS_STRICT,
27                      ecma_parse_strict_mode_must_be_equal_to_parser_is_strict);
28 
29 #if ENABLED (JERRY_ES2015)
30 JERRY_STATIC_ASSERT (PARSER_SAVE_STATUS_FLAGS (PARSER_ALLOW_SUPER) == 0x1,
31                      incorrect_saving_of_ecma_parse_allow_super);
32 JERRY_STATIC_ASSERT (PARSER_RESTORE_STATUS_FLAGS (ECMA_PARSE_ALLOW_SUPER) == PARSER_ALLOW_SUPER,
33                      incorrect_restoring_of_ecma_parse_allow_super);
34 
35 JERRY_STATIC_ASSERT (PARSER_RESTORE_STATUS_FLAGS (ECMA_PARSE_FUNCTION_CONTEXT) == 0,
36                      ecma_parse_function_context_must_not_be_transformed);
37 #endif /* ENABLED (JERRY_ES2015) */
38 
39 /** \addtogroup parser Parser
40  * @{
41  *
42  * \addtogroup jsparser JavaScript
43  * @{
44  *
45  * \addtogroup jsparser_parser Parser
46  * @{
47  */
48 
49 /**
50  * Compute real literal indicies.
51  *
52  * @return length of the prefix opcodes
53  */
54 static void
parser_compute_indicies(parser_context_t * context_p,uint16_t * ident_end,uint16_t * const_literal_end)55 parser_compute_indicies (parser_context_t *context_p, /**< context */
56                          uint16_t *ident_end, /**< end of the identifier group */
57                          uint16_t *const_literal_end) /**< end of the const literal group */
58 {
59   parser_list_iterator_t literal_iterator;
60   lexer_literal_t *literal_p;
61 
62   uint16_t ident_count = 0;
63   uint16_t const_literal_count = 0;
64 
65   uint16_t ident_index;
66   uint16_t const_literal_index;
67   uint16_t literal_index;
68 
69   /* First phase: count the number of items in each group. */
70   parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
71   while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)))
72   {
73     switch (literal_p->type)
74     {
75       case LEXER_IDENT_LITERAL:
76       {
77         if (literal_p->status_flags & LEXER_FLAG_USED)
78         {
79           ident_count++;
80           break;
81         }
82 #if !ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
83         else if (!(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
84         {
85           jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length);
86           /* This literal should not be freed even if an error is encountered later. */
87           literal_p->status_flags |= LEXER_FLAG_SOURCE_PTR;
88         }
89 #endif /* !ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
90         continue;
91       }
92       case LEXER_STRING_LITERAL:
93       {
94         const_literal_count++;
95         break;
96       }
97       case LEXER_NUMBER_LITERAL:
98       {
99         const_literal_count++;
100         continue;
101       }
102       case LEXER_FUNCTION_LITERAL:
103       case LEXER_REGEXP_LITERAL:
104       {
105         continue;
106       }
107       default:
108       {
109         JERRY_ASSERT (literal_p->type == LEXER_UNUSED_LITERAL);
110         continue;
111       }
112     }
113 
114 #if !ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
115     const uint8_t *char_p = literal_p->u.char_p;
116     uint32_t status_flags = context_p->status_flags;
117 
118     if ((literal_p->status_flags & LEXER_FLAG_SOURCE_PTR)
119         && literal_p->prop.length < 0xfff)
120     {
121       size_t bytes_to_end = (size_t) (context_p->source_end_p - char_p);
122 
123       if (bytes_to_end < 0xfffff)
124       {
125         literal_p->u.source_data = ((uint32_t) bytes_to_end) | (((uint32_t) literal_p->prop.length) << 20);
126         literal_p->status_flags |= LEXER_FLAG_LATE_INIT;
127         status_flags |= PARSER_HAS_LATE_LIT_INIT;
128         context_p->status_flags = status_flags;
129         char_p = NULL;
130       }
131     }
132 
133     if (char_p != NULL)
134     {
135       literal_p->u.value = ecma_find_or_create_literal_string (char_p,
136                                                                literal_p->prop.length);
137 
138       if (!(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
139       {
140         jmem_heap_free_block ((void *) char_p, literal_p->prop.length);
141         /* This literal should not be freed even if an error is encountered later. */
142         literal_p->status_flags |= LEXER_FLAG_SOURCE_PTR;
143       }
144     }
145 #endif /* !ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
146   }
147 
148   ident_index = context_p->register_count;
149   const_literal_index = (uint16_t) (ident_index + ident_count);
150   literal_index = (uint16_t) (const_literal_index + const_literal_count);
151 
152   /* Second phase: Assign an index to each literal. */
153   parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
154 
155   while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)))
156   {
157     switch (literal_p->type)
158     {
159       case LEXER_IDENT_LITERAL:
160       {
161         if (literal_p->status_flags & LEXER_FLAG_USED)
162         {
163           literal_p->prop.index = ident_index;
164           ident_index++;
165         }
166         break;
167       }
168       case LEXER_STRING_LITERAL:
169       case LEXER_NUMBER_LITERAL:
170       {
171         JERRY_ASSERT ((literal_p->status_flags & ~(LEXER_FLAG_SOURCE_PTR | LEXER_FLAG_LATE_INIT)) == 0);
172         literal_p->prop.index = const_literal_index;
173         const_literal_index++;
174         break;
175       }
176       case LEXER_FUNCTION_LITERAL:
177       case LEXER_REGEXP_LITERAL:
178       {
179         JERRY_ASSERT (literal_p->status_flags == 0);
180 
181         literal_p->prop.index = literal_index;
182         literal_index++;
183         break;
184       }
185       default:
186       {
187         JERRY_ASSERT (literal_p->type == LEXER_UNUSED_LITERAL
188                       && literal_p->status_flags == LEXER_FLAG_FUNCTION_ARGUMENT);
189         break;
190       }
191     }
192   }
193 
194   JERRY_ASSERT (ident_index == context_p->register_count + ident_count);
195   JERRY_ASSERT (const_literal_index == ident_index + const_literal_count);
196   JERRY_ASSERT (literal_index <= context_p->register_count + context_p->literal_count);
197 
198   context_p->literal_count = literal_index;
199 
200   *ident_end = ident_index;
201   *const_literal_end = const_literal_index;
202 } /* parser_compute_indicies */
203 
204 /**
205  * Initialize literal pool.
206  */
207 static void
parser_init_literal_pool(parser_context_t * context_p,ecma_value_t * literal_pool_p)208 parser_init_literal_pool (parser_context_t *context_p, /**< context */
209                           ecma_value_t *literal_pool_p) /**< start of literal pool */
210 {
211   parser_list_iterator_t literal_iterator;
212   lexer_literal_t *literal_p;
213 
214   parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
215 
216   while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)))
217   {
218     switch (literal_p->type)
219     {
220       case LEXER_IDENT_LITERAL:
221       {
222         if (!(literal_p->status_flags & LEXER_FLAG_USED))
223         {
224           break;
225         }
226         /* FALLTHRU */
227       }
228       case LEXER_STRING_LITERAL:
229       {
230         ecma_value_t lit_value;
231 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
232         lit_value = ecma_find_or_create_literal_string (literal_p->u.char_p,
233                                                         literal_p->prop.length);
234 #else /* !ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
235         lit_value = literal_p->u.value;
236 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
237 
238         JERRY_ASSERT (literal_p->prop.index >= context_p->register_count);
239         literal_pool_p[literal_p->prop.index] = lit_value;
240 
241 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
242         if (!context_p->is_show_opcodes
243             && !(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
244         {
245           jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length);
246         }
247 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
248         break;
249       }
250       case LEXER_NUMBER_LITERAL:
251       {
252         JERRY_ASSERT (literal_p->prop.index >= context_p->register_count);
253 
254         literal_pool_p[literal_p->prop.index] = literal_p->u.value;
255         break;
256       }
257       case LEXER_FUNCTION_LITERAL:
258       case LEXER_REGEXP_LITERAL:
259       {
260         JERRY_ASSERT (literal_p->prop.index >= context_p->register_count);
261 
262         ECMA_SET_INTERNAL_VALUE_POINTER (literal_pool_p[literal_p->prop.index],
263                                          literal_p->u.bytecode_p);
264         break;
265       }
266       default:
267       {
268         JERRY_ASSERT (literal_p->type == LEXER_UNUSED_LITERAL);
269         break;
270       }
271     }
272   }
273 } /* parser_init_literal_pool */
274 
275 /*
276  * During byte code post processing certain bytes are not
277  * copied into the final byte code buffer. For example, if
278  * one byte is enough for encoding a literal index, the
279  * second byte is not copied. However, when a byte is skipped,
280  * the offsets of those branches which crosses (jumps over)
281  * that byte code should also be decreased by one. Instead
282  * of finding these jumps every time when a byte is skipped,
283  * all branch offset updates are computed in one step.
284  *
285  * Branch offset mapping example:
286  *
287  * Let's assume that each parser_mem_page of the byte_code
288  * buffer is 8 bytes long and only 4 bytes are kept for a
289  * given page:
290  *
291  * +---+---+---+---+---+---+---+---+
292  * | X | 1 | 2 | 3 | X | 4 | X | X |
293  * +---+---+---+---+---+---+---+---+
294  *
295  * X marks those bytes which are removed. The resulting
296  * offset mapping is the following:
297  *
298  * +---+---+---+---+---+---+---+---+
299  * | 0 | 1 | 2 | 3 | 3 | 4 | 4 | 4 |
300  * +---+---+---+---+---+---+---+---+
301  *
302  * Each X is simply replaced by the index of the previous
303  * index starting from zero. This shows the number of
304  * copied bytes before a given byte including the byte
305  * itself. The last byte always shows the number of bytes
306  * copied from this page.
307  *
308  * This mapping allows recomputing all branch targets,
309  * since mapping[to] - mapping[from] is the new argument
310  * for forward branches. As for backward branches, the
311  * equation is reversed to mapping[from] - mapping[to].
312  *
313  * The mapping is relative to one page, so distance
314  * computation affecting multiple pages requires a loop.
315  * We should also note that only argument bytes can
316  * be skipped, so removed bytes cannot be targeted by
317  * branches. Valid branches always target instruction
318  * starts only.
319  */
320 
321 /**
322  * Recompute the argument of a forward branch.
323  *
324  * @return the new distance
325  */
326 static size_t
parser_update_forward_branch(parser_mem_page_t * page_p,size_t full_distance,uint8_t bytes_copied_before_jump)327 parser_update_forward_branch (parser_mem_page_t *page_p, /**< current page */
328                               size_t full_distance, /**< full distance */
329                               uint8_t bytes_copied_before_jump) /**< bytes copied before jump */
330 {
331   size_t new_distance = 0;
332 
333   while (full_distance > PARSER_CBC_STREAM_PAGE_SIZE)
334   {
335     new_distance += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK;
336     full_distance -= PARSER_CBC_STREAM_PAGE_SIZE;
337     page_p = page_p->next_p;
338   }
339 
340   new_distance += page_p->bytes[full_distance - 1] & CBC_LOWER_SEVEN_BIT_MASK;
341   return new_distance - bytes_copied_before_jump;
342 } /* parser_update_forward_branch */
343 
344 /**
345  * Recompute the argument of a backward branch.
346  *
347  * @return the new distance
348  */
349 static size_t
parser_update_backward_branch(parser_mem_page_t * page_p,size_t full_distance,uint8_t bytes_copied_before_jump)350 parser_update_backward_branch (parser_mem_page_t *page_p, /**< current page */
351                                size_t full_distance, /**< full distance */
352                                uint8_t bytes_copied_before_jump) /**< bytes copied before jump */
353 {
354   size_t new_distance = bytes_copied_before_jump;
355 
356   while (full_distance >= PARSER_CBC_STREAM_PAGE_SIZE)
357   {
358     JERRY_ASSERT (page_p != NULL);
359     new_distance += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK;
360     full_distance -= PARSER_CBC_STREAM_PAGE_SIZE;
361     page_p = page_p->next_p;
362   }
363 
364   if (full_distance > 0)
365   {
366     size_t offset = PARSER_CBC_STREAM_PAGE_SIZE - full_distance;
367 
368     JERRY_ASSERT (page_p != NULL);
369 
370     new_distance += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK;
371     new_distance -= page_p->bytes[offset - 1] & CBC_LOWER_SEVEN_BIT_MASK;
372   }
373 
374   return new_distance;
375 } /* parser_update_backward_branch */
376 
377 /**
378  * Update targets of all branches in one step.
379  */
380 static void
parse_update_branches(parser_context_t * context_p,uint8_t * byte_code_p)381 parse_update_branches (parser_context_t *context_p, /**< context */
382                        uint8_t *byte_code_p) /**< byte code */
383 {
384   parser_mem_page_t *page_p = context_p->byte_code.first_p;
385   parser_mem_page_t *prev_page_p = NULL;
386   parser_mem_page_t *last_page_p = context_p->byte_code.last_p;
387   size_t last_position = context_p->byte_code.last_position;
388   size_t offset = 0;
389   size_t bytes_copied = 0;
390 
391   if (last_position >= PARSER_CBC_STREAM_PAGE_SIZE)
392   {
393     last_page_p = NULL;
394     last_position = 0;
395   }
396 
397   while (page_p != last_page_p || offset < last_position)
398   {
399     /* Branch instructions are marked to improve search speed. */
400     if (page_p->bytes[offset] & CBC_HIGHEST_BIT_MASK)
401     {
402       uint8_t *bytes_p = byte_code_p + bytes_copied;
403       uint8_t flags;
404       uint8_t bytes_copied_before_jump = 0;
405       size_t branch_argument_length;
406       size_t target_distance;
407       size_t length;
408 
409       if (offset > 0)
410       {
411         bytes_copied_before_jump = page_p->bytes[offset - 1] & CBC_LOWER_SEVEN_BIT_MASK;
412       }
413       bytes_p += bytes_copied_before_jump;
414 
415       if (*bytes_p == CBC_EXT_OPCODE)
416       {
417         bytes_p++;
418         flags = cbc_ext_flags[*bytes_p];
419       }
420       else
421       {
422         flags = cbc_flags[*bytes_p];
423       }
424 
425       JERRY_ASSERT (flags & CBC_HAS_BRANCH_ARG);
426       branch_argument_length = CBC_BRANCH_OFFSET_LENGTH (*bytes_p);
427       bytes_p++;
428 
429       /* Decoding target. */
430       length = branch_argument_length;
431       target_distance = 0;
432       do
433       {
434         target_distance = (target_distance << 8) | *bytes_p;
435         bytes_p++;
436       }
437       while (--length > 0);
438 
439       if (CBC_BRANCH_IS_FORWARD (flags))
440       {
441         /* Branch target was not set. */
442         JERRY_ASSERT (target_distance > 0);
443 
444         target_distance = parser_update_forward_branch (page_p,
445                                                         offset + target_distance,
446                                                         bytes_copied_before_jump);
447       }
448       else
449       {
450         if (target_distance < offset)
451         {
452           uint8_t bytes_copied_before_target = page_p->bytes[offset - target_distance - 1];
453           bytes_copied_before_target = bytes_copied_before_target & CBC_LOWER_SEVEN_BIT_MASK;
454 
455           target_distance = (size_t) (bytes_copied_before_jump - bytes_copied_before_target);
456         }
457         else if (target_distance == offset)
458         {
459           target_distance = bytes_copied_before_jump;
460         }
461         else
462         {
463           target_distance = parser_update_backward_branch (prev_page_p,
464                                                            target_distance - offset,
465                                                            bytes_copied_before_jump);
466         }
467       }
468 
469       /* Encoding target again. */
470       do
471       {
472         bytes_p--;
473         *bytes_p = (uint8_t) (target_distance & 0xff);
474         target_distance >>= 8;
475       }
476       while (--branch_argument_length > 0);
477     }
478 
479     offset++;
480     if (offset >= PARSER_CBC_STREAM_PAGE_SIZE)
481     {
482       parser_mem_page_t *next_p = page_p->next_p;
483 
484       /* We reverse the pages before the current page. */
485       page_p->next_p = prev_page_p;
486       prev_page_p = page_p;
487 
488       bytes_copied += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK;
489       page_p = next_p;
490       offset = 0;
491     }
492   }
493 
494   /* After this point the pages of the byte code stream are
495    * not used anymore. However, they needs to be freed during
496    * cleanup, so the first and last pointers of the stream
497    * descriptor are reversed as well. */
498   if (last_page_p != NULL)
499   {
500     JERRY_ASSERT (last_page_p == context_p->byte_code.last_p);
501     last_page_p->next_p = prev_page_p;
502   }
503   else
504   {
505     last_page_p = context_p->byte_code.last_p;
506   }
507 
508   context_p->byte_code.last_p = context_p->byte_code.first_p;
509   context_p->byte_code.first_p = last_page_p;
510 } /* parse_update_branches */
511 
512 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
513 
514 /**
515  * Print literal.
516  */
517 static void
parse_print_literal(ecma_compiled_code_t * compiled_code_p,uint16_t literal_index,parser_list_t * literal_pool_p)518 parse_print_literal (ecma_compiled_code_t *compiled_code_p, /**< compiled code */
519                      uint16_t literal_index, /**< literal index */
520                      parser_list_t *literal_pool_p) /**< literal pool */
521 {
522   parser_list_iterator_t literal_iterator;
523   uint16_t argument_end;
524   uint16_t register_end;
525   uint16_t ident_end;
526 
527   if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
528   {
529     cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p;
530     argument_end = args_p->argument_end;
531     register_end = args_p->register_end;
532     ident_end = args_p->ident_end;
533   }
534   else
535   {
536     cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p;
537     argument_end = args_p->argument_end;
538     register_end = args_p->register_end;
539     ident_end = args_p->ident_end;
540   }
541 
542 #if ENABLED (JERRY_ES2015)
543   if (compiled_code_p->status_flags & CBC_CODE_FLAGS_REST_PARAMETER)
544   {
545     argument_end++;
546   }
547 #endif /* ENABLED (JERRY_ES2015) */
548 
549   if (literal_index < argument_end)
550   {
551     JERRY_DEBUG_MSG (" arg:%d", literal_index);
552     return;
553   }
554 
555   if (literal_index < register_end)
556   {
557     JERRY_DEBUG_MSG (" reg:%d", literal_index);
558     return;
559   }
560 
561   parser_list_iterator_init (literal_pool_p, &literal_iterator);
562 
563   while (true)
564   {
565     lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator);
566 
567     JERRY_ASSERT (literal_p != NULL);
568 
569     if (literal_p->prop.index == literal_index)
570     {
571       if (literal_index < ident_end)
572       {
573         JERRY_DEBUG_MSG (" ident:%d->", literal_index);
574       }
575       else
576       {
577         JERRY_DEBUG_MSG (" lit:%d->", literal_index);
578       }
579 
580       util_print_literal (literal_p);
581       return;
582     }
583   }
584 } /* parse_print_literal */
585 
586 #define PARSER_READ_IDENTIFIER_INDEX(name) \
587   name = *byte_code_p++; \
588   if (name >= encoding_limit) \
589   { \
590     name = (uint16_t) (((name << 8) | byte_code_p[0]) - encoding_delta); \
591     byte_code_p++; \
592   }
593 
594 /**
595  * Print byte code.
596  */
597 static void
parse_print_final_cbc(ecma_compiled_code_t * compiled_code_p,parser_list_t * literal_pool_p,size_t length)598 parse_print_final_cbc (ecma_compiled_code_t *compiled_code_p, /**< compiled code */
599                        parser_list_t *literal_pool_p, /**< literal pool */
600                        size_t length) /**< length of byte code */
601 {
602   uint8_t flags;
603   uint8_t *byte_code_start_p;
604   uint8_t *byte_code_end_p;
605   uint8_t *byte_code_p;
606   uint16_t encoding_limit;
607   uint16_t encoding_delta;
608   uint16_t stack_limit;
609   uint16_t argument_end;
610   uint16_t register_end;
611   uint16_t ident_end;
612   uint16_t const_literal_end;
613   uint16_t literal_end;
614 
615   if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
616   {
617     cbc_uint16_arguments_t *args = (cbc_uint16_arguments_t *) compiled_code_p;
618     stack_limit = args->stack_limit;
619     argument_end = args->argument_end;
620     register_end = args->register_end;
621     ident_end = args->ident_end;
622     const_literal_end = args->const_literal_end;
623     literal_end = args->literal_end;
624   }
625   else
626   {
627     cbc_uint8_arguments_t *args = (cbc_uint8_arguments_t *) compiled_code_p;
628     stack_limit = args->stack_limit;
629     argument_end = args->argument_end;
630     register_end = args->register_end;
631     ident_end = args->ident_end;
632     const_literal_end = args->const_literal_end;
633     literal_end = args->literal_end;
634   }
635 
636   JERRY_DEBUG_MSG ("\nFinal byte code dump:\n\n  Maximum stack depth: %d\n  Flags: [",
637                    (int) (stack_limit + register_end));
638 
639   if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING))
640   {
641     JERRY_DEBUG_MSG ("small_lit_enc");
642     encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT;
643     encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA;
644   }
645   else
646   {
647     JERRY_DEBUG_MSG ("full_lit_enc");
648     encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT;
649     encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA;
650   }
651 
652   if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
653   {
654     JERRY_DEBUG_MSG (",uint16_arguments");
655   }
656 
657   if (compiled_code_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE)
658   {
659     JERRY_DEBUG_MSG (",strict_mode");
660   }
661 
662   if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
663   {
664     JERRY_DEBUG_MSG (",mapped_arguments_needed");
665   }
666 
667   if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UNMAPPED_ARGUMENTS_NEEDED)
668   {
669     JERRY_DEBUG_MSG (",unmapped_arguments_needed");
670   }
671 
672   if (compiled_code_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)
673   {
674     JERRY_DEBUG_MSG (",no_lexical_env");
675   }
676 
677 #if ENABLED (JERRY_ES2015)
678   if (compiled_code_p->status_flags & CBC_CODE_FLAGS_ARROW_FUNCTION)
679   {
680     JERRY_DEBUG_MSG (",arrow");
681   }
682 
683   if (compiled_code_p->status_flags & CBC_CODE_FLAGS_CLASS_CONSTRUCTOR)
684   {
685     JERRY_DEBUG_MSG (",constructor");
686   }
687 
688   if (compiled_code_p->status_flags & CBC_CODE_FLAGS_GENERATOR)
689   {
690     JERRY_DEBUG_MSG (",generator");
691   }
692 #endif /* ENABLED (JERRY_ES2015) */
693 
694   JERRY_DEBUG_MSG ("]\n");
695 
696   JERRY_DEBUG_MSG ("  Argument range end: %d\n", (int) argument_end);
697   JERRY_DEBUG_MSG ("  Register range end: %d\n", (int) register_end);
698   JERRY_DEBUG_MSG ("  Identifier range end: %d\n", (int) ident_end);
699   JERRY_DEBUG_MSG ("  Const literal range end: %d\n", (int) const_literal_end);
700   JERRY_DEBUG_MSG ("  Literal range end: %d\n\n", (int) literal_end);
701 
702   byte_code_start_p = (uint8_t *) compiled_code_p;
703 
704   if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
705   {
706     byte_code_start_p += sizeof (cbc_uint16_arguments_t);
707   }
708   else
709   {
710     byte_code_start_p += sizeof (cbc_uint8_arguments_t);
711   }
712 
713   byte_code_start_p += (unsigned int) (literal_end - register_end) * sizeof (ecma_value_t);
714 
715   byte_code_end_p = byte_code_start_p + length;
716   byte_code_p = byte_code_start_p;
717 
718   while (byte_code_p < byte_code_end_p)
719   {
720     cbc_opcode_t opcode = (cbc_opcode_t) *byte_code_p;
721     cbc_ext_opcode_t ext_opcode = CBC_EXT_NOP;
722     size_t cbc_offset = (size_t) (byte_code_p - byte_code_start_p);
723 
724     if (opcode != CBC_EXT_OPCODE)
725     {
726       flags = cbc_flags[opcode];
727       JERRY_DEBUG_MSG (" %3d : %s", (int) cbc_offset, cbc_names[opcode]);
728       byte_code_p++;
729     }
730     else
731     {
732       ext_opcode = (cbc_ext_opcode_t) byte_code_p[1];
733       flags = cbc_ext_flags[ext_opcode];
734       JERRY_DEBUG_MSG (" %3d : %s", (int) cbc_offset, cbc_ext_names[ext_opcode]);
735       byte_code_p += 2;
736 
737 #if ENABLED (JERRY_LINE_INFO)
738       if (ext_opcode == CBC_EXT_LINE)
739       {
740         uint32_t value = 0;
741         uint8_t byte;
742 
743         do
744         {
745           byte = *byte_code_p++;
746           value = (value << 7) | (byte & CBC_LOWER_SEVEN_BIT_MASK);
747         }
748         while (byte & CBC_HIGHEST_BIT_MASK);
749 
750         JERRY_DEBUG_MSG (" %d\n", (int) value);
751         continue;
752       }
753 #endif /* ENABLED (JERRY_LINE_INFO) */
754     }
755 
756     if (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2))
757     {
758       uint16_t literal_index;
759 
760       PARSER_READ_IDENTIFIER_INDEX (literal_index);
761       parse_print_literal (compiled_code_p, literal_index, literal_pool_p);
762     }
763 
764     if (flags & CBC_HAS_LITERAL_ARG2)
765     {
766       uint16_t literal_index;
767 
768       PARSER_READ_IDENTIFIER_INDEX (literal_index);
769       parse_print_literal (compiled_code_p, literal_index, literal_pool_p);
770 
771       if (!(flags & CBC_HAS_LITERAL_ARG))
772       {
773         PARSER_READ_IDENTIFIER_INDEX (literal_index);
774         parse_print_literal (compiled_code_p, literal_index, literal_pool_p);
775       }
776     }
777 
778     if (flags & CBC_HAS_BYTE_ARG)
779     {
780       if (opcode == CBC_PUSH_NUMBER_POS_BYTE
781           || ext_opcode == CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE)
782       {
783         JERRY_DEBUG_MSG (" number:%d", (int) *byte_code_p + 1);
784       }
785       else if (opcode == CBC_PUSH_NUMBER_NEG_BYTE
786                || ext_opcode == CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE)
787       {
788         JERRY_DEBUG_MSG (" number:%d", -((int) *byte_code_p + 1));
789       }
790       else
791       {
792         JERRY_DEBUG_MSG (" byte_arg:%d", *byte_code_p);
793       }
794       byte_code_p++;
795     }
796 
797     if (flags & CBC_HAS_BRANCH_ARG)
798     {
799       size_t branch_offset_length = (opcode != CBC_EXT_OPCODE ? CBC_BRANCH_OFFSET_LENGTH (opcode)
800                                                               : CBC_BRANCH_OFFSET_LENGTH (ext_opcode));
801       size_t offset = 0;
802 
803       do
804       {
805         offset = (offset << 8) | *byte_code_p++;
806       }
807       while (--branch_offset_length > 0);
808 
809       JERRY_DEBUG_MSG (" offset:%d(->%d)",
810                        (int) offset,
811                        (int) (cbc_offset + (CBC_BRANCH_IS_FORWARD (flags) ? offset : -offset)));
812     }
813 
814     JERRY_DEBUG_MSG ("\n");
815   }
816 } /* parse_print_final_cbc */
817 
818 #undef PARSER_READ_IDENTIFIER_INDEX
819 
820 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
821 
822 #if ENABLED (JERRY_DEBUGGER)
823 
824 /**
825  * Send current breakpoint list.
826  */
827 static void
parser_send_breakpoints(parser_context_t * context_p,jerry_debugger_header_type_t type)828 parser_send_breakpoints (parser_context_t *context_p, /**< context */
829                          jerry_debugger_header_type_t type) /**< message type */
830 {
831   JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
832   JERRY_ASSERT (context_p->breakpoint_info_count > 0);
833 
834   jerry_debugger_send_data (type,
835                             context_p->breakpoint_info,
836                             context_p->breakpoint_info_count * sizeof (parser_breakpoint_info_t));
837 
838   context_p->breakpoint_info_count = 0;
839 } /* parser_send_breakpoints */
840 
841 /**
842  * Append a breakpoint info.
843  */
844 void
parser_append_breakpoint_info(parser_context_t * context_p,jerry_debugger_header_type_t type,uint32_t value)845 parser_append_breakpoint_info (parser_context_t *context_p, /**< context */
846                                jerry_debugger_header_type_t type, /**< message type */
847                                uint32_t value) /**< line or offset of the breakpoint */
848 {
849   JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
850 
851   context_p->status_flags |= PARSER_DEBUGGER_BREAKPOINT_APPENDED;
852 
853   if (context_p->breakpoint_info_count >= JERRY_DEBUGGER_SEND_MAX (parser_breakpoint_info_t))
854   {
855     parser_send_breakpoints (context_p, type);
856   }
857 
858   context_p->breakpoint_info[context_p->breakpoint_info_count].value = value;
859   context_p->breakpoint_info_count = (uint16_t) (context_p->breakpoint_info_count + 1);
860 } /* parser_append_breakpoint_info */
861 
862 #endif /* ENABLED (JERRY_DEBUGGER) */
863 
864 /**
865  * Forward iterator: move to the next byte code
866  *
867  * @param page_p page
868  * @param offset offset
869  */
870 #define PARSER_NEXT_BYTE(page_p, offset) \
871   do { \
872     if (++(offset) >= PARSER_CBC_STREAM_PAGE_SIZE) \
873     { \
874       offset = 0; \
875       page_p = page_p->next_p; \
876     } \
877   } while (0)
878 
879 /**
880  * Forward iterator: move to the next byte code. Also updates the offset of the previous byte code.
881  *
882  * @param page_p page
883  * @param offset offset
884  * @param real_offset real offset
885  */
886 #define PARSER_NEXT_BYTE_UPDATE(page_p, offset, real_offset) \
887   do { \
888     page_p->bytes[offset] = real_offset; \
889     if (++(offset) >= PARSER_CBC_STREAM_PAGE_SIZE) \
890     { \
891       offset = 0; \
892       real_offset = 0; \
893       page_p = page_p->next_p; \
894     } \
895   } while (0)
896 
897 /**
898  * Post processing main function.
899  *
900  * @return compiled code
901  */
902 static ecma_compiled_code_t *
parser_post_processing(parser_context_t * context_p)903 parser_post_processing (parser_context_t *context_p) /**< context */
904 {
905   uint16_t literal_one_byte_limit;
906   uint16_t ident_end;
907   uint16_t const_literal_end;
908   parser_mem_page_t *page_p;
909   parser_mem_page_t *last_page_p;
910   size_t last_position;
911   size_t offset;
912   size_t length;
913   size_t literal_length;
914   size_t total_size;
915 #if ENABLED (JERRY_SNAPSHOT_SAVE)
916   size_t total_size_used;
917 #endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */
918   uint8_t real_offset;
919   uint8_t *byte_code_p;
920   bool needs_uint16_arguments;
921   cbc_opcode_t last_opcode = CBC_EXT_OPCODE;
922   ecma_compiled_code_t *compiled_code_p;
923   ecma_value_t *literal_pool_p;
924   uint8_t *dst_p;
925 
926   CHECK_JERRY_STACK_USAGE(context_p);
927 
928 #if ENABLED (JERRY_ES2015)
929   if ((context_p->status_flags & (PARSER_IS_FUNCTION | PARSER_LEXICAL_BLOCK_NEEDED))
930       == (PARSER_IS_FUNCTION | PARSER_LEXICAL_BLOCK_NEEDED))
931   {
932     PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
933 #ifndef JERRY_NDEBUG
934     PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
935 #endif /* !JERRY_NDEBUG */
936 
937     context_p->status_flags &= (uint32_t) ~PARSER_LEXICAL_BLOCK_NEEDED;
938 
939     parser_emit_cbc (context_p, CBC_CONTEXT_END);
940 
941     parser_branch_t branch;
942     parser_stack_pop (context_p, &branch, sizeof (parser_branch_t));
943     parser_set_branch_to_current_position (context_p, &branch);
944   }
945 #endif /* ENABLED (JERRY_ES2015) */
946 
947   JERRY_ASSERT (context_p->stack_depth == 0);
948 #ifndef JERRY_NDEBUG
949   JERRY_ASSERT (context_p->context_stack_depth == 0);
950 #endif /* !JERRY_NDEBUG */
951 
952   if ((size_t) context_p->stack_limit + (size_t) context_p->register_count > PARSER_MAXIMUM_STACK_LIMIT)
953   {
954     parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED);
955   }
956 
957   JERRY_ASSERT (context_p->literal_count <= PARSER_MAXIMUM_NUMBER_OF_LITERALS);
958 
959 #if ENABLED (JERRY_DEBUGGER)
960   if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
961       && !(context_p->status_flags & PARSER_DEBUGGER_BREAKPOINT_APPENDED))
962   {
963     /* Always provide at least one breakpoint. */
964     parser_emit_cbc (context_p, CBC_BREAKPOINT_DISABLED);
965     parser_flush_cbc (context_p);
966 
967     parser_append_breakpoint_info (context_p, JERRY_DEBUGGER_BREAKPOINT_LIST, context_p->token.line);
968 
969     context_p->last_breakpoint_line = context_p->token.line;
970   }
971 
972   if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
973       && context_p->breakpoint_info_count > 0)
974   {
975     parser_send_breakpoints (context_p, JERRY_DEBUGGER_BREAKPOINT_LIST);
976     JERRY_ASSERT (context_p->breakpoint_info_count == 0);
977   }
978 #endif /* ENABLED (JERRY_DEBUGGER) */
979 
980   parser_compute_indicies (context_p, &ident_end, &const_literal_end);
981 
982   if (context_p->literal_count <= CBC_MAXIMUM_SMALL_VALUE)
983   {
984     literal_one_byte_limit = CBC_MAXIMUM_BYTE_VALUE - 1;
985   }
986   else
987   {
988     literal_one_byte_limit = CBC_LOWER_SEVEN_BIT_MASK;
989   }
990 
991   last_page_p = context_p->byte_code.last_p;
992   last_position = context_p->byte_code.last_position;
993 
994   if (last_position >= PARSER_CBC_STREAM_PAGE_SIZE)
995   {
996     last_page_p = NULL;
997     last_position = 0;
998   }
999 
1000   page_p = context_p->byte_code.first_p;
1001   offset = 0;
1002   length = 0;
1003 
1004   while (page_p != last_page_p || offset < last_position)
1005   {
1006     uint8_t *opcode_p;
1007     uint8_t flags;
1008     size_t branch_offset_length;
1009 
1010     opcode_p = page_p->bytes + offset;
1011     last_opcode = (cbc_opcode_t) (*opcode_p);
1012     PARSER_NEXT_BYTE (page_p, offset);
1013     branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (last_opcode);
1014     flags = cbc_flags[last_opcode];
1015     length++;
1016 
1017     if (last_opcode == CBC_EXT_OPCODE)
1018     {
1019       cbc_ext_opcode_t ext_opcode;
1020 
1021       ext_opcode = (cbc_ext_opcode_t) page_p->bytes[offset];
1022       branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (ext_opcode);
1023       flags = cbc_ext_flags[ext_opcode];
1024       PARSER_NEXT_BYTE (page_p, offset);
1025       length++;
1026 
1027 #if ENABLED (JERRY_ES2015)
1028       if (ext_opcode == CBC_EXT_RETURN_PROMISE
1029           || ext_opcode == CBC_EXT_RETURN_PROMISE_UNDEFINED)
1030       {
1031         last_opcode = CBC_RETURN;
1032       }
1033 #endif /* ENABLED (JERRY_ES2015) */
1034 
1035 #if ENABLED (JERRY_LINE_INFO)
1036       if (ext_opcode == CBC_EXT_LINE)
1037       {
1038         uint8_t last_byte = 0;
1039 
1040         do
1041         {
1042           last_byte = page_p->bytes[offset];
1043           PARSER_NEXT_BYTE (page_p, offset);
1044           length++;
1045         }
1046         while (last_byte & CBC_HIGHEST_BIT_MASK);
1047 
1048         continue;
1049       }
1050 #endif /* ENABLED (JERRY_LINE_INFO) */
1051     }
1052 
1053     while (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2))
1054     {
1055       uint8_t *first_byte = page_p->bytes + offset;
1056       uint32_t literal_index = *first_byte;
1057 
1058       PARSER_NEXT_BYTE (page_p, offset);
1059       length++;
1060 
1061       literal_index |= ((uint32_t) page_p->bytes[offset]) << 8;
1062 
1063       if (literal_index >= PARSER_REGISTER_START)
1064       {
1065         literal_index -= PARSER_REGISTER_START;
1066       }
1067       else
1068       {
1069         literal_index = (PARSER_GET_LITERAL (literal_index))->prop.index;
1070       }
1071 
1072       if (literal_index <= literal_one_byte_limit)
1073       {
1074         *first_byte = (uint8_t) literal_index;
1075       }
1076       else
1077       {
1078         if (context_p->literal_count <= CBC_MAXIMUM_SMALL_VALUE)
1079         {
1080           JERRY_ASSERT (literal_index <= CBC_MAXIMUM_SMALL_VALUE);
1081           *first_byte = CBC_MAXIMUM_BYTE_VALUE;
1082           page_p->bytes[offset] = (uint8_t) (literal_index - CBC_MAXIMUM_BYTE_VALUE);
1083           length++;
1084         }
1085         else
1086         {
1087           JERRY_ASSERT (literal_index <= CBC_MAXIMUM_FULL_VALUE);
1088           *first_byte = (uint8_t) ((literal_index >> 8) | CBC_HIGHEST_BIT_MASK);
1089           page_p->bytes[offset] = (uint8_t) (literal_index & 0xff);
1090           length++;
1091         }
1092       }
1093       PARSER_NEXT_BYTE (page_p, offset);
1094 
1095       if (flags & CBC_HAS_LITERAL_ARG2)
1096       {
1097         if (flags & CBC_HAS_LITERAL_ARG)
1098         {
1099           flags = CBC_HAS_LITERAL_ARG;
1100         }
1101         else
1102         {
1103           flags = CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2;
1104         }
1105       }
1106       else
1107       {
1108         break;
1109       }
1110     }
1111 
1112     if (flags & CBC_HAS_BYTE_ARG)
1113     {
1114       /* This argument will be copied without modification. */
1115       PARSER_NEXT_BYTE (page_p, offset);
1116       length++;
1117     }
1118 
1119     if (flags & CBC_HAS_BRANCH_ARG)
1120     {
1121       bool prefix_zero = true;
1122 
1123       /* The leading zeroes are dropped from the stream.
1124        * Although dropping these zeroes for backward
1125        * branches are unnecessary, we use the same
1126        * code path for simplicity. */
1127       JERRY_ASSERT (branch_offset_length > 0 && branch_offset_length <= 3);
1128 
1129       while (--branch_offset_length > 0)
1130       {
1131         uint8_t byte = page_p->bytes[offset];
1132         if (byte > 0 || !prefix_zero)
1133         {
1134           prefix_zero = false;
1135           length++;
1136         }
1137         else
1138         {
1139           JERRY_ASSERT (CBC_BRANCH_IS_FORWARD (flags));
1140         }
1141         PARSER_NEXT_BYTE (page_p, offset);
1142       }
1143 
1144       if (last_opcode == (cbc_opcode_t) (CBC_JUMP_FORWARD + PARSER_MAX_BRANCH_LENGTH - 1)
1145           && prefix_zero
1146           && page_p->bytes[offset] == PARSER_MAX_BRANCH_LENGTH + 1)
1147       {
1148         /* Uncoditional jumps which jump right after the instruction
1149          * are effectively NOPs. These jumps are removed from the
1150          * stream. The 1 byte long CBC_JUMP_FORWARD form marks these
1151          * instructions, since this form is constructed during post
1152          * processing and cannot be emitted directly. */
1153         *opcode_p = CBC_JUMP_FORWARD;
1154         length--;
1155       }
1156       else
1157       {
1158         /* Other last bytes are always copied. */
1159         length++;
1160       }
1161 
1162       PARSER_NEXT_BYTE (page_p, offset);
1163     }
1164   }
1165 
1166   if (!(context_p->status_flags & PARSER_NO_END_LABEL)
1167       || !(PARSER_OPCODE_IS_RETURN (last_opcode)))
1168   {
1169     context_p->status_flags &= (uint32_t) ~PARSER_NO_END_LABEL;
1170 
1171 #if ENABLED (JERRY_ES2015)
1172     if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION)
1173     {
1174       length++;
1175     }
1176 #endif /* ENABLED (JERRY_ES2015) */
1177 
1178     length++;
1179   }
1180 
1181   needs_uint16_arguments = false;
1182   total_size = sizeof (cbc_uint8_arguments_t);
1183 
1184   if (context_p->stack_limit > CBC_MAXIMUM_BYTE_VALUE
1185       || context_p->register_count > CBC_MAXIMUM_BYTE_VALUE
1186       || context_p->literal_count > CBC_MAXIMUM_BYTE_VALUE)
1187   {
1188     needs_uint16_arguments = true;
1189     total_size = sizeof (cbc_uint16_arguments_t);
1190   }
1191 
1192   literal_length = (size_t) (context_p->literal_count - context_p->register_count) * sizeof (ecma_value_t);
1193 
1194   total_size += literal_length + length;
1195 
1196   if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
1197   {
1198     total_size += context_p->argument_count * sizeof (ecma_value_t);
1199   }
1200 
1201 #if ENABLED (JERRY_ES2015)
1202   if (context_p->tagged_template_literal_cp != JMEM_CP_NULL)
1203   {
1204     total_size += sizeof (ecma_value_t);
1205   }
1206 #endif /* ENABLED (JERRY_ES2015) */
1207 
1208 #if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
1209   if (JERRY_CONTEXT (resource_name) != ECMA_VALUE_UNDEFINED)
1210   {
1211     total_size += sizeof (ecma_value_t);
1212   }
1213 #endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
1214 
1215 #if ENABLED (JERRY_SNAPSHOT_SAVE)
1216   total_size_used = total_size;
1217 #endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */
1218   total_size = JERRY_ALIGNUP (total_size, JMEM_ALIGNMENT);
1219 
1220   compiled_code_p = (ecma_compiled_code_t *) parser_malloc (context_p, total_size);
1221 
1222 #if ENABLED (JERRY_SNAPSHOT_SAVE)
1223   // Avoid getting junk bytes at the end when bytes at the end remain unused:
1224   if (total_size_used < total_size)
1225   {
1226     memset (((uint8_t *) compiled_code_p) + total_size_used, 0, total_size - total_size_used);
1227   }
1228 #endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */
1229 
1230 #if ENABLED (JERRY_MEM_STATS)
1231   jmem_stats_allocate_byte_code_bytes (total_size);
1232 #endif /* ENABLED (JERRY_MEM_STATS) */
1233 
1234   byte_code_p = (uint8_t *) compiled_code_p;
1235   compiled_code_p->size = (uint16_t) (total_size >> JMEM_ALIGNMENT_LOG);
1236   compiled_code_p->refs = 1;
1237   compiled_code_p->status_flags = CBC_CODE_FLAGS_FUNCTION;
1238 
1239 #if ENABLED (JERRY_ES2015)
1240   if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
1241   {
1242     JERRY_ASSERT (context_p->argument_count > 0);
1243     context_p->argument_count--;
1244   }
1245 #endif /* ENABLED (JERRY_ES2015) */
1246 
1247   if (needs_uint16_arguments)
1248   {
1249     cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p;
1250 
1251     args_p->stack_limit = context_p->stack_limit;
1252     args_p->argument_end = context_p->argument_count;
1253     args_p->register_end = context_p->register_count;
1254     args_p->ident_end = ident_end;
1255     args_p->const_literal_end = const_literal_end;
1256     args_p->literal_end = context_p->literal_count;
1257 
1258     compiled_code_p->status_flags |= CBC_CODE_FLAGS_UINT16_ARGUMENTS;
1259     byte_code_p += sizeof (cbc_uint16_arguments_t);
1260   }
1261   else
1262   {
1263     cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p;
1264 
1265     args_p->stack_limit = (uint8_t) context_p->stack_limit;
1266     args_p->argument_end = (uint8_t) context_p->argument_count;
1267     args_p->register_end = (uint8_t) context_p->register_count;
1268     args_p->ident_end = (uint8_t) ident_end;
1269     args_p->const_literal_end = (uint8_t) const_literal_end;
1270     args_p->literal_end = (uint8_t) context_p->literal_count;
1271 
1272     byte_code_p += sizeof (cbc_uint8_arguments_t);
1273   }
1274 
1275   uint16_t encoding_limit;
1276   uint16_t encoding_delta;
1277 
1278   if (context_p->literal_count > CBC_MAXIMUM_SMALL_VALUE)
1279   {
1280     compiled_code_p->status_flags |= CBC_CODE_FLAGS_FULL_LITERAL_ENCODING;
1281     encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT;
1282     encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA;
1283   }
1284   else
1285   {
1286     encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT;
1287     encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA;
1288   }
1289 
1290   if (context_p->status_flags & PARSER_IS_STRICT)
1291   {
1292     compiled_code_p->status_flags |= CBC_CODE_FLAGS_STRICT_MODE;
1293   }
1294 
1295   if (context_p->status_flags & PARSER_ARGUMENTS_NEEDED)
1296   {
1297     if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
1298     {
1299       compiled_code_p->status_flags |= CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED;
1300     }
1301     else
1302     {
1303       compiled_code_p->status_flags |= CBC_CODE_FLAGS_UNMAPPED_ARGUMENTS_NEEDED;
1304     }
1305 
1306     /* Arguments is stored in the lexical environment. */
1307     JERRY_ASSERT (context_p->status_flags & PARSER_LEXICAL_ENV_NEEDED);
1308   }
1309 
1310   if (!(context_p->status_flags & PARSER_LEXICAL_ENV_NEEDED))
1311   {
1312     compiled_code_p->status_flags |= CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED;
1313   }
1314 
1315 #if ENABLED (JERRY_ES2015)
1316   if (context_p->status_flags & (PARSER_IS_PROPERTY_GETTER | PARSER_IS_PROPERTY_SETTER))
1317   {
1318     compiled_code_p->status_flags |= CBC_CODE_FLAGS_ACCESSOR;
1319   }
1320 
1321   if (context_p->status_flags & PARSER_IS_ARROW_FUNCTION)
1322   {
1323     compiled_code_p->status_flags |= CBC_CODE_FLAGS_ARROW_FUNCTION;
1324   }
1325 
1326   if (context_p->status_flags & PARSER_CLASS_CONSTRUCTOR)
1327   {
1328     compiled_code_p->status_flags |= CBC_CODE_FLAGS_CLASS_CONSTRUCTOR;
1329   }
1330 
1331   if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)
1332   {
1333     compiled_code_p->status_flags |= CBC_CODE_FLAGS_GENERATOR;
1334   }
1335 
1336   if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
1337   {
1338     compiled_code_p->status_flags |= CBC_CODE_FLAGS_REST_PARAMETER;
1339   }
1340 
1341   if (context_p->tagged_template_literal_cp != JMEM_CP_NULL)
1342   {
1343     compiled_code_p->status_flags |= CBC_CODE_FLAG_HAS_TAGGED_LITERALS;
1344   }
1345 
1346   if (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)
1347   {
1348     JERRY_ASSERT (!(context_p->status_flags & PARSER_IS_FUNCTION));
1349     compiled_code_p->status_flags |= CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED;
1350   }
1351 #endif /* ENABLED (JERRY_ES2015) */
1352 
1353   literal_pool_p = ((ecma_value_t *) byte_code_p) - context_p->register_count;
1354   byte_code_p += literal_length;
1355   dst_p = byte_code_p;
1356 
1357   parser_init_literal_pool (context_p, literal_pool_p);
1358 
1359   page_p = context_p->byte_code.first_p;
1360   offset = 0;
1361   real_offset = 0;
1362   uint8_t last_register_index = (uint8_t) JERRY_MIN (context_p->register_count,
1363                                                      (PARSER_MAXIMUM_NUMBER_OF_REGISTERS - 1));
1364 
1365   while (page_p != last_page_p || offset < last_position)
1366   {
1367     uint8_t flags;
1368     uint8_t *opcode_p;
1369     uint8_t *branch_mark_p;
1370     cbc_opcode_t opcode;
1371     size_t branch_offset_length;
1372 
1373     opcode_p = dst_p;
1374     branch_mark_p = page_p->bytes + offset;
1375     opcode = (cbc_opcode_t) (*branch_mark_p);
1376     branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (opcode);
1377 
1378     if (opcode == CBC_JUMP_FORWARD)
1379     {
1380       /* These opcodes are deleted from the stream. */
1381       size_t counter = PARSER_MAX_BRANCH_LENGTH + 1;
1382 
1383       do
1384       {
1385         PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1386       }
1387       while (--counter > 0);
1388 
1389       continue;
1390     }
1391 
1392     /* Storing the opcode */
1393     *dst_p++ = (uint8_t) opcode;
1394     real_offset++;
1395     PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1396     flags = cbc_flags[opcode];
1397 
1398 #if ENABLED (JERRY_DEBUGGER)
1399     if (opcode == CBC_BREAKPOINT_DISABLED)
1400     {
1401       uint32_t bp_offset = (uint32_t) (((uint8_t *) dst_p) - ((uint8_t *) compiled_code_p) - 1);
1402       parser_append_breakpoint_info (context_p, JERRY_DEBUGGER_BREAKPOINT_OFFSET_LIST, bp_offset);
1403     }
1404 #endif /* ENABLED (JERRY_DEBUGGER) */
1405 
1406     if (opcode == CBC_EXT_OPCODE)
1407     {
1408       cbc_ext_opcode_t ext_opcode;
1409 
1410       ext_opcode = (cbc_ext_opcode_t) page_p->bytes[offset];
1411       flags = cbc_ext_flags[ext_opcode];
1412       branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (ext_opcode);
1413 
1414       /* Storing the extended opcode */
1415       *dst_p++ = (uint8_t) ext_opcode;
1416       opcode_p++;
1417       real_offset++;
1418       PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1419 
1420 #if ENABLED (JERRY_LINE_INFO)
1421       if (ext_opcode == CBC_EXT_LINE)
1422       {
1423         uint8_t last_byte = 0;
1424 
1425         do
1426         {
1427           last_byte = page_p->bytes[offset];
1428           *dst_p++ = last_byte;
1429 
1430           real_offset++;
1431           PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1432         }
1433         while (last_byte & CBC_HIGHEST_BIT_MASK);
1434 
1435         continue;
1436       }
1437 #endif /* ENABLED (JERRY_LINE_INFO) */
1438     }
1439 
1440     /* Only literal and call arguments can be combined. */
1441     JERRY_ASSERT (!(flags & CBC_HAS_BRANCH_ARG)
1442                    || !(flags & (CBC_HAS_BYTE_ARG | CBC_HAS_LITERAL_ARG)));
1443 
1444     while (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2))
1445     {
1446       uint16_t first_byte = page_p->bytes[offset];
1447 
1448       uint8_t *opcode_pos_p = dst_p - 1;
1449       *dst_p++ = (uint8_t) first_byte;
1450       real_offset++;
1451       PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1452 
1453       if (first_byte > literal_one_byte_limit)
1454       {
1455         *dst_p++ = page_p->bytes[offset];
1456 
1457         if (first_byte > encoding_limit)
1458         {
1459           first_byte = (uint16_t) (((first_byte << 8) | dst_p[-1]) - encoding_delta);
1460         }
1461         real_offset++;
1462       }
1463       PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1464 
1465       if (flags & CBC_HAS_LITERAL_ARG2)
1466       {
1467         if (flags & CBC_HAS_LITERAL_ARG)
1468         {
1469           flags = CBC_HAS_LITERAL_ARG;
1470         }
1471         else
1472         {
1473           flags = CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2;
1474         }
1475       }
1476       else
1477       {
1478         if (opcode == CBC_ASSIGN_SET_IDENT && JERRY_LIKELY (first_byte < last_register_index))
1479         {
1480           *opcode_pos_p = CBC_MOV_IDENT;
1481         }
1482 
1483         break;
1484       }
1485     }
1486 
1487     if (flags & CBC_HAS_BYTE_ARG)
1488     {
1489       /* This argument will be copied without modification. */
1490       *dst_p++ = page_p->bytes[offset];
1491       real_offset++;
1492       PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1493       continue;
1494     }
1495 
1496     if (flags & CBC_HAS_BRANCH_ARG)
1497     {
1498       *branch_mark_p |= CBC_HIGHEST_BIT_MASK;
1499       bool prefix_zero = true;
1500 
1501       /* The leading zeroes are dropped from the stream. */
1502       JERRY_ASSERT (branch_offset_length > 0 && branch_offset_length <= 3);
1503 
1504       while (--branch_offset_length > 0)
1505       {
1506         uint8_t byte = page_p->bytes[offset];
1507         if (byte > 0 || !prefix_zero)
1508         {
1509           prefix_zero = false;
1510           *dst_p++ = page_p->bytes[offset];
1511           real_offset++;
1512         }
1513         else
1514         {
1515           /* When a leading zero is dropped, the branch
1516            * offset length must be decreased as well. */
1517           (*opcode_p)--;
1518         }
1519         PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1520       }
1521 
1522       *dst_p++ = page_p->bytes[offset];
1523       real_offset++;
1524       PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1525       continue;
1526     }
1527   }
1528 
1529 #if ENABLED (JERRY_DEBUGGER)
1530   if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
1531       && context_p->breakpoint_info_count > 0)
1532   {
1533     parser_send_breakpoints (context_p, JERRY_DEBUGGER_BREAKPOINT_OFFSET_LIST);
1534     JERRY_ASSERT (context_p->breakpoint_info_count == 0);
1535   }
1536 #endif /* ENABLED (JERRY_DEBUGGER) */
1537 
1538   if (!(context_p->status_flags & PARSER_NO_END_LABEL))
1539   {
1540     *dst_p++ = CBC_RETURN_WITH_BLOCK;
1541 
1542 #if ENABLED (JERRY_ES2015)
1543     if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION)
1544     {
1545       dst_p[-1] = CBC_EXT_OPCODE;
1546       dst_p[0] = CBC_EXT_RETURN_PROMISE_UNDEFINED;
1547       dst_p++;
1548     }
1549 #endif /* ENABLED (JERRY_ES2015) */
1550   }
1551   JERRY_ASSERT (dst_p == byte_code_p + length);
1552 
1553   parse_update_branches (context_p, byte_code_p);
1554 
1555   parser_cbc_stream_free (&context_p->byte_code);
1556 
1557 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
1558   if (context_p->is_show_opcodes)
1559   {
1560     parser_list_iterator_t literal_iterator;
1561     lexer_literal_t *literal_p;
1562 
1563     parse_print_final_cbc (compiled_code_p, &context_p->literal_pool, length);
1564     JERRY_DEBUG_MSG ("\nByte code size: %d bytes\n", (int) length);
1565     context_p->total_byte_code_size += (uint32_t) length;
1566 
1567     parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
1568     while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)))
1569     {
1570       if ((literal_p->type == LEXER_IDENT_LITERAL || literal_p->type == LEXER_STRING_LITERAL)
1571           && !(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
1572       {
1573         jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length);
1574       }
1575     }
1576   }
1577 #else /* !ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
1578   if (context_p->status_flags & PARSER_HAS_LATE_LIT_INIT)
1579   {
1580     parser_list_iterator_t literal_iterator;
1581     lexer_literal_t *literal_p;
1582     uint16_t register_count = context_p->register_count;
1583 
1584     parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
1585     while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)))
1586     {
1587       if ((literal_p->status_flags & LEXER_FLAG_LATE_INIT)
1588           && literal_p->prop.index >= register_count)
1589       {
1590         uint32_t source_data = literal_p->u.source_data;
1591         const uint8_t *char_p = context_p->source_end_p - (source_data & 0xfffff);
1592         ecma_value_t lit_value = ecma_find_or_create_literal_string (char_p,
1593                                                                      source_data >> 20);
1594         literal_pool_p[literal_p->prop.index] = lit_value;
1595       }
1596     }
1597   }
1598 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
1599 
1600   if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
1601   {
1602     parser_list_iterator_t literal_iterator;
1603     uint16_t argument_count = 0;
1604     uint16_t register_count = context_p->register_count;
1605     ecma_value_t *argument_base_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size);
1606     argument_base_p -= context_p->argument_count;
1607 
1608     parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
1609     while (argument_count < context_p->argument_count)
1610     {
1611       lexer_literal_t *literal_p;
1612       literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator);
1613 
1614       JERRY_ASSERT (literal_p != NULL);
1615 
1616       if (!(literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT))
1617       {
1618         continue;
1619       }
1620 
1621       /* All arguments must be moved to initialized registers. */
1622       if (literal_p->type == LEXER_UNUSED_LITERAL)
1623       {
1624         argument_base_p[argument_count] = ECMA_VALUE_EMPTY;
1625         argument_count++;
1626         continue;
1627       }
1628 
1629       JERRY_ASSERT (literal_p->type == LEXER_IDENT_LITERAL);
1630 
1631       JERRY_ASSERT (literal_p->prop.index >= register_count);
1632 
1633       argument_base_p[argument_count] = literal_pool_p[literal_p->prop.index];
1634       argument_count++;
1635     }
1636   }
1637 
1638 #if ENABLED (JERRY_ES2015)
1639   if (context_p->tagged_template_literal_cp != JMEM_CP_NULL)
1640   {
1641     ecma_value_t *tagged_base_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size);
1642 
1643     if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
1644     {
1645       tagged_base_p -= context_p->argument_count;
1646     }
1647 
1648     tagged_base_p[-1] = (ecma_value_t) context_p->tagged_template_literal_cp;
1649 
1650     ecma_collection_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
1651                                                                        context_p->tagged_template_literal_cp);
1652 
1653     for (uint32_t i = 0; i < collection_p->item_count; i++)
1654     {
1655       ecma_free_value (collection_p->buffer_p[i]);
1656     }
1657   }
1658 #endif /* ENABLED (JERRY_ES2015) */
1659 
1660 #if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
1661   if (JERRY_CONTEXT (resource_name) != ECMA_VALUE_UNDEFINED)
1662   {
1663     ecma_value_t *resource_name_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size);
1664 
1665     if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
1666     {
1667       resource_name_p -= context_p->argument_count;
1668     }
1669 
1670 #if ENABLED (JERRY_ES2015)
1671     if (context_p->tagged_template_literal_cp != JMEM_CP_NULL)
1672     {
1673       resource_name_p--;
1674     }
1675 #endif /* ENABLED (JERRY_ES2015) */
1676 
1677     resource_name_p[-1] = JERRY_CONTEXT (resource_name);
1678   }
1679 #endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
1680 
1681 #if ENABLED (JERRY_DEBUGGER)
1682   if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
1683   {
1684     jerry_debugger_send_function_cp (JERRY_DEBUGGER_BYTE_CODE_CP, compiled_code_p);
1685   }
1686 #endif /* ENABLED (JERRY_DEBUGGER) */
1687 
1688   return compiled_code_p;
1689 } /* parser_post_processing */
1690 
1691 #undef PARSER_NEXT_BYTE
1692 #undef PARSER_NEXT_BYTE_UPDATE
1693 
1694 /**
1695  * Free identifiers and literals.
1696  */
1697 static void
parser_free_literals(parser_list_t * literal_pool_p)1698 parser_free_literals (parser_list_t *literal_pool_p) /**< literals */
1699 {
1700   parser_list_iterator_t literal_iterator;
1701   lexer_literal_t *literal_p;
1702 
1703   parser_list_iterator_init (literal_pool_p, &literal_iterator);
1704   while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1705   {
1706     util_free_literal (literal_p);
1707   }
1708 
1709   parser_list_free (literal_pool_p);
1710 } /* parser_free_literals */
1711 
1712 /**
1713  * Parse function arguments
1714  */
1715 static void
parser_parse_function_arguments(parser_context_t * context_p,lexer_token_type_t end_type)1716 parser_parse_function_arguments (parser_context_t *context_p, /**< context */
1717                                  lexer_token_type_t end_type) /**< expected end type */
1718 {
1719   JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
1720 
1721 #if ENABLED (JERRY_ES2015)
1722   JERRY_ASSERT (context_p->status_flags & PARSER_IS_FUNCTION);
1723   JERRY_ASSERT (!(context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED));
1724 
1725   bool has_duplicated_arg_names = false;
1726 
1727   /* TODO: Currently async iterators are not supported, so generators ignore the async modifier. */
1728   uint32_t mask = (PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION);
1729   if ((context_p->status_flags & mask) == mask)
1730   {
1731     context_p->status_flags &= (uint32_t) ~PARSER_IS_ASYNC_FUNCTION;
1732   }
1733 #endif /* ENABLED (JERRY_ES2015) */
1734 
1735   if (context_p->token.type == end_type)
1736   {
1737 #if ENABLED (JERRY_ES2015)
1738     if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)
1739     {
1740       parser_emit_cbc_ext (context_p, CBC_EXT_CREATE_GENERATOR);
1741       parser_emit_cbc (context_p, CBC_POP);
1742     }
1743 
1744     context_p->status_flags &= (uint32_t) ~PARSER_DISALLOW_AWAIT_YIELD;
1745 #endif /* ENABLED (JERRY_ES2015) */
1746     scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS);
1747     return;
1748   }
1749 
1750 #if ENABLED (JERRY_ES2015)
1751   bool has_mapped_arguments = (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_MAPPED_ARGUMENTS) != 0;
1752 #endif /* ENABLED (JERRY_ES2015) */
1753 
1754   scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_ARGS);
1755   scanner_set_active (context_p);
1756 
1757 #if ENABLED (JERRY_ES2015)
1758   context_p->status_flags |= PARSER_FUNCTION_IS_PARSING_ARGS;
1759 #endif /* ENABLED (JERRY_ES2015) */
1760 
1761   while (true)
1762   {
1763 #if ENABLED (JERRY_ES2015)
1764     if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
1765     {
1766       parser_raise_error (context_p, PARSER_ERR_FORMAL_PARAM_AFTER_REST_PARAMETER);
1767     }
1768     else if (context_p->token.type == LEXER_THREE_DOTS)
1769     {
1770       if (context_p->status_flags & PARSER_IS_PROPERTY_SETTER)
1771       {
1772         parser_raise_error (context_p, PARSER_ERR_SETTER_REST_PARAMETER);
1773       }
1774       lexer_next_token (context_p);
1775 
1776       if (has_duplicated_arg_names)
1777       {
1778         parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
1779       }
1780 
1781       context_p->status_flags |= PARSER_FUNCTION_HAS_REST_PARAM | PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM;
1782     }
1783 
1784     if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
1785     {
1786       if (has_duplicated_arg_names)
1787       {
1788         parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
1789       }
1790 
1791       context_p->status_flags |= PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM;
1792 
1793       parser_emit_cbc_literal (context_p,
1794                                CBC_PUSH_LITERAL,
1795                                (uint16_t) (PARSER_REGISTER_START + context_p->argument_count));
1796 
1797       uint32_t flags = (PARSER_PATTERN_BINDING
1798                         | PARSER_PATTERN_TARGET_ON_STACK
1799                         | PARSER_PATTERN_LOCAL
1800                         | PARSER_PATTERN_ARGUMENTS);
1801 
1802       if (context_p->next_scanner_info_p->source_p == context_p->source_p)
1803       {
1804         JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER);
1805 
1806         if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
1807         {
1808           parser_raise_error (context_p, PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER);
1809         }
1810 
1811         flags |= PARSER_PATTERN_TARGET_DEFAULT;
1812       }
1813 
1814       parser_parse_initializer (context_p, flags);
1815 
1816       context_p->argument_count++;
1817       if (context_p->argument_count >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
1818       {
1819         parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED);
1820       }
1821 
1822       if (context_p->token.type != LEXER_COMMA)
1823       {
1824         break;
1825       }
1826 
1827       lexer_next_token (context_p);
1828       continue;
1829     }
1830 #endif /* ENABLED (JERRY_ES2015) */
1831 
1832     if (context_p->token.type != LEXER_LITERAL
1833         || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
1834     {
1835       parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
1836     }
1837 
1838     lexer_construct_literal_object (context_p,
1839                                     &context_p->token.lit_location,
1840                                     LEXER_IDENT_LITERAL);
1841 
1842     if (context_p->token.keyword_type >= LEXER_FIRST_NON_STRICT_ARGUMENTS)
1843     {
1844       context_p->status_flags |= PARSER_HAS_NON_STRICT_ARG;
1845     }
1846 
1847     CHECK_JERRY_STACK_USAGE(context_p);
1848 
1849     if (JERRY_UNLIKELY (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT))
1850     {
1851 #if ENABLED (JERRY_ES2015)
1852       if ((context_p->status_flags & PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM)
1853           || (context_p->status_flags & PARSER_IS_ARROW_FUNCTION))
1854       {
1855         parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
1856       }
1857       has_duplicated_arg_names = true;
1858 #endif /* ENABLED (JERRY_ES2015) */
1859 
1860       context_p->status_flags |= PARSER_HAS_NON_STRICT_ARG;
1861     }
1862     else
1863     {
1864       context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT;
1865     }
1866 
1867     lexer_next_token (context_p);
1868 
1869 #if ENABLED (JERRY_ES2015)
1870     uint16_t literal_index = context_p->lit_object.index;
1871 
1872     if (context_p->token.type == LEXER_ASSIGN)
1873     {
1874       JERRY_ASSERT (!has_mapped_arguments);
1875 
1876       if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
1877       {
1878         parser_raise_error (context_p, PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER);
1879       }
1880 
1881       parser_branch_t skip_init;
1882 
1883       if (has_duplicated_arg_names)
1884       {
1885         parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
1886       }
1887 
1888       context_p->status_flags |= PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM;
1889 
1890       /* LEXER_ASSIGN does not overwrite lit_object. */
1891       parser_emit_cbc_literal (context_p,
1892                                CBC_PUSH_LITERAL,
1893                                (uint16_t) (PARSER_REGISTER_START + context_p->argument_count));
1894       parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init);
1895 
1896       lexer_next_token (context_p);
1897       parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
1898 
1899       parser_set_branch_to_current_position (context_p, &skip_init);
1900 
1901       uint16_t opcode = CBC_ASSIGN_LET_CONST;
1902 
1903       if (literal_index >= PARSER_REGISTER_START)
1904       {
1905         opcode = CBC_ASSIGN_SET_IDENT;
1906       }
1907       else if (!scanner_literal_is_created (context_p, literal_index))
1908       {
1909         opcode = CBC_INIT_ARG_OR_CATCH;
1910       }
1911 
1912       parser_emit_cbc_literal (context_p, opcode, literal_index);
1913     }
1914     else if (!has_mapped_arguments && literal_index < PARSER_REGISTER_START)
1915     {
1916       uint16_t opcode = CBC_INIT_ARG_OR_FUNC;
1917 
1918       if (scanner_literal_is_created (context_p, literal_index))
1919       {
1920         opcode = CBC_ASSIGN_LET_CONST_LITERAL;
1921       }
1922 
1923       parser_emit_cbc_literal_value (context_p,
1924                                      opcode,
1925                                      (uint16_t) (PARSER_REGISTER_START + context_p->argument_count),
1926                                      literal_index);
1927     }
1928 #endif /* ENABLED (JERRY_ES2015) */
1929 
1930     context_p->argument_count++;
1931     if (context_p->argument_count >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
1932     {
1933       parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED);
1934     }
1935 
1936     if (context_p->token.type != LEXER_COMMA)
1937     {
1938       break;
1939     }
1940 
1941     lexer_next_token (context_p);
1942   }
1943 
1944   if (context_p->token.type != end_type)
1945   {
1946     parser_error_t error = ((end_type == LEXER_RIGHT_PAREN) ? PARSER_ERR_RIGHT_PAREN_EXPECTED
1947                                                             : PARSER_ERR_IDENTIFIER_EXPECTED);
1948 
1949     parser_raise_error (context_p, error);
1950   }
1951 
1952   scanner_revert_active (context_p);
1953 
1954 #if ENABLED (JERRY_ES2015)
1955   JERRY_ASSERT (!has_mapped_arguments || !(context_p->status_flags & PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM));
1956 
1957   if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)
1958   {
1959     parser_emit_cbc_ext (context_p, CBC_EXT_CREATE_GENERATOR);
1960     parser_emit_cbc (context_p, CBC_POP);
1961   }
1962 
1963   if (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)
1964   {
1965     if ((context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_LEXICAL_ENV_NEEDED)
1966         || scanner_is_context_needed (context_p, PARSER_CHECK_FUNCTION_CONTEXT))
1967     {
1968       context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
1969 
1970       parser_branch_t branch;
1971       parser_emit_cbc_forward_branch (context_p, CBC_BLOCK_CREATE_CONTEXT, &branch);
1972       parser_stack_push (context_p, &branch, sizeof (parser_branch_t));
1973 
1974 #ifndef JERRY_NDEBUG
1975       context_p->context_stack_depth = PARSER_BLOCK_CONTEXT_STACK_ALLOCATION;
1976 #endif /* !JERRY_NDEBUG */
1977     }
1978     else
1979     {
1980       context_p->status_flags &= (uint32_t) ~PARSER_LEXICAL_BLOCK_NEEDED;
1981     }
1982   }
1983 
1984   context_p->status_flags &= (uint32_t) ~(PARSER_DISALLOW_AWAIT_YIELD | PARSER_FUNCTION_IS_PARSING_ARGS);
1985 #endif /* ENABLED (JERRY_ES2015) */
1986 
1987   scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_BODY);
1988 } /* parser_parse_function_arguments */
1989 
1990 #ifndef JERRY_NDEBUG
1991 JERRY_STATIC_ASSERT (PARSER_SCANNING_SUCCESSFUL == PARSER_HAS_LATE_LIT_INIT,
1992                      parser_scanning_successful_should_share_the_bit_position_with_parser_has_late_lit_init);
1993 #endif /* !JERRY_NDEBUG */
1994 
1995 /**
1996  * Parse and compile EcmaScript source code
1997  *
1998  * Note: source must be a valid UTF-8 string
1999  *
2000  * @return compiled code
2001  */
2002 static ecma_compiled_code_t *
parser_parse_source(const uint8_t * arg_list_p,size_t arg_list_size,const uint8_t * source_p,size_t source_size,uint32_t parse_opts,parser_error_location_t * error_location_p)2003 parser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
2004                      size_t arg_list_size, /**< size of function argument list */
2005                      const uint8_t *source_p, /**< valid UTF-8 source code */
2006                      size_t source_size, /**< size of the source code */
2007                      uint32_t parse_opts, /**< ecma_parse_opts_t option bits */
2008                      parser_error_location_t *error_location_p) /**< error location */
2009 {
2010   parser_context_t context;
2011   ecma_compiled_code_t *compiled_code_p;
2012 
2013   context.error = PARSER_ERR_NO_ERROR;
2014 
2015   if (error_location_p != NULL)
2016   {
2017     error_location_p->error = PARSER_ERR_NO_ERROR;
2018   }
2019 
2020   context.status_flags = parse_opts & PARSER_STRICT_MODE_MASK;
2021   context.global_status_flags = parse_opts;
2022 
2023   if (arg_list_p != NULL)
2024   {
2025     context.status_flags |= PARSER_IS_FUNCTION;
2026 #if ENABLED (JERRY_ES2015)
2027     if (parse_opts & ECMA_PARSE_GENERATOR_FUNCTION)
2028     {
2029       context.status_flags |= PARSER_IS_GENERATOR_FUNCTION;
2030     }
2031 #endif /* ENABLED (JERRY_ES2015) */
2032   }
2033 
2034 #if ENABLED (JERRY_ES2015)
2035   context.status_flags |= PARSER_RESTORE_STATUS_FLAGS (parse_opts);
2036   context.tagged_template_literal_cp = JMEM_CP_NULL;
2037 #endif /* ENABLED (JERRY_ES2015) */
2038 
2039   context.stack_depth = 0;
2040   context.stack_limit = 0;
2041   context.last_context_p = NULL;
2042   context.last_statement.current_p = NULL;
2043 
2044   context.token.flags = 0;
2045   context.line = 1;
2046   context.column = 1;
2047 
2048   scanner_info_t scanner_info_end;
2049   scanner_info_end.next_p = NULL;
2050   scanner_info_end.source_p = NULL;
2051   scanner_info_end.type = SCANNER_TYPE_END;
2052   context.next_scanner_info_p = &scanner_info_end;
2053   context.active_scanner_info_p = NULL;
2054   context.skipped_scanner_info_p = NULL;
2055   context.skipped_scanner_info_end_p = NULL;
2056 
2057   context.last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
2058 
2059   context.argument_count = 0;
2060   context.register_count = 0;
2061   context.literal_count = 0;
2062 
2063   parser_cbc_stream_init (&context.byte_code);
2064   context.byte_code_size = 0;
2065   parser_list_init (&context.literal_pool,
2066                     sizeof (lexer_literal_t),
2067                     (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_literal_t)));
2068   context.scope_stack_p = NULL;
2069   context.scope_stack_size = 0;
2070   context.scope_stack_top = 0;
2071   context.scope_stack_reg_top = 0;
2072 #if ENABLED (JERRY_ES2015)
2073   context.scope_stack_global_end = 0;
2074   context.tagged_template_literal_cp = JMEM_CP_NULL;
2075 #endif /* ENABLED (JERRY_ES2015) */
2076 
2077 #ifndef JERRY_NDEBUG
2078   context.context_stack_depth = 0;
2079 #endif /* !JERRY_NDEBUG */
2080 
2081 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2082   context.is_show_opcodes = (JERRY_CONTEXT (jerry_init_flags) & ECMA_INIT_SHOW_OPCODES);
2083   context.total_byte_code_size = 0;
2084 
2085   if (context.is_show_opcodes)
2086   {
2087     JERRY_DEBUG_MSG ("\n--- %s parsing start ---\n\n",
2088                      (arg_list_p == NULL) ? "Script"
2089                                           : "Function");
2090   }
2091 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2092 
2093   scanner_scan_all (&context,
2094                     arg_list_p,
2095                     arg_list_p + arg_list_size,
2096                     source_p,
2097                     source_p + source_size);
2098 
2099   if (JERRY_UNLIKELY (context.error != PARSER_ERR_NO_ERROR))
2100   {
2101     JERRY_ASSERT (context.error == PARSER_ERR_OUT_OF_MEMORY);
2102 
2103     if (error_location_p != NULL)
2104     {
2105       error_location_p->error = context.error;
2106       error_location_p->line = context.token.line;
2107       error_location_p->column = context.token.column;
2108     }
2109     return NULL;
2110   }
2111 
2112   if (arg_list_p == NULL)
2113   {
2114     context.source_p = source_p;
2115     context.source_end_p = source_p + source_size;
2116   }
2117   else
2118   {
2119     context.source_p = arg_list_p;
2120     context.source_end_p = arg_list_p + arg_list_size;
2121   }
2122 
2123   context.u.allocated_buffer_p = NULL;
2124   context.line = 1;
2125   context.column = 1;
2126   context.token.flags = 0;
2127 
2128   parser_stack_init (&context);
2129 
2130 #if ENABLED (JERRY_DEBUGGER)
2131   context.breakpoint_info_count = 0;
2132 #endif /* ENABLED (JERRY_DEBUGGER) */
2133 
2134 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2135   if (context.global_status_flags & ECMA_PARSE_MODULE)
2136   {
2137     context.status_flags |= PARSER_IS_STRICT;
2138   }
2139 
2140   context.module_current_node_p = NULL;
2141 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2142 
2143   PARSER_TRY (context.try_buffer)
2144   {
2145     /* Pushing a dummy value ensures the stack is never empty.
2146      * This simplifies the stack management routines. */
2147     parser_stack_push_uint8 (&context, CBC_MAXIMUM_BYTE_VALUE);
2148     /* The next token must always be present to make decisions
2149      * in the parser. Therefore when a token is consumed, the
2150      * lexer_next_token() must be immediately called. */
2151     lexer_next_token (&context);
2152 
2153     if (arg_list_p != NULL)
2154     {
2155       parser_parse_function_arguments (&context, LEXER_EOS);
2156 
2157       JERRY_ASSERT (context.next_scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS);
2158       scanner_release_next (&context, sizeof (scanner_info_t));
2159 
2160       context.source_p = source_p;
2161       context.source_end_p = source_p + source_size;
2162       context.line = 1;
2163       context.column = 1;
2164 
2165       lexer_next_token (&context);
2166     }
2167 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2168     else if (parse_opts & ECMA_PARSE_MODULE)
2169     {
2170       scanner_create_variables (&context, SCANNER_CREATE_VARS_NO_OPTS);
2171     }
2172 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2173     else
2174     {
2175       JERRY_ASSERT (context.next_scanner_info_p->source_p == source_p
2176                     && context.next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
2177 
2178 #if ENABLED (JERRY_ES2015)
2179       if (scanner_is_context_needed (&context, PARSER_CHECK_GLOBAL_CONTEXT))
2180       {
2181         context.status_flags |= PARSER_LEXICAL_BLOCK_NEEDED;
2182       }
2183 
2184       if ((parse_opts & ECMA_PARSE_EVAL) == 0)
2185       {
2186         scanner_check_variables (&context);
2187       }
2188 #endif /* ENABLED (JERRY_ES2015) */
2189 
2190       scanner_create_variables (&context, SCANNER_CREATE_VARS_IS_SCRIPT);
2191     }
2192 
2193     parser_parse_statements (&context);
2194 
2195     JERRY_ASSERT (context.last_statement.current_p == NULL);
2196 
2197     JERRY_ASSERT (context.last_cbc_opcode == PARSER_CBC_UNAVAILABLE);
2198     JERRY_ASSERT (context.u.allocated_buffer_p == NULL);
2199 
2200 #ifndef JERRY_NDEBUG
2201     JERRY_ASSERT (context.status_flags & PARSER_SCANNING_SUCCESSFUL);
2202     JERRY_ASSERT (!(context.global_status_flags & ECMA_PARSE_INTERNAL_FOR_IN_OFF_CONTEXT_ERROR));
2203     context.status_flags &= (uint32_t) ~PARSER_SCANNING_SUCCESSFUL;
2204 #endif /* !JERRY_NDEBUG */
2205 
2206     JERRY_ASSERT (!(context.status_flags & PARSER_HAS_LATE_LIT_INIT));
2207 
2208     compiled_code_p = parser_post_processing (&context);
2209     parser_list_free (&context.literal_pool);
2210 
2211     /* When parsing is successful, only the dummy value can be remained on the stack. */
2212     JERRY_ASSERT (context.stack_top_uint8 == CBC_MAXIMUM_BYTE_VALUE
2213                   && context.stack.last_position == 1
2214                   && context.stack.first_p != NULL
2215                   && context.stack.first_p->next_p == NULL
2216                   && context.stack.last_p == NULL);
2217 
2218     JERRY_ASSERT (arg_list_p != NULL || !(context.status_flags & PARSER_ARGUMENTS_NEEDED));
2219 
2220 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2221     if (context.is_show_opcodes)
2222     {
2223       JERRY_DEBUG_MSG ("\n%s parsing successfully completed. Total byte code size: %d bytes\n",
2224                        (arg_list_p == NULL) ? "Script"
2225                                             : "Function",
2226                        (int) context.total_byte_code_size);
2227     }
2228 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2229   }
2230   PARSER_CATCH
2231   {
2232     if (context.last_statement.current_p != NULL)
2233     {
2234       parser_free_jumps (context.last_statement);
2235     }
2236 
2237     parser_free_allocated_buffer (&context);
2238 
2239     scanner_cleanup (&context);
2240 
2241 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2242     if (context.module_current_node_p != NULL)
2243     {
2244       ecma_module_release_module_nodes (context.module_current_node_p);
2245     }
2246 #endif
2247 
2248     if (error_location_p != NULL)
2249     {
2250       error_location_p->error = context.error;
2251       error_location_p->line = context.token.line;
2252       error_location_p->column = context.token.column;
2253     }
2254 
2255     compiled_code_p = NULL;
2256     parser_free_literals (&context.literal_pool);
2257     parser_cbc_stream_free (&context.byte_code);
2258   }
2259   PARSER_TRY_END
2260 
2261   if (context.scope_stack_p != NULL)
2262   {
2263     parser_free (context.scope_stack_p, context.scope_stack_size * sizeof (parser_scope_stack_t));
2264   }
2265 
2266 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2267   if (context.is_show_opcodes)
2268   {
2269     JERRY_DEBUG_MSG ("\n--- %s parsing end ---\n\n",
2270                      (arg_list_p == NULL) ? "Script"
2271                                           : "Function");
2272   }
2273 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2274 
2275   parser_stack_free (&context);
2276 
2277   return compiled_code_p;
2278 } /* parser_parse_source */
2279 
2280 /**
2281  * Save parser context before function parsing.
2282  */
2283 static void
parser_save_context(parser_context_t * context_p,parser_saved_context_t * saved_context_p)2284 parser_save_context (parser_context_t *context_p, /**< context */
2285                      parser_saved_context_t *saved_context_p) /**< target for saving the context */
2286 {
2287   JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE);
2288 
2289 #if ENABLED (JERRY_DEBUGGER)
2290   if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
2291       && context_p->breakpoint_info_count > 0)
2292   {
2293     parser_send_breakpoints (context_p, JERRY_DEBUGGER_BREAKPOINT_LIST);
2294     context_p->breakpoint_info_count = 0;
2295   }
2296 #endif /* ENABLED (JERRY_DEBUGGER) */
2297 
2298 #if ENABLED (JERRY_ES2015)
2299   if (context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS)
2300   {
2301     context_p->status_flags |= PARSER_LEXICAL_BLOCK_NEEDED;
2302   }
2303 #endif /* ENABLED (JERRY_ES2015) */
2304 
2305   /* Save private part of the context. */
2306 
2307   saved_context_p->status_flags = context_p->status_flags;
2308   saved_context_p->stack_depth = context_p->stack_depth;
2309   saved_context_p->stack_limit = context_p->stack_limit;
2310   saved_context_p->prev_context_p = context_p->last_context_p;
2311   saved_context_p->last_statement = context_p->last_statement;
2312 
2313   saved_context_p->argument_count = context_p->argument_count;
2314   saved_context_p->register_count = context_p->register_count;
2315   saved_context_p->literal_count = context_p->literal_count;
2316 
2317   saved_context_p->byte_code = context_p->byte_code;
2318   saved_context_p->byte_code_size = context_p->byte_code_size;
2319   saved_context_p->literal_pool_data = context_p->literal_pool.data;
2320   saved_context_p->scope_stack_p = context_p->scope_stack_p;
2321   saved_context_p->scope_stack_size = context_p->scope_stack_size;
2322   saved_context_p->scope_stack_top = context_p->scope_stack_top;
2323   saved_context_p->scope_stack_reg_top = context_p->scope_stack_reg_top;
2324 #if ENABLED (JERRY_ES2015)
2325   saved_context_p->scope_stack_global_end = context_p->scope_stack_global_end;
2326   saved_context_p->tagged_template_literal_cp = context_p->tagged_template_literal_cp;
2327 #endif /* ENABLED (JERRY_ES2015) */
2328 
2329 #ifndef JERRY_NDEBUG
2330   saved_context_p->context_stack_depth = context_p->context_stack_depth;
2331 #endif /* !JERRY_NDEBUG */
2332 
2333   /* Reset private part of the context. */
2334 
2335   context_p->status_flags &= PARSER_IS_STRICT;
2336   context_p->stack_depth = 0;
2337   context_p->stack_limit = 0;
2338   context_p->last_context_p = saved_context_p;
2339   context_p->last_statement.current_p = NULL;
2340 
2341   context_p->argument_count = 0;
2342   context_p->register_count = 0;
2343   context_p->literal_count = 0;
2344 
2345   parser_cbc_stream_init (&context_p->byte_code);
2346   context_p->byte_code_size = 0;
2347   parser_list_reset (&context_p->literal_pool);
2348   context_p->scope_stack_p = NULL;
2349   context_p->scope_stack_size = 0;
2350   context_p->scope_stack_top = 0;
2351   context_p->scope_stack_reg_top = 0;
2352 #if ENABLED (JERRY_ES2015)
2353   context_p->scope_stack_global_end = 0;
2354   context_p->tagged_template_literal_cp = JMEM_CP_NULL;
2355 #endif /* ENABLED (JERRY_ES2015) */
2356 
2357 #ifndef JERRY_NDEBUG
2358   context_p->context_stack_depth = 0;
2359 #endif /* !JERRY_NDEBUG */
2360 } /* parser_save_context */
2361 
2362 /**
2363  * Restore parser context after function parsing.
2364  */
2365 static void
parser_restore_context(parser_context_t * context_p,parser_saved_context_t * saved_context_p)2366 parser_restore_context (parser_context_t *context_p, /**< context */
2367                         parser_saved_context_t *saved_context_p) /**< target for saving the context */
2368 {
2369   parser_list_free (&context_p->literal_pool);
2370 
2371   if (context_p->scope_stack_p != NULL)
2372   {
2373     parser_free (context_p->scope_stack_p, context_p->scope_stack_size * sizeof (parser_scope_stack_t));
2374   }
2375 
2376   /* Restore private part of the context. */
2377 
2378   JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE);
2379 
2380   context_p->status_flags = saved_context_p->status_flags;
2381   context_p->stack_depth = saved_context_p->stack_depth;
2382   context_p->stack_limit = saved_context_p->stack_limit;
2383   context_p->last_context_p = saved_context_p->prev_context_p;
2384   context_p->last_statement = saved_context_p->last_statement;
2385 
2386   context_p->argument_count = saved_context_p->argument_count;
2387   context_p->register_count = saved_context_p->register_count;
2388   context_p->literal_count = saved_context_p->literal_count;
2389 
2390   context_p->byte_code = saved_context_p->byte_code;
2391   context_p->byte_code_size = saved_context_p->byte_code_size;
2392   context_p->literal_pool.data = saved_context_p->literal_pool_data;
2393   context_p->scope_stack_p = saved_context_p->scope_stack_p;
2394   context_p->scope_stack_size = saved_context_p->scope_stack_size;
2395   context_p->scope_stack_top = saved_context_p->scope_stack_top;
2396   context_p->scope_stack_reg_top = saved_context_p->scope_stack_reg_top;
2397 #if ENABLED (JERRY_ES2015)
2398   context_p->scope_stack_global_end = saved_context_p->scope_stack_global_end;
2399   context_p->tagged_template_literal_cp = saved_context_p->tagged_template_literal_cp;
2400 #endif /* ENABLED (JERRY_ES2015) */
2401 
2402 #ifndef JERRY_NDEBUG
2403   context_p->context_stack_depth = saved_context_p->context_stack_depth;
2404 #endif /* !JERRY_NDEBUG */
2405 } /* parser_restore_context */
2406 
2407 /**
2408  * Parse function code
2409  *
2410  * @return compiled code
2411  */
2412 ecma_compiled_code_t *
parser_parse_function(parser_context_t * context_p,uint32_t status_flags)2413 parser_parse_function (parser_context_t *context_p, /**< context */
2414                        uint32_t status_flags) /**< extra status flags */
2415 {
2416   parser_saved_context_t saved_context;
2417   ecma_compiled_code_t *compiled_code_p;
2418 
2419   JERRY_ASSERT (status_flags & PARSER_IS_FUNCTION);
2420   parser_save_context (context_p, &saved_context);
2421   context_p->status_flags |= status_flags;
2422 #if ENABLED (JERRY_ES2015)
2423   context_p->status_flags |= PARSER_ALLOW_NEW_TARGET;
2424 #endif /* ENABLED (JERRY_ES2015) */
2425 
2426 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2427   if (context_p->is_show_opcodes)
2428   {
2429 #if ENABLED (JERRY_ES2015)
2430     JERRY_DEBUG_MSG ("\n--- %s parsing start ---\n\n",
2431                      (context_p->status_flags & PARSER_CLASS_CONSTRUCTOR) ? "Class constructor"
2432                                                                           : "Function");
2433 #else /* !ENABLED (JERRY_ES2015) */
2434     JERRY_DEBUG_MSG ("\n--- Function parsing start ---\n\n");
2435 #endif /* ENABLED (JERRY_ES2015) */
2436   }
2437 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2438 
2439 #if ENABLED (JERRY_DEBUGGER)
2440   if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
2441   {
2442     jerry_debugger_send_parse_function (context_p->token.line, context_p->token.column);
2443   }
2444 #endif /* ENABLED (JERRY_DEBUGGER) */
2445 
2446   CHECK_JERRY_STACK_USAGE(context_p);
2447 
2448   lexer_next_token (context_p);
2449 
2450   if (context_p->token.type != LEXER_LEFT_PAREN)
2451   {
2452     parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIST_EXPECTED);
2453   }
2454 
2455   lexer_next_token (context_p);
2456 
2457   parser_parse_function_arguments (context_p, LEXER_RIGHT_PAREN);
2458   lexer_next_token (context_p);
2459 
2460   if ((context_p->status_flags & PARSER_IS_PROPERTY_GETTER)
2461       && context_p->argument_count != 0)
2462   {
2463     parser_raise_error (context_p, PARSER_ERR_NO_ARGUMENTS_EXPECTED);
2464   }
2465 
2466   if ((context_p->status_flags & PARSER_IS_PROPERTY_SETTER)
2467       && context_p->argument_count != 1)
2468   {
2469     parser_raise_error (context_p, PARSER_ERR_ONE_ARGUMENT_EXPECTED);
2470   }
2471 
2472 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2473   if (context_p->is_show_opcodes
2474       && (context_p->status_flags & PARSER_HAS_NON_STRICT_ARG))
2475   {
2476     JERRY_DEBUG_MSG ("  Note: legacy (non-strict) argument definition\n\n");
2477   }
2478 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2479 
2480   if (context_p->token.type != LEXER_LEFT_BRACE)
2481   {
2482     parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED);
2483   }
2484 
2485   lexer_next_token (context_p);
2486   parser_parse_statements (context_p);
2487   compiled_code_p = parser_post_processing (context_p);
2488 
2489 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2490   if (context_p->is_show_opcodes)
2491   {
2492 #if ENABLED (JERRY_ES2015)
2493     JERRY_DEBUG_MSG ("\n--- %s parsing end ---\n\n",
2494                      (context_p->status_flags & PARSER_CLASS_CONSTRUCTOR) ? "Class constructor"
2495                                                                           : "Function");
2496 #else /* !ENABLED (JERRY_ES2015) */
2497     JERRY_DEBUG_MSG ("\n--- Function parsing end ---\n\n");
2498 #endif /* ENABLED (JERRY_ES2015) */
2499   }
2500 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2501 
2502   parser_restore_context (context_p, &saved_context);
2503 
2504   return compiled_code_p;
2505 } /* parser_parse_function */
2506 
2507 #if ENABLED (JERRY_ES2015)
2508 
2509 /**
2510  * Parse arrow function code
2511  *
2512  * @return compiled code
2513  */
2514 ecma_compiled_code_t *
parser_parse_arrow_function(parser_context_t * context_p,uint32_t status_flags)2515 parser_parse_arrow_function (parser_context_t *context_p, /**< context */
2516                              uint32_t status_flags) /**< extra status flags */
2517 {
2518   parser_saved_context_t saved_context;
2519   ecma_compiled_code_t *compiled_code_p;
2520 
2521   JERRY_ASSERT (status_flags & PARSER_IS_FUNCTION);
2522   JERRY_ASSERT (status_flags & PARSER_IS_ARROW_FUNCTION);
2523   parser_save_context (context_p, &saved_context);
2524   context_p->status_flags |= status_flags;
2525   context_p->status_flags |= saved_context.status_flags & (PARSER_ALLOW_NEW_TARGET
2526                                                            | PARSER_ALLOW_SUPER
2527                                                            | PARSER_ALLOW_SUPER_CALL);
2528 
2529 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2530   if (context_p->is_show_opcodes)
2531   {
2532     JERRY_DEBUG_MSG ("\n--- Arrow function parsing start ---\n\n");
2533   }
2534 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2535 
2536 #if ENABLED (JERRY_DEBUGGER)
2537   if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
2538   {
2539     jerry_debugger_send_parse_function (context_p->token.line, context_p->token.column);
2540   }
2541 #endif /* ENABLED (JERRY_DEBUGGER) */
2542 
2543   if (context_p->token.type == LEXER_LEFT_PAREN)
2544   {
2545     lexer_next_token (context_p);
2546     parser_parse_function_arguments (context_p, LEXER_RIGHT_PAREN);
2547     lexer_next_token (context_p);
2548   }
2549   else
2550   {
2551     parser_parse_function_arguments (context_p, LEXER_ARROW);
2552   }
2553 
2554   JERRY_ASSERT (context_p->token.type == LEXER_ARROW);
2555 
2556   lexer_next_token (context_p);
2557 
2558   if (context_p->token.type == LEXER_LEFT_BRACE)
2559   {
2560     lexer_next_token (context_p);
2561 
2562     context_p->status_flags |= PARSER_IS_CLOSURE;
2563     parser_parse_statements (context_p);
2564 
2565     /* Unlike normal function, arrow functions consume their close brace. */
2566     JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE);
2567     lexer_next_token (context_p);
2568   }
2569   else
2570   {
2571     if (context_p->status_flags & PARSER_IS_STRICT
2572         && context_p->status_flags & PARSER_HAS_NON_STRICT_ARG)
2573     {
2574       parser_raise_error (context_p, PARSER_ERR_NON_STRICT_ARG_DEFINITION);
2575     }
2576 
2577     parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
2578 
2579     if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION)
2580     {
2581       parser_emit_cbc_ext (context_p, CBC_EXT_RETURN_PROMISE);
2582     }
2583     else
2584     {
2585       if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
2586       {
2587         context_p->last_cbc_opcode = CBC_RETURN_WITH_LITERAL;
2588       }
2589       else
2590       {
2591         parser_emit_cbc (context_p, CBC_RETURN);
2592       }
2593     }
2594     parser_flush_cbc (context_p);
2595 
2596     lexer_update_await_yield (context_p, saved_context.status_flags);
2597   }
2598 
2599   compiled_code_p = parser_post_processing (context_p);
2600 
2601 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2602   if (context_p->is_show_opcodes)
2603   {
2604     JERRY_DEBUG_MSG ("\n--- Arrow function parsing end ---\n\n");
2605   }
2606 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2607 
2608   parser_restore_context (context_p, &saved_context);
2609 
2610   return compiled_code_p;
2611 } /* parser_parse_arrow_function */
2612 
2613 #endif /* ENABLED (JERRY_ES2015) */
2614 
2615 /**
2616  * Raise a parse error.
2617  */
2618 void
parser_raise_error(parser_context_t * context_p,parser_error_t error)2619 parser_raise_error (parser_context_t *context_p, /**< context */
2620                     parser_error_t error) /**< error code */
2621 {
2622   /* Must be compatible with the scanner because
2623    * the lexer might throws errors during prescanning. */
2624   parser_saved_context_t *saved_context_p = context_p->last_context_p;
2625 
2626   while (saved_context_p != NULL)
2627   {
2628     parser_cbc_stream_free (&saved_context_p->byte_code);
2629 
2630     /* First the current literal pool is freed, and then it is replaced
2631      * by the literal pool coming from the saved context. Since literals
2632      * are not used anymore, this is a valid replacement. The last pool
2633      * is freed by parser_parse_source. */
2634 
2635     parser_free_literals (&context_p->literal_pool);
2636     context_p->literal_pool.data = saved_context_p->literal_pool_data;
2637 
2638     if (context_p->scope_stack_p != NULL)
2639     {
2640       parser_free (context_p->scope_stack_p, context_p->scope_stack_size * sizeof (parser_scope_stack_t));
2641     }
2642     context_p->scope_stack_p = saved_context_p->scope_stack_p;
2643     context_p->scope_stack_size = saved_context_p->scope_stack_size;
2644 
2645     if (saved_context_p->last_statement.current_p != NULL)
2646     {
2647       parser_free_jumps (saved_context_p->last_statement);
2648     }
2649 
2650 #if ENABLED (JERRY_ES2015)
2651     if (saved_context_p->tagged_template_literal_cp != JMEM_CP_NULL)
2652     {
2653       ecma_collection_free (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
2654                                                              saved_context_p->tagged_template_literal_cp));
2655     }
2656 #endif /* ENABLED (JERRY_ES2015)  */
2657 
2658     saved_context_p = saved_context_p->prev_context_p;
2659   }
2660 
2661 #if ENABLED (JERRY_ES2015)
2662   if (context_p->tagged_template_literal_cp != JMEM_CP_NULL)
2663   {
2664     ecma_collection_free (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
2665                                                            context_p->tagged_template_literal_cp));
2666   }
2667 #endif /* ENABLED (JERRY_ES2015)  */
2668 
2669   context_p->error = error;
2670   PARSER_THROW (context_p->try_buffer);
2671   /* Should never been reached. */
2672   JERRY_ASSERT (0);
2673 } /* parser_raise_error */
2674 
2675 #endif /* ENABLED (JERRY_PARSER) */
2676 
2677 /**
2678  * Parse EcmaScript source code
2679  *
2680  * Note:
2681  *      if arg_list_p is not NULL, a function body is parsed
2682  *      returned value must be freed with ecma_free_value
2683  *
2684  * @return true - if success
2685  *         syntax error - otherwise
2686  */
2687 ecma_value_t
parser_parse_script(const uint8_t * arg_list_p,size_t arg_list_size,const uint8_t * source_p,size_t source_size,uint32_t parse_opts,ecma_compiled_code_t ** bytecode_data_p)2688 parser_parse_script (const uint8_t *arg_list_p, /**< function argument list */
2689                      size_t arg_list_size, /**< size of function argument list */
2690                      const uint8_t *source_p, /**< source code */
2691                      size_t source_size, /**< size of the source code */
2692                      uint32_t parse_opts, /**< ecma_parse_opts_t option bits */
2693                      ecma_compiled_code_t **bytecode_data_p) /**< [out] JS bytecode */
2694 {
2695 #if ENABLED (JERRY_PARSER)
2696   parser_error_location_t parser_error;
2697 
2698 #if ENABLED (JERRY_DEBUGGER)
2699   if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
2700   {
2701     jerry_debugger_send_string (JERRY_DEBUGGER_SOURCE_CODE,
2702                                 JERRY_DEBUGGER_NO_SUBTYPE,
2703                                 source_p,
2704                                 source_size);
2705   }
2706 #endif /* ENABLED (JERRY_DEBUGGER) */
2707 
2708   *bytecode_data_p = parser_parse_source (arg_list_p,
2709                                           arg_list_size,
2710                                           source_p,
2711                                           source_size,
2712                                           parse_opts,
2713                                           &parser_error);
2714 
2715   if (!*bytecode_data_p)
2716   {
2717 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2718     if (JERRY_CONTEXT (module_top_context_p) != NULL)
2719     {
2720       ecma_module_cleanup ();
2721     }
2722 #endif
2723 #if ENABLED (JERRY_DEBUGGER)
2724     if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
2725     {
2726       jerry_debugger_send_type (JERRY_DEBUGGER_PARSE_ERROR);
2727     }
2728 #endif /* ENABLED (JERRY_DEBUGGER) */
2729 
2730     if (parser_error.error == PARSER_ERR_OUT_OF_MEMORY)
2731     {
2732       /* It is unlikely that memory can be allocated in an out-of-memory
2733        * situation. However, a simple value can still be thrown. */
2734       jcontext_raise_exception (ECMA_VALUE_NULL);
2735       return ECMA_VALUE_ERROR;
2736     }
2737 
2738     if (parser_error.error == PARSER_ERR_INVALID_REGEXP)
2739     {
2740       /* The RegExp compiler has already raised an exception. */
2741       JERRY_ASSERT (jcontext_has_pending_exception ());
2742       return ECMA_VALUE_ERROR;
2743     }
2744 
2745 #if ENABLED (JERRY_ERROR_MESSAGES)
2746     const lit_utf8_byte_t *err_bytes_p = (const lit_utf8_byte_t *) parser_error_to_string (parser_error.error);
2747     lit_utf8_size_t err_bytes_size = lit_zt_utf8_string_size (err_bytes_p);
2748 
2749     ecma_string_t *err_str_p = ecma_new_ecma_string_from_utf8 (err_bytes_p, err_bytes_size);
2750     ecma_value_t err_str_val = ecma_make_string_value (err_str_p);
2751     ecma_value_t line_str_val = ecma_make_uint32_value (parser_error.line);
2752     ecma_value_t col_str_val = ecma_make_uint32_value (parser_error.column);
2753 
2754     ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_SYNTAX,
2755                                                                       "% [%:%:%]",
2756                                                                       err_str_val,
2757                                                                       JERRY_CONTEXT (resource_name),
2758                                                                       line_str_val,
2759                                                                       col_str_val);
2760 
2761     ecma_free_value (col_str_val);
2762     ecma_free_value (line_str_val);
2763     ecma_free_value (err_str_val);
2764 
2765     return error_value;
2766 #else /* !ENABLED (JERRY_ERROR_MESSAGES) */
2767     return ecma_raise_syntax_error ("");
2768 #endif /* ENABLED (JERRY_ERROR_MESSAGES) */
2769   }
2770 
2771 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2772   if (JERRY_CONTEXT (module_top_context_p) != NULL)
2773   {
2774     ecma_value_t ret_value = ecma_module_parse_modules ();
2775 
2776     if (ECMA_IS_VALUE_ERROR (ret_value))
2777     {
2778       ecma_bytecode_deref (*bytecode_data_p);
2779       *bytecode_data_p = NULL;
2780       ecma_module_cleanup ();
2781 
2782       return ret_value;
2783     }
2784   }
2785 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2786 
2787 #if ENABLED (JERRY_DEBUGGER)
2788   if ((JERRY_CONTEXT (debugger_flags) & (JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_PARSER_WAIT))
2789       == (JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_PARSER_WAIT))
2790   {
2791     JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_PARSER_WAIT_MODE);
2792     jerry_debugger_send_type (JERRY_DEBUGGER_WAITING_AFTER_PARSE);
2793 
2794     while (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_PARSER_WAIT_MODE)
2795     {
2796       jerry_debugger_receive (NULL);
2797 
2798       if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED))
2799       {
2800         break;
2801       }
2802 
2803       jerry_debugger_transport_sleep ();
2804     }
2805   }
2806 #endif /* ENABLED (JERRY_DEBUGGER) */
2807 
2808   return ECMA_VALUE_TRUE;
2809 #else /* !ENABLED (JERRY_PARSER) */
2810   JERRY_UNUSED (arg_list_p);
2811   JERRY_UNUSED (arg_list_size);
2812   JERRY_UNUSED (source_p);
2813   JERRY_UNUSED (source_size);
2814   JERRY_UNUSED (parse_opts);
2815   JERRY_UNUSED (bytecode_data_p);
2816 
2817   return ecma_raise_syntax_error (ECMA_ERR_MSG ("The parser has been disabled."));
2818 #endif /* ENABLED (JERRY_PARSER) */
2819 } /* parser_parse_script */
2820 
2821 /**
2822  * @}
2823  * @}
2824  * @}
2825  */
2826