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