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