1425bb815Sopenharmony_ci/* Copyright JS Foundation and other contributors, http://js.foundation
2425bb815Sopenharmony_ci *
3425bb815Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4425bb815Sopenharmony_ci * you may not use this file except in compliance with the License.
5425bb815Sopenharmony_ci * You may obtain a copy of the License at
6425bb815Sopenharmony_ci *
7425bb815Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8425bb815Sopenharmony_ci *
9425bb815Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10425bb815Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS
11425bb815Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12425bb815Sopenharmony_ci * See the License for the specific language governing permissions and
13425bb815Sopenharmony_ci * limitations under the License.
14425bb815Sopenharmony_ci */
15425bb815Sopenharmony_ci
16425bb815Sopenharmony_ci#include "debugger.h"
17425bb815Sopenharmony_ci#include "ecma-exceptions.h"
18425bb815Sopenharmony_ci#include "ecma-helpers.h"
19425bb815Sopenharmony_ci#include "ecma-literal-storage.h"
20425bb815Sopenharmony_ci#include "ecma-module.h"
21425bb815Sopenharmony_ci#include "jcontext.h"
22425bb815Sopenharmony_ci#include "js-parser-internal.h"
23425bb815Sopenharmony_ci
24425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER)
25425bb815Sopenharmony_ci
26425bb815Sopenharmony_ciJERRY_STATIC_ASSERT ((int) ECMA_PARSE_STRICT_MODE == (int) PARSER_IS_STRICT,
27425bb815Sopenharmony_ci                     ecma_parse_strict_mode_must_be_equal_to_parser_is_strict);
28425bb815Sopenharmony_ci
29425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
30425bb815Sopenharmony_ciJERRY_STATIC_ASSERT (PARSER_SAVE_STATUS_FLAGS (PARSER_ALLOW_SUPER) == 0x1,
31425bb815Sopenharmony_ci                     incorrect_saving_of_ecma_parse_allow_super);
32425bb815Sopenharmony_ciJERRY_STATIC_ASSERT (PARSER_RESTORE_STATUS_FLAGS (ECMA_PARSE_ALLOW_SUPER) == PARSER_ALLOW_SUPER,
33425bb815Sopenharmony_ci                     incorrect_restoring_of_ecma_parse_allow_super);
34425bb815Sopenharmony_ci
35425bb815Sopenharmony_ciJERRY_STATIC_ASSERT (PARSER_RESTORE_STATUS_FLAGS (ECMA_PARSE_FUNCTION_CONTEXT) == 0,
36425bb815Sopenharmony_ci                     ecma_parse_function_context_must_not_be_transformed);
37425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
38425bb815Sopenharmony_ci
39425bb815Sopenharmony_ci/** \addtogroup parser Parser
40425bb815Sopenharmony_ci * @{
41425bb815Sopenharmony_ci *
42425bb815Sopenharmony_ci * \addtogroup jsparser JavaScript
43425bb815Sopenharmony_ci * @{
44425bb815Sopenharmony_ci *
45425bb815Sopenharmony_ci * \addtogroup jsparser_parser Parser
46425bb815Sopenharmony_ci * @{
47425bb815Sopenharmony_ci */
48425bb815Sopenharmony_ci
49425bb815Sopenharmony_ci/**
50425bb815Sopenharmony_ci * Compute real literal indicies.
51425bb815Sopenharmony_ci *
52425bb815Sopenharmony_ci * @return length of the prefix opcodes
53425bb815Sopenharmony_ci */
54425bb815Sopenharmony_cistatic void
55425bb815Sopenharmony_ciparser_compute_indicies (parser_context_t *context_p, /**< context */
56425bb815Sopenharmony_ci                         uint16_t *ident_end, /**< end of the identifier group */
57425bb815Sopenharmony_ci                         uint16_t *const_literal_end) /**< end of the const literal group */
58425bb815Sopenharmony_ci{
59425bb815Sopenharmony_ci  parser_list_iterator_t literal_iterator;
60425bb815Sopenharmony_ci  lexer_literal_t *literal_p;
61425bb815Sopenharmony_ci
62425bb815Sopenharmony_ci  uint16_t ident_count = 0;
63425bb815Sopenharmony_ci  uint16_t const_literal_count = 0;
64425bb815Sopenharmony_ci
65425bb815Sopenharmony_ci  uint16_t ident_index;
66425bb815Sopenharmony_ci  uint16_t const_literal_index;
67425bb815Sopenharmony_ci  uint16_t literal_index;
68425bb815Sopenharmony_ci
69425bb815Sopenharmony_ci  /* First phase: count the number of items in each group. */
70425bb815Sopenharmony_ci  parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
71425bb815Sopenharmony_ci  while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)))
72425bb815Sopenharmony_ci  {
73425bb815Sopenharmony_ci    switch (literal_p->type)
74425bb815Sopenharmony_ci    {
75425bb815Sopenharmony_ci      case LEXER_IDENT_LITERAL:
76425bb815Sopenharmony_ci      {
77425bb815Sopenharmony_ci        if (literal_p->status_flags & LEXER_FLAG_USED)
78425bb815Sopenharmony_ci        {
79425bb815Sopenharmony_ci          ident_count++;
80425bb815Sopenharmony_ci          break;
81425bb815Sopenharmony_ci        }
82425bb815Sopenharmony_ci#if !ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
83425bb815Sopenharmony_ci        else if (!(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
84425bb815Sopenharmony_ci        {
85425bb815Sopenharmony_ci          jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length);
86425bb815Sopenharmony_ci          /* This literal should not be freed even if an error is encountered later. */
87425bb815Sopenharmony_ci          literal_p->status_flags |= LEXER_FLAG_SOURCE_PTR;
88425bb815Sopenharmony_ci        }
89425bb815Sopenharmony_ci#endif /* !ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
90425bb815Sopenharmony_ci        continue;
91425bb815Sopenharmony_ci      }
92425bb815Sopenharmony_ci      case LEXER_STRING_LITERAL:
93425bb815Sopenharmony_ci      {
94425bb815Sopenharmony_ci        const_literal_count++;
95425bb815Sopenharmony_ci        break;
96425bb815Sopenharmony_ci      }
97425bb815Sopenharmony_ci      case LEXER_NUMBER_LITERAL:
98425bb815Sopenharmony_ci      {
99425bb815Sopenharmony_ci        const_literal_count++;
100425bb815Sopenharmony_ci        continue;
101425bb815Sopenharmony_ci      }
102425bb815Sopenharmony_ci      case LEXER_FUNCTION_LITERAL:
103425bb815Sopenharmony_ci      case LEXER_REGEXP_LITERAL:
104425bb815Sopenharmony_ci      {
105425bb815Sopenharmony_ci        continue;
106425bb815Sopenharmony_ci      }
107425bb815Sopenharmony_ci      default:
108425bb815Sopenharmony_ci      {
109425bb815Sopenharmony_ci        JERRY_ASSERT (literal_p->type == LEXER_UNUSED_LITERAL);
110425bb815Sopenharmony_ci        continue;
111425bb815Sopenharmony_ci      }
112425bb815Sopenharmony_ci    }
113425bb815Sopenharmony_ci
114425bb815Sopenharmony_ci#if !ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
115425bb815Sopenharmony_ci    const uint8_t *char_p = literal_p->u.char_p;
116425bb815Sopenharmony_ci    uint32_t status_flags = context_p->status_flags;
117425bb815Sopenharmony_ci
118425bb815Sopenharmony_ci    if ((literal_p->status_flags & LEXER_FLAG_SOURCE_PTR)
119425bb815Sopenharmony_ci        && literal_p->prop.length < 0xfff)
120425bb815Sopenharmony_ci    {
121425bb815Sopenharmony_ci      size_t bytes_to_end = (size_t) (context_p->source_end_p - char_p);
122425bb815Sopenharmony_ci
123425bb815Sopenharmony_ci      if (bytes_to_end < 0xfffff)
124425bb815Sopenharmony_ci      {
125425bb815Sopenharmony_ci        literal_p->u.source_data = ((uint32_t) bytes_to_end) | (((uint32_t) literal_p->prop.length) << 20);
126425bb815Sopenharmony_ci        literal_p->status_flags |= LEXER_FLAG_LATE_INIT;
127425bb815Sopenharmony_ci        status_flags |= PARSER_HAS_LATE_LIT_INIT;
128425bb815Sopenharmony_ci        context_p->status_flags = status_flags;
129425bb815Sopenharmony_ci        char_p = NULL;
130425bb815Sopenharmony_ci      }
131425bb815Sopenharmony_ci    }
132425bb815Sopenharmony_ci
133425bb815Sopenharmony_ci    if (char_p != NULL)
134425bb815Sopenharmony_ci    {
135425bb815Sopenharmony_ci      literal_p->u.value = ecma_find_or_create_literal_string (char_p,
136425bb815Sopenharmony_ci                                                               literal_p->prop.length);
137425bb815Sopenharmony_ci
138425bb815Sopenharmony_ci      if (!(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
139425bb815Sopenharmony_ci      {
140425bb815Sopenharmony_ci        jmem_heap_free_block ((void *) char_p, literal_p->prop.length);
141425bb815Sopenharmony_ci        /* This literal should not be freed even if an error is encountered later. */
142425bb815Sopenharmony_ci        literal_p->status_flags |= LEXER_FLAG_SOURCE_PTR;
143425bb815Sopenharmony_ci      }
144425bb815Sopenharmony_ci    }
145425bb815Sopenharmony_ci#endif /* !ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
146425bb815Sopenharmony_ci  }
147425bb815Sopenharmony_ci
148425bb815Sopenharmony_ci  ident_index = context_p->register_count;
149425bb815Sopenharmony_ci  const_literal_index = (uint16_t) (ident_index + ident_count);
150425bb815Sopenharmony_ci  literal_index = (uint16_t) (const_literal_index + const_literal_count);
151425bb815Sopenharmony_ci
152425bb815Sopenharmony_ci  /* Second phase: Assign an index to each literal. */
153425bb815Sopenharmony_ci  parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
154425bb815Sopenharmony_ci
155425bb815Sopenharmony_ci  while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)))
156425bb815Sopenharmony_ci  {
157425bb815Sopenharmony_ci    switch (literal_p->type)
158425bb815Sopenharmony_ci    {
159425bb815Sopenharmony_ci      case LEXER_IDENT_LITERAL:
160425bb815Sopenharmony_ci      {
161425bb815Sopenharmony_ci        if (literal_p->status_flags & LEXER_FLAG_USED)
162425bb815Sopenharmony_ci        {
163425bb815Sopenharmony_ci          literal_p->prop.index = ident_index;
164425bb815Sopenharmony_ci          ident_index++;
165425bb815Sopenharmony_ci        }
166425bb815Sopenharmony_ci        break;
167425bb815Sopenharmony_ci      }
168425bb815Sopenharmony_ci      case LEXER_STRING_LITERAL:
169425bb815Sopenharmony_ci      case LEXER_NUMBER_LITERAL:
170425bb815Sopenharmony_ci      {
171425bb815Sopenharmony_ci        JERRY_ASSERT ((literal_p->status_flags & ~(LEXER_FLAG_SOURCE_PTR | LEXER_FLAG_LATE_INIT)) == 0);
172425bb815Sopenharmony_ci        literal_p->prop.index = const_literal_index;
173425bb815Sopenharmony_ci        const_literal_index++;
174425bb815Sopenharmony_ci        break;
175425bb815Sopenharmony_ci      }
176425bb815Sopenharmony_ci      case LEXER_FUNCTION_LITERAL:
177425bb815Sopenharmony_ci      case LEXER_REGEXP_LITERAL:
178425bb815Sopenharmony_ci      {
179425bb815Sopenharmony_ci        JERRY_ASSERT (literal_p->status_flags == 0);
180425bb815Sopenharmony_ci
181425bb815Sopenharmony_ci        literal_p->prop.index = literal_index;
182425bb815Sopenharmony_ci        literal_index++;
183425bb815Sopenharmony_ci        break;
184425bb815Sopenharmony_ci      }
185425bb815Sopenharmony_ci      default:
186425bb815Sopenharmony_ci      {
187425bb815Sopenharmony_ci        JERRY_ASSERT (literal_p->type == LEXER_UNUSED_LITERAL
188425bb815Sopenharmony_ci                      && literal_p->status_flags == LEXER_FLAG_FUNCTION_ARGUMENT);
189425bb815Sopenharmony_ci        break;
190425bb815Sopenharmony_ci      }
191425bb815Sopenharmony_ci    }
192425bb815Sopenharmony_ci  }
193425bb815Sopenharmony_ci
194425bb815Sopenharmony_ci  JERRY_ASSERT (ident_index == context_p->register_count + ident_count);
195425bb815Sopenharmony_ci  JERRY_ASSERT (const_literal_index == ident_index + const_literal_count);
196425bb815Sopenharmony_ci  JERRY_ASSERT (literal_index <= context_p->register_count + context_p->literal_count);
197425bb815Sopenharmony_ci
198425bb815Sopenharmony_ci  context_p->literal_count = literal_index;
199425bb815Sopenharmony_ci
200425bb815Sopenharmony_ci  *ident_end = ident_index;
201425bb815Sopenharmony_ci  *const_literal_end = const_literal_index;
202425bb815Sopenharmony_ci} /* parser_compute_indicies */
203425bb815Sopenharmony_ci
204425bb815Sopenharmony_ci/**
205425bb815Sopenharmony_ci * Initialize literal pool.
206425bb815Sopenharmony_ci */
207425bb815Sopenharmony_cistatic void
208425bb815Sopenharmony_ciparser_init_literal_pool (parser_context_t *context_p, /**< context */
209425bb815Sopenharmony_ci                          ecma_value_t *literal_pool_p) /**< start of literal pool */
210425bb815Sopenharmony_ci{
211425bb815Sopenharmony_ci  parser_list_iterator_t literal_iterator;
212425bb815Sopenharmony_ci  lexer_literal_t *literal_p;
213425bb815Sopenharmony_ci
214425bb815Sopenharmony_ci  parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
215425bb815Sopenharmony_ci
216425bb815Sopenharmony_ci  while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)))
217425bb815Sopenharmony_ci  {
218425bb815Sopenharmony_ci    switch (literal_p->type)
219425bb815Sopenharmony_ci    {
220425bb815Sopenharmony_ci      case LEXER_IDENT_LITERAL:
221425bb815Sopenharmony_ci      {
222425bb815Sopenharmony_ci        if (!(literal_p->status_flags & LEXER_FLAG_USED))
223425bb815Sopenharmony_ci        {
224425bb815Sopenharmony_ci          break;
225425bb815Sopenharmony_ci        }
226425bb815Sopenharmony_ci        /* FALLTHRU */
227425bb815Sopenharmony_ci      }
228425bb815Sopenharmony_ci      case LEXER_STRING_LITERAL:
229425bb815Sopenharmony_ci      {
230425bb815Sopenharmony_ci        ecma_value_t lit_value;
231425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
232425bb815Sopenharmony_ci        lit_value = ecma_find_or_create_literal_string (literal_p->u.char_p,
233425bb815Sopenharmony_ci                                                        literal_p->prop.length);
234425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
235425bb815Sopenharmony_ci        lit_value = literal_p->u.value;
236425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
237425bb815Sopenharmony_ci
238425bb815Sopenharmony_ci        JERRY_ASSERT (literal_p->prop.index >= context_p->register_count);
239425bb815Sopenharmony_ci        literal_pool_p[literal_p->prop.index] = lit_value;
240425bb815Sopenharmony_ci
241425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
242425bb815Sopenharmony_ci        if (!context_p->is_show_opcodes
243425bb815Sopenharmony_ci            && !(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
244425bb815Sopenharmony_ci        {
245425bb815Sopenharmony_ci          jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length);
246425bb815Sopenharmony_ci        }
247425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
248425bb815Sopenharmony_ci        break;
249425bb815Sopenharmony_ci      }
250425bb815Sopenharmony_ci      case LEXER_NUMBER_LITERAL:
251425bb815Sopenharmony_ci      {
252425bb815Sopenharmony_ci        JERRY_ASSERT (literal_p->prop.index >= context_p->register_count);
253425bb815Sopenharmony_ci
254425bb815Sopenharmony_ci        literal_pool_p[literal_p->prop.index] = literal_p->u.value;
255425bb815Sopenharmony_ci        break;
256425bb815Sopenharmony_ci      }
257425bb815Sopenharmony_ci      case LEXER_FUNCTION_LITERAL:
258425bb815Sopenharmony_ci      case LEXER_REGEXP_LITERAL:
259425bb815Sopenharmony_ci      {
260425bb815Sopenharmony_ci        JERRY_ASSERT (literal_p->prop.index >= context_p->register_count);
261425bb815Sopenharmony_ci
262425bb815Sopenharmony_ci        ECMA_SET_INTERNAL_VALUE_POINTER (literal_pool_p[literal_p->prop.index],
263425bb815Sopenharmony_ci                                         literal_p->u.bytecode_p);
264425bb815Sopenharmony_ci        break;
265425bb815Sopenharmony_ci      }
266425bb815Sopenharmony_ci      default:
267425bb815Sopenharmony_ci      {
268425bb815Sopenharmony_ci        JERRY_ASSERT (literal_p->type == LEXER_UNUSED_LITERAL);
269425bb815Sopenharmony_ci        break;
270425bb815Sopenharmony_ci      }
271425bb815Sopenharmony_ci    }
272425bb815Sopenharmony_ci  }
273425bb815Sopenharmony_ci} /* parser_init_literal_pool */
274425bb815Sopenharmony_ci
275425bb815Sopenharmony_ci/*
276425bb815Sopenharmony_ci * During byte code post processing certain bytes are not
277425bb815Sopenharmony_ci * copied into the final byte code buffer. For example, if
278425bb815Sopenharmony_ci * one byte is enough for encoding a literal index, the
279425bb815Sopenharmony_ci * second byte is not copied. However, when a byte is skipped,
280425bb815Sopenharmony_ci * the offsets of those branches which crosses (jumps over)
281425bb815Sopenharmony_ci * that byte code should also be decreased by one. Instead
282425bb815Sopenharmony_ci * of finding these jumps every time when a byte is skipped,
283425bb815Sopenharmony_ci * all branch offset updates are computed in one step.
284425bb815Sopenharmony_ci *
285425bb815Sopenharmony_ci * Branch offset mapping example:
286425bb815Sopenharmony_ci *
287425bb815Sopenharmony_ci * Let's assume that each parser_mem_page of the byte_code
288425bb815Sopenharmony_ci * buffer is 8 bytes long and only 4 bytes are kept for a
289425bb815Sopenharmony_ci * given page:
290425bb815Sopenharmony_ci *
291425bb815Sopenharmony_ci * +---+---+---+---+---+---+---+---+
292425bb815Sopenharmony_ci * | X | 1 | 2 | 3 | X | 4 | X | X |
293425bb815Sopenharmony_ci * +---+---+---+---+---+---+---+---+
294425bb815Sopenharmony_ci *
295425bb815Sopenharmony_ci * X marks those bytes which are removed. The resulting
296425bb815Sopenharmony_ci * offset mapping is the following:
297425bb815Sopenharmony_ci *
298425bb815Sopenharmony_ci * +---+---+---+---+---+---+---+---+
299425bb815Sopenharmony_ci * | 0 | 1 | 2 | 3 | 3 | 4 | 4 | 4 |
300425bb815Sopenharmony_ci * +---+---+---+---+---+---+---+---+
301425bb815Sopenharmony_ci *
302425bb815Sopenharmony_ci * Each X is simply replaced by the index of the previous
303425bb815Sopenharmony_ci * index starting from zero. This shows the number of
304425bb815Sopenharmony_ci * copied bytes before a given byte including the byte
305425bb815Sopenharmony_ci * itself. The last byte always shows the number of bytes
306425bb815Sopenharmony_ci * copied from this page.
307425bb815Sopenharmony_ci *
308425bb815Sopenharmony_ci * This mapping allows recomputing all branch targets,
309425bb815Sopenharmony_ci * since mapping[to] - mapping[from] is the new argument
310425bb815Sopenharmony_ci * for forward branches. As for backward branches, the
311425bb815Sopenharmony_ci * equation is reversed to mapping[from] - mapping[to].
312425bb815Sopenharmony_ci *
313425bb815Sopenharmony_ci * The mapping is relative to one page, so distance
314425bb815Sopenharmony_ci * computation affecting multiple pages requires a loop.
315425bb815Sopenharmony_ci * We should also note that only argument bytes can
316425bb815Sopenharmony_ci * be skipped, so removed bytes cannot be targeted by
317425bb815Sopenharmony_ci * branches. Valid branches always target instruction
318425bb815Sopenharmony_ci * starts only.
319425bb815Sopenharmony_ci */
320425bb815Sopenharmony_ci
321425bb815Sopenharmony_ci/**
322425bb815Sopenharmony_ci * Recompute the argument of a forward branch.
323425bb815Sopenharmony_ci *
324425bb815Sopenharmony_ci * @return the new distance
325425bb815Sopenharmony_ci */
326425bb815Sopenharmony_cistatic size_t
327425bb815Sopenharmony_ciparser_update_forward_branch (parser_mem_page_t *page_p, /**< current page */
328425bb815Sopenharmony_ci                              size_t full_distance, /**< full distance */
329425bb815Sopenharmony_ci                              uint8_t bytes_copied_before_jump) /**< bytes copied before jump */
330425bb815Sopenharmony_ci{
331425bb815Sopenharmony_ci  size_t new_distance = 0;
332425bb815Sopenharmony_ci
333425bb815Sopenharmony_ci  while (full_distance > PARSER_CBC_STREAM_PAGE_SIZE)
334425bb815Sopenharmony_ci  {
335425bb815Sopenharmony_ci    new_distance += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK;
336425bb815Sopenharmony_ci    full_distance -= PARSER_CBC_STREAM_PAGE_SIZE;
337425bb815Sopenharmony_ci    page_p = page_p->next_p;
338425bb815Sopenharmony_ci  }
339425bb815Sopenharmony_ci
340425bb815Sopenharmony_ci  new_distance += page_p->bytes[full_distance - 1] & CBC_LOWER_SEVEN_BIT_MASK;
341425bb815Sopenharmony_ci  return new_distance - bytes_copied_before_jump;
342425bb815Sopenharmony_ci} /* parser_update_forward_branch */
343425bb815Sopenharmony_ci
344425bb815Sopenharmony_ci/**
345425bb815Sopenharmony_ci * Recompute the argument of a backward branch.
346425bb815Sopenharmony_ci *
347425bb815Sopenharmony_ci * @return the new distance
348425bb815Sopenharmony_ci */
349425bb815Sopenharmony_cistatic size_t
350425bb815Sopenharmony_ciparser_update_backward_branch (parser_mem_page_t *page_p, /**< current page */
351425bb815Sopenharmony_ci                               size_t full_distance, /**< full distance */
352425bb815Sopenharmony_ci                               uint8_t bytes_copied_before_jump) /**< bytes copied before jump */
353425bb815Sopenharmony_ci{
354425bb815Sopenharmony_ci  size_t new_distance = bytes_copied_before_jump;
355425bb815Sopenharmony_ci
356425bb815Sopenharmony_ci  while (full_distance >= PARSER_CBC_STREAM_PAGE_SIZE)
357425bb815Sopenharmony_ci  {
358425bb815Sopenharmony_ci    JERRY_ASSERT (page_p != NULL);
359425bb815Sopenharmony_ci    new_distance += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK;
360425bb815Sopenharmony_ci    full_distance -= PARSER_CBC_STREAM_PAGE_SIZE;
361425bb815Sopenharmony_ci    page_p = page_p->next_p;
362425bb815Sopenharmony_ci  }
363425bb815Sopenharmony_ci
364425bb815Sopenharmony_ci  if (full_distance > 0)
365425bb815Sopenharmony_ci  {
366425bb815Sopenharmony_ci    size_t offset = PARSER_CBC_STREAM_PAGE_SIZE - full_distance;
367425bb815Sopenharmony_ci
368425bb815Sopenharmony_ci    JERRY_ASSERT (page_p != NULL);
369425bb815Sopenharmony_ci
370425bb815Sopenharmony_ci    new_distance += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK;
371425bb815Sopenharmony_ci    new_distance -= page_p->bytes[offset - 1] & CBC_LOWER_SEVEN_BIT_MASK;
372425bb815Sopenharmony_ci  }
373425bb815Sopenharmony_ci
374425bb815Sopenharmony_ci  return new_distance;
375425bb815Sopenharmony_ci} /* parser_update_backward_branch */
376425bb815Sopenharmony_ci
377425bb815Sopenharmony_ci/**
378425bb815Sopenharmony_ci * Update targets of all branches in one step.
379425bb815Sopenharmony_ci */
380425bb815Sopenharmony_cistatic void
381425bb815Sopenharmony_ciparse_update_branches (parser_context_t *context_p, /**< context */
382425bb815Sopenharmony_ci                       uint8_t *byte_code_p) /**< byte code */
383425bb815Sopenharmony_ci{
384425bb815Sopenharmony_ci  parser_mem_page_t *page_p = context_p->byte_code.first_p;
385425bb815Sopenharmony_ci  parser_mem_page_t *prev_page_p = NULL;
386425bb815Sopenharmony_ci  parser_mem_page_t *last_page_p = context_p->byte_code.last_p;
387425bb815Sopenharmony_ci  size_t last_position = context_p->byte_code.last_position;
388425bb815Sopenharmony_ci  size_t offset = 0;
389425bb815Sopenharmony_ci  size_t bytes_copied = 0;
390425bb815Sopenharmony_ci
391425bb815Sopenharmony_ci  if (last_position >= PARSER_CBC_STREAM_PAGE_SIZE)
392425bb815Sopenharmony_ci  {
393425bb815Sopenharmony_ci    last_page_p = NULL;
394425bb815Sopenharmony_ci    last_position = 0;
395425bb815Sopenharmony_ci  }
396425bb815Sopenharmony_ci
397425bb815Sopenharmony_ci  while (page_p != last_page_p || offset < last_position)
398425bb815Sopenharmony_ci  {
399425bb815Sopenharmony_ci    /* Branch instructions are marked to improve search speed. */
400425bb815Sopenharmony_ci    if (page_p->bytes[offset] & CBC_HIGHEST_BIT_MASK)
401425bb815Sopenharmony_ci    {
402425bb815Sopenharmony_ci      uint8_t *bytes_p = byte_code_p + bytes_copied;
403425bb815Sopenharmony_ci      uint8_t flags;
404425bb815Sopenharmony_ci      uint8_t bytes_copied_before_jump = 0;
405425bb815Sopenharmony_ci      size_t branch_argument_length;
406425bb815Sopenharmony_ci      size_t target_distance;
407425bb815Sopenharmony_ci      size_t length;
408425bb815Sopenharmony_ci
409425bb815Sopenharmony_ci      if (offset > 0)
410425bb815Sopenharmony_ci      {
411425bb815Sopenharmony_ci        bytes_copied_before_jump = page_p->bytes[offset - 1] & CBC_LOWER_SEVEN_BIT_MASK;
412425bb815Sopenharmony_ci      }
413425bb815Sopenharmony_ci      bytes_p += bytes_copied_before_jump;
414425bb815Sopenharmony_ci
415425bb815Sopenharmony_ci      if (*bytes_p == CBC_EXT_OPCODE)
416425bb815Sopenharmony_ci      {
417425bb815Sopenharmony_ci        bytes_p++;
418425bb815Sopenharmony_ci        flags = cbc_ext_flags[*bytes_p];
419425bb815Sopenharmony_ci      }
420425bb815Sopenharmony_ci      else
421425bb815Sopenharmony_ci      {
422425bb815Sopenharmony_ci        flags = cbc_flags[*bytes_p];
423425bb815Sopenharmony_ci      }
424425bb815Sopenharmony_ci
425425bb815Sopenharmony_ci      JERRY_ASSERT (flags & CBC_HAS_BRANCH_ARG);
426425bb815Sopenharmony_ci      branch_argument_length = CBC_BRANCH_OFFSET_LENGTH (*bytes_p);
427425bb815Sopenharmony_ci      bytes_p++;
428425bb815Sopenharmony_ci
429425bb815Sopenharmony_ci      /* Decoding target. */
430425bb815Sopenharmony_ci      length = branch_argument_length;
431425bb815Sopenharmony_ci      target_distance = 0;
432425bb815Sopenharmony_ci      do
433425bb815Sopenharmony_ci      {
434425bb815Sopenharmony_ci        target_distance = (target_distance << 8) | *bytes_p;
435425bb815Sopenharmony_ci        bytes_p++;
436425bb815Sopenharmony_ci      }
437425bb815Sopenharmony_ci      while (--length > 0);
438425bb815Sopenharmony_ci
439425bb815Sopenharmony_ci      if (CBC_BRANCH_IS_FORWARD (flags))
440425bb815Sopenharmony_ci      {
441425bb815Sopenharmony_ci        /* Branch target was not set. */
442425bb815Sopenharmony_ci        JERRY_ASSERT (target_distance > 0);
443425bb815Sopenharmony_ci
444425bb815Sopenharmony_ci        target_distance = parser_update_forward_branch (page_p,
445425bb815Sopenharmony_ci                                                        offset + target_distance,
446425bb815Sopenharmony_ci                                                        bytes_copied_before_jump);
447425bb815Sopenharmony_ci      }
448425bb815Sopenharmony_ci      else
449425bb815Sopenharmony_ci      {
450425bb815Sopenharmony_ci        if (target_distance < offset)
451425bb815Sopenharmony_ci        {
452425bb815Sopenharmony_ci          uint8_t bytes_copied_before_target = page_p->bytes[offset - target_distance - 1];
453425bb815Sopenharmony_ci          bytes_copied_before_target = bytes_copied_before_target & CBC_LOWER_SEVEN_BIT_MASK;
454425bb815Sopenharmony_ci
455425bb815Sopenharmony_ci          target_distance = (size_t) (bytes_copied_before_jump - bytes_copied_before_target);
456425bb815Sopenharmony_ci        }
457425bb815Sopenharmony_ci        else if (target_distance == offset)
458425bb815Sopenharmony_ci        {
459425bb815Sopenharmony_ci          target_distance = bytes_copied_before_jump;
460425bb815Sopenharmony_ci        }
461425bb815Sopenharmony_ci        else
462425bb815Sopenharmony_ci        {
463425bb815Sopenharmony_ci          target_distance = parser_update_backward_branch (prev_page_p,
464425bb815Sopenharmony_ci                                                           target_distance - offset,
465425bb815Sopenharmony_ci                                                           bytes_copied_before_jump);
466425bb815Sopenharmony_ci        }
467425bb815Sopenharmony_ci      }
468425bb815Sopenharmony_ci
469425bb815Sopenharmony_ci      /* Encoding target again. */
470425bb815Sopenharmony_ci      do
471425bb815Sopenharmony_ci      {
472425bb815Sopenharmony_ci        bytes_p--;
473425bb815Sopenharmony_ci        *bytes_p = (uint8_t) (target_distance & 0xff);
474425bb815Sopenharmony_ci        target_distance >>= 8;
475425bb815Sopenharmony_ci      }
476425bb815Sopenharmony_ci      while (--branch_argument_length > 0);
477425bb815Sopenharmony_ci    }
478425bb815Sopenharmony_ci
479425bb815Sopenharmony_ci    offset++;
480425bb815Sopenharmony_ci    if (offset >= PARSER_CBC_STREAM_PAGE_SIZE)
481425bb815Sopenharmony_ci    {
482425bb815Sopenharmony_ci      parser_mem_page_t *next_p = page_p->next_p;
483425bb815Sopenharmony_ci
484425bb815Sopenharmony_ci      /* We reverse the pages before the current page. */
485425bb815Sopenharmony_ci      page_p->next_p = prev_page_p;
486425bb815Sopenharmony_ci      prev_page_p = page_p;
487425bb815Sopenharmony_ci
488425bb815Sopenharmony_ci      bytes_copied += page_p->bytes[PARSER_CBC_STREAM_PAGE_SIZE - 1] & CBC_LOWER_SEVEN_BIT_MASK;
489425bb815Sopenharmony_ci      page_p = next_p;
490425bb815Sopenharmony_ci      offset = 0;
491425bb815Sopenharmony_ci    }
492425bb815Sopenharmony_ci  }
493425bb815Sopenharmony_ci
494425bb815Sopenharmony_ci  /* After this point the pages of the byte code stream are
495425bb815Sopenharmony_ci   * not used anymore. However, they needs to be freed during
496425bb815Sopenharmony_ci   * cleanup, so the first and last pointers of the stream
497425bb815Sopenharmony_ci   * descriptor are reversed as well. */
498425bb815Sopenharmony_ci  if (last_page_p != NULL)
499425bb815Sopenharmony_ci  {
500425bb815Sopenharmony_ci    JERRY_ASSERT (last_page_p == context_p->byte_code.last_p);
501425bb815Sopenharmony_ci    last_page_p->next_p = prev_page_p;
502425bb815Sopenharmony_ci  }
503425bb815Sopenharmony_ci  else
504425bb815Sopenharmony_ci  {
505425bb815Sopenharmony_ci    last_page_p = context_p->byte_code.last_p;
506425bb815Sopenharmony_ci  }
507425bb815Sopenharmony_ci
508425bb815Sopenharmony_ci  context_p->byte_code.last_p = context_p->byte_code.first_p;
509425bb815Sopenharmony_ci  context_p->byte_code.first_p = last_page_p;
510425bb815Sopenharmony_ci} /* parse_update_branches */
511425bb815Sopenharmony_ci
512425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
513425bb815Sopenharmony_ci
514425bb815Sopenharmony_ci/**
515425bb815Sopenharmony_ci * Print literal.
516425bb815Sopenharmony_ci */
517425bb815Sopenharmony_cistatic void
518425bb815Sopenharmony_ciparse_print_literal (ecma_compiled_code_t *compiled_code_p, /**< compiled code */
519425bb815Sopenharmony_ci                     uint16_t literal_index, /**< literal index */
520425bb815Sopenharmony_ci                     parser_list_t *literal_pool_p) /**< literal pool */
521425bb815Sopenharmony_ci{
522425bb815Sopenharmony_ci  parser_list_iterator_t literal_iterator;
523425bb815Sopenharmony_ci  uint16_t argument_end;
524425bb815Sopenharmony_ci  uint16_t register_end;
525425bb815Sopenharmony_ci  uint16_t ident_end;
526425bb815Sopenharmony_ci
527425bb815Sopenharmony_ci  if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
528425bb815Sopenharmony_ci  {
529425bb815Sopenharmony_ci    cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p;
530425bb815Sopenharmony_ci    argument_end = args_p->argument_end;
531425bb815Sopenharmony_ci    register_end = args_p->register_end;
532425bb815Sopenharmony_ci    ident_end = args_p->ident_end;
533425bb815Sopenharmony_ci  }
534425bb815Sopenharmony_ci  else
535425bb815Sopenharmony_ci  {
536425bb815Sopenharmony_ci    cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p;
537425bb815Sopenharmony_ci    argument_end = args_p->argument_end;
538425bb815Sopenharmony_ci    register_end = args_p->register_end;
539425bb815Sopenharmony_ci    ident_end = args_p->ident_end;
540425bb815Sopenharmony_ci  }
541425bb815Sopenharmony_ci
542425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
543425bb815Sopenharmony_ci  if (compiled_code_p->status_flags & CBC_CODE_FLAGS_REST_PARAMETER)
544425bb815Sopenharmony_ci  {
545425bb815Sopenharmony_ci    argument_end++;
546425bb815Sopenharmony_ci  }
547425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
548425bb815Sopenharmony_ci
549425bb815Sopenharmony_ci  if (literal_index < argument_end)
550425bb815Sopenharmony_ci  {
551425bb815Sopenharmony_ci    JERRY_DEBUG_MSG (" arg:%d", literal_index);
552425bb815Sopenharmony_ci    return;
553425bb815Sopenharmony_ci  }
554425bb815Sopenharmony_ci
555425bb815Sopenharmony_ci  if (literal_index < register_end)
556425bb815Sopenharmony_ci  {
557425bb815Sopenharmony_ci    JERRY_DEBUG_MSG (" reg:%d", literal_index);
558425bb815Sopenharmony_ci    return;
559425bb815Sopenharmony_ci  }
560425bb815Sopenharmony_ci
561425bb815Sopenharmony_ci  parser_list_iterator_init (literal_pool_p, &literal_iterator);
562425bb815Sopenharmony_ci
563425bb815Sopenharmony_ci  while (true)
564425bb815Sopenharmony_ci  {
565425bb815Sopenharmony_ci    lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator);
566425bb815Sopenharmony_ci
567425bb815Sopenharmony_ci    JERRY_ASSERT (literal_p != NULL);
568425bb815Sopenharmony_ci
569425bb815Sopenharmony_ci    if (literal_p->prop.index == literal_index)
570425bb815Sopenharmony_ci    {
571425bb815Sopenharmony_ci      if (literal_index < ident_end)
572425bb815Sopenharmony_ci      {
573425bb815Sopenharmony_ci        JERRY_DEBUG_MSG (" ident:%d->", literal_index);
574425bb815Sopenharmony_ci      }
575425bb815Sopenharmony_ci      else
576425bb815Sopenharmony_ci      {
577425bb815Sopenharmony_ci        JERRY_DEBUG_MSG (" lit:%d->", literal_index);
578425bb815Sopenharmony_ci      }
579425bb815Sopenharmony_ci
580425bb815Sopenharmony_ci      util_print_literal (literal_p);
581425bb815Sopenharmony_ci      return;
582425bb815Sopenharmony_ci    }
583425bb815Sopenharmony_ci  }
584425bb815Sopenharmony_ci} /* parse_print_literal */
585425bb815Sopenharmony_ci
586425bb815Sopenharmony_ci#define PARSER_READ_IDENTIFIER_INDEX(name) \
587425bb815Sopenharmony_ci  name = *byte_code_p++; \
588425bb815Sopenharmony_ci  if (name >= encoding_limit) \
589425bb815Sopenharmony_ci  { \
590425bb815Sopenharmony_ci    name = (uint16_t) (((name << 8) | byte_code_p[0]) - encoding_delta); \
591425bb815Sopenharmony_ci    byte_code_p++; \
592425bb815Sopenharmony_ci  }
593425bb815Sopenharmony_ci
594425bb815Sopenharmony_ci/**
595425bb815Sopenharmony_ci * Print byte code.
596425bb815Sopenharmony_ci */
597425bb815Sopenharmony_cistatic void
598425bb815Sopenharmony_ciparse_print_final_cbc (ecma_compiled_code_t *compiled_code_p, /**< compiled code */
599425bb815Sopenharmony_ci                       parser_list_t *literal_pool_p, /**< literal pool */
600425bb815Sopenharmony_ci                       size_t length) /**< length of byte code */
601425bb815Sopenharmony_ci{
602425bb815Sopenharmony_ci  uint8_t flags;
603425bb815Sopenharmony_ci  uint8_t *byte_code_start_p;
604425bb815Sopenharmony_ci  uint8_t *byte_code_end_p;
605425bb815Sopenharmony_ci  uint8_t *byte_code_p;
606425bb815Sopenharmony_ci  uint16_t encoding_limit;
607425bb815Sopenharmony_ci  uint16_t encoding_delta;
608425bb815Sopenharmony_ci  uint16_t stack_limit;
609425bb815Sopenharmony_ci  uint16_t argument_end;
610425bb815Sopenharmony_ci  uint16_t register_end;
611425bb815Sopenharmony_ci  uint16_t ident_end;
612425bb815Sopenharmony_ci  uint16_t const_literal_end;
613425bb815Sopenharmony_ci  uint16_t literal_end;
614425bb815Sopenharmony_ci
615425bb815Sopenharmony_ci  if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
616425bb815Sopenharmony_ci  {
617425bb815Sopenharmony_ci    cbc_uint16_arguments_t *args = (cbc_uint16_arguments_t *) compiled_code_p;
618425bb815Sopenharmony_ci    stack_limit = args->stack_limit;
619425bb815Sopenharmony_ci    argument_end = args->argument_end;
620425bb815Sopenharmony_ci    register_end = args->register_end;
621425bb815Sopenharmony_ci    ident_end = args->ident_end;
622425bb815Sopenharmony_ci    const_literal_end = args->const_literal_end;
623425bb815Sopenharmony_ci    literal_end = args->literal_end;
624425bb815Sopenharmony_ci  }
625425bb815Sopenharmony_ci  else
626425bb815Sopenharmony_ci  {
627425bb815Sopenharmony_ci    cbc_uint8_arguments_t *args = (cbc_uint8_arguments_t *) compiled_code_p;
628425bb815Sopenharmony_ci    stack_limit = args->stack_limit;
629425bb815Sopenharmony_ci    argument_end = args->argument_end;
630425bb815Sopenharmony_ci    register_end = args->register_end;
631425bb815Sopenharmony_ci    ident_end = args->ident_end;
632425bb815Sopenharmony_ci    const_literal_end = args->const_literal_end;
633425bb815Sopenharmony_ci    literal_end = args->literal_end;
634425bb815Sopenharmony_ci  }
635425bb815Sopenharmony_ci
636425bb815Sopenharmony_ci  JERRY_DEBUG_MSG ("\nFinal byte code dump:\n\n  Maximum stack depth: %d\n  Flags: [",
637425bb815Sopenharmony_ci                   (int) (stack_limit + register_end));
638425bb815Sopenharmony_ci
639425bb815Sopenharmony_ci  if (!(compiled_code_p->status_flags & CBC_CODE_FLAGS_FULL_LITERAL_ENCODING))
640425bb815Sopenharmony_ci  {
641425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("small_lit_enc");
642425bb815Sopenharmony_ci    encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT;
643425bb815Sopenharmony_ci    encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA;
644425bb815Sopenharmony_ci  }
645425bb815Sopenharmony_ci  else
646425bb815Sopenharmony_ci  {
647425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("full_lit_enc");
648425bb815Sopenharmony_ci    encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT;
649425bb815Sopenharmony_ci    encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA;
650425bb815Sopenharmony_ci  }
651425bb815Sopenharmony_ci
652425bb815Sopenharmony_ci  if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
653425bb815Sopenharmony_ci  {
654425bb815Sopenharmony_ci    JERRY_DEBUG_MSG (",uint16_arguments");
655425bb815Sopenharmony_ci  }
656425bb815Sopenharmony_ci
657425bb815Sopenharmony_ci  if (compiled_code_p->status_flags & CBC_CODE_FLAGS_STRICT_MODE)
658425bb815Sopenharmony_ci  {
659425bb815Sopenharmony_ci    JERRY_DEBUG_MSG (",strict_mode");
660425bb815Sopenharmony_ci  }
661425bb815Sopenharmony_ci
662425bb815Sopenharmony_ci  if (compiled_code_p->status_flags & CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED)
663425bb815Sopenharmony_ci  {
664425bb815Sopenharmony_ci    JERRY_DEBUG_MSG (",mapped_arguments_needed");
665425bb815Sopenharmony_ci  }
666425bb815Sopenharmony_ci
667425bb815Sopenharmony_ci  if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UNMAPPED_ARGUMENTS_NEEDED)
668425bb815Sopenharmony_ci  {
669425bb815Sopenharmony_ci    JERRY_DEBUG_MSG (",unmapped_arguments_needed");
670425bb815Sopenharmony_ci  }
671425bb815Sopenharmony_ci
672425bb815Sopenharmony_ci  if (compiled_code_p->status_flags & CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED)
673425bb815Sopenharmony_ci  {
674425bb815Sopenharmony_ci    JERRY_DEBUG_MSG (",no_lexical_env");
675425bb815Sopenharmony_ci  }
676425bb815Sopenharmony_ci
677425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
678425bb815Sopenharmony_ci  if (compiled_code_p->status_flags & CBC_CODE_FLAGS_ARROW_FUNCTION)
679425bb815Sopenharmony_ci  {
680425bb815Sopenharmony_ci    JERRY_DEBUG_MSG (",arrow");
681425bb815Sopenharmony_ci  }
682425bb815Sopenharmony_ci
683425bb815Sopenharmony_ci  if (compiled_code_p->status_flags & CBC_CODE_FLAGS_CLASS_CONSTRUCTOR)
684425bb815Sopenharmony_ci  {
685425bb815Sopenharmony_ci    JERRY_DEBUG_MSG (",constructor");
686425bb815Sopenharmony_ci  }
687425bb815Sopenharmony_ci
688425bb815Sopenharmony_ci  if (compiled_code_p->status_flags & CBC_CODE_FLAGS_GENERATOR)
689425bb815Sopenharmony_ci  {
690425bb815Sopenharmony_ci    JERRY_DEBUG_MSG (",generator");
691425bb815Sopenharmony_ci  }
692425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
693425bb815Sopenharmony_ci
694425bb815Sopenharmony_ci  JERRY_DEBUG_MSG ("]\n");
695425bb815Sopenharmony_ci
696425bb815Sopenharmony_ci  JERRY_DEBUG_MSG ("  Argument range end: %d\n", (int) argument_end);
697425bb815Sopenharmony_ci  JERRY_DEBUG_MSG ("  Register range end: %d\n", (int) register_end);
698425bb815Sopenharmony_ci  JERRY_DEBUG_MSG ("  Identifier range end: %d\n", (int) ident_end);
699425bb815Sopenharmony_ci  JERRY_DEBUG_MSG ("  Const literal range end: %d\n", (int) const_literal_end);
700425bb815Sopenharmony_ci  JERRY_DEBUG_MSG ("  Literal range end: %d\n\n", (int) literal_end);
701425bb815Sopenharmony_ci
702425bb815Sopenharmony_ci  byte_code_start_p = (uint8_t *) compiled_code_p;
703425bb815Sopenharmony_ci
704425bb815Sopenharmony_ci  if (compiled_code_p->status_flags & CBC_CODE_FLAGS_UINT16_ARGUMENTS)
705425bb815Sopenharmony_ci  {
706425bb815Sopenharmony_ci    byte_code_start_p += sizeof (cbc_uint16_arguments_t);
707425bb815Sopenharmony_ci  }
708425bb815Sopenharmony_ci  else
709425bb815Sopenharmony_ci  {
710425bb815Sopenharmony_ci    byte_code_start_p += sizeof (cbc_uint8_arguments_t);
711425bb815Sopenharmony_ci  }
712425bb815Sopenharmony_ci
713425bb815Sopenharmony_ci  byte_code_start_p += (unsigned int) (literal_end - register_end) * sizeof (ecma_value_t);
714425bb815Sopenharmony_ci
715425bb815Sopenharmony_ci  byte_code_end_p = byte_code_start_p + length;
716425bb815Sopenharmony_ci  byte_code_p = byte_code_start_p;
717425bb815Sopenharmony_ci
718425bb815Sopenharmony_ci  while (byte_code_p < byte_code_end_p)
719425bb815Sopenharmony_ci  {
720425bb815Sopenharmony_ci    cbc_opcode_t opcode = (cbc_opcode_t) *byte_code_p;
721425bb815Sopenharmony_ci    cbc_ext_opcode_t ext_opcode = CBC_EXT_NOP;
722425bb815Sopenharmony_ci    size_t cbc_offset = (size_t) (byte_code_p - byte_code_start_p);
723425bb815Sopenharmony_ci
724425bb815Sopenharmony_ci    if (opcode != CBC_EXT_OPCODE)
725425bb815Sopenharmony_ci    {
726425bb815Sopenharmony_ci      flags = cbc_flags[opcode];
727425bb815Sopenharmony_ci      JERRY_DEBUG_MSG (" %3d : %s", (int) cbc_offset, cbc_names[opcode]);
728425bb815Sopenharmony_ci      byte_code_p++;
729425bb815Sopenharmony_ci    }
730425bb815Sopenharmony_ci    else
731425bb815Sopenharmony_ci    {
732425bb815Sopenharmony_ci      ext_opcode = (cbc_ext_opcode_t) byte_code_p[1];
733425bb815Sopenharmony_ci      flags = cbc_ext_flags[ext_opcode];
734425bb815Sopenharmony_ci      JERRY_DEBUG_MSG (" %3d : %s", (int) cbc_offset, cbc_ext_names[ext_opcode]);
735425bb815Sopenharmony_ci      byte_code_p += 2;
736425bb815Sopenharmony_ci
737425bb815Sopenharmony_ci#if ENABLED (JERRY_LINE_INFO)
738425bb815Sopenharmony_ci      if (ext_opcode == CBC_EXT_LINE)
739425bb815Sopenharmony_ci      {
740425bb815Sopenharmony_ci        uint32_t value = 0;
741425bb815Sopenharmony_ci        uint8_t byte;
742425bb815Sopenharmony_ci
743425bb815Sopenharmony_ci        do
744425bb815Sopenharmony_ci        {
745425bb815Sopenharmony_ci          byte = *byte_code_p++;
746425bb815Sopenharmony_ci          value = (value << 7) | (byte & CBC_LOWER_SEVEN_BIT_MASK);
747425bb815Sopenharmony_ci        }
748425bb815Sopenharmony_ci        while (byte & CBC_HIGHEST_BIT_MASK);
749425bb815Sopenharmony_ci
750425bb815Sopenharmony_ci        JERRY_DEBUG_MSG (" %d\n", (int) value);
751425bb815Sopenharmony_ci        continue;
752425bb815Sopenharmony_ci      }
753425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_LINE_INFO) */
754425bb815Sopenharmony_ci    }
755425bb815Sopenharmony_ci
756425bb815Sopenharmony_ci    if (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2))
757425bb815Sopenharmony_ci    {
758425bb815Sopenharmony_ci      uint16_t literal_index;
759425bb815Sopenharmony_ci
760425bb815Sopenharmony_ci      PARSER_READ_IDENTIFIER_INDEX (literal_index);
761425bb815Sopenharmony_ci      parse_print_literal (compiled_code_p, literal_index, literal_pool_p);
762425bb815Sopenharmony_ci    }
763425bb815Sopenharmony_ci
764425bb815Sopenharmony_ci    if (flags & CBC_HAS_LITERAL_ARG2)
765425bb815Sopenharmony_ci    {
766425bb815Sopenharmony_ci      uint16_t literal_index;
767425bb815Sopenharmony_ci
768425bb815Sopenharmony_ci      PARSER_READ_IDENTIFIER_INDEX (literal_index);
769425bb815Sopenharmony_ci      parse_print_literal (compiled_code_p, literal_index, literal_pool_p);
770425bb815Sopenharmony_ci
771425bb815Sopenharmony_ci      if (!(flags & CBC_HAS_LITERAL_ARG))
772425bb815Sopenharmony_ci      {
773425bb815Sopenharmony_ci        PARSER_READ_IDENTIFIER_INDEX (literal_index);
774425bb815Sopenharmony_ci        parse_print_literal (compiled_code_p, literal_index, literal_pool_p);
775425bb815Sopenharmony_ci      }
776425bb815Sopenharmony_ci    }
777425bb815Sopenharmony_ci
778425bb815Sopenharmony_ci    if (flags & CBC_HAS_BYTE_ARG)
779425bb815Sopenharmony_ci    {
780425bb815Sopenharmony_ci      if (opcode == CBC_PUSH_NUMBER_POS_BYTE
781425bb815Sopenharmony_ci          || ext_opcode == CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_POS_BYTE)
782425bb815Sopenharmony_ci      {
783425bb815Sopenharmony_ci        JERRY_DEBUG_MSG (" number:%d", (int) *byte_code_p + 1);
784425bb815Sopenharmony_ci      }
785425bb815Sopenharmony_ci      else if (opcode == CBC_PUSH_NUMBER_NEG_BYTE
786425bb815Sopenharmony_ci               || ext_opcode == CBC_EXT_PUSH_LITERAL_PUSH_NUMBER_NEG_BYTE)
787425bb815Sopenharmony_ci      {
788425bb815Sopenharmony_ci        JERRY_DEBUG_MSG (" number:%d", -((int) *byte_code_p + 1));
789425bb815Sopenharmony_ci      }
790425bb815Sopenharmony_ci      else
791425bb815Sopenharmony_ci      {
792425bb815Sopenharmony_ci        JERRY_DEBUG_MSG (" byte_arg:%d", *byte_code_p);
793425bb815Sopenharmony_ci      }
794425bb815Sopenharmony_ci      byte_code_p++;
795425bb815Sopenharmony_ci    }
796425bb815Sopenharmony_ci
797425bb815Sopenharmony_ci    if (flags & CBC_HAS_BRANCH_ARG)
798425bb815Sopenharmony_ci    {
799425bb815Sopenharmony_ci      size_t branch_offset_length = (opcode != CBC_EXT_OPCODE ? CBC_BRANCH_OFFSET_LENGTH (opcode)
800425bb815Sopenharmony_ci                                                              : CBC_BRANCH_OFFSET_LENGTH (ext_opcode));
801425bb815Sopenharmony_ci      size_t offset = 0;
802425bb815Sopenharmony_ci
803425bb815Sopenharmony_ci      do
804425bb815Sopenharmony_ci      {
805425bb815Sopenharmony_ci        offset = (offset << 8) | *byte_code_p++;
806425bb815Sopenharmony_ci      }
807425bb815Sopenharmony_ci      while (--branch_offset_length > 0);
808425bb815Sopenharmony_ci
809425bb815Sopenharmony_ci      JERRY_DEBUG_MSG (" offset:%d(->%d)",
810425bb815Sopenharmony_ci                       (int) offset,
811425bb815Sopenharmony_ci                       (int) (cbc_offset + (CBC_BRANCH_IS_FORWARD (flags) ? offset : -offset)));
812425bb815Sopenharmony_ci    }
813425bb815Sopenharmony_ci
814425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("\n");
815425bb815Sopenharmony_ci  }
816425bb815Sopenharmony_ci} /* parse_print_final_cbc */
817425bb815Sopenharmony_ci
818425bb815Sopenharmony_ci#undef PARSER_READ_IDENTIFIER_INDEX
819425bb815Sopenharmony_ci
820425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
821425bb815Sopenharmony_ci
822425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
823425bb815Sopenharmony_ci
824425bb815Sopenharmony_ci/**
825425bb815Sopenharmony_ci * Send current breakpoint list.
826425bb815Sopenharmony_ci */
827425bb815Sopenharmony_cistatic void
828425bb815Sopenharmony_ciparser_send_breakpoints (parser_context_t *context_p, /**< context */
829425bb815Sopenharmony_ci                         jerry_debugger_header_type_t type) /**< message type */
830425bb815Sopenharmony_ci{
831425bb815Sopenharmony_ci  JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
832425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->breakpoint_info_count > 0);
833425bb815Sopenharmony_ci
834425bb815Sopenharmony_ci  jerry_debugger_send_data (type,
835425bb815Sopenharmony_ci                            context_p->breakpoint_info,
836425bb815Sopenharmony_ci                            context_p->breakpoint_info_count * sizeof (parser_breakpoint_info_t));
837425bb815Sopenharmony_ci
838425bb815Sopenharmony_ci  context_p->breakpoint_info_count = 0;
839425bb815Sopenharmony_ci} /* parser_send_breakpoints */
840425bb815Sopenharmony_ci
841425bb815Sopenharmony_ci/**
842425bb815Sopenharmony_ci * Append a breakpoint info.
843425bb815Sopenharmony_ci */
844425bb815Sopenharmony_civoid
845425bb815Sopenharmony_ciparser_append_breakpoint_info (parser_context_t *context_p, /**< context */
846425bb815Sopenharmony_ci                               jerry_debugger_header_type_t type, /**< message type */
847425bb815Sopenharmony_ci                               uint32_t value) /**< line or offset of the breakpoint */
848425bb815Sopenharmony_ci{
849425bb815Sopenharmony_ci  JERRY_ASSERT (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED);
850425bb815Sopenharmony_ci
851425bb815Sopenharmony_ci  context_p->status_flags |= PARSER_DEBUGGER_BREAKPOINT_APPENDED;
852425bb815Sopenharmony_ci
853425bb815Sopenharmony_ci  if (context_p->breakpoint_info_count >= JERRY_DEBUGGER_SEND_MAX (parser_breakpoint_info_t))
854425bb815Sopenharmony_ci  {
855425bb815Sopenharmony_ci    parser_send_breakpoints (context_p, type);
856425bb815Sopenharmony_ci  }
857425bb815Sopenharmony_ci
858425bb815Sopenharmony_ci  context_p->breakpoint_info[context_p->breakpoint_info_count].value = value;
859425bb815Sopenharmony_ci  context_p->breakpoint_info_count = (uint16_t) (context_p->breakpoint_info_count + 1);
860425bb815Sopenharmony_ci} /* parser_append_breakpoint_info */
861425bb815Sopenharmony_ci
862425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
863425bb815Sopenharmony_ci
864425bb815Sopenharmony_ci/**
865425bb815Sopenharmony_ci * Forward iterator: move to the next byte code
866425bb815Sopenharmony_ci *
867425bb815Sopenharmony_ci * @param page_p page
868425bb815Sopenharmony_ci * @param offset offset
869425bb815Sopenharmony_ci */
870425bb815Sopenharmony_ci#define PARSER_NEXT_BYTE(page_p, offset) \
871425bb815Sopenharmony_ci  do { \
872425bb815Sopenharmony_ci    if (++(offset) >= PARSER_CBC_STREAM_PAGE_SIZE) \
873425bb815Sopenharmony_ci    { \
874425bb815Sopenharmony_ci      offset = 0; \
875425bb815Sopenharmony_ci      page_p = page_p->next_p; \
876425bb815Sopenharmony_ci    } \
877425bb815Sopenharmony_ci  } while (0)
878425bb815Sopenharmony_ci
879425bb815Sopenharmony_ci/**
880425bb815Sopenharmony_ci * Forward iterator: move to the next byte code. Also updates the offset of the previous byte code.
881425bb815Sopenharmony_ci *
882425bb815Sopenharmony_ci * @param page_p page
883425bb815Sopenharmony_ci * @param offset offset
884425bb815Sopenharmony_ci * @param real_offset real offset
885425bb815Sopenharmony_ci */
886425bb815Sopenharmony_ci#define PARSER_NEXT_BYTE_UPDATE(page_p, offset, real_offset) \
887425bb815Sopenharmony_ci  do { \
888425bb815Sopenharmony_ci    page_p->bytes[offset] = real_offset; \
889425bb815Sopenharmony_ci    if (++(offset) >= PARSER_CBC_STREAM_PAGE_SIZE) \
890425bb815Sopenharmony_ci    { \
891425bb815Sopenharmony_ci      offset = 0; \
892425bb815Sopenharmony_ci      real_offset = 0; \
893425bb815Sopenharmony_ci      page_p = page_p->next_p; \
894425bb815Sopenharmony_ci    } \
895425bb815Sopenharmony_ci  } while (0)
896425bb815Sopenharmony_ci
897425bb815Sopenharmony_ci/**
898425bb815Sopenharmony_ci * Post processing main function.
899425bb815Sopenharmony_ci *
900425bb815Sopenharmony_ci * @return compiled code
901425bb815Sopenharmony_ci */
902425bb815Sopenharmony_cistatic ecma_compiled_code_t *
903425bb815Sopenharmony_ciparser_post_processing (parser_context_t *context_p) /**< context */
904425bb815Sopenharmony_ci{
905425bb815Sopenharmony_ci  uint16_t literal_one_byte_limit;
906425bb815Sopenharmony_ci  uint16_t ident_end;
907425bb815Sopenharmony_ci  uint16_t const_literal_end;
908425bb815Sopenharmony_ci  parser_mem_page_t *page_p;
909425bb815Sopenharmony_ci  parser_mem_page_t *last_page_p;
910425bb815Sopenharmony_ci  size_t last_position;
911425bb815Sopenharmony_ci  size_t offset;
912425bb815Sopenharmony_ci  size_t length;
913425bb815Sopenharmony_ci  size_t literal_length;
914425bb815Sopenharmony_ci  size_t total_size;
915425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_SAVE)
916425bb815Sopenharmony_ci  size_t total_size_used;
917425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */
918425bb815Sopenharmony_ci  uint8_t real_offset;
919425bb815Sopenharmony_ci  uint8_t *byte_code_p;
920425bb815Sopenharmony_ci  bool needs_uint16_arguments;
921425bb815Sopenharmony_ci  cbc_opcode_t last_opcode = CBC_EXT_OPCODE;
922425bb815Sopenharmony_ci  ecma_compiled_code_t *compiled_code_p;
923425bb815Sopenharmony_ci  ecma_value_t *literal_pool_p;
924425bb815Sopenharmony_ci  uint8_t *dst_p;
925425bb815Sopenharmony_ci
926425bb815Sopenharmony_ci  CHECK_JERRY_STACK_USAGE(context_p);
927425bb815Sopenharmony_ci
928425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
929425bb815Sopenharmony_ci  if ((context_p->status_flags & (PARSER_IS_FUNCTION | PARSER_LEXICAL_BLOCK_NEEDED))
930425bb815Sopenharmony_ci      == (PARSER_IS_FUNCTION | PARSER_LEXICAL_BLOCK_NEEDED))
931425bb815Sopenharmony_ci  {
932425bb815Sopenharmony_ci    PARSER_MINUS_EQUAL_U16 (context_p->stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
933425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG
934425bb815Sopenharmony_ci    PARSER_MINUS_EQUAL_U16 (context_p->context_stack_depth, PARSER_BLOCK_CONTEXT_STACK_ALLOCATION);
935425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
936425bb815Sopenharmony_ci
937425bb815Sopenharmony_ci    context_p->status_flags &= (uint32_t) ~PARSER_LEXICAL_BLOCK_NEEDED;
938425bb815Sopenharmony_ci
939425bb815Sopenharmony_ci    parser_emit_cbc (context_p, CBC_CONTEXT_END);
940425bb815Sopenharmony_ci
941425bb815Sopenharmony_ci    parser_branch_t branch;
942425bb815Sopenharmony_ci    parser_stack_pop (context_p, &branch, sizeof (parser_branch_t));
943425bb815Sopenharmony_ci    parser_set_branch_to_current_position (context_p, &branch);
944425bb815Sopenharmony_ci  }
945425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
946425bb815Sopenharmony_ci
947425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->stack_depth == 0);
948425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG
949425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->context_stack_depth == 0);
950425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
951425bb815Sopenharmony_ci
952425bb815Sopenharmony_ci  if ((size_t) context_p->stack_limit + (size_t) context_p->register_count > PARSER_MAXIMUM_STACK_LIMIT)
953425bb815Sopenharmony_ci  {
954425bb815Sopenharmony_ci    parser_raise_error (context_p, PARSER_ERR_STACK_LIMIT_REACHED);
955425bb815Sopenharmony_ci  }
956425bb815Sopenharmony_ci
957425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->literal_count <= PARSER_MAXIMUM_NUMBER_OF_LITERALS);
958425bb815Sopenharmony_ci
959425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
960425bb815Sopenharmony_ci  if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
961425bb815Sopenharmony_ci      && !(context_p->status_flags & PARSER_DEBUGGER_BREAKPOINT_APPENDED))
962425bb815Sopenharmony_ci  {
963425bb815Sopenharmony_ci    /* Always provide at least one breakpoint. */
964425bb815Sopenharmony_ci    parser_emit_cbc (context_p, CBC_BREAKPOINT_DISABLED);
965425bb815Sopenharmony_ci    parser_flush_cbc (context_p);
966425bb815Sopenharmony_ci
967425bb815Sopenharmony_ci    parser_append_breakpoint_info (context_p, JERRY_DEBUGGER_BREAKPOINT_LIST, context_p->token.line);
968425bb815Sopenharmony_ci
969425bb815Sopenharmony_ci    context_p->last_breakpoint_line = context_p->token.line;
970425bb815Sopenharmony_ci  }
971425bb815Sopenharmony_ci
972425bb815Sopenharmony_ci  if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
973425bb815Sopenharmony_ci      && context_p->breakpoint_info_count > 0)
974425bb815Sopenharmony_ci  {
975425bb815Sopenharmony_ci    parser_send_breakpoints (context_p, JERRY_DEBUGGER_BREAKPOINT_LIST);
976425bb815Sopenharmony_ci    JERRY_ASSERT (context_p->breakpoint_info_count == 0);
977425bb815Sopenharmony_ci  }
978425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
979425bb815Sopenharmony_ci
980425bb815Sopenharmony_ci  parser_compute_indicies (context_p, &ident_end, &const_literal_end);
981425bb815Sopenharmony_ci
982425bb815Sopenharmony_ci  if (context_p->literal_count <= CBC_MAXIMUM_SMALL_VALUE)
983425bb815Sopenharmony_ci  {
984425bb815Sopenharmony_ci    literal_one_byte_limit = CBC_MAXIMUM_BYTE_VALUE - 1;
985425bb815Sopenharmony_ci  }
986425bb815Sopenharmony_ci  else
987425bb815Sopenharmony_ci  {
988425bb815Sopenharmony_ci    literal_one_byte_limit = CBC_LOWER_SEVEN_BIT_MASK;
989425bb815Sopenharmony_ci  }
990425bb815Sopenharmony_ci
991425bb815Sopenharmony_ci  last_page_p = context_p->byte_code.last_p;
992425bb815Sopenharmony_ci  last_position = context_p->byte_code.last_position;
993425bb815Sopenharmony_ci
994425bb815Sopenharmony_ci  if (last_position >= PARSER_CBC_STREAM_PAGE_SIZE)
995425bb815Sopenharmony_ci  {
996425bb815Sopenharmony_ci    last_page_p = NULL;
997425bb815Sopenharmony_ci    last_position = 0;
998425bb815Sopenharmony_ci  }
999425bb815Sopenharmony_ci
1000425bb815Sopenharmony_ci  page_p = context_p->byte_code.first_p;
1001425bb815Sopenharmony_ci  offset = 0;
1002425bb815Sopenharmony_ci  length = 0;
1003425bb815Sopenharmony_ci
1004425bb815Sopenharmony_ci  while (page_p != last_page_p || offset < last_position)
1005425bb815Sopenharmony_ci  {
1006425bb815Sopenharmony_ci    uint8_t *opcode_p;
1007425bb815Sopenharmony_ci    uint8_t flags;
1008425bb815Sopenharmony_ci    size_t branch_offset_length;
1009425bb815Sopenharmony_ci
1010425bb815Sopenharmony_ci    opcode_p = page_p->bytes + offset;
1011425bb815Sopenharmony_ci    last_opcode = (cbc_opcode_t) (*opcode_p);
1012425bb815Sopenharmony_ci    PARSER_NEXT_BYTE (page_p, offset);
1013425bb815Sopenharmony_ci    branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (last_opcode);
1014425bb815Sopenharmony_ci    flags = cbc_flags[last_opcode];
1015425bb815Sopenharmony_ci    length++;
1016425bb815Sopenharmony_ci
1017425bb815Sopenharmony_ci    if (last_opcode == CBC_EXT_OPCODE)
1018425bb815Sopenharmony_ci    {
1019425bb815Sopenharmony_ci      cbc_ext_opcode_t ext_opcode;
1020425bb815Sopenharmony_ci
1021425bb815Sopenharmony_ci      ext_opcode = (cbc_ext_opcode_t) page_p->bytes[offset];
1022425bb815Sopenharmony_ci      branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (ext_opcode);
1023425bb815Sopenharmony_ci      flags = cbc_ext_flags[ext_opcode];
1024425bb815Sopenharmony_ci      PARSER_NEXT_BYTE (page_p, offset);
1025425bb815Sopenharmony_ci      length++;
1026425bb815Sopenharmony_ci
1027425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1028425bb815Sopenharmony_ci      if (ext_opcode == CBC_EXT_RETURN_PROMISE
1029425bb815Sopenharmony_ci          || ext_opcode == CBC_EXT_RETURN_PROMISE_UNDEFINED)
1030425bb815Sopenharmony_ci      {
1031425bb815Sopenharmony_ci        last_opcode = CBC_RETURN;
1032425bb815Sopenharmony_ci      }
1033425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1034425bb815Sopenharmony_ci
1035425bb815Sopenharmony_ci#if ENABLED (JERRY_LINE_INFO)
1036425bb815Sopenharmony_ci      if (ext_opcode == CBC_EXT_LINE)
1037425bb815Sopenharmony_ci      {
1038425bb815Sopenharmony_ci        uint8_t last_byte = 0;
1039425bb815Sopenharmony_ci
1040425bb815Sopenharmony_ci        do
1041425bb815Sopenharmony_ci        {
1042425bb815Sopenharmony_ci          last_byte = page_p->bytes[offset];
1043425bb815Sopenharmony_ci          PARSER_NEXT_BYTE (page_p, offset);
1044425bb815Sopenharmony_ci          length++;
1045425bb815Sopenharmony_ci        }
1046425bb815Sopenharmony_ci        while (last_byte & CBC_HIGHEST_BIT_MASK);
1047425bb815Sopenharmony_ci
1048425bb815Sopenharmony_ci        continue;
1049425bb815Sopenharmony_ci      }
1050425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_LINE_INFO) */
1051425bb815Sopenharmony_ci    }
1052425bb815Sopenharmony_ci
1053425bb815Sopenharmony_ci    while (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2))
1054425bb815Sopenharmony_ci    {
1055425bb815Sopenharmony_ci      uint8_t *first_byte = page_p->bytes + offset;
1056425bb815Sopenharmony_ci      uint32_t literal_index = *first_byte;
1057425bb815Sopenharmony_ci
1058425bb815Sopenharmony_ci      PARSER_NEXT_BYTE (page_p, offset);
1059425bb815Sopenharmony_ci      length++;
1060425bb815Sopenharmony_ci
1061425bb815Sopenharmony_ci      literal_index |= ((uint32_t) page_p->bytes[offset]) << 8;
1062425bb815Sopenharmony_ci
1063425bb815Sopenharmony_ci      if (literal_index >= PARSER_REGISTER_START)
1064425bb815Sopenharmony_ci      {
1065425bb815Sopenharmony_ci        literal_index -= PARSER_REGISTER_START;
1066425bb815Sopenharmony_ci      }
1067425bb815Sopenharmony_ci      else
1068425bb815Sopenharmony_ci      {
1069425bb815Sopenharmony_ci        literal_index = (PARSER_GET_LITERAL (literal_index))->prop.index;
1070425bb815Sopenharmony_ci      }
1071425bb815Sopenharmony_ci
1072425bb815Sopenharmony_ci      if (literal_index <= literal_one_byte_limit)
1073425bb815Sopenharmony_ci      {
1074425bb815Sopenharmony_ci        *first_byte = (uint8_t) literal_index;
1075425bb815Sopenharmony_ci      }
1076425bb815Sopenharmony_ci      else
1077425bb815Sopenharmony_ci      {
1078425bb815Sopenharmony_ci        if (context_p->literal_count <= CBC_MAXIMUM_SMALL_VALUE)
1079425bb815Sopenharmony_ci        {
1080425bb815Sopenharmony_ci          JERRY_ASSERT (literal_index <= CBC_MAXIMUM_SMALL_VALUE);
1081425bb815Sopenharmony_ci          *first_byte = CBC_MAXIMUM_BYTE_VALUE;
1082425bb815Sopenharmony_ci          page_p->bytes[offset] = (uint8_t) (literal_index - CBC_MAXIMUM_BYTE_VALUE);
1083425bb815Sopenharmony_ci          length++;
1084425bb815Sopenharmony_ci        }
1085425bb815Sopenharmony_ci        else
1086425bb815Sopenharmony_ci        {
1087425bb815Sopenharmony_ci          JERRY_ASSERT (literal_index <= CBC_MAXIMUM_FULL_VALUE);
1088425bb815Sopenharmony_ci          *first_byte = (uint8_t) ((literal_index >> 8) | CBC_HIGHEST_BIT_MASK);
1089425bb815Sopenharmony_ci          page_p->bytes[offset] = (uint8_t) (literal_index & 0xff);
1090425bb815Sopenharmony_ci          length++;
1091425bb815Sopenharmony_ci        }
1092425bb815Sopenharmony_ci      }
1093425bb815Sopenharmony_ci      PARSER_NEXT_BYTE (page_p, offset);
1094425bb815Sopenharmony_ci
1095425bb815Sopenharmony_ci      if (flags & CBC_HAS_LITERAL_ARG2)
1096425bb815Sopenharmony_ci      {
1097425bb815Sopenharmony_ci        if (flags & CBC_HAS_LITERAL_ARG)
1098425bb815Sopenharmony_ci        {
1099425bb815Sopenharmony_ci          flags = CBC_HAS_LITERAL_ARG;
1100425bb815Sopenharmony_ci        }
1101425bb815Sopenharmony_ci        else
1102425bb815Sopenharmony_ci        {
1103425bb815Sopenharmony_ci          flags = CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2;
1104425bb815Sopenharmony_ci        }
1105425bb815Sopenharmony_ci      }
1106425bb815Sopenharmony_ci      else
1107425bb815Sopenharmony_ci      {
1108425bb815Sopenharmony_ci        break;
1109425bb815Sopenharmony_ci      }
1110425bb815Sopenharmony_ci    }
1111425bb815Sopenharmony_ci
1112425bb815Sopenharmony_ci    if (flags & CBC_HAS_BYTE_ARG)
1113425bb815Sopenharmony_ci    {
1114425bb815Sopenharmony_ci      /* This argument will be copied without modification. */
1115425bb815Sopenharmony_ci      PARSER_NEXT_BYTE (page_p, offset);
1116425bb815Sopenharmony_ci      length++;
1117425bb815Sopenharmony_ci    }
1118425bb815Sopenharmony_ci
1119425bb815Sopenharmony_ci    if (flags & CBC_HAS_BRANCH_ARG)
1120425bb815Sopenharmony_ci    {
1121425bb815Sopenharmony_ci      bool prefix_zero = true;
1122425bb815Sopenharmony_ci
1123425bb815Sopenharmony_ci      /* The leading zeroes are dropped from the stream.
1124425bb815Sopenharmony_ci       * Although dropping these zeroes for backward
1125425bb815Sopenharmony_ci       * branches are unnecessary, we use the same
1126425bb815Sopenharmony_ci       * code path for simplicity. */
1127425bb815Sopenharmony_ci      JERRY_ASSERT (branch_offset_length > 0 && branch_offset_length <= 3);
1128425bb815Sopenharmony_ci
1129425bb815Sopenharmony_ci      while (--branch_offset_length > 0)
1130425bb815Sopenharmony_ci      {
1131425bb815Sopenharmony_ci        uint8_t byte = page_p->bytes[offset];
1132425bb815Sopenharmony_ci        if (byte > 0 || !prefix_zero)
1133425bb815Sopenharmony_ci        {
1134425bb815Sopenharmony_ci          prefix_zero = false;
1135425bb815Sopenharmony_ci          length++;
1136425bb815Sopenharmony_ci        }
1137425bb815Sopenharmony_ci        else
1138425bb815Sopenharmony_ci        {
1139425bb815Sopenharmony_ci          JERRY_ASSERT (CBC_BRANCH_IS_FORWARD (flags));
1140425bb815Sopenharmony_ci        }
1141425bb815Sopenharmony_ci        PARSER_NEXT_BYTE (page_p, offset);
1142425bb815Sopenharmony_ci      }
1143425bb815Sopenharmony_ci
1144425bb815Sopenharmony_ci      if (last_opcode == (cbc_opcode_t) (CBC_JUMP_FORWARD + PARSER_MAX_BRANCH_LENGTH - 1)
1145425bb815Sopenharmony_ci          && prefix_zero
1146425bb815Sopenharmony_ci          && page_p->bytes[offset] == PARSER_MAX_BRANCH_LENGTH + 1)
1147425bb815Sopenharmony_ci      {
1148425bb815Sopenharmony_ci        /* Uncoditional jumps which jump right after the instruction
1149425bb815Sopenharmony_ci         * are effectively NOPs. These jumps are removed from the
1150425bb815Sopenharmony_ci         * stream. The 1 byte long CBC_JUMP_FORWARD form marks these
1151425bb815Sopenharmony_ci         * instructions, since this form is constructed during post
1152425bb815Sopenharmony_ci         * processing and cannot be emitted directly. */
1153425bb815Sopenharmony_ci        *opcode_p = CBC_JUMP_FORWARD;
1154425bb815Sopenharmony_ci        length--;
1155425bb815Sopenharmony_ci      }
1156425bb815Sopenharmony_ci      else
1157425bb815Sopenharmony_ci      {
1158425bb815Sopenharmony_ci        /* Other last bytes are always copied. */
1159425bb815Sopenharmony_ci        length++;
1160425bb815Sopenharmony_ci      }
1161425bb815Sopenharmony_ci
1162425bb815Sopenharmony_ci      PARSER_NEXT_BYTE (page_p, offset);
1163425bb815Sopenharmony_ci    }
1164425bb815Sopenharmony_ci  }
1165425bb815Sopenharmony_ci
1166425bb815Sopenharmony_ci  if (!(context_p->status_flags & PARSER_NO_END_LABEL)
1167425bb815Sopenharmony_ci      || !(PARSER_OPCODE_IS_RETURN (last_opcode)))
1168425bb815Sopenharmony_ci  {
1169425bb815Sopenharmony_ci    context_p->status_flags &= (uint32_t) ~PARSER_NO_END_LABEL;
1170425bb815Sopenharmony_ci
1171425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1172425bb815Sopenharmony_ci    if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION)
1173425bb815Sopenharmony_ci    {
1174425bb815Sopenharmony_ci      length++;
1175425bb815Sopenharmony_ci    }
1176425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1177425bb815Sopenharmony_ci
1178425bb815Sopenharmony_ci    length++;
1179425bb815Sopenharmony_ci  }
1180425bb815Sopenharmony_ci
1181425bb815Sopenharmony_ci  needs_uint16_arguments = false;
1182425bb815Sopenharmony_ci  total_size = sizeof (cbc_uint8_arguments_t);
1183425bb815Sopenharmony_ci
1184425bb815Sopenharmony_ci  if (context_p->stack_limit > CBC_MAXIMUM_BYTE_VALUE
1185425bb815Sopenharmony_ci      || context_p->register_count > CBC_MAXIMUM_BYTE_VALUE
1186425bb815Sopenharmony_ci      || context_p->literal_count > CBC_MAXIMUM_BYTE_VALUE)
1187425bb815Sopenharmony_ci  {
1188425bb815Sopenharmony_ci    needs_uint16_arguments = true;
1189425bb815Sopenharmony_ci    total_size = sizeof (cbc_uint16_arguments_t);
1190425bb815Sopenharmony_ci  }
1191425bb815Sopenharmony_ci
1192425bb815Sopenharmony_ci  literal_length = (size_t) (context_p->literal_count - context_p->register_count) * sizeof (ecma_value_t);
1193425bb815Sopenharmony_ci
1194425bb815Sopenharmony_ci  total_size += literal_length + length;
1195425bb815Sopenharmony_ci
1196425bb815Sopenharmony_ci  if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
1197425bb815Sopenharmony_ci  {
1198425bb815Sopenharmony_ci    total_size += context_p->argument_count * sizeof (ecma_value_t);
1199425bb815Sopenharmony_ci  }
1200425bb815Sopenharmony_ci
1201425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1202425bb815Sopenharmony_ci  if (context_p->tagged_template_literal_cp != JMEM_CP_NULL)
1203425bb815Sopenharmony_ci  {
1204425bb815Sopenharmony_ci    total_size += sizeof (ecma_value_t);
1205425bb815Sopenharmony_ci  }
1206425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1207425bb815Sopenharmony_ci
1208425bb815Sopenharmony_ci#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
1209425bb815Sopenharmony_ci  if (JERRY_CONTEXT (resource_name) != ECMA_VALUE_UNDEFINED)
1210425bb815Sopenharmony_ci  {
1211425bb815Sopenharmony_ci    total_size += sizeof (ecma_value_t);
1212425bb815Sopenharmony_ci  }
1213425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
1214425bb815Sopenharmony_ci
1215425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_SAVE)
1216425bb815Sopenharmony_ci  total_size_used = total_size;
1217425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */
1218425bb815Sopenharmony_ci  total_size = JERRY_ALIGNUP (total_size, JMEM_ALIGNMENT);
1219425bb815Sopenharmony_ci
1220425bb815Sopenharmony_ci  compiled_code_p = (ecma_compiled_code_t *) parser_malloc (context_p, total_size);
1221425bb815Sopenharmony_ci
1222425bb815Sopenharmony_ci#if ENABLED (JERRY_SNAPSHOT_SAVE)
1223425bb815Sopenharmony_ci  // Avoid getting junk bytes at the end when bytes at the end remain unused:
1224425bb815Sopenharmony_ci  if (total_size_used < total_size)
1225425bb815Sopenharmony_ci  {
1226425bb815Sopenharmony_ci    memset (((uint8_t *) compiled_code_p) + total_size_used, 0, total_size - total_size_used);
1227425bb815Sopenharmony_ci  }
1228425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_SNAPSHOT_SAVE) */
1229425bb815Sopenharmony_ci
1230425bb815Sopenharmony_ci#if ENABLED (JERRY_MEM_STATS)
1231425bb815Sopenharmony_ci  jmem_stats_allocate_byte_code_bytes (total_size);
1232425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_MEM_STATS) */
1233425bb815Sopenharmony_ci
1234425bb815Sopenharmony_ci  byte_code_p = (uint8_t *) compiled_code_p;
1235425bb815Sopenharmony_ci  compiled_code_p->size = (uint16_t) (total_size >> JMEM_ALIGNMENT_LOG);
1236425bb815Sopenharmony_ci  compiled_code_p->refs = 1;
1237425bb815Sopenharmony_ci  compiled_code_p->status_flags = CBC_CODE_FLAGS_FUNCTION;
1238425bb815Sopenharmony_ci
1239425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1240425bb815Sopenharmony_ci  if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
1241425bb815Sopenharmony_ci  {
1242425bb815Sopenharmony_ci    JERRY_ASSERT (context_p->argument_count > 0);
1243425bb815Sopenharmony_ci    context_p->argument_count--;
1244425bb815Sopenharmony_ci  }
1245425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1246425bb815Sopenharmony_ci
1247425bb815Sopenharmony_ci  if (needs_uint16_arguments)
1248425bb815Sopenharmony_ci  {
1249425bb815Sopenharmony_ci    cbc_uint16_arguments_t *args_p = (cbc_uint16_arguments_t *) compiled_code_p;
1250425bb815Sopenharmony_ci
1251425bb815Sopenharmony_ci    args_p->stack_limit = context_p->stack_limit;
1252425bb815Sopenharmony_ci    args_p->argument_end = context_p->argument_count;
1253425bb815Sopenharmony_ci    args_p->register_end = context_p->register_count;
1254425bb815Sopenharmony_ci    args_p->ident_end = ident_end;
1255425bb815Sopenharmony_ci    args_p->const_literal_end = const_literal_end;
1256425bb815Sopenharmony_ci    args_p->literal_end = context_p->literal_count;
1257425bb815Sopenharmony_ci
1258425bb815Sopenharmony_ci    compiled_code_p->status_flags |= CBC_CODE_FLAGS_UINT16_ARGUMENTS;
1259425bb815Sopenharmony_ci    byte_code_p += sizeof (cbc_uint16_arguments_t);
1260425bb815Sopenharmony_ci  }
1261425bb815Sopenharmony_ci  else
1262425bb815Sopenharmony_ci  {
1263425bb815Sopenharmony_ci    cbc_uint8_arguments_t *args_p = (cbc_uint8_arguments_t *) compiled_code_p;
1264425bb815Sopenharmony_ci
1265425bb815Sopenharmony_ci    args_p->stack_limit = (uint8_t) context_p->stack_limit;
1266425bb815Sopenharmony_ci    args_p->argument_end = (uint8_t) context_p->argument_count;
1267425bb815Sopenharmony_ci    args_p->register_end = (uint8_t) context_p->register_count;
1268425bb815Sopenharmony_ci    args_p->ident_end = (uint8_t) ident_end;
1269425bb815Sopenharmony_ci    args_p->const_literal_end = (uint8_t) const_literal_end;
1270425bb815Sopenharmony_ci    args_p->literal_end = (uint8_t) context_p->literal_count;
1271425bb815Sopenharmony_ci
1272425bb815Sopenharmony_ci    byte_code_p += sizeof (cbc_uint8_arguments_t);
1273425bb815Sopenharmony_ci  }
1274425bb815Sopenharmony_ci
1275425bb815Sopenharmony_ci  uint16_t encoding_limit;
1276425bb815Sopenharmony_ci  uint16_t encoding_delta;
1277425bb815Sopenharmony_ci
1278425bb815Sopenharmony_ci  if (context_p->literal_count > CBC_MAXIMUM_SMALL_VALUE)
1279425bb815Sopenharmony_ci  {
1280425bb815Sopenharmony_ci    compiled_code_p->status_flags |= CBC_CODE_FLAGS_FULL_LITERAL_ENCODING;
1281425bb815Sopenharmony_ci    encoding_limit = CBC_FULL_LITERAL_ENCODING_LIMIT;
1282425bb815Sopenharmony_ci    encoding_delta = CBC_FULL_LITERAL_ENCODING_DELTA;
1283425bb815Sopenharmony_ci  }
1284425bb815Sopenharmony_ci  else
1285425bb815Sopenharmony_ci  {
1286425bb815Sopenharmony_ci    encoding_limit = CBC_SMALL_LITERAL_ENCODING_LIMIT;
1287425bb815Sopenharmony_ci    encoding_delta = CBC_SMALL_LITERAL_ENCODING_DELTA;
1288425bb815Sopenharmony_ci  }
1289425bb815Sopenharmony_ci
1290425bb815Sopenharmony_ci  if (context_p->status_flags & PARSER_IS_STRICT)
1291425bb815Sopenharmony_ci  {
1292425bb815Sopenharmony_ci    compiled_code_p->status_flags |= CBC_CODE_FLAGS_STRICT_MODE;
1293425bb815Sopenharmony_ci  }
1294425bb815Sopenharmony_ci
1295425bb815Sopenharmony_ci  if (context_p->status_flags & PARSER_ARGUMENTS_NEEDED)
1296425bb815Sopenharmony_ci  {
1297425bb815Sopenharmony_ci    if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
1298425bb815Sopenharmony_ci    {
1299425bb815Sopenharmony_ci      compiled_code_p->status_flags |= CBC_CODE_FLAGS_MAPPED_ARGUMENTS_NEEDED;
1300425bb815Sopenharmony_ci    }
1301425bb815Sopenharmony_ci    else
1302425bb815Sopenharmony_ci    {
1303425bb815Sopenharmony_ci      compiled_code_p->status_flags |= CBC_CODE_FLAGS_UNMAPPED_ARGUMENTS_NEEDED;
1304425bb815Sopenharmony_ci    }
1305425bb815Sopenharmony_ci
1306425bb815Sopenharmony_ci    /* Arguments is stored in the lexical environment. */
1307425bb815Sopenharmony_ci    JERRY_ASSERT (context_p->status_flags & PARSER_LEXICAL_ENV_NEEDED);
1308425bb815Sopenharmony_ci  }
1309425bb815Sopenharmony_ci
1310425bb815Sopenharmony_ci  if (!(context_p->status_flags & PARSER_LEXICAL_ENV_NEEDED))
1311425bb815Sopenharmony_ci  {
1312425bb815Sopenharmony_ci    compiled_code_p->status_flags |= CBC_CODE_FLAGS_LEXICAL_ENV_NOT_NEEDED;
1313425bb815Sopenharmony_ci  }
1314425bb815Sopenharmony_ci
1315425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1316425bb815Sopenharmony_ci  if (context_p->status_flags & (PARSER_IS_PROPERTY_GETTER | PARSER_IS_PROPERTY_SETTER))
1317425bb815Sopenharmony_ci  {
1318425bb815Sopenharmony_ci    compiled_code_p->status_flags |= CBC_CODE_FLAGS_ACCESSOR;
1319425bb815Sopenharmony_ci  }
1320425bb815Sopenharmony_ci
1321425bb815Sopenharmony_ci  if (context_p->status_flags & PARSER_IS_ARROW_FUNCTION)
1322425bb815Sopenharmony_ci  {
1323425bb815Sopenharmony_ci    compiled_code_p->status_flags |= CBC_CODE_FLAGS_ARROW_FUNCTION;
1324425bb815Sopenharmony_ci  }
1325425bb815Sopenharmony_ci
1326425bb815Sopenharmony_ci  if (context_p->status_flags & PARSER_CLASS_CONSTRUCTOR)
1327425bb815Sopenharmony_ci  {
1328425bb815Sopenharmony_ci    compiled_code_p->status_flags |= CBC_CODE_FLAGS_CLASS_CONSTRUCTOR;
1329425bb815Sopenharmony_ci  }
1330425bb815Sopenharmony_ci
1331425bb815Sopenharmony_ci  if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)
1332425bb815Sopenharmony_ci  {
1333425bb815Sopenharmony_ci    compiled_code_p->status_flags |= CBC_CODE_FLAGS_GENERATOR;
1334425bb815Sopenharmony_ci  }
1335425bb815Sopenharmony_ci
1336425bb815Sopenharmony_ci  if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
1337425bb815Sopenharmony_ci  {
1338425bb815Sopenharmony_ci    compiled_code_p->status_flags |= CBC_CODE_FLAGS_REST_PARAMETER;
1339425bb815Sopenharmony_ci  }
1340425bb815Sopenharmony_ci
1341425bb815Sopenharmony_ci  if (context_p->tagged_template_literal_cp != JMEM_CP_NULL)
1342425bb815Sopenharmony_ci  {
1343425bb815Sopenharmony_ci    compiled_code_p->status_flags |= CBC_CODE_FLAG_HAS_TAGGED_LITERALS;
1344425bb815Sopenharmony_ci  }
1345425bb815Sopenharmony_ci
1346425bb815Sopenharmony_ci  if (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)
1347425bb815Sopenharmony_ci  {
1348425bb815Sopenharmony_ci    JERRY_ASSERT (!(context_p->status_flags & PARSER_IS_FUNCTION));
1349425bb815Sopenharmony_ci    compiled_code_p->status_flags |= CBC_CODE_FLAGS_LEXICAL_BLOCK_NEEDED;
1350425bb815Sopenharmony_ci  }
1351425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1352425bb815Sopenharmony_ci
1353425bb815Sopenharmony_ci  literal_pool_p = ((ecma_value_t *) byte_code_p) - context_p->register_count;
1354425bb815Sopenharmony_ci  byte_code_p += literal_length;
1355425bb815Sopenharmony_ci  dst_p = byte_code_p;
1356425bb815Sopenharmony_ci
1357425bb815Sopenharmony_ci  parser_init_literal_pool (context_p, literal_pool_p);
1358425bb815Sopenharmony_ci
1359425bb815Sopenharmony_ci  page_p = context_p->byte_code.first_p;
1360425bb815Sopenharmony_ci  offset = 0;
1361425bb815Sopenharmony_ci  real_offset = 0;
1362425bb815Sopenharmony_ci  uint8_t last_register_index = (uint8_t) JERRY_MIN (context_p->register_count,
1363425bb815Sopenharmony_ci                                                     (PARSER_MAXIMUM_NUMBER_OF_REGISTERS - 1));
1364425bb815Sopenharmony_ci
1365425bb815Sopenharmony_ci  while (page_p != last_page_p || offset < last_position)
1366425bb815Sopenharmony_ci  {
1367425bb815Sopenharmony_ci    uint8_t flags;
1368425bb815Sopenharmony_ci    uint8_t *opcode_p;
1369425bb815Sopenharmony_ci    uint8_t *branch_mark_p;
1370425bb815Sopenharmony_ci    cbc_opcode_t opcode;
1371425bb815Sopenharmony_ci    size_t branch_offset_length;
1372425bb815Sopenharmony_ci
1373425bb815Sopenharmony_ci    opcode_p = dst_p;
1374425bb815Sopenharmony_ci    branch_mark_p = page_p->bytes + offset;
1375425bb815Sopenharmony_ci    opcode = (cbc_opcode_t) (*branch_mark_p);
1376425bb815Sopenharmony_ci    branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (opcode);
1377425bb815Sopenharmony_ci
1378425bb815Sopenharmony_ci    if (opcode == CBC_JUMP_FORWARD)
1379425bb815Sopenharmony_ci    {
1380425bb815Sopenharmony_ci      /* These opcodes are deleted from the stream. */
1381425bb815Sopenharmony_ci      size_t counter = PARSER_MAX_BRANCH_LENGTH + 1;
1382425bb815Sopenharmony_ci
1383425bb815Sopenharmony_ci      do
1384425bb815Sopenharmony_ci      {
1385425bb815Sopenharmony_ci        PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1386425bb815Sopenharmony_ci      }
1387425bb815Sopenharmony_ci      while (--counter > 0);
1388425bb815Sopenharmony_ci
1389425bb815Sopenharmony_ci      continue;
1390425bb815Sopenharmony_ci    }
1391425bb815Sopenharmony_ci
1392425bb815Sopenharmony_ci    /* Storing the opcode */
1393425bb815Sopenharmony_ci    *dst_p++ = (uint8_t) opcode;
1394425bb815Sopenharmony_ci    real_offset++;
1395425bb815Sopenharmony_ci    PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1396425bb815Sopenharmony_ci    flags = cbc_flags[opcode];
1397425bb815Sopenharmony_ci
1398425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
1399425bb815Sopenharmony_ci    if (opcode == CBC_BREAKPOINT_DISABLED)
1400425bb815Sopenharmony_ci    {
1401425bb815Sopenharmony_ci      uint32_t bp_offset = (uint32_t) (((uint8_t *) dst_p) - ((uint8_t *) compiled_code_p) - 1);
1402425bb815Sopenharmony_ci      parser_append_breakpoint_info (context_p, JERRY_DEBUGGER_BREAKPOINT_OFFSET_LIST, bp_offset);
1403425bb815Sopenharmony_ci    }
1404425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
1405425bb815Sopenharmony_ci
1406425bb815Sopenharmony_ci    if (opcode == CBC_EXT_OPCODE)
1407425bb815Sopenharmony_ci    {
1408425bb815Sopenharmony_ci      cbc_ext_opcode_t ext_opcode;
1409425bb815Sopenharmony_ci
1410425bb815Sopenharmony_ci      ext_opcode = (cbc_ext_opcode_t) page_p->bytes[offset];
1411425bb815Sopenharmony_ci      flags = cbc_ext_flags[ext_opcode];
1412425bb815Sopenharmony_ci      branch_offset_length = CBC_BRANCH_OFFSET_LENGTH (ext_opcode);
1413425bb815Sopenharmony_ci
1414425bb815Sopenharmony_ci      /* Storing the extended opcode */
1415425bb815Sopenharmony_ci      *dst_p++ = (uint8_t) ext_opcode;
1416425bb815Sopenharmony_ci      opcode_p++;
1417425bb815Sopenharmony_ci      real_offset++;
1418425bb815Sopenharmony_ci      PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1419425bb815Sopenharmony_ci
1420425bb815Sopenharmony_ci#if ENABLED (JERRY_LINE_INFO)
1421425bb815Sopenharmony_ci      if (ext_opcode == CBC_EXT_LINE)
1422425bb815Sopenharmony_ci      {
1423425bb815Sopenharmony_ci        uint8_t last_byte = 0;
1424425bb815Sopenharmony_ci
1425425bb815Sopenharmony_ci        do
1426425bb815Sopenharmony_ci        {
1427425bb815Sopenharmony_ci          last_byte = page_p->bytes[offset];
1428425bb815Sopenharmony_ci          *dst_p++ = last_byte;
1429425bb815Sopenharmony_ci
1430425bb815Sopenharmony_ci          real_offset++;
1431425bb815Sopenharmony_ci          PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1432425bb815Sopenharmony_ci        }
1433425bb815Sopenharmony_ci        while (last_byte & CBC_HIGHEST_BIT_MASK);
1434425bb815Sopenharmony_ci
1435425bb815Sopenharmony_ci        continue;
1436425bb815Sopenharmony_ci      }
1437425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_LINE_INFO) */
1438425bb815Sopenharmony_ci    }
1439425bb815Sopenharmony_ci
1440425bb815Sopenharmony_ci    /* Only literal and call arguments can be combined. */
1441425bb815Sopenharmony_ci    JERRY_ASSERT (!(flags & CBC_HAS_BRANCH_ARG)
1442425bb815Sopenharmony_ci                   || !(flags & (CBC_HAS_BYTE_ARG | CBC_HAS_LITERAL_ARG)));
1443425bb815Sopenharmony_ci
1444425bb815Sopenharmony_ci    while (flags & (CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2))
1445425bb815Sopenharmony_ci    {
1446425bb815Sopenharmony_ci      uint16_t first_byte = page_p->bytes[offset];
1447425bb815Sopenharmony_ci
1448425bb815Sopenharmony_ci      uint8_t *opcode_pos_p = dst_p - 1;
1449425bb815Sopenharmony_ci      *dst_p++ = (uint8_t) first_byte;
1450425bb815Sopenharmony_ci      real_offset++;
1451425bb815Sopenharmony_ci      PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1452425bb815Sopenharmony_ci
1453425bb815Sopenharmony_ci      if (first_byte > literal_one_byte_limit)
1454425bb815Sopenharmony_ci      {
1455425bb815Sopenharmony_ci        *dst_p++ = page_p->bytes[offset];
1456425bb815Sopenharmony_ci
1457425bb815Sopenharmony_ci        if (first_byte > encoding_limit)
1458425bb815Sopenharmony_ci        {
1459425bb815Sopenharmony_ci          first_byte = (uint16_t) (((first_byte << 8) | dst_p[-1]) - encoding_delta);
1460425bb815Sopenharmony_ci        }
1461425bb815Sopenharmony_ci        real_offset++;
1462425bb815Sopenharmony_ci      }
1463425bb815Sopenharmony_ci      PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1464425bb815Sopenharmony_ci
1465425bb815Sopenharmony_ci      if (flags & CBC_HAS_LITERAL_ARG2)
1466425bb815Sopenharmony_ci      {
1467425bb815Sopenharmony_ci        if (flags & CBC_HAS_LITERAL_ARG)
1468425bb815Sopenharmony_ci        {
1469425bb815Sopenharmony_ci          flags = CBC_HAS_LITERAL_ARG;
1470425bb815Sopenharmony_ci        }
1471425bb815Sopenharmony_ci        else
1472425bb815Sopenharmony_ci        {
1473425bb815Sopenharmony_ci          flags = CBC_HAS_LITERAL_ARG | CBC_HAS_LITERAL_ARG2;
1474425bb815Sopenharmony_ci        }
1475425bb815Sopenharmony_ci      }
1476425bb815Sopenharmony_ci      else
1477425bb815Sopenharmony_ci      {
1478425bb815Sopenharmony_ci        if (opcode == CBC_ASSIGN_SET_IDENT && JERRY_LIKELY (first_byte < last_register_index))
1479425bb815Sopenharmony_ci        {
1480425bb815Sopenharmony_ci          *opcode_pos_p = CBC_MOV_IDENT;
1481425bb815Sopenharmony_ci        }
1482425bb815Sopenharmony_ci
1483425bb815Sopenharmony_ci        break;
1484425bb815Sopenharmony_ci      }
1485425bb815Sopenharmony_ci    }
1486425bb815Sopenharmony_ci
1487425bb815Sopenharmony_ci    if (flags & CBC_HAS_BYTE_ARG)
1488425bb815Sopenharmony_ci    {
1489425bb815Sopenharmony_ci      /* This argument will be copied without modification. */
1490425bb815Sopenharmony_ci      *dst_p++ = page_p->bytes[offset];
1491425bb815Sopenharmony_ci      real_offset++;
1492425bb815Sopenharmony_ci      PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1493425bb815Sopenharmony_ci      continue;
1494425bb815Sopenharmony_ci    }
1495425bb815Sopenharmony_ci
1496425bb815Sopenharmony_ci    if (flags & CBC_HAS_BRANCH_ARG)
1497425bb815Sopenharmony_ci    {
1498425bb815Sopenharmony_ci      *branch_mark_p |= CBC_HIGHEST_BIT_MASK;
1499425bb815Sopenharmony_ci      bool prefix_zero = true;
1500425bb815Sopenharmony_ci
1501425bb815Sopenharmony_ci      /* The leading zeroes are dropped from the stream. */
1502425bb815Sopenharmony_ci      JERRY_ASSERT (branch_offset_length > 0 && branch_offset_length <= 3);
1503425bb815Sopenharmony_ci
1504425bb815Sopenharmony_ci      while (--branch_offset_length > 0)
1505425bb815Sopenharmony_ci      {
1506425bb815Sopenharmony_ci        uint8_t byte = page_p->bytes[offset];
1507425bb815Sopenharmony_ci        if (byte > 0 || !prefix_zero)
1508425bb815Sopenharmony_ci        {
1509425bb815Sopenharmony_ci          prefix_zero = false;
1510425bb815Sopenharmony_ci          *dst_p++ = page_p->bytes[offset];
1511425bb815Sopenharmony_ci          real_offset++;
1512425bb815Sopenharmony_ci        }
1513425bb815Sopenharmony_ci        else
1514425bb815Sopenharmony_ci        {
1515425bb815Sopenharmony_ci          /* When a leading zero is dropped, the branch
1516425bb815Sopenharmony_ci           * offset length must be decreased as well. */
1517425bb815Sopenharmony_ci          (*opcode_p)--;
1518425bb815Sopenharmony_ci        }
1519425bb815Sopenharmony_ci        PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1520425bb815Sopenharmony_ci      }
1521425bb815Sopenharmony_ci
1522425bb815Sopenharmony_ci      *dst_p++ = page_p->bytes[offset];
1523425bb815Sopenharmony_ci      real_offset++;
1524425bb815Sopenharmony_ci      PARSER_NEXT_BYTE_UPDATE (page_p, offset, real_offset);
1525425bb815Sopenharmony_ci      continue;
1526425bb815Sopenharmony_ci    }
1527425bb815Sopenharmony_ci  }
1528425bb815Sopenharmony_ci
1529425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
1530425bb815Sopenharmony_ci  if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
1531425bb815Sopenharmony_ci      && context_p->breakpoint_info_count > 0)
1532425bb815Sopenharmony_ci  {
1533425bb815Sopenharmony_ci    parser_send_breakpoints (context_p, JERRY_DEBUGGER_BREAKPOINT_OFFSET_LIST);
1534425bb815Sopenharmony_ci    JERRY_ASSERT (context_p->breakpoint_info_count == 0);
1535425bb815Sopenharmony_ci  }
1536425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
1537425bb815Sopenharmony_ci
1538425bb815Sopenharmony_ci  if (!(context_p->status_flags & PARSER_NO_END_LABEL))
1539425bb815Sopenharmony_ci  {
1540425bb815Sopenharmony_ci    *dst_p++ = CBC_RETURN_WITH_BLOCK;
1541425bb815Sopenharmony_ci
1542425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1543425bb815Sopenharmony_ci    if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION)
1544425bb815Sopenharmony_ci    {
1545425bb815Sopenharmony_ci      dst_p[-1] = CBC_EXT_OPCODE;
1546425bb815Sopenharmony_ci      dst_p[0] = CBC_EXT_RETURN_PROMISE_UNDEFINED;
1547425bb815Sopenharmony_ci      dst_p++;
1548425bb815Sopenharmony_ci    }
1549425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1550425bb815Sopenharmony_ci  }
1551425bb815Sopenharmony_ci  JERRY_ASSERT (dst_p == byte_code_p + length);
1552425bb815Sopenharmony_ci
1553425bb815Sopenharmony_ci  parse_update_branches (context_p, byte_code_p);
1554425bb815Sopenharmony_ci
1555425bb815Sopenharmony_ci  parser_cbc_stream_free (&context_p->byte_code);
1556425bb815Sopenharmony_ci
1557425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
1558425bb815Sopenharmony_ci  if (context_p->is_show_opcodes)
1559425bb815Sopenharmony_ci  {
1560425bb815Sopenharmony_ci    parser_list_iterator_t literal_iterator;
1561425bb815Sopenharmony_ci    lexer_literal_t *literal_p;
1562425bb815Sopenharmony_ci
1563425bb815Sopenharmony_ci    parse_print_final_cbc (compiled_code_p, &context_p->literal_pool, length);
1564425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("\nByte code size: %d bytes\n", (int) length);
1565425bb815Sopenharmony_ci    context_p->total_byte_code_size += (uint32_t) length;
1566425bb815Sopenharmony_ci
1567425bb815Sopenharmony_ci    parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
1568425bb815Sopenharmony_ci    while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)))
1569425bb815Sopenharmony_ci    {
1570425bb815Sopenharmony_ci      if ((literal_p->type == LEXER_IDENT_LITERAL || literal_p->type == LEXER_STRING_LITERAL)
1571425bb815Sopenharmony_ci          && !(literal_p->status_flags & LEXER_FLAG_SOURCE_PTR))
1572425bb815Sopenharmony_ci      {
1573425bb815Sopenharmony_ci        jmem_heap_free_block ((void *) literal_p->u.char_p, literal_p->prop.length);
1574425bb815Sopenharmony_ci      }
1575425bb815Sopenharmony_ci    }
1576425bb815Sopenharmony_ci  }
1577425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
1578425bb815Sopenharmony_ci  if (context_p->status_flags & PARSER_HAS_LATE_LIT_INIT)
1579425bb815Sopenharmony_ci  {
1580425bb815Sopenharmony_ci    parser_list_iterator_t literal_iterator;
1581425bb815Sopenharmony_ci    lexer_literal_t *literal_p;
1582425bb815Sopenharmony_ci    uint16_t register_count = context_p->register_count;
1583425bb815Sopenharmony_ci
1584425bb815Sopenharmony_ci    parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
1585425bb815Sopenharmony_ci    while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)))
1586425bb815Sopenharmony_ci    {
1587425bb815Sopenharmony_ci      if ((literal_p->status_flags & LEXER_FLAG_LATE_INIT)
1588425bb815Sopenharmony_ci          && literal_p->prop.index >= register_count)
1589425bb815Sopenharmony_ci      {
1590425bb815Sopenharmony_ci        uint32_t source_data = literal_p->u.source_data;
1591425bb815Sopenharmony_ci        const uint8_t *char_p = context_p->source_end_p - (source_data & 0xfffff);
1592425bb815Sopenharmony_ci        ecma_value_t lit_value = ecma_find_or_create_literal_string (char_p,
1593425bb815Sopenharmony_ci                                                                     source_data >> 20);
1594425bb815Sopenharmony_ci        literal_pool_p[literal_p->prop.index] = lit_value;
1595425bb815Sopenharmony_ci      }
1596425bb815Sopenharmony_ci    }
1597425bb815Sopenharmony_ci  }
1598425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
1599425bb815Sopenharmony_ci
1600425bb815Sopenharmony_ci  if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
1601425bb815Sopenharmony_ci  {
1602425bb815Sopenharmony_ci    parser_list_iterator_t literal_iterator;
1603425bb815Sopenharmony_ci    uint16_t argument_count = 0;
1604425bb815Sopenharmony_ci    uint16_t register_count = context_p->register_count;
1605425bb815Sopenharmony_ci    ecma_value_t *argument_base_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size);
1606425bb815Sopenharmony_ci    argument_base_p -= context_p->argument_count;
1607425bb815Sopenharmony_ci
1608425bb815Sopenharmony_ci    parser_list_iterator_init (&context_p->literal_pool, &literal_iterator);
1609425bb815Sopenharmony_ci    while (argument_count < context_p->argument_count)
1610425bb815Sopenharmony_ci    {
1611425bb815Sopenharmony_ci      lexer_literal_t *literal_p;
1612425bb815Sopenharmony_ci      literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator);
1613425bb815Sopenharmony_ci
1614425bb815Sopenharmony_ci      JERRY_ASSERT (literal_p != NULL);
1615425bb815Sopenharmony_ci
1616425bb815Sopenharmony_ci      if (!(literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT))
1617425bb815Sopenharmony_ci      {
1618425bb815Sopenharmony_ci        continue;
1619425bb815Sopenharmony_ci      }
1620425bb815Sopenharmony_ci
1621425bb815Sopenharmony_ci      /* All arguments must be moved to initialized registers. */
1622425bb815Sopenharmony_ci      if (literal_p->type == LEXER_UNUSED_LITERAL)
1623425bb815Sopenharmony_ci      {
1624425bb815Sopenharmony_ci        argument_base_p[argument_count] = ECMA_VALUE_EMPTY;
1625425bb815Sopenharmony_ci        argument_count++;
1626425bb815Sopenharmony_ci        continue;
1627425bb815Sopenharmony_ci      }
1628425bb815Sopenharmony_ci
1629425bb815Sopenharmony_ci      JERRY_ASSERT (literal_p->type == LEXER_IDENT_LITERAL);
1630425bb815Sopenharmony_ci
1631425bb815Sopenharmony_ci      JERRY_ASSERT (literal_p->prop.index >= register_count);
1632425bb815Sopenharmony_ci
1633425bb815Sopenharmony_ci      argument_base_p[argument_count] = literal_pool_p[literal_p->prop.index];
1634425bb815Sopenharmony_ci      argument_count++;
1635425bb815Sopenharmony_ci    }
1636425bb815Sopenharmony_ci  }
1637425bb815Sopenharmony_ci
1638425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1639425bb815Sopenharmony_ci  if (context_p->tagged_template_literal_cp != JMEM_CP_NULL)
1640425bb815Sopenharmony_ci  {
1641425bb815Sopenharmony_ci    ecma_value_t *tagged_base_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size);
1642425bb815Sopenharmony_ci
1643425bb815Sopenharmony_ci    if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
1644425bb815Sopenharmony_ci    {
1645425bb815Sopenharmony_ci      tagged_base_p -= context_p->argument_count;
1646425bb815Sopenharmony_ci    }
1647425bb815Sopenharmony_ci
1648425bb815Sopenharmony_ci    tagged_base_p[-1] = (ecma_value_t) context_p->tagged_template_literal_cp;
1649425bb815Sopenharmony_ci
1650425bb815Sopenharmony_ci    ecma_collection_t *collection_p = ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
1651425bb815Sopenharmony_ci                                                                       context_p->tagged_template_literal_cp);
1652425bb815Sopenharmony_ci
1653425bb815Sopenharmony_ci    for (uint32_t i = 0; i < collection_p->item_count; i++)
1654425bb815Sopenharmony_ci    {
1655425bb815Sopenharmony_ci      ecma_free_value (collection_p->buffer_p[i]);
1656425bb815Sopenharmony_ci    }
1657425bb815Sopenharmony_ci  }
1658425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1659425bb815Sopenharmony_ci
1660425bb815Sopenharmony_ci#if ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM)
1661425bb815Sopenharmony_ci  if (JERRY_CONTEXT (resource_name) != ECMA_VALUE_UNDEFINED)
1662425bb815Sopenharmony_ci  {
1663425bb815Sopenharmony_ci    ecma_value_t *resource_name_p = (ecma_value_t *) (((uint8_t *) compiled_code_p) + total_size);
1664425bb815Sopenharmony_ci
1665425bb815Sopenharmony_ci    if (PARSER_NEEDS_MAPPED_ARGUMENTS (context_p->status_flags))
1666425bb815Sopenharmony_ci    {
1667425bb815Sopenharmony_ci      resource_name_p -= context_p->argument_count;
1668425bb815Sopenharmony_ci    }
1669425bb815Sopenharmony_ci
1670425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1671425bb815Sopenharmony_ci    if (context_p->tagged_template_literal_cp != JMEM_CP_NULL)
1672425bb815Sopenharmony_ci    {
1673425bb815Sopenharmony_ci      resource_name_p--;
1674425bb815Sopenharmony_ci    }
1675425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1676425bb815Sopenharmony_ci
1677425bb815Sopenharmony_ci    resource_name_p[-1] = JERRY_CONTEXT (resource_name);
1678425bb815Sopenharmony_ci  }
1679425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_LINE_INFO) || ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
1680425bb815Sopenharmony_ci
1681425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
1682425bb815Sopenharmony_ci  if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
1683425bb815Sopenharmony_ci  {
1684425bb815Sopenharmony_ci    jerry_debugger_send_function_cp (JERRY_DEBUGGER_BYTE_CODE_CP, compiled_code_p);
1685425bb815Sopenharmony_ci  }
1686425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
1687425bb815Sopenharmony_ci
1688425bb815Sopenharmony_ci  return compiled_code_p;
1689425bb815Sopenharmony_ci} /* parser_post_processing */
1690425bb815Sopenharmony_ci
1691425bb815Sopenharmony_ci#undef PARSER_NEXT_BYTE
1692425bb815Sopenharmony_ci#undef PARSER_NEXT_BYTE_UPDATE
1693425bb815Sopenharmony_ci
1694425bb815Sopenharmony_ci/**
1695425bb815Sopenharmony_ci * Free identifiers and literals.
1696425bb815Sopenharmony_ci */
1697425bb815Sopenharmony_cistatic void
1698425bb815Sopenharmony_ciparser_free_literals (parser_list_t *literal_pool_p) /**< literals */
1699425bb815Sopenharmony_ci{
1700425bb815Sopenharmony_ci  parser_list_iterator_t literal_iterator;
1701425bb815Sopenharmony_ci  lexer_literal_t *literal_p;
1702425bb815Sopenharmony_ci
1703425bb815Sopenharmony_ci  parser_list_iterator_init (literal_pool_p, &literal_iterator);
1704425bb815Sopenharmony_ci  while ((literal_p = (lexer_literal_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1705425bb815Sopenharmony_ci  {
1706425bb815Sopenharmony_ci    util_free_literal (literal_p);
1707425bb815Sopenharmony_ci  }
1708425bb815Sopenharmony_ci
1709425bb815Sopenharmony_ci  parser_list_free (literal_pool_p);
1710425bb815Sopenharmony_ci} /* parser_free_literals */
1711425bb815Sopenharmony_ci
1712425bb815Sopenharmony_ci/**
1713425bb815Sopenharmony_ci * Parse function arguments
1714425bb815Sopenharmony_ci */
1715425bb815Sopenharmony_cistatic void
1716425bb815Sopenharmony_ciparser_parse_function_arguments (parser_context_t *context_p, /**< context */
1717425bb815Sopenharmony_ci                                 lexer_token_type_t end_type) /**< expected end type */
1718425bb815Sopenharmony_ci{
1719425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
1720425bb815Sopenharmony_ci
1721425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1722425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->status_flags & PARSER_IS_FUNCTION);
1723425bb815Sopenharmony_ci  JERRY_ASSERT (!(context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED));
1724425bb815Sopenharmony_ci
1725425bb815Sopenharmony_ci  bool has_duplicated_arg_names = false;
1726425bb815Sopenharmony_ci
1727425bb815Sopenharmony_ci  /* TODO: Currently async iterators are not supported, so generators ignore the async modifier. */
1728425bb815Sopenharmony_ci  uint32_t mask = (PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION);
1729425bb815Sopenharmony_ci  if ((context_p->status_flags & mask) == mask)
1730425bb815Sopenharmony_ci  {
1731425bb815Sopenharmony_ci    context_p->status_flags &= (uint32_t) ~PARSER_IS_ASYNC_FUNCTION;
1732425bb815Sopenharmony_ci  }
1733425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1734425bb815Sopenharmony_ci
1735425bb815Sopenharmony_ci  if (context_p->token.type == end_type)
1736425bb815Sopenharmony_ci  {
1737425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1738425bb815Sopenharmony_ci    if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)
1739425bb815Sopenharmony_ci    {
1740425bb815Sopenharmony_ci      parser_emit_cbc_ext (context_p, CBC_EXT_CREATE_GENERATOR);
1741425bb815Sopenharmony_ci      parser_emit_cbc (context_p, CBC_POP);
1742425bb815Sopenharmony_ci    }
1743425bb815Sopenharmony_ci
1744425bb815Sopenharmony_ci    context_p->status_flags &= (uint32_t) ~PARSER_DISALLOW_AWAIT_YIELD;
1745425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1746425bb815Sopenharmony_ci    scanner_create_variables (context_p, SCANNER_CREATE_VARS_NO_OPTS);
1747425bb815Sopenharmony_ci    return;
1748425bb815Sopenharmony_ci  }
1749425bb815Sopenharmony_ci
1750425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1751425bb815Sopenharmony_ci  bool has_mapped_arguments = (context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_MAPPED_ARGUMENTS) != 0;
1752425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1753425bb815Sopenharmony_ci
1754425bb815Sopenharmony_ci  scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_ARGS);
1755425bb815Sopenharmony_ci  scanner_set_active (context_p);
1756425bb815Sopenharmony_ci
1757425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1758425bb815Sopenharmony_ci  context_p->status_flags |= PARSER_FUNCTION_IS_PARSING_ARGS;
1759425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1760425bb815Sopenharmony_ci
1761425bb815Sopenharmony_ci  while (true)
1762425bb815Sopenharmony_ci  {
1763425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1764425bb815Sopenharmony_ci    if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
1765425bb815Sopenharmony_ci    {
1766425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_FORMAL_PARAM_AFTER_REST_PARAMETER);
1767425bb815Sopenharmony_ci    }
1768425bb815Sopenharmony_ci    else if (context_p->token.type == LEXER_THREE_DOTS)
1769425bb815Sopenharmony_ci    {
1770425bb815Sopenharmony_ci      if (context_p->status_flags & PARSER_IS_PROPERTY_SETTER)
1771425bb815Sopenharmony_ci      {
1772425bb815Sopenharmony_ci        parser_raise_error (context_p, PARSER_ERR_SETTER_REST_PARAMETER);
1773425bb815Sopenharmony_ci      }
1774425bb815Sopenharmony_ci      lexer_next_token (context_p);
1775425bb815Sopenharmony_ci
1776425bb815Sopenharmony_ci      if (has_duplicated_arg_names)
1777425bb815Sopenharmony_ci      {
1778425bb815Sopenharmony_ci        parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
1779425bb815Sopenharmony_ci      }
1780425bb815Sopenharmony_ci
1781425bb815Sopenharmony_ci      context_p->status_flags |= PARSER_FUNCTION_HAS_REST_PARAM | PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM;
1782425bb815Sopenharmony_ci    }
1783425bb815Sopenharmony_ci
1784425bb815Sopenharmony_ci    if (context_p->token.type == LEXER_LEFT_SQUARE || context_p->token.type == LEXER_LEFT_BRACE)
1785425bb815Sopenharmony_ci    {
1786425bb815Sopenharmony_ci      if (has_duplicated_arg_names)
1787425bb815Sopenharmony_ci      {
1788425bb815Sopenharmony_ci        parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
1789425bb815Sopenharmony_ci      }
1790425bb815Sopenharmony_ci
1791425bb815Sopenharmony_ci      context_p->status_flags |= PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM;
1792425bb815Sopenharmony_ci
1793425bb815Sopenharmony_ci      parser_emit_cbc_literal (context_p,
1794425bb815Sopenharmony_ci                               CBC_PUSH_LITERAL,
1795425bb815Sopenharmony_ci                               (uint16_t) (PARSER_REGISTER_START + context_p->argument_count));
1796425bb815Sopenharmony_ci
1797425bb815Sopenharmony_ci      uint32_t flags = (PARSER_PATTERN_BINDING
1798425bb815Sopenharmony_ci                        | PARSER_PATTERN_TARGET_ON_STACK
1799425bb815Sopenharmony_ci                        | PARSER_PATTERN_LOCAL
1800425bb815Sopenharmony_ci                        | PARSER_PATTERN_ARGUMENTS);
1801425bb815Sopenharmony_ci
1802425bb815Sopenharmony_ci      if (context_p->next_scanner_info_p->source_p == context_p->source_p)
1803425bb815Sopenharmony_ci      {
1804425bb815Sopenharmony_ci        JERRY_ASSERT (context_p->next_scanner_info_p->type == SCANNER_TYPE_INITIALIZER);
1805425bb815Sopenharmony_ci
1806425bb815Sopenharmony_ci        if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
1807425bb815Sopenharmony_ci        {
1808425bb815Sopenharmony_ci          parser_raise_error (context_p, PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER);
1809425bb815Sopenharmony_ci        }
1810425bb815Sopenharmony_ci
1811425bb815Sopenharmony_ci        flags |= PARSER_PATTERN_TARGET_DEFAULT;
1812425bb815Sopenharmony_ci      }
1813425bb815Sopenharmony_ci
1814425bb815Sopenharmony_ci      parser_parse_initializer (context_p, flags);
1815425bb815Sopenharmony_ci
1816425bb815Sopenharmony_ci      context_p->argument_count++;
1817425bb815Sopenharmony_ci      if (context_p->argument_count >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
1818425bb815Sopenharmony_ci      {
1819425bb815Sopenharmony_ci        parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED);
1820425bb815Sopenharmony_ci      }
1821425bb815Sopenharmony_ci
1822425bb815Sopenharmony_ci      if (context_p->token.type != LEXER_COMMA)
1823425bb815Sopenharmony_ci      {
1824425bb815Sopenharmony_ci        break;
1825425bb815Sopenharmony_ci      }
1826425bb815Sopenharmony_ci
1827425bb815Sopenharmony_ci      lexer_next_token (context_p);
1828425bb815Sopenharmony_ci      continue;
1829425bb815Sopenharmony_ci    }
1830425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1831425bb815Sopenharmony_ci
1832425bb815Sopenharmony_ci    if (context_p->token.type != LEXER_LITERAL
1833425bb815Sopenharmony_ci        || context_p->token.lit_location.type != LEXER_IDENT_LITERAL)
1834425bb815Sopenharmony_ci    {
1835425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_IDENTIFIER_EXPECTED);
1836425bb815Sopenharmony_ci    }
1837425bb815Sopenharmony_ci
1838425bb815Sopenharmony_ci    lexer_construct_literal_object (context_p,
1839425bb815Sopenharmony_ci                                    &context_p->token.lit_location,
1840425bb815Sopenharmony_ci                                    LEXER_IDENT_LITERAL);
1841425bb815Sopenharmony_ci
1842425bb815Sopenharmony_ci    if (context_p->token.keyword_type >= LEXER_FIRST_NON_STRICT_ARGUMENTS)
1843425bb815Sopenharmony_ci    {
1844425bb815Sopenharmony_ci      context_p->status_flags |= PARSER_HAS_NON_STRICT_ARG;
1845425bb815Sopenharmony_ci    }
1846425bb815Sopenharmony_ci
1847425bb815Sopenharmony_ci    CHECK_JERRY_STACK_USAGE(context_p);
1848425bb815Sopenharmony_ci
1849425bb815Sopenharmony_ci    if (JERRY_UNLIKELY (context_p->lit_object.literal_p->status_flags & LEXER_FLAG_FUNCTION_ARGUMENT))
1850425bb815Sopenharmony_ci    {
1851425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1852425bb815Sopenharmony_ci      if ((context_p->status_flags & PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM)
1853425bb815Sopenharmony_ci          || (context_p->status_flags & PARSER_IS_ARROW_FUNCTION))
1854425bb815Sopenharmony_ci      {
1855425bb815Sopenharmony_ci        parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
1856425bb815Sopenharmony_ci      }
1857425bb815Sopenharmony_ci      has_duplicated_arg_names = true;
1858425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1859425bb815Sopenharmony_ci
1860425bb815Sopenharmony_ci      context_p->status_flags |= PARSER_HAS_NON_STRICT_ARG;
1861425bb815Sopenharmony_ci    }
1862425bb815Sopenharmony_ci    else
1863425bb815Sopenharmony_ci    {
1864425bb815Sopenharmony_ci      context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_FUNCTION_ARGUMENT;
1865425bb815Sopenharmony_ci    }
1866425bb815Sopenharmony_ci
1867425bb815Sopenharmony_ci    lexer_next_token (context_p);
1868425bb815Sopenharmony_ci
1869425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1870425bb815Sopenharmony_ci    uint16_t literal_index = context_p->lit_object.index;
1871425bb815Sopenharmony_ci
1872425bb815Sopenharmony_ci    if (context_p->token.type == LEXER_ASSIGN)
1873425bb815Sopenharmony_ci    {
1874425bb815Sopenharmony_ci      JERRY_ASSERT (!has_mapped_arguments);
1875425bb815Sopenharmony_ci
1876425bb815Sopenharmony_ci      if (context_p->status_flags & PARSER_FUNCTION_HAS_REST_PARAM)
1877425bb815Sopenharmony_ci      {
1878425bb815Sopenharmony_ci        parser_raise_error (context_p, PARSER_ERR_REST_PARAMETER_DEFAULT_INITIALIZER);
1879425bb815Sopenharmony_ci      }
1880425bb815Sopenharmony_ci
1881425bb815Sopenharmony_ci      parser_branch_t skip_init;
1882425bb815Sopenharmony_ci
1883425bb815Sopenharmony_ci      if (has_duplicated_arg_names)
1884425bb815Sopenharmony_ci      {
1885425bb815Sopenharmony_ci        parser_raise_error (context_p, PARSER_ERR_DUPLICATED_ARGUMENT_NAMES);
1886425bb815Sopenharmony_ci      }
1887425bb815Sopenharmony_ci
1888425bb815Sopenharmony_ci      context_p->status_flags |= PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM;
1889425bb815Sopenharmony_ci
1890425bb815Sopenharmony_ci      /* LEXER_ASSIGN does not overwrite lit_object. */
1891425bb815Sopenharmony_ci      parser_emit_cbc_literal (context_p,
1892425bb815Sopenharmony_ci                               CBC_PUSH_LITERAL,
1893425bb815Sopenharmony_ci                               (uint16_t) (PARSER_REGISTER_START + context_p->argument_count));
1894425bb815Sopenharmony_ci      parser_emit_cbc_ext_forward_branch (context_p, CBC_EXT_DEFAULT_INITIALIZER, &skip_init);
1895425bb815Sopenharmony_ci
1896425bb815Sopenharmony_ci      lexer_next_token (context_p);
1897425bb815Sopenharmony_ci      parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
1898425bb815Sopenharmony_ci
1899425bb815Sopenharmony_ci      parser_set_branch_to_current_position (context_p, &skip_init);
1900425bb815Sopenharmony_ci
1901425bb815Sopenharmony_ci      uint16_t opcode = CBC_ASSIGN_LET_CONST;
1902425bb815Sopenharmony_ci
1903425bb815Sopenharmony_ci      if (literal_index >= PARSER_REGISTER_START)
1904425bb815Sopenharmony_ci      {
1905425bb815Sopenharmony_ci        opcode = CBC_ASSIGN_SET_IDENT;
1906425bb815Sopenharmony_ci      }
1907425bb815Sopenharmony_ci      else if (!scanner_literal_is_created (context_p, literal_index))
1908425bb815Sopenharmony_ci      {
1909425bb815Sopenharmony_ci        opcode = CBC_INIT_ARG_OR_CATCH;
1910425bb815Sopenharmony_ci      }
1911425bb815Sopenharmony_ci
1912425bb815Sopenharmony_ci      parser_emit_cbc_literal (context_p, opcode, literal_index);
1913425bb815Sopenharmony_ci    }
1914425bb815Sopenharmony_ci    else if (!has_mapped_arguments && literal_index < PARSER_REGISTER_START)
1915425bb815Sopenharmony_ci    {
1916425bb815Sopenharmony_ci      uint16_t opcode = CBC_INIT_ARG_OR_FUNC;
1917425bb815Sopenharmony_ci
1918425bb815Sopenharmony_ci      if (scanner_literal_is_created (context_p, literal_index))
1919425bb815Sopenharmony_ci      {
1920425bb815Sopenharmony_ci        opcode = CBC_ASSIGN_LET_CONST_LITERAL;
1921425bb815Sopenharmony_ci      }
1922425bb815Sopenharmony_ci
1923425bb815Sopenharmony_ci      parser_emit_cbc_literal_value (context_p,
1924425bb815Sopenharmony_ci                                     opcode,
1925425bb815Sopenharmony_ci                                     (uint16_t) (PARSER_REGISTER_START + context_p->argument_count),
1926425bb815Sopenharmony_ci                                     literal_index);
1927425bb815Sopenharmony_ci    }
1928425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1929425bb815Sopenharmony_ci
1930425bb815Sopenharmony_ci    context_p->argument_count++;
1931425bb815Sopenharmony_ci    if (context_p->argument_count >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
1932425bb815Sopenharmony_ci    {
1933425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIMIT_REACHED);
1934425bb815Sopenharmony_ci    }
1935425bb815Sopenharmony_ci
1936425bb815Sopenharmony_ci    if (context_p->token.type != LEXER_COMMA)
1937425bb815Sopenharmony_ci    {
1938425bb815Sopenharmony_ci      break;
1939425bb815Sopenharmony_ci    }
1940425bb815Sopenharmony_ci
1941425bb815Sopenharmony_ci    lexer_next_token (context_p);
1942425bb815Sopenharmony_ci  }
1943425bb815Sopenharmony_ci
1944425bb815Sopenharmony_ci  if (context_p->token.type != end_type)
1945425bb815Sopenharmony_ci  {
1946425bb815Sopenharmony_ci    parser_error_t error = ((end_type == LEXER_RIGHT_PAREN) ? PARSER_ERR_RIGHT_PAREN_EXPECTED
1947425bb815Sopenharmony_ci                                                            : PARSER_ERR_IDENTIFIER_EXPECTED);
1948425bb815Sopenharmony_ci
1949425bb815Sopenharmony_ci    parser_raise_error (context_p, error);
1950425bb815Sopenharmony_ci  }
1951425bb815Sopenharmony_ci
1952425bb815Sopenharmony_ci  scanner_revert_active (context_p);
1953425bb815Sopenharmony_ci
1954425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
1955425bb815Sopenharmony_ci  JERRY_ASSERT (!has_mapped_arguments || !(context_p->status_flags & PARSER_FUNCTION_HAS_NON_SIMPLE_PARAM));
1956425bb815Sopenharmony_ci
1957425bb815Sopenharmony_ci  if (context_p->status_flags & PARSER_IS_GENERATOR_FUNCTION)
1958425bb815Sopenharmony_ci  {
1959425bb815Sopenharmony_ci    parser_emit_cbc_ext (context_p, CBC_EXT_CREATE_GENERATOR);
1960425bb815Sopenharmony_ci    parser_emit_cbc (context_p, CBC_POP);
1961425bb815Sopenharmony_ci  }
1962425bb815Sopenharmony_ci
1963425bb815Sopenharmony_ci  if (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)
1964425bb815Sopenharmony_ci  {
1965425bb815Sopenharmony_ci    if ((context_p->next_scanner_info_p->u8_arg & SCANNER_FUNCTION_LEXICAL_ENV_NEEDED)
1966425bb815Sopenharmony_ci        || scanner_is_context_needed (context_p, PARSER_CHECK_FUNCTION_CONTEXT))
1967425bb815Sopenharmony_ci    {
1968425bb815Sopenharmony_ci      context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
1969425bb815Sopenharmony_ci
1970425bb815Sopenharmony_ci      parser_branch_t branch;
1971425bb815Sopenharmony_ci      parser_emit_cbc_forward_branch (context_p, CBC_BLOCK_CREATE_CONTEXT, &branch);
1972425bb815Sopenharmony_ci      parser_stack_push (context_p, &branch, sizeof (parser_branch_t));
1973425bb815Sopenharmony_ci
1974425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG
1975425bb815Sopenharmony_ci      context_p->context_stack_depth = PARSER_BLOCK_CONTEXT_STACK_ALLOCATION;
1976425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
1977425bb815Sopenharmony_ci    }
1978425bb815Sopenharmony_ci    else
1979425bb815Sopenharmony_ci    {
1980425bb815Sopenharmony_ci      context_p->status_flags &= (uint32_t) ~PARSER_LEXICAL_BLOCK_NEEDED;
1981425bb815Sopenharmony_ci    }
1982425bb815Sopenharmony_ci  }
1983425bb815Sopenharmony_ci
1984425bb815Sopenharmony_ci  context_p->status_flags &= (uint32_t) ~(PARSER_DISALLOW_AWAIT_YIELD | PARSER_FUNCTION_IS_PARSING_ARGS);
1985425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
1986425bb815Sopenharmony_ci
1987425bb815Sopenharmony_ci  scanner_create_variables (context_p, SCANNER_CREATE_VARS_IS_FUNCTION_BODY);
1988425bb815Sopenharmony_ci} /* parser_parse_function_arguments */
1989425bb815Sopenharmony_ci
1990425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG
1991425bb815Sopenharmony_ciJERRY_STATIC_ASSERT (PARSER_SCANNING_SUCCESSFUL == PARSER_HAS_LATE_LIT_INIT,
1992425bb815Sopenharmony_ci                     parser_scanning_successful_should_share_the_bit_position_with_parser_has_late_lit_init);
1993425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
1994425bb815Sopenharmony_ci
1995425bb815Sopenharmony_ci/**
1996425bb815Sopenharmony_ci * Parse and compile EcmaScript source code
1997425bb815Sopenharmony_ci *
1998425bb815Sopenharmony_ci * Note: source must be a valid UTF-8 string
1999425bb815Sopenharmony_ci *
2000425bb815Sopenharmony_ci * @return compiled code
2001425bb815Sopenharmony_ci */
2002425bb815Sopenharmony_cistatic ecma_compiled_code_t *
2003425bb815Sopenharmony_ciparser_parse_source (const uint8_t *arg_list_p, /**< function argument list */
2004425bb815Sopenharmony_ci                     size_t arg_list_size, /**< size of function argument list */
2005425bb815Sopenharmony_ci                     const uint8_t *source_p, /**< valid UTF-8 source code */
2006425bb815Sopenharmony_ci                     size_t source_size, /**< size of the source code */
2007425bb815Sopenharmony_ci                     uint32_t parse_opts, /**< ecma_parse_opts_t option bits */
2008425bb815Sopenharmony_ci                     parser_error_location_t *error_location_p) /**< error location */
2009425bb815Sopenharmony_ci{
2010425bb815Sopenharmony_ci  parser_context_t context;
2011425bb815Sopenharmony_ci  ecma_compiled_code_t *compiled_code_p;
2012425bb815Sopenharmony_ci
2013425bb815Sopenharmony_ci  context.error = PARSER_ERR_NO_ERROR;
2014425bb815Sopenharmony_ci
2015425bb815Sopenharmony_ci  if (error_location_p != NULL)
2016425bb815Sopenharmony_ci  {
2017425bb815Sopenharmony_ci    error_location_p->error = PARSER_ERR_NO_ERROR;
2018425bb815Sopenharmony_ci  }
2019425bb815Sopenharmony_ci
2020425bb815Sopenharmony_ci  context.status_flags = parse_opts & PARSER_STRICT_MODE_MASK;
2021425bb815Sopenharmony_ci  context.global_status_flags = parse_opts;
2022425bb815Sopenharmony_ci
2023425bb815Sopenharmony_ci  if (arg_list_p != NULL)
2024425bb815Sopenharmony_ci  {
2025425bb815Sopenharmony_ci    context.status_flags |= PARSER_IS_FUNCTION;
2026425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2027425bb815Sopenharmony_ci    if (parse_opts & ECMA_PARSE_GENERATOR_FUNCTION)
2028425bb815Sopenharmony_ci    {
2029425bb815Sopenharmony_ci      context.status_flags |= PARSER_IS_GENERATOR_FUNCTION;
2030425bb815Sopenharmony_ci    }
2031425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2032425bb815Sopenharmony_ci  }
2033425bb815Sopenharmony_ci
2034425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2035425bb815Sopenharmony_ci  context.status_flags |= PARSER_RESTORE_STATUS_FLAGS (parse_opts);
2036425bb815Sopenharmony_ci  context.tagged_template_literal_cp = JMEM_CP_NULL;
2037425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2038425bb815Sopenharmony_ci
2039425bb815Sopenharmony_ci  context.stack_depth = 0;
2040425bb815Sopenharmony_ci  context.stack_limit = 0;
2041425bb815Sopenharmony_ci  context.last_context_p = NULL;
2042425bb815Sopenharmony_ci  context.last_statement.current_p = NULL;
2043425bb815Sopenharmony_ci
2044425bb815Sopenharmony_ci  context.token.flags = 0;
2045425bb815Sopenharmony_ci  context.line = 1;
2046425bb815Sopenharmony_ci  context.column = 1;
2047425bb815Sopenharmony_ci
2048425bb815Sopenharmony_ci  scanner_info_t scanner_info_end;
2049425bb815Sopenharmony_ci  scanner_info_end.next_p = NULL;
2050425bb815Sopenharmony_ci  scanner_info_end.source_p = NULL;
2051425bb815Sopenharmony_ci  scanner_info_end.type = SCANNER_TYPE_END;
2052425bb815Sopenharmony_ci  context.next_scanner_info_p = &scanner_info_end;
2053425bb815Sopenharmony_ci  context.active_scanner_info_p = NULL;
2054425bb815Sopenharmony_ci  context.skipped_scanner_info_p = NULL;
2055425bb815Sopenharmony_ci  context.skipped_scanner_info_end_p = NULL;
2056425bb815Sopenharmony_ci
2057425bb815Sopenharmony_ci  context.last_cbc_opcode = PARSER_CBC_UNAVAILABLE;
2058425bb815Sopenharmony_ci
2059425bb815Sopenharmony_ci  context.argument_count = 0;
2060425bb815Sopenharmony_ci  context.register_count = 0;
2061425bb815Sopenharmony_ci  context.literal_count = 0;
2062425bb815Sopenharmony_ci
2063425bb815Sopenharmony_ci  parser_cbc_stream_init (&context.byte_code);
2064425bb815Sopenharmony_ci  context.byte_code_size = 0;
2065425bb815Sopenharmony_ci  parser_list_init (&context.literal_pool,
2066425bb815Sopenharmony_ci                    sizeof (lexer_literal_t),
2067425bb815Sopenharmony_ci                    (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_literal_t)));
2068425bb815Sopenharmony_ci  context.scope_stack_p = NULL;
2069425bb815Sopenharmony_ci  context.scope_stack_size = 0;
2070425bb815Sopenharmony_ci  context.scope_stack_top = 0;
2071425bb815Sopenharmony_ci  context.scope_stack_reg_top = 0;
2072425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2073425bb815Sopenharmony_ci  context.scope_stack_global_end = 0;
2074425bb815Sopenharmony_ci  context.tagged_template_literal_cp = JMEM_CP_NULL;
2075425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2076425bb815Sopenharmony_ci
2077425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG
2078425bb815Sopenharmony_ci  context.context_stack_depth = 0;
2079425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
2080425bb815Sopenharmony_ci
2081425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2082425bb815Sopenharmony_ci  context.is_show_opcodes = (JERRY_CONTEXT (jerry_init_flags) & ECMA_INIT_SHOW_OPCODES);
2083425bb815Sopenharmony_ci  context.total_byte_code_size = 0;
2084425bb815Sopenharmony_ci
2085425bb815Sopenharmony_ci  if (context.is_show_opcodes)
2086425bb815Sopenharmony_ci  {
2087425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("\n--- %s parsing start ---\n\n",
2088425bb815Sopenharmony_ci                     (arg_list_p == NULL) ? "Script"
2089425bb815Sopenharmony_ci                                          : "Function");
2090425bb815Sopenharmony_ci  }
2091425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2092425bb815Sopenharmony_ci
2093425bb815Sopenharmony_ci  scanner_scan_all (&context,
2094425bb815Sopenharmony_ci                    arg_list_p,
2095425bb815Sopenharmony_ci                    arg_list_p + arg_list_size,
2096425bb815Sopenharmony_ci                    source_p,
2097425bb815Sopenharmony_ci                    source_p + source_size);
2098425bb815Sopenharmony_ci
2099425bb815Sopenharmony_ci  if (JERRY_UNLIKELY (context.error != PARSER_ERR_NO_ERROR))
2100425bb815Sopenharmony_ci  {
2101425bb815Sopenharmony_ci    JERRY_ASSERT (context.error == PARSER_ERR_OUT_OF_MEMORY);
2102425bb815Sopenharmony_ci
2103425bb815Sopenharmony_ci    if (error_location_p != NULL)
2104425bb815Sopenharmony_ci    {
2105425bb815Sopenharmony_ci      error_location_p->error = context.error;
2106425bb815Sopenharmony_ci      error_location_p->line = context.token.line;
2107425bb815Sopenharmony_ci      error_location_p->column = context.token.column;
2108425bb815Sopenharmony_ci    }
2109425bb815Sopenharmony_ci    return NULL;
2110425bb815Sopenharmony_ci  }
2111425bb815Sopenharmony_ci
2112425bb815Sopenharmony_ci  if (arg_list_p == NULL)
2113425bb815Sopenharmony_ci  {
2114425bb815Sopenharmony_ci    context.source_p = source_p;
2115425bb815Sopenharmony_ci    context.source_end_p = source_p + source_size;
2116425bb815Sopenharmony_ci  }
2117425bb815Sopenharmony_ci  else
2118425bb815Sopenharmony_ci  {
2119425bb815Sopenharmony_ci    context.source_p = arg_list_p;
2120425bb815Sopenharmony_ci    context.source_end_p = arg_list_p + arg_list_size;
2121425bb815Sopenharmony_ci  }
2122425bb815Sopenharmony_ci
2123425bb815Sopenharmony_ci  context.u.allocated_buffer_p = NULL;
2124425bb815Sopenharmony_ci  context.line = 1;
2125425bb815Sopenharmony_ci  context.column = 1;
2126425bb815Sopenharmony_ci  context.token.flags = 0;
2127425bb815Sopenharmony_ci
2128425bb815Sopenharmony_ci  parser_stack_init (&context);
2129425bb815Sopenharmony_ci
2130425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
2131425bb815Sopenharmony_ci  context.breakpoint_info_count = 0;
2132425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
2133425bb815Sopenharmony_ci
2134425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2135425bb815Sopenharmony_ci  if (context.global_status_flags & ECMA_PARSE_MODULE)
2136425bb815Sopenharmony_ci  {
2137425bb815Sopenharmony_ci    context.status_flags |= PARSER_IS_STRICT;
2138425bb815Sopenharmony_ci  }
2139425bb815Sopenharmony_ci
2140425bb815Sopenharmony_ci  context.module_current_node_p = NULL;
2141425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2142425bb815Sopenharmony_ci
2143425bb815Sopenharmony_ci  PARSER_TRY (context.try_buffer)
2144425bb815Sopenharmony_ci  {
2145425bb815Sopenharmony_ci    /* Pushing a dummy value ensures the stack is never empty.
2146425bb815Sopenharmony_ci     * This simplifies the stack management routines. */
2147425bb815Sopenharmony_ci    parser_stack_push_uint8 (&context, CBC_MAXIMUM_BYTE_VALUE);
2148425bb815Sopenharmony_ci    /* The next token must always be present to make decisions
2149425bb815Sopenharmony_ci     * in the parser. Therefore when a token is consumed, the
2150425bb815Sopenharmony_ci     * lexer_next_token() must be immediately called. */
2151425bb815Sopenharmony_ci    lexer_next_token (&context);
2152425bb815Sopenharmony_ci
2153425bb815Sopenharmony_ci    if (arg_list_p != NULL)
2154425bb815Sopenharmony_ci    {
2155425bb815Sopenharmony_ci      parser_parse_function_arguments (&context, LEXER_EOS);
2156425bb815Sopenharmony_ci
2157425bb815Sopenharmony_ci      JERRY_ASSERT (context.next_scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS);
2158425bb815Sopenharmony_ci      scanner_release_next (&context, sizeof (scanner_info_t));
2159425bb815Sopenharmony_ci
2160425bb815Sopenharmony_ci      context.source_p = source_p;
2161425bb815Sopenharmony_ci      context.source_end_p = source_p + source_size;
2162425bb815Sopenharmony_ci      context.line = 1;
2163425bb815Sopenharmony_ci      context.column = 1;
2164425bb815Sopenharmony_ci
2165425bb815Sopenharmony_ci      lexer_next_token (&context);
2166425bb815Sopenharmony_ci    }
2167425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2168425bb815Sopenharmony_ci    else if (parse_opts & ECMA_PARSE_MODULE)
2169425bb815Sopenharmony_ci    {
2170425bb815Sopenharmony_ci      scanner_create_variables (&context, SCANNER_CREATE_VARS_NO_OPTS);
2171425bb815Sopenharmony_ci    }
2172425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2173425bb815Sopenharmony_ci    else
2174425bb815Sopenharmony_ci    {
2175425bb815Sopenharmony_ci      JERRY_ASSERT (context.next_scanner_info_p->source_p == source_p
2176425bb815Sopenharmony_ci                    && context.next_scanner_info_p->type == SCANNER_TYPE_FUNCTION);
2177425bb815Sopenharmony_ci
2178425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2179425bb815Sopenharmony_ci      if (scanner_is_context_needed (&context, PARSER_CHECK_GLOBAL_CONTEXT))
2180425bb815Sopenharmony_ci      {
2181425bb815Sopenharmony_ci        context.status_flags |= PARSER_LEXICAL_BLOCK_NEEDED;
2182425bb815Sopenharmony_ci      }
2183425bb815Sopenharmony_ci
2184425bb815Sopenharmony_ci      if ((parse_opts & ECMA_PARSE_EVAL) == 0)
2185425bb815Sopenharmony_ci      {
2186425bb815Sopenharmony_ci        scanner_check_variables (&context);
2187425bb815Sopenharmony_ci      }
2188425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2189425bb815Sopenharmony_ci
2190425bb815Sopenharmony_ci      scanner_create_variables (&context, SCANNER_CREATE_VARS_IS_SCRIPT);
2191425bb815Sopenharmony_ci    }
2192425bb815Sopenharmony_ci
2193425bb815Sopenharmony_ci    parser_parse_statements (&context);
2194425bb815Sopenharmony_ci
2195425bb815Sopenharmony_ci    JERRY_ASSERT (context.last_statement.current_p == NULL);
2196425bb815Sopenharmony_ci
2197425bb815Sopenharmony_ci    JERRY_ASSERT (context.last_cbc_opcode == PARSER_CBC_UNAVAILABLE);
2198425bb815Sopenharmony_ci    JERRY_ASSERT (context.u.allocated_buffer_p == NULL);
2199425bb815Sopenharmony_ci
2200425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG
2201425bb815Sopenharmony_ci    JERRY_ASSERT (context.status_flags & PARSER_SCANNING_SUCCESSFUL);
2202425bb815Sopenharmony_ci    JERRY_ASSERT (!(context.global_status_flags & ECMA_PARSE_INTERNAL_FOR_IN_OFF_CONTEXT_ERROR));
2203425bb815Sopenharmony_ci    context.status_flags &= (uint32_t) ~PARSER_SCANNING_SUCCESSFUL;
2204425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
2205425bb815Sopenharmony_ci
2206425bb815Sopenharmony_ci    JERRY_ASSERT (!(context.status_flags & PARSER_HAS_LATE_LIT_INIT));
2207425bb815Sopenharmony_ci
2208425bb815Sopenharmony_ci    compiled_code_p = parser_post_processing (&context);
2209425bb815Sopenharmony_ci    parser_list_free (&context.literal_pool);
2210425bb815Sopenharmony_ci
2211425bb815Sopenharmony_ci    /* When parsing is successful, only the dummy value can be remained on the stack. */
2212425bb815Sopenharmony_ci    JERRY_ASSERT (context.stack_top_uint8 == CBC_MAXIMUM_BYTE_VALUE
2213425bb815Sopenharmony_ci                  && context.stack.last_position == 1
2214425bb815Sopenharmony_ci                  && context.stack.first_p != NULL
2215425bb815Sopenharmony_ci                  && context.stack.first_p->next_p == NULL
2216425bb815Sopenharmony_ci                  && context.stack.last_p == NULL);
2217425bb815Sopenharmony_ci
2218425bb815Sopenharmony_ci    JERRY_ASSERT (arg_list_p != NULL || !(context.status_flags & PARSER_ARGUMENTS_NEEDED));
2219425bb815Sopenharmony_ci
2220425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2221425bb815Sopenharmony_ci    if (context.is_show_opcodes)
2222425bb815Sopenharmony_ci    {
2223425bb815Sopenharmony_ci      JERRY_DEBUG_MSG ("\n%s parsing successfully completed. Total byte code size: %d bytes\n",
2224425bb815Sopenharmony_ci                       (arg_list_p == NULL) ? "Script"
2225425bb815Sopenharmony_ci                                            : "Function",
2226425bb815Sopenharmony_ci                       (int) context.total_byte_code_size);
2227425bb815Sopenharmony_ci    }
2228425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2229425bb815Sopenharmony_ci  }
2230425bb815Sopenharmony_ci  PARSER_CATCH
2231425bb815Sopenharmony_ci  {
2232425bb815Sopenharmony_ci    if (context.last_statement.current_p != NULL)
2233425bb815Sopenharmony_ci    {
2234425bb815Sopenharmony_ci      parser_free_jumps (context.last_statement);
2235425bb815Sopenharmony_ci    }
2236425bb815Sopenharmony_ci
2237425bb815Sopenharmony_ci    parser_free_allocated_buffer (&context);
2238425bb815Sopenharmony_ci
2239425bb815Sopenharmony_ci    scanner_cleanup (&context);
2240425bb815Sopenharmony_ci
2241425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2242425bb815Sopenharmony_ci    if (context.module_current_node_p != NULL)
2243425bb815Sopenharmony_ci    {
2244425bb815Sopenharmony_ci      ecma_module_release_module_nodes (context.module_current_node_p);
2245425bb815Sopenharmony_ci    }
2246425bb815Sopenharmony_ci#endif
2247425bb815Sopenharmony_ci
2248425bb815Sopenharmony_ci    if (error_location_p != NULL)
2249425bb815Sopenharmony_ci    {
2250425bb815Sopenharmony_ci      error_location_p->error = context.error;
2251425bb815Sopenharmony_ci      error_location_p->line = context.token.line;
2252425bb815Sopenharmony_ci      error_location_p->column = context.token.column;
2253425bb815Sopenharmony_ci    }
2254425bb815Sopenharmony_ci
2255425bb815Sopenharmony_ci    compiled_code_p = NULL;
2256425bb815Sopenharmony_ci    parser_free_literals (&context.literal_pool);
2257425bb815Sopenharmony_ci    parser_cbc_stream_free (&context.byte_code);
2258425bb815Sopenharmony_ci  }
2259425bb815Sopenharmony_ci  PARSER_TRY_END
2260425bb815Sopenharmony_ci
2261425bb815Sopenharmony_ci  if (context.scope_stack_p != NULL)
2262425bb815Sopenharmony_ci  {
2263425bb815Sopenharmony_ci    parser_free (context.scope_stack_p, context.scope_stack_size * sizeof (parser_scope_stack_t));
2264425bb815Sopenharmony_ci  }
2265425bb815Sopenharmony_ci
2266425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2267425bb815Sopenharmony_ci  if (context.is_show_opcodes)
2268425bb815Sopenharmony_ci  {
2269425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("\n--- %s parsing end ---\n\n",
2270425bb815Sopenharmony_ci                     (arg_list_p == NULL) ? "Script"
2271425bb815Sopenharmony_ci                                          : "Function");
2272425bb815Sopenharmony_ci  }
2273425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2274425bb815Sopenharmony_ci
2275425bb815Sopenharmony_ci  parser_stack_free (&context);
2276425bb815Sopenharmony_ci
2277425bb815Sopenharmony_ci  return compiled_code_p;
2278425bb815Sopenharmony_ci} /* parser_parse_source */
2279425bb815Sopenharmony_ci
2280425bb815Sopenharmony_ci/**
2281425bb815Sopenharmony_ci * Save parser context before function parsing.
2282425bb815Sopenharmony_ci */
2283425bb815Sopenharmony_cistatic void
2284425bb815Sopenharmony_ciparser_save_context (parser_context_t *context_p, /**< context */
2285425bb815Sopenharmony_ci                     parser_saved_context_t *saved_context_p) /**< target for saving the context */
2286425bb815Sopenharmony_ci{
2287425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE);
2288425bb815Sopenharmony_ci
2289425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
2290425bb815Sopenharmony_ci  if ((JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
2291425bb815Sopenharmony_ci      && context_p->breakpoint_info_count > 0)
2292425bb815Sopenharmony_ci  {
2293425bb815Sopenharmony_ci    parser_send_breakpoints (context_p, JERRY_DEBUGGER_BREAKPOINT_LIST);
2294425bb815Sopenharmony_ci    context_p->breakpoint_info_count = 0;
2295425bb815Sopenharmony_ci  }
2296425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
2297425bb815Sopenharmony_ci
2298425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2299425bb815Sopenharmony_ci  if (context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS)
2300425bb815Sopenharmony_ci  {
2301425bb815Sopenharmony_ci    context_p->status_flags |= PARSER_LEXICAL_BLOCK_NEEDED;
2302425bb815Sopenharmony_ci  }
2303425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2304425bb815Sopenharmony_ci
2305425bb815Sopenharmony_ci  /* Save private part of the context. */
2306425bb815Sopenharmony_ci
2307425bb815Sopenharmony_ci  saved_context_p->status_flags = context_p->status_flags;
2308425bb815Sopenharmony_ci  saved_context_p->stack_depth = context_p->stack_depth;
2309425bb815Sopenharmony_ci  saved_context_p->stack_limit = context_p->stack_limit;
2310425bb815Sopenharmony_ci  saved_context_p->prev_context_p = context_p->last_context_p;
2311425bb815Sopenharmony_ci  saved_context_p->last_statement = context_p->last_statement;
2312425bb815Sopenharmony_ci
2313425bb815Sopenharmony_ci  saved_context_p->argument_count = context_p->argument_count;
2314425bb815Sopenharmony_ci  saved_context_p->register_count = context_p->register_count;
2315425bb815Sopenharmony_ci  saved_context_p->literal_count = context_p->literal_count;
2316425bb815Sopenharmony_ci
2317425bb815Sopenharmony_ci  saved_context_p->byte_code = context_p->byte_code;
2318425bb815Sopenharmony_ci  saved_context_p->byte_code_size = context_p->byte_code_size;
2319425bb815Sopenharmony_ci  saved_context_p->literal_pool_data = context_p->literal_pool.data;
2320425bb815Sopenharmony_ci  saved_context_p->scope_stack_p = context_p->scope_stack_p;
2321425bb815Sopenharmony_ci  saved_context_p->scope_stack_size = context_p->scope_stack_size;
2322425bb815Sopenharmony_ci  saved_context_p->scope_stack_top = context_p->scope_stack_top;
2323425bb815Sopenharmony_ci  saved_context_p->scope_stack_reg_top = context_p->scope_stack_reg_top;
2324425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2325425bb815Sopenharmony_ci  saved_context_p->scope_stack_global_end = context_p->scope_stack_global_end;
2326425bb815Sopenharmony_ci  saved_context_p->tagged_template_literal_cp = context_p->tagged_template_literal_cp;
2327425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2328425bb815Sopenharmony_ci
2329425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG
2330425bb815Sopenharmony_ci  saved_context_p->context_stack_depth = context_p->context_stack_depth;
2331425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
2332425bb815Sopenharmony_ci
2333425bb815Sopenharmony_ci  /* Reset private part of the context. */
2334425bb815Sopenharmony_ci
2335425bb815Sopenharmony_ci  context_p->status_flags &= PARSER_IS_STRICT;
2336425bb815Sopenharmony_ci  context_p->stack_depth = 0;
2337425bb815Sopenharmony_ci  context_p->stack_limit = 0;
2338425bb815Sopenharmony_ci  context_p->last_context_p = saved_context_p;
2339425bb815Sopenharmony_ci  context_p->last_statement.current_p = NULL;
2340425bb815Sopenharmony_ci
2341425bb815Sopenharmony_ci  context_p->argument_count = 0;
2342425bb815Sopenharmony_ci  context_p->register_count = 0;
2343425bb815Sopenharmony_ci  context_p->literal_count = 0;
2344425bb815Sopenharmony_ci
2345425bb815Sopenharmony_ci  parser_cbc_stream_init (&context_p->byte_code);
2346425bb815Sopenharmony_ci  context_p->byte_code_size = 0;
2347425bb815Sopenharmony_ci  parser_list_reset (&context_p->literal_pool);
2348425bb815Sopenharmony_ci  context_p->scope_stack_p = NULL;
2349425bb815Sopenharmony_ci  context_p->scope_stack_size = 0;
2350425bb815Sopenharmony_ci  context_p->scope_stack_top = 0;
2351425bb815Sopenharmony_ci  context_p->scope_stack_reg_top = 0;
2352425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2353425bb815Sopenharmony_ci  context_p->scope_stack_global_end = 0;
2354425bb815Sopenharmony_ci  context_p->tagged_template_literal_cp = JMEM_CP_NULL;
2355425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2356425bb815Sopenharmony_ci
2357425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG
2358425bb815Sopenharmony_ci  context_p->context_stack_depth = 0;
2359425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
2360425bb815Sopenharmony_ci} /* parser_save_context */
2361425bb815Sopenharmony_ci
2362425bb815Sopenharmony_ci/**
2363425bb815Sopenharmony_ci * Restore parser context after function parsing.
2364425bb815Sopenharmony_ci */
2365425bb815Sopenharmony_cistatic void
2366425bb815Sopenharmony_ciparser_restore_context (parser_context_t *context_p, /**< context */
2367425bb815Sopenharmony_ci                        parser_saved_context_t *saved_context_p) /**< target for saving the context */
2368425bb815Sopenharmony_ci{
2369425bb815Sopenharmony_ci  parser_list_free (&context_p->literal_pool);
2370425bb815Sopenharmony_ci
2371425bb815Sopenharmony_ci  if (context_p->scope_stack_p != NULL)
2372425bb815Sopenharmony_ci  {
2373425bb815Sopenharmony_ci    parser_free (context_p->scope_stack_p, context_p->scope_stack_size * sizeof (parser_scope_stack_t));
2374425bb815Sopenharmony_ci  }
2375425bb815Sopenharmony_ci
2376425bb815Sopenharmony_ci  /* Restore private part of the context. */
2377425bb815Sopenharmony_ci
2378425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->last_cbc_opcode == PARSER_CBC_UNAVAILABLE);
2379425bb815Sopenharmony_ci
2380425bb815Sopenharmony_ci  context_p->status_flags = saved_context_p->status_flags;
2381425bb815Sopenharmony_ci  context_p->stack_depth = saved_context_p->stack_depth;
2382425bb815Sopenharmony_ci  context_p->stack_limit = saved_context_p->stack_limit;
2383425bb815Sopenharmony_ci  context_p->last_context_p = saved_context_p->prev_context_p;
2384425bb815Sopenharmony_ci  context_p->last_statement = saved_context_p->last_statement;
2385425bb815Sopenharmony_ci
2386425bb815Sopenharmony_ci  context_p->argument_count = saved_context_p->argument_count;
2387425bb815Sopenharmony_ci  context_p->register_count = saved_context_p->register_count;
2388425bb815Sopenharmony_ci  context_p->literal_count = saved_context_p->literal_count;
2389425bb815Sopenharmony_ci
2390425bb815Sopenharmony_ci  context_p->byte_code = saved_context_p->byte_code;
2391425bb815Sopenharmony_ci  context_p->byte_code_size = saved_context_p->byte_code_size;
2392425bb815Sopenharmony_ci  context_p->literal_pool.data = saved_context_p->literal_pool_data;
2393425bb815Sopenharmony_ci  context_p->scope_stack_p = saved_context_p->scope_stack_p;
2394425bb815Sopenharmony_ci  context_p->scope_stack_size = saved_context_p->scope_stack_size;
2395425bb815Sopenharmony_ci  context_p->scope_stack_top = saved_context_p->scope_stack_top;
2396425bb815Sopenharmony_ci  context_p->scope_stack_reg_top = saved_context_p->scope_stack_reg_top;
2397425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2398425bb815Sopenharmony_ci  context_p->scope_stack_global_end = saved_context_p->scope_stack_global_end;
2399425bb815Sopenharmony_ci  context_p->tagged_template_literal_cp = saved_context_p->tagged_template_literal_cp;
2400425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2401425bb815Sopenharmony_ci
2402425bb815Sopenharmony_ci#ifndef JERRY_NDEBUG
2403425bb815Sopenharmony_ci  context_p->context_stack_depth = saved_context_p->context_stack_depth;
2404425bb815Sopenharmony_ci#endif /* !JERRY_NDEBUG */
2405425bb815Sopenharmony_ci} /* parser_restore_context */
2406425bb815Sopenharmony_ci
2407425bb815Sopenharmony_ci/**
2408425bb815Sopenharmony_ci * Parse function code
2409425bb815Sopenharmony_ci *
2410425bb815Sopenharmony_ci * @return compiled code
2411425bb815Sopenharmony_ci */
2412425bb815Sopenharmony_ciecma_compiled_code_t *
2413425bb815Sopenharmony_ciparser_parse_function (parser_context_t *context_p, /**< context */
2414425bb815Sopenharmony_ci                       uint32_t status_flags) /**< extra status flags */
2415425bb815Sopenharmony_ci{
2416425bb815Sopenharmony_ci  parser_saved_context_t saved_context;
2417425bb815Sopenharmony_ci  ecma_compiled_code_t *compiled_code_p;
2418425bb815Sopenharmony_ci
2419425bb815Sopenharmony_ci  JERRY_ASSERT (status_flags & PARSER_IS_FUNCTION);
2420425bb815Sopenharmony_ci  parser_save_context (context_p, &saved_context);
2421425bb815Sopenharmony_ci  context_p->status_flags |= status_flags;
2422425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2423425bb815Sopenharmony_ci  context_p->status_flags |= PARSER_ALLOW_NEW_TARGET;
2424425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2425425bb815Sopenharmony_ci
2426425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2427425bb815Sopenharmony_ci  if (context_p->is_show_opcodes)
2428425bb815Sopenharmony_ci  {
2429425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2430425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("\n--- %s parsing start ---\n\n",
2431425bb815Sopenharmony_ci                     (context_p->status_flags & PARSER_CLASS_CONSTRUCTOR) ? "Class constructor"
2432425bb815Sopenharmony_ci                                                                          : "Function");
2433425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
2434425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("\n--- Function parsing start ---\n\n");
2435425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2436425bb815Sopenharmony_ci  }
2437425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2438425bb815Sopenharmony_ci
2439425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
2440425bb815Sopenharmony_ci  if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
2441425bb815Sopenharmony_ci  {
2442425bb815Sopenharmony_ci    jerry_debugger_send_parse_function (context_p->token.line, context_p->token.column);
2443425bb815Sopenharmony_ci  }
2444425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
2445425bb815Sopenharmony_ci
2446425bb815Sopenharmony_ci  CHECK_JERRY_STACK_USAGE(context_p);
2447425bb815Sopenharmony_ci
2448425bb815Sopenharmony_ci  lexer_next_token (context_p);
2449425bb815Sopenharmony_ci
2450425bb815Sopenharmony_ci  if (context_p->token.type != LEXER_LEFT_PAREN)
2451425bb815Sopenharmony_ci  {
2452425bb815Sopenharmony_ci    parser_raise_error (context_p, PARSER_ERR_ARGUMENT_LIST_EXPECTED);
2453425bb815Sopenharmony_ci  }
2454425bb815Sopenharmony_ci
2455425bb815Sopenharmony_ci  lexer_next_token (context_p);
2456425bb815Sopenharmony_ci
2457425bb815Sopenharmony_ci  parser_parse_function_arguments (context_p, LEXER_RIGHT_PAREN);
2458425bb815Sopenharmony_ci  lexer_next_token (context_p);
2459425bb815Sopenharmony_ci
2460425bb815Sopenharmony_ci  if ((context_p->status_flags & PARSER_IS_PROPERTY_GETTER)
2461425bb815Sopenharmony_ci      && context_p->argument_count != 0)
2462425bb815Sopenharmony_ci  {
2463425bb815Sopenharmony_ci    parser_raise_error (context_p, PARSER_ERR_NO_ARGUMENTS_EXPECTED);
2464425bb815Sopenharmony_ci  }
2465425bb815Sopenharmony_ci
2466425bb815Sopenharmony_ci  if ((context_p->status_flags & PARSER_IS_PROPERTY_SETTER)
2467425bb815Sopenharmony_ci      && context_p->argument_count != 1)
2468425bb815Sopenharmony_ci  {
2469425bb815Sopenharmony_ci    parser_raise_error (context_p, PARSER_ERR_ONE_ARGUMENT_EXPECTED);
2470425bb815Sopenharmony_ci  }
2471425bb815Sopenharmony_ci
2472425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2473425bb815Sopenharmony_ci  if (context_p->is_show_opcodes
2474425bb815Sopenharmony_ci      && (context_p->status_flags & PARSER_HAS_NON_STRICT_ARG))
2475425bb815Sopenharmony_ci  {
2476425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("  Note: legacy (non-strict) argument definition\n\n");
2477425bb815Sopenharmony_ci  }
2478425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2479425bb815Sopenharmony_ci
2480425bb815Sopenharmony_ci  if (context_p->token.type != LEXER_LEFT_BRACE)
2481425bb815Sopenharmony_ci  {
2482425bb815Sopenharmony_ci    parser_raise_error (context_p, PARSER_ERR_LEFT_BRACE_EXPECTED);
2483425bb815Sopenharmony_ci  }
2484425bb815Sopenharmony_ci
2485425bb815Sopenharmony_ci  lexer_next_token (context_p);
2486425bb815Sopenharmony_ci  parser_parse_statements (context_p);
2487425bb815Sopenharmony_ci  compiled_code_p = parser_post_processing (context_p);
2488425bb815Sopenharmony_ci
2489425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2490425bb815Sopenharmony_ci  if (context_p->is_show_opcodes)
2491425bb815Sopenharmony_ci  {
2492425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2493425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("\n--- %s parsing end ---\n\n",
2494425bb815Sopenharmony_ci                     (context_p->status_flags & PARSER_CLASS_CONSTRUCTOR) ? "Class constructor"
2495425bb815Sopenharmony_ci                                                                          : "Function");
2496425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ES2015) */
2497425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("\n--- Function parsing end ---\n\n");
2498425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2499425bb815Sopenharmony_ci  }
2500425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2501425bb815Sopenharmony_ci
2502425bb815Sopenharmony_ci  parser_restore_context (context_p, &saved_context);
2503425bb815Sopenharmony_ci
2504425bb815Sopenharmony_ci  return compiled_code_p;
2505425bb815Sopenharmony_ci} /* parser_parse_function */
2506425bb815Sopenharmony_ci
2507425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2508425bb815Sopenharmony_ci
2509425bb815Sopenharmony_ci/**
2510425bb815Sopenharmony_ci * Parse arrow function code
2511425bb815Sopenharmony_ci *
2512425bb815Sopenharmony_ci * @return compiled code
2513425bb815Sopenharmony_ci */
2514425bb815Sopenharmony_ciecma_compiled_code_t *
2515425bb815Sopenharmony_ciparser_parse_arrow_function (parser_context_t *context_p, /**< context */
2516425bb815Sopenharmony_ci                             uint32_t status_flags) /**< extra status flags */
2517425bb815Sopenharmony_ci{
2518425bb815Sopenharmony_ci  parser_saved_context_t saved_context;
2519425bb815Sopenharmony_ci  ecma_compiled_code_t *compiled_code_p;
2520425bb815Sopenharmony_ci
2521425bb815Sopenharmony_ci  JERRY_ASSERT (status_flags & PARSER_IS_FUNCTION);
2522425bb815Sopenharmony_ci  JERRY_ASSERT (status_flags & PARSER_IS_ARROW_FUNCTION);
2523425bb815Sopenharmony_ci  parser_save_context (context_p, &saved_context);
2524425bb815Sopenharmony_ci  context_p->status_flags |= status_flags;
2525425bb815Sopenharmony_ci  context_p->status_flags |= saved_context.status_flags & (PARSER_ALLOW_NEW_TARGET
2526425bb815Sopenharmony_ci                                                           | PARSER_ALLOW_SUPER
2527425bb815Sopenharmony_ci                                                           | PARSER_ALLOW_SUPER_CALL);
2528425bb815Sopenharmony_ci
2529425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2530425bb815Sopenharmony_ci  if (context_p->is_show_opcodes)
2531425bb815Sopenharmony_ci  {
2532425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("\n--- Arrow function parsing start ---\n\n");
2533425bb815Sopenharmony_ci  }
2534425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2535425bb815Sopenharmony_ci
2536425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
2537425bb815Sopenharmony_ci  if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
2538425bb815Sopenharmony_ci  {
2539425bb815Sopenharmony_ci    jerry_debugger_send_parse_function (context_p->token.line, context_p->token.column);
2540425bb815Sopenharmony_ci  }
2541425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
2542425bb815Sopenharmony_ci
2543425bb815Sopenharmony_ci  if (context_p->token.type == LEXER_LEFT_PAREN)
2544425bb815Sopenharmony_ci  {
2545425bb815Sopenharmony_ci    lexer_next_token (context_p);
2546425bb815Sopenharmony_ci    parser_parse_function_arguments (context_p, LEXER_RIGHT_PAREN);
2547425bb815Sopenharmony_ci    lexer_next_token (context_p);
2548425bb815Sopenharmony_ci  }
2549425bb815Sopenharmony_ci  else
2550425bb815Sopenharmony_ci  {
2551425bb815Sopenharmony_ci    parser_parse_function_arguments (context_p, LEXER_ARROW);
2552425bb815Sopenharmony_ci  }
2553425bb815Sopenharmony_ci
2554425bb815Sopenharmony_ci  JERRY_ASSERT (context_p->token.type == LEXER_ARROW);
2555425bb815Sopenharmony_ci
2556425bb815Sopenharmony_ci  lexer_next_token (context_p);
2557425bb815Sopenharmony_ci
2558425bb815Sopenharmony_ci  if (context_p->token.type == LEXER_LEFT_BRACE)
2559425bb815Sopenharmony_ci  {
2560425bb815Sopenharmony_ci    lexer_next_token (context_p);
2561425bb815Sopenharmony_ci
2562425bb815Sopenharmony_ci    context_p->status_flags |= PARSER_IS_CLOSURE;
2563425bb815Sopenharmony_ci    parser_parse_statements (context_p);
2564425bb815Sopenharmony_ci
2565425bb815Sopenharmony_ci    /* Unlike normal function, arrow functions consume their close brace. */
2566425bb815Sopenharmony_ci    JERRY_ASSERT (context_p->token.type == LEXER_RIGHT_BRACE);
2567425bb815Sopenharmony_ci    lexer_next_token (context_p);
2568425bb815Sopenharmony_ci  }
2569425bb815Sopenharmony_ci  else
2570425bb815Sopenharmony_ci  {
2571425bb815Sopenharmony_ci    if (context_p->status_flags & PARSER_IS_STRICT
2572425bb815Sopenharmony_ci        && context_p->status_flags & PARSER_HAS_NON_STRICT_ARG)
2573425bb815Sopenharmony_ci    {
2574425bb815Sopenharmony_ci      parser_raise_error (context_p, PARSER_ERR_NON_STRICT_ARG_DEFINITION);
2575425bb815Sopenharmony_ci    }
2576425bb815Sopenharmony_ci
2577425bb815Sopenharmony_ci    parser_parse_expression (context_p, PARSE_EXPR_NO_COMMA);
2578425bb815Sopenharmony_ci
2579425bb815Sopenharmony_ci    if (context_p->status_flags & PARSER_IS_ASYNC_FUNCTION)
2580425bb815Sopenharmony_ci    {
2581425bb815Sopenharmony_ci      parser_emit_cbc_ext (context_p, CBC_EXT_RETURN_PROMISE);
2582425bb815Sopenharmony_ci    }
2583425bb815Sopenharmony_ci    else
2584425bb815Sopenharmony_ci    {
2585425bb815Sopenharmony_ci      if (context_p->last_cbc_opcode == CBC_PUSH_LITERAL)
2586425bb815Sopenharmony_ci      {
2587425bb815Sopenharmony_ci        context_p->last_cbc_opcode = CBC_RETURN_WITH_LITERAL;
2588425bb815Sopenharmony_ci      }
2589425bb815Sopenharmony_ci      else
2590425bb815Sopenharmony_ci      {
2591425bb815Sopenharmony_ci        parser_emit_cbc (context_p, CBC_RETURN);
2592425bb815Sopenharmony_ci      }
2593425bb815Sopenharmony_ci    }
2594425bb815Sopenharmony_ci    parser_flush_cbc (context_p);
2595425bb815Sopenharmony_ci
2596425bb815Sopenharmony_ci    lexer_update_await_yield (context_p, saved_context.status_flags);
2597425bb815Sopenharmony_ci  }
2598425bb815Sopenharmony_ci
2599425bb815Sopenharmony_ci  compiled_code_p = parser_post_processing (context_p);
2600425bb815Sopenharmony_ci
2601425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2602425bb815Sopenharmony_ci  if (context_p->is_show_opcodes)
2603425bb815Sopenharmony_ci  {
2604425bb815Sopenharmony_ci    JERRY_DEBUG_MSG ("\n--- Arrow function parsing end ---\n\n");
2605425bb815Sopenharmony_ci  }
2606425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2607425bb815Sopenharmony_ci
2608425bb815Sopenharmony_ci  parser_restore_context (context_p, &saved_context);
2609425bb815Sopenharmony_ci
2610425bb815Sopenharmony_ci  return compiled_code_p;
2611425bb815Sopenharmony_ci} /* parser_parse_arrow_function */
2612425bb815Sopenharmony_ci
2613425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015) */
2614425bb815Sopenharmony_ci
2615425bb815Sopenharmony_ci/**
2616425bb815Sopenharmony_ci * Raise a parse error.
2617425bb815Sopenharmony_ci */
2618425bb815Sopenharmony_civoid
2619425bb815Sopenharmony_ciparser_raise_error (parser_context_t *context_p, /**< context */
2620425bb815Sopenharmony_ci                    parser_error_t error) /**< error code */
2621425bb815Sopenharmony_ci{
2622425bb815Sopenharmony_ci  /* Must be compatible with the scanner because
2623425bb815Sopenharmony_ci   * the lexer might throws errors during prescanning. */
2624425bb815Sopenharmony_ci  parser_saved_context_t *saved_context_p = context_p->last_context_p;
2625425bb815Sopenharmony_ci
2626425bb815Sopenharmony_ci  while (saved_context_p != NULL)
2627425bb815Sopenharmony_ci  {
2628425bb815Sopenharmony_ci    parser_cbc_stream_free (&saved_context_p->byte_code);
2629425bb815Sopenharmony_ci
2630425bb815Sopenharmony_ci    /* First the current literal pool is freed, and then it is replaced
2631425bb815Sopenharmony_ci     * by the literal pool coming from the saved context. Since literals
2632425bb815Sopenharmony_ci     * are not used anymore, this is a valid replacement. The last pool
2633425bb815Sopenharmony_ci     * is freed by parser_parse_source. */
2634425bb815Sopenharmony_ci
2635425bb815Sopenharmony_ci    parser_free_literals (&context_p->literal_pool);
2636425bb815Sopenharmony_ci    context_p->literal_pool.data = saved_context_p->literal_pool_data;
2637425bb815Sopenharmony_ci
2638425bb815Sopenharmony_ci    if (context_p->scope_stack_p != NULL)
2639425bb815Sopenharmony_ci    {
2640425bb815Sopenharmony_ci      parser_free (context_p->scope_stack_p, context_p->scope_stack_size * sizeof (parser_scope_stack_t));
2641425bb815Sopenharmony_ci    }
2642425bb815Sopenharmony_ci    context_p->scope_stack_p = saved_context_p->scope_stack_p;
2643425bb815Sopenharmony_ci    context_p->scope_stack_size = saved_context_p->scope_stack_size;
2644425bb815Sopenharmony_ci
2645425bb815Sopenharmony_ci    if (saved_context_p->last_statement.current_p != NULL)
2646425bb815Sopenharmony_ci    {
2647425bb815Sopenharmony_ci      parser_free_jumps (saved_context_p->last_statement);
2648425bb815Sopenharmony_ci    }
2649425bb815Sopenharmony_ci
2650425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2651425bb815Sopenharmony_ci    if (saved_context_p->tagged_template_literal_cp != JMEM_CP_NULL)
2652425bb815Sopenharmony_ci    {
2653425bb815Sopenharmony_ci      ecma_collection_free (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
2654425bb815Sopenharmony_ci                                                             saved_context_p->tagged_template_literal_cp));
2655425bb815Sopenharmony_ci    }
2656425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015)  */
2657425bb815Sopenharmony_ci
2658425bb815Sopenharmony_ci    saved_context_p = saved_context_p->prev_context_p;
2659425bb815Sopenharmony_ci  }
2660425bb815Sopenharmony_ci
2661425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015)
2662425bb815Sopenharmony_ci  if (context_p->tagged_template_literal_cp != JMEM_CP_NULL)
2663425bb815Sopenharmony_ci  {
2664425bb815Sopenharmony_ci    ecma_collection_free (ECMA_GET_INTERNAL_VALUE_POINTER (ecma_collection_t,
2665425bb815Sopenharmony_ci                                                           context_p->tagged_template_literal_cp));
2666425bb815Sopenharmony_ci  }
2667425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015)  */
2668425bb815Sopenharmony_ci
2669425bb815Sopenharmony_ci  context_p->error = error;
2670425bb815Sopenharmony_ci  PARSER_THROW (context_p->try_buffer);
2671425bb815Sopenharmony_ci  /* Should never been reached. */
2672425bb815Sopenharmony_ci  JERRY_ASSERT (0);
2673425bb815Sopenharmony_ci} /* parser_raise_error */
2674425bb815Sopenharmony_ci
2675425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER) */
2676425bb815Sopenharmony_ci
2677425bb815Sopenharmony_ci/**
2678425bb815Sopenharmony_ci * Parse EcmaScript source code
2679425bb815Sopenharmony_ci *
2680425bb815Sopenharmony_ci * Note:
2681425bb815Sopenharmony_ci *      if arg_list_p is not NULL, a function body is parsed
2682425bb815Sopenharmony_ci *      returned value must be freed with ecma_free_value
2683425bb815Sopenharmony_ci *
2684425bb815Sopenharmony_ci * @return true - if success
2685425bb815Sopenharmony_ci *         syntax error - otherwise
2686425bb815Sopenharmony_ci */
2687425bb815Sopenharmony_ciecma_value_t
2688425bb815Sopenharmony_ciparser_parse_script (const uint8_t *arg_list_p, /**< function argument list */
2689425bb815Sopenharmony_ci                     size_t arg_list_size, /**< size of function argument list */
2690425bb815Sopenharmony_ci                     const uint8_t *source_p, /**< source code */
2691425bb815Sopenharmony_ci                     size_t source_size, /**< size of the source code */
2692425bb815Sopenharmony_ci                     uint32_t parse_opts, /**< ecma_parse_opts_t option bits */
2693425bb815Sopenharmony_ci                     ecma_compiled_code_t **bytecode_data_p) /**< [out] JS bytecode */
2694425bb815Sopenharmony_ci{
2695425bb815Sopenharmony_ci#if ENABLED (JERRY_PARSER)
2696425bb815Sopenharmony_ci  parser_error_location_t parser_error;
2697425bb815Sopenharmony_ci
2698425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
2699425bb815Sopenharmony_ci  if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
2700425bb815Sopenharmony_ci  {
2701425bb815Sopenharmony_ci    jerry_debugger_send_string (JERRY_DEBUGGER_SOURCE_CODE,
2702425bb815Sopenharmony_ci                                JERRY_DEBUGGER_NO_SUBTYPE,
2703425bb815Sopenharmony_ci                                source_p,
2704425bb815Sopenharmony_ci                                source_size);
2705425bb815Sopenharmony_ci  }
2706425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
2707425bb815Sopenharmony_ci
2708425bb815Sopenharmony_ci  *bytecode_data_p = parser_parse_source (arg_list_p,
2709425bb815Sopenharmony_ci                                          arg_list_size,
2710425bb815Sopenharmony_ci                                          source_p,
2711425bb815Sopenharmony_ci                                          source_size,
2712425bb815Sopenharmony_ci                                          parse_opts,
2713425bb815Sopenharmony_ci                                          &parser_error);
2714425bb815Sopenharmony_ci
2715425bb815Sopenharmony_ci  if (!*bytecode_data_p)
2716425bb815Sopenharmony_ci  {
2717425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2718425bb815Sopenharmony_ci    if (JERRY_CONTEXT (module_top_context_p) != NULL)
2719425bb815Sopenharmony_ci    {
2720425bb815Sopenharmony_ci      ecma_module_cleanup ();
2721425bb815Sopenharmony_ci    }
2722425bb815Sopenharmony_ci#endif
2723425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
2724425bb815Sopenharmony_ci    if (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED)
2725425bb815Sopenharmony_ci    {
2726425bb815Sopenharmony_ci      jerry_debugger_send_type (JERRY_DEBUGGER_PARSE_ERROR);
2727425bb815Sopenharmony_ci    }
2728425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
2729425bb815Sopenharmony_ci
2730425bb815Sopenharmony_ci    if (parser_error.error == PARSER_ERR_OUT_OF_MEMORY)
2731425bb815Sopenharmony_ci    {
2732425bb815Sopenharmony_ci      /* It is unlikely that memory can be allocated in an out-of-memory
2733425bb815Sopenharmony_ci       * situation. However, a simple value can still be thrown. */
2734425bb815Sopenharmony_ci      jcontext_raise_exception (ECMA_VALUE_NULL);
2735425bb815Sopenharmony_ci      return ECMA_VALUE_ERROR;
2736425bb815Sopenharmony_ci    }
2737425bb815Sopenharmony_ci
2738425bb815Sopenharmony_ci    if (parser_error.error == PARSER_ERR_INVALID_REGEXP)
2739425bb815Sopenharmony_ci    {
2740425bb815Sopenharmony_ci      /* The RegExp compiler has already raised an exception. */
2741425bb815Sopenharmony_ci      JERRY_ASSERT (jcontext_has_pending_exception ());
2742425bb815Sopenharmony_ci      return ECMA_VALUE_ERROR;
2743425bb815Sopenharmony_ci    }
2744425bb815Sopenharmony_ci
2745425bb815Sopenharmony_ci#if ENABLED (JERRY_ERROR_MESSAGES)
2746425bb815Sopenharmony_ci    const lit_utf8_byte_t *err_bytes_p = (const lit_utf8_byte_t *) parser_error_to_string (parser_error.error);
2747425bb815Sopenharmony_ci    lit_utf8_size_t err_bytes_size = lit_zt_utf8_string_size (err_bytes_p);
2748425bb815Sopenharmony_ci
2749425bb815Sopenharmony_ci    ecma_string_t *err_str_p = ecma_new_ecma_string_from_utf8 (err_bytes_p, err_bytes_size);
2750425bb815Sopenharmony_ci    ecma_value_t err_str_val = ecma_make_string_value (err_str_p);
2751425bb815Sopenharmony_ci    ecma_value_t line_str_val = ecma_make_uint32_value (parser_error.line);
2752425bb815Sopenharmony_ci    ecma_value_t col_str_val = ecma_make_uint32_value (parser_error.column);
2753425bb815Sopenharmony_ci
2754425bb815Sopenharmony_ci    ecma_value_t error_value = ecma_raise_standard_error_with_format (ECMA_ERROR_SYNTAX,
2755425bb815Sopenharmony_ci                                                                      "% [%:%:%]",
2756425bb815Sopenharmony_ci                                                                      err_str_val,
2757425bb815Sopenharmony_ci                                                                      JERRY_CONTEXT (resource_name),
2758425bb815Sopenharmony_ci                                                                      line_str_val,
2759425bb815Sopenharmony_ci                                                                      col_str_val);
2760425bb815Sopenharmony_ci
2761425bb815Sopenharmony_ci    ecma_free_value (col_str_val);
2762425bb815Sopenharmony_ci    ecma_free_value (line_str_val);
2763425bb815Sopenharmony_ci    ecma_free_value (err_str_val);
2764425bb815Sopenharmony_ci
2765425bb815Sopenharmony_ci    return error_value;
2766425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_ERROR_MESSAGES) */
2767425bb815Sopenharmony_ci    return ecma_raise_syntax_error ("");
2768425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ERROR_MESSAGES) */
2769425bb815Sopenharmony_ci  }
2770425bb815Sopenharmony_ci
2771425bb815Sopenharmony_ci#if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2772425bb815Sopenharmony_ci  if (JERRY_CONTEXT (module_top_context_p) != NULL)
2773425bb815Sopenharmony_ci  {
2774425bb815Sopenharmony_ci    ecma_value_t ret_value = ecma_module_parse_modules ();
2775425bb815Sopenharmony_ci
2776425bb815Sopenharmony_ci    if (ECMA_IS_VALUE_ERROR (ret_value))
2777425bb815Sopenharmony_ci    {
2778425bb815Sopenharmony_ci      ecma_bytecode_deref (*bytecode_data_p);
2779425bb815Sopenharmony_ci      *bytecode_data_p = NULL;
2780425bb815Sopenharmony_ci      ecma_module_cleanup ();
2781425bb815Sopenharmony_ci
2782425bb815Sopenharmony_ci      return ret_value;
2783425bb815Sopenharmony_ci    }
2784425bb815Sopenharmony_ci  }
2785425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2786425bb815Sopenharmony_ci
2787425bb815Sopenharmony_ci#if ENABLED (JERRY_DEBUGGER)
2788425bb815Sopenharmony_ci  if ((JERRY_CONTEXT (debugger_flags) & (JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_PARSER_WAIT))
2789425bb815Sopenharmony_ci      == (JERRY_DEBUGGER_CONNECTED | JERRY_DEBUGGER_PARSER_WAIT))
2790425bb815Sopenharmony_ci  {
2791425bb815Sopenharmony_ci    JERRY_DEBUGGER_SET_FLAGS (JERRY_DEBUGGER_PARSER_WAIT_MODE);
2792425bb815Sopenharmony_ci    jerry_debugger_send_type (JERRY_DEBUGGER_WAITING_AFTER_PARSE);
2793425bb815Sopenharmony_ci
2794425bb815Sopenharmony_ci    while (JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_PARSER_WAIT_MODE)
2795425bb815Sopenharmony_ci    {
2796425bb815Sopenharmony_ci      jerry_debugger_receive (NULL);
2797425bb815Sopenharmony_ci
2798425bb815Sopenharmony_ci      if (!(JERRY_CONTEXT (debugger_flags) & JERRY_DEBUGGER_CONNECTED))
2799425bb815Sopenharmony_ci      {
2800425bb815Sopenharmony_ci        break;
2801425bb815Sopenharmony_ci      }
2802425bb815Sopenharmony_ci
2803425bb815Sopenharmony_ci      jerry_debugger_transport_sleep ();
2804425bb815Sopenharmony_ci    }
2805425bb815Sopenharmony_ci  }
2806425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_DEBUGGER) */
2807425bb815Sopenharmony_ci
2808425bb815Sopenharmony_ci  return ECMA_VALUE_TRUE;
2809425bb815Sopenharmony_ci#else /* !ENABLED (JERRY_PARSER) */
2810425bb815Sopenharmony_ci  JERRY_UNUSED (arg_list_p);
2811425bb815Sopenharmony_ci  JERRY_UNUSED (arg_list_size);
2812425bb815Sopenharmony_ci  JERRY_UNUSED (source_p);
2813425bb815Sopenharmony_ci  JERRY_UNUSED (source_size);
2814425bb815Sopenharmony_ci  JERRY_UNUSED (parse_opts);
2815425bb815Sopenharmony_ci  JERRY_UNUSED (bytecode_data_p);
2816425bb815Sopenharmony_ci
2817425bb815Sopenharmony_ci  return ecma_raise_syntax_error (ECMA_ERR_MSG ("The parser has been disabled."));
2818425bb815Sopenharmony_ci#endif /* ENABLED (JERRY_PARSER) */
2819425bb815Sopenharmony_ci} /* parser_parse_script */
2820425bb815Sopenharmony_ci
2821425bb815Sopenharmony_ci/**
2822425bb815Sopenharmony_ci * @}
2823425bb815Sopenharmony_ci * @}
2824425bb815Sopenharmony_ci * @}
2825425bb815Sopenharmony_ci */
2826