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
26JERRY_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)
30JERRY_STATIC_ASSERT (PARSER_SAVE_STATUS_FLAGS (PARSER_ALLOW_SUPER) == 0x1,
31                     incorrect_saving_of_ecma_parse_allow_super);
32JERRY_STATIC_ASSERT (PARSER_RESTORE_STATUS_FLAGS (ECMA_PARSE_ALLOW_SUPER) == PARSER_ALLOW_SUPER,
33                     incorrect_restoring_of_ecma_parse_allow_super);
34
35JERRY_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 */
54static void
55parser_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 */
207static void
208parser_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 */
326static size_t
327parser_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 */
349static size_t
350parser_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 */
380static void
381parse_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 */
517static void
518parse_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 */
597static void
598parse_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 */
827static void
828parser_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 */
844void
845parser_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 */
902static ecma_compiled_code_t *
903parser_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 */
1697static void
1698parser_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 */
1715static void
1716parser_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
1991JERRY_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 */
2002static ecma_compiled_code_t *
2003parser_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 */
2283static void
2284parser_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 */
2365static void
2366parser_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 */
2412ecma_compiled_code_t *
2413parser_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 */
2514ecma_compiled_code_t *
2515parser_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 */
2618void
2619parser_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 */
2687ecma_value_t
2688parser_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