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