1 /* Copyright JS Foundation and other contributors, http://js.foundation
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecma-helpers.h"
17 #include "jcontext.h"
18 #include "js-parser-internal.h"
19 #include "js-scanner-internal.h"
20 #include "lit-char-helpers.h"
21
22 #if ENABLED (JERRY_PARSER)
23
24 /** \addtogroup parser Parser
25 * @{
26 *
27 * \addtogroup jsparser JavaScript
28 * @{
29 *
30 * \addtogroup jsparser_scanner Scanner
31 * @{
32 */
33
34 JERRY_STATIC_ASSERT (PARSER_MAXIMUM_NUMBER_OF_LITERALS + PARSER_MAXIMUM_NUMBER_OF_REGISTERS < PARSER_REGISTER_START,
35 maximum_number_of_literals_plus_registers_must_be_less_than_register_start);
36
37 #if ENABLED (JERRY_ES2015)
38
39 JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG & SCANNER_LITERAL_IS_LOCAL) == 0,
40 is_arrow_arg_binding_flag_must_not_use_local_flags);
41
42 JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_LET & SCANNER_LITERAL_IS_LOCAL) != 0,
43 is_let_flag_must_use_local_flags);
44
45 JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_CONST & SCANNER_LITERAL_IS_LOCAL) != 0,
46 is_const_flag_must_use_local_flags);
47
48 JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_FUNC_DECLARATION & SCANNER_LITERAL_IS_LOCAL) != 0,
49 is_func_declaration_flag_must_use_local_flags);
50
51 JERRY_STATIC_ASSERT ((SCANNER_LITERAL_IS_DESTRUCTURED_ARG & SCANNER_LITERAL_IS_LOCAL) != 0,
52 is_arg_binding_flag_must_use_local_flags);
53
54 JERRY_STATIC_ASSERT (SCANNER_LITERAL_IS_FUNC_DECLARATION != SCANNER_LITERAL_IS_DESTRUCTURED_ARG,
55 is_func_declaration_must_be_different_from_is_arg_binding);
56
57 JERRY_STATIC_ASSERT (PARSER_SCOPE_STACK_IS_CONST_REG == PARSER_SCOPE_STACK_IS_LOCAL_CREATED,
58 scope_stack_is_const_reg_and_scope_stack_is_local_created_must_be_the_same);
59
60 #endif /* ENABLED (JERRY_ES2015) */
61
62 /**
63 * Raise a scanner error.
64 */
65 void
scanner_raise_error(parser_context_t * context_p)66 scanner_raise_error (parser_context_t *context_p) /**< context */
67 {
68 PARSER_THROW (context_p->try_buffer);
69 /* Should never been reached. */
70 JERRY_ASSERT (0);
71 } /* scanner_raise_error */
72
73 #if ENABLED (JERRY_ES2015)
74
75 /**
76 * Raise a variable redeclaration error.
77 */
78 void
scanner_raise_redeclaration_error(parser_context_t * context_p)79 scanner_raise_redeclaration_error (parser_context_t *context_p) /**< context */
80 {
81 scanner_info_t *info_p = scanner_insert_info (context_p, context_p->source_p, sizeof (scanner_info_t));
82 info_p->type = SCANNER_TYPE_ERR_REDECLARED;
83
84 scanner_raise_error (context_p);
85 } /* scanner_raise_redeclaration_error */
86
87 #endif /* ENABLED (JERRY_ES2015) */
88
89 /**
90 * Allocate memory for scanner.
91 *
92 * @return allocated memory
93 */
94 void *
scanner_malloc(parser_context_t * context_p,size_t size)95 scanner_malloc (parser_context_t *context_p, /**< context */
96 size_t size) /**< size of the memory block */
97 {
98 void *result;
99
100 JERRY_ASSERT (size > 0);
101 result = jmem_heap_alloc_block_null_on_error (size);
102
103 if (result == NULL)
104 {
105 scanner_cleanup (context_p);
106
107 /* This is the only error which specify its reason. */
108 context_p->error = PARSER_ERR_OUT_OF_MEMORY;
109 PARSER_THROW (context_p->try_buffer);
110 }
111 return result;
112 } /* scanner_malloc */
113
114 /**
115 * Free memory allocated by scanner_malloc.
116 */
117 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_free(void * ptr,size_t size)118 scanner_free (void *ptr, /**< pointer to free */
119 size_t size) /**< size of the memory block */
120 {
121 jmem_heap_free_block (ptr, size);
122 } /* scanner_free */
123
124 /**
125 * Count the size of a stream after an info block.
126 *
127 * @return the size in bytes
128 */
129 size_t
scanner_get_stream_size(scanner_info_t * info_p,size_t size)130 scanner_get_stream_size (scanner_info_t *info_p, /**< scanner info block */
131 size_t size) /**< size excluding the stream */
132 {
133 const uint8_t *data_p = ((const uint8_t *) info_p) + size;
134 const uint8_t *data_p_start = data_p;
135
136 while (data_p[0] != SCANNER_STREAM_TYPE_END)
137 {
138 switch (data_p[0] & SCANNER_STREAM_TYPE_MASK)
139 {
140 case SCANNER_STREAM_TYPE_VAR:
141 #if ENABLED (JERRY_ES2015)
142 case SCANNER_STREAM_TYPE_LET:
143 case SCANNER_STREAM_TYPE_CONST:
144 case SCANNER_STREAM_TYPE_LOCAL:
145 #endif /* ENABLED (JERRY_ES2015) */
146 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
147 case SCANNER_STREAM_TYPE_IMPORT:
148 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
149 case SCANNER_STREAM_TYPE_ARG:
150 #if ENABLED (JERRY_ES2015)
151 case SCANNER_STREAM_TYPE_ARG_VAR:
152 case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
153 case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
154 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
155 case SCANNER_STREAM_TYPE_ARG_FUNC:
156 #if ENABLED (JERRY_ES2015)
157 case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
158 #endif /* ENABLED (JERRY_ES2015) */
159 case SCANNER_STREAM_TYPE_FUNC:
160 {
161 break;
162 }
163 default:
164 {
165 JERRY_ASSERT ((data_p[0] & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_HOLE);
166 data_p++;
167 continue;
168 }
169 }
170
171 data_p += 3;
172
173 if (data_p[-3] & SCANNER_STREAM_UINT16_DIFF)
174 {
175 data_p++;
176 }
177 else if (data_p[-1] == 0)
178 {
179 data_p += sizeof (const uint8_t *);
180 }
181 }
182
183 return size + 1 + (size_t) (data_p - data_p_start);
184 } /* scanner_get_stream_size */
185
186 /**
187 * Insert a scanner info block into the scanner info chain.
188 *
189 * @return newly allocated scanner info
190 */
191 scanner_info_t *
scanner_insert_info(parser_context_t * context_p,const uint8_t * source_p,size_t size)192 scanner_insert_info (parser_context_t *context_p, /**< context */
193 const uint8_t *source_p, /**< triggering position */
194 size_t size) /**< size of the memory block */
195 {
196 scanner_info_t *new_scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, size);
197 scanner_info_t *scanner_info_p = context_p->next_scanner_info_p;
198 scanner_info_t *prev_scanner_info_p = NULL;
199
200 JERRY_ASSERT (scanner_info_p != NULL);
201 JERRY_ASSERT (source_p != NULL);
202
203 new_scanner_info_p->source_p = source_p;
204
205 while (source_p < scanner_info_p->source_p)
206 {
207 prev_scanner_info_p = scanner_info_p;
208 scanner_info_p = scanner_info_p->next_p;
209
210 JERRY_ASSERT (scanner_info_p != NULL);
211 }
212
213 /* Multiple scanner info blocks cannot be assigned to the same position. */
214 JERRY_ASSERT (source_p != scanner_info_p->source_p);
215
216 new_scanner_info_p->next_p = scanner_info_p;
217
218 if (JERRY_LIKELY (prev_scanner_info_p == NULL))
219 {
220 context_p->next_scanner_info_p = new_scanner_info_p;
221 }
222 else
223 {
224 prev_scanner_info_p->next_p = new_scanner_info_p;
225 }
226
227 return new_scanner_info_p;
228 } /* scanner_insert_info */
229
230 /**
231 * Insert a scanner info block into the scanner info chain before a given info block.
232 *
233 * @return newly allocated scanner info
234 */
235 scanner_info_t *
scanner_insert_info_before(parser_context_t * context_p,const uint8_t * source_p,scanner_info_t * start_info_p,size_t size)236 scanner_insert_info_before (parser_context_t *context_p, /**< context */
237 const uint8_t *source_p, /**< triggering position */
238 scanner_info_t *start_info_p, /**< first info position */
239 size_t size) /**< size of the memory block */
240 {
241 JERRY_ASSERT (start_info_p != NULL);
242
243 scanner_info_t *new_scanner_info_p = (scanner_info_t *) scanner_malloc (context_p, size);
244 scanner_info_t *scanner_info_p = start_info_p->next_p;
245 scanner_info_t *prev_scanner_info_p = start_info_p;
246
247 new_scanner_info_p->source_p = source_p;
248
249 while (source_p < scanner_info_p->source_p)
250 {
251 prev_scanner_info_p = scanner_info_p;
252 scanner_info_p = scanner_info_p->next_p;
253
254 JERRY_ASSERT (scanner_info_p != NULL);
255 }
256
257 /* Multiple scanner info blocks cannot be assigned to the same position. */
258 JERRY_ASSERT (source_p != scanner_info_p->source_p);
259
260 new_scanner_info_p->next_p = scanner_info_p;
261
262 prev_scanner_info_p->next_p = new_scanner_info_p;
263 return new_scanner_info_p;
264 } /* scanner_insert_info_before */
265
266 /**
267 * Release the next scanner info.
268 */
269 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_release_next(parser_context_t * context_p,size_t size)270 scanner_release_next (parser_context_t *context_p, /**< context */
271 size_t size) /**< size of the memory block */
272 {
273 scanner_info_t *next_p = context_p->next_scanner_info_p->next_p;
274
275 jmem_heap_free_block (context_p->next_scanner_info_p, size);
276 context_p->next_scanner_info_p = next_p;
277 } /* scanner_release_next */
278
279 /**
280 * Set the active scanner info to the next scanner info.
281 */
282 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_set_active(parser_context_t * context_p)283 scanner_set_active (parser_context_t *context_p) /**< context */
284 {
285 scanner_info_t *scanner_info_p = context_p->next_scanner_info_p;
286
287 context_p->next_scanner_info_p = scanner_info_p->next_p;
288 scanner_info_p->next_p = context_p->active_scanner_info_p;
289 context_p->active_scanner_info_p = scanner_info_p;
290 } /* scanner_set_active */
291
292 /**
293 * Set the next scanner info to the active scanner info.
294 */
295 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_revert_active(parser_context_t * context_p)296 scanner_revert_active (parser_context_t *context_p) /**< context */
297 {
298 scanner_info_t *scanner_info_p = context_p->active_scanner_info_p;
299
300 context_p->active_scanner_info_p = scanner_info_p->next_p;
301 scanner_info_p->next_p = context_p->next_scanner_info_p;
302 context_p->next_scanner_info_p = scanner_info_p;
303 } /* scanner_revert_active */
304
305 /**
306 * Release the active scanner info.
307 */
308 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_release_active(parser_context_t * context_p,size_t size)309 scanner_release_active (parser_context_t *context_p, /**< context */
310 size_t size) /**< size of the memory block */
311 {
312 scanner_info_t *next_p = context_p->active_scanner_info_p->next_p;
313
314 jmem_heap_free_block (context_p->active_scanner_info_p, size);
315 context_p->active_scanner_info_p = next_p;
316 } /* scanner_release_active */
317
318 /**
319 * Release switch cases.
320 */
321 void
scanner_release_switch_cases(scanner_case_info_t * case_p)322 scanner_release_switch_cases (scanner_case_info_t *case_p) /**< case list */
323 {
324 while (case_p != NULL)
325 {
326 scanner_case_info_t *next_p = case_p->next_p;
327
328 jmem_heap_free_block (case_p, sizeof (scanner_case_info_t));
329 case_p = next_p;
330 }
331 } /* scanner_release_switch_cases */
332
333 /**
334 * Seek to correct position in the scanner info list.
335 */
336 void
scanner_seek(parser_context_t * context_p)337 scanner_seek (parser_context_t *context_p) /**< context */
338 {
339 const uint8_t *source_p = context_p->source_p;
340 scanner_info_t *prev_p;
341
342 if (context_p->skipped_scanner_info_p != NULL)
343 {
344 JERRY_ASSERT (context_p->skipped_scanner_info_p->source_p != NULL);
345
346 context_p->skipped_scanner_info_end_p->next_p = context_p->next_scanner_info_p;
347
348 if (context_p->skipped_scanner_info_end_p->source_p <= source_p)
349 {
350 prev_p = context_p->skipped_scanner_info_end_p;
351 }
352 else
353 {
354 prev_p = context_p->skipped_scanner_info_p;
355
356 if (prev_p->source_p > source_p)
357 {
358 context_p->next_scanner_info_p = prev_p;
359 context_p->skipped_scanner_info_p = NULL;
360 return;
361 }
362
363 context_p->skipped_scanner_info_p = prev_p;
364 }
365 }
366 else
367 {
368 prev_p = context_p->next_scanner_info_p;
369
370 if (prev_p->source_p == NULL || prev_p->source_p > source_p)
371 {
372 return;
373 }
374
375 context_p->skipped_scanner_info_p = prev_p;
376 }
377
378 while (prev_p->next_p->source_p != NULL && prev_p->next_p->source_p <= source_p)
379 {
380 prev_p = prev_p->next_p;
381 }
382
383 context_p->skipped_scanner_info_end_p = prev_p;
384 context_p->next_scanner_info_p = prev_p->next_p;
385 } /* scanner_seek */
386
387 /**
388 * Push a new literal pool.
389 *
390 * @return the newly created literal pool
391 */
392 scanner_literal_pool_t *
scanner_push_literal_pool(parser_context_t * context_p,scanner_context_t * scanner_context_p,uint16_t status_flags)393 scanner_push_literal_pool (parser_context_t *context_p, /**< context */
394 scanner_context_t *scanner_context_p, /**< scanner context */
395 uint16_t status_flags) /**< combination of scanner_literal_pool_flags_t flags */
396 {
397 scanner_literal_pool_t *prev_literal_pool_p = scanner_context_p->active_literal_pool_p;
398 scanner_literal_pool_t *literal_pool_p;
399
400 literal_pool_p = (scanner_literal_pool_t *) scanner_malloc (context_p, sizeof (scanner_literal_pool_t));
401
402 if (!(status_flags & SCANNER_LITERAL_POOL_FUNCTION))
403 {
404 JERRY_ASSERT (prev_literal_pool_p != NULL);
405 status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS;
406
407 #if ENABLED (JERRY_ES2015)
408 const uint16_t copied_flags = (SCANNER_LITERAL_POOL_IN_WITH
409 | SCANNER_LITERAL_POOL_GENERATOR
410 | SCANNER_LITERAL_POOL_ASYNC);
411 #else /* !ENABLED (JERRY_ES2015) */
412 const uint16_t copied_flags = SCANNER_LITERAL_POOL_IN_WITH;
413 #endif /* ENABLED (JERRY_ES2015) */
414
415 status_flags |= (uint16_t) (prev_literal_pool_p->status_flags & copied_flags);
416 }
417 #if ENABLED (JERRY_ES2015)
418 else
419 {
420 context_p->status_flags &= (uint32_t) ~(PARSER_IS_GENERATOR_FUNCTION | PARSER_IS_ASYNC_FUNCTION);
421
422 if (status_flags & SCANNER_LITERAL_POOL_GENERATOR)
423 {
424 context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
425 }
426
427 if (status_flags & SCANNER_LITERAL_POOL_ASYNC)
428 {
429 context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
430 }
431 }
432 #endif /* ENABLED (JERRY_ES2015) */
433
434 if (prev_literal_pool_p != NULL)
435 {
436 const uint16_t copied_flags = SCANNER_LITERAL_POOL_IS_STRICT;
437 status_flags |= (uint16_t) (prev_literal_pool_p->status_flags & copied_flags);
438
439 /* The logical value of these flags must be the same. */
440 JERRY_ASSERT (!(status_flags & SCANNER_LITERAL_POOL_IS_STRICT) == !(context_p->status_flags & PARSER_IS_STRICT));
441 }
442
443 parser_list_init (&literal_pool_p->literal_pool,
444 sizeof (lexer_lit_location_t),
445 (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_lit_location_t)));
446 literal_pool_p->source_p = NULL;
447 literal_pool_p->status_flags = status_flags;
448 literal_pool_p->no_declarations = 0;
449
450 literal_pool_p->prev_p = prev_literal_pool_p;
451 scanner_context_p->active_literal_pool_p = literal_pool_p;
452
453 return literal_pool_p;
454 } /* scanner_push_literal_pool */
455
456 JERRY_STATIC_ASSERT (PARSER_MAXIMUM_IDENT_LENGTH <= UINT8_MAX,
457 maximum_ident_length_must_fit_in_a_byte);
458
459 /**
460 * Checks whether a literal is equal to "arguments".
461 */
462 static inline bool JERRY_ATTR_ALWAYS_INLINE
scanner_literal_is_arguments(lexer_lit_location_t * literal_p)463 scanner_literal_is_arguments (lexer_lit_location_t *literal_p) /**< literal */
464 {
465 return lexer_compare_identifier_to_string (literal_p, (const uint8_t *) "arguments", 9);
466 } /* scanner_literal_is_arguments */
467
468 /**
469 * Pop the last literal pool from the end.
470 */
471 void
scanner_pop_literal_pool(parser_context_t * context_p,scanner_context_t * scanner_context_p)472 scanner_pop_literal_pool (parser_context_t *context_p, /**< context */
473 scanner_context_t *scanner_context_p) /**< scanner context */
474 {
475 scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
476 scanner_literal_pool_t *prev_literal_pool_p = literal_pool_p->prev_p;
477
478 if (literal_pool_p->source_p == NULL)
479 {
480 JERRY_ASSERT (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION);
481 JERRY_ASSERT (literal_pool_p->literal_pool.data.first_p == NULL
482 && literal_pool_p->literal_pool.data.last_p == NULL);
483
484 scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p;
485 scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
486 return;
487 }
488
489 parser_list_iterator_t literal_iterator;
490 lexer_lit_location_t *literal_p;
491 uint16_t status_flags = literal_pool_p->status_flags;
492 bool arguments_required = ((status_flags & (SCANNER_LITERAL_POOL_CAN_EVAL | SCANNER_LITERAL_POOL_NO_ARGUMENTS))
493 == SCANNER_LITERAL_POOL_CAN_EVAL);
494
495 uint8_t can_eval_types = 0;
496 #if ENABLED (JERRY_ES2015)
497 if (prev_literal_pool_p == NULL && !(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL))
498 {
499 can_eval_types |= SCANNER_LITERAL_IS_FUNC;
500 }
501 #endif /* ENABLED (JERRY_ES2015) */
502
503 if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && prev_literal_pool_p != NULL)
504 {
505 prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
506 }
507
508 #if ENABLED (JERRY_DEBUGGER)
509 if (scanner_context_p->status_flags & SCANNER_CONTEXT_DEBUGGER_ENABLED)
510 {
511 /* When debugger is enabled, identifiers are not stored in registers. However,
512 * this does not affect 'eval' detection, so 'arguments' object is not created. */
513 status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
514 }
515 #endif /* ENABLED (JERRY_DEBUGGER) */
516
517 parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
518
519 const uint8_t *prev_source_p = literal_pool_p->source_p - 1;
520 size_t compressed_size = 1;
521 uint32_t no_declarations = literal_pool_p->no_declarations;
522
523 while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
524 {
525 uint8_t type = literal_p->type;
526
527 if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK))
528 {
529 continue;
530 }
531
532 if (!(status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) && scanner_literal_is_arguments (literal_p))
533 {
534 status_flags |= SCANNER_LITERAL_POOL_NO_ARGUMENTS;
535
536 if (type & (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_LOCAL))
537 {
538 arguments_required = false;
539 }
540 else
541 {
542 literal_p->type = 0;
543 arguments_required = true;
544 continue;
545 }
546 }
547
548 #if ENABLED (JERRY_ES2015)
549 if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION)
550 && (type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_FUNC_DECLARATION)) == SCANNER_LITERAL_IS_FUNC)
551 {
552 if (prev_literal_pool_p == NULL
553 && (context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)
554 && scanner_scope_find_let_declaration (context_p, literal_p))
555 {
556 literal_p->type = 0;
557 continue;
558 }
559
560 if (!(type & SCANNER_LITERAL_IS_ARG))
561 {
562 type |= SCANNER_LITERAL_IS_VAR;
563 }
564
565 type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC;
566 literal_p->type = type;
567 }
568 #endif /* ENABLED (JERRY_ES2015) */
569
570 if ((type & SCANNER_LITERAL_IS_LOCAL)
571 || ((type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG))
572 && (status_flags & SCANNER_LITERAL_POOL_FUNCTION)))
573 {
574 JERRY_ASSERT ((status_flags & SCANNER_LITERAL_POOL_FUNCTION)
575 || !(literal_p->type & SCANNER_LITERAL_IS_ARG));
576
577 if (literal_p->length == 0)
578 {
579 compressed_size += 1;
580 continue;
581 }
582
583 no_declarations++;
584
585 if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) || (type & can_eval_types))
586 {
587 type |= SCANNER_LITERAL_NO_REG;
588 literal_p->type = type;
589 }
590
591 if (type & SCANNER_LITERAL_IS_FUNC)
592 {
593 no_declarations++;
594
595 #if ENABLED (JERRY_ES2015)
596 if ((type & (SCANNER_LITERAL_IS_CONST | SCANNER_LITERAL_IS_ARG)) == SCANNER_LITERAL_IS_CONST)
597 {
598 JERRY_ASSERT (type & SCANNER_LITERAL_IS_LET);
599
600 /* Catch parameters cannot be functions. */
601 literal_p->type = (uint8_t) (type & ~SCANNER_LITERAL_IS_FUNC);
602 no_declarations--;
603 }
604 #else /* !ENABLED (JERRY_ES2015) */
605 if (type & SCANNER_LITERAL_IS_LOCAL)
606 {
607 /* Catch parameters cannot be functions. */
608 literal_p->type = (uint8_t) (type & ~SCANNER_LITERAL_IS_FUNC);
609 no_declarations--;
610 }
611 #endif /* ENABLED (JERRY_ES2015) */
612 }
613
614 intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p);
615
616 if (diff >= 1 && diff <= UINT8_MAX)
617 {
618 compressed_size += 2 + 1;
619 }
620 else if (diff >= -UINT8_MAX && diff <= UINT16_MAX)
621 {
622 compressed_size += 2 + 2;
623 }
624 else
625 {
626 compressed_size += 2 + 1 + sizeof (const uint8_t *);
627 }
628
629 prev_source_p = literal_p->char_p + literal_p->length;
630
631 if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION)
632 #if ENABLED (JERRY_ES2015)
633 || ((type & SCANNER_LITERAL_IS_FUNC) && (status_flags & SCANNER_LITERAL_POOL_IS_STRICT))
634 #endif /* ENABLED (JERRY_ES2015) */
635 || !(type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC)))
636 {
637 continue;
638 }
639 }
640
641 if (prev_literal_pool_p != NULL && literal_p->length > 0)
642 {
643 /* Propagate literal to upper level. */
644 lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p,
645 prev_literal_pool_p,
646 literal_p);
647 uint8_t extended_type = literal_location_p->type;
648
649 if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) || (type & SCANNER_LITERAL_NO_REG))
650 {
651 extended_type |= SCANNER_LITERAL_NO_REG;
652 }
653
654 #if ENABLED (JERRY_ES2015)
655 extended_type |= SCANNER_LITERAL_IS_USED;
656
657 if (status_flags & SCANNER_LITERAL_POOL_FUNCTION_STATEMENT)
658 {
659 extended_type |= SCANNER_LITERAL_EARLY_CREATE;
660 }
661
662 const uint8_t mask = (SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_LOCAL);
663
664 if ((type & SCANNER_LITERAL_IS_ARG)
665 || (literal_location_p->type & mask) == SCANNER_LITERAL_IS_LET
666 || (literal_location_p->type & mask) == SCANNER_LITERAL_IS_CONST)
667 {
668 /* Clears the SCANNER_LITERAL_IS_VAR and SCANNER_LITERAL_IS_FUNC flags
669 * for speculative arrow parameters and local (non-var) functions. */
670 type = 0;
671 }
672 #endif /* ENABLED (JERRY_ES2015) */
673
674 type = (uint8_t) (type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_FUNC));
675 JERRY_ASSERT (type == 0 || !(status_flags & SCANNER_LITERAL_POOL_FUNCTION));
676
677 literal_location_p->type = (uint8_t) (extended_type | type);
678 }
679 }
680
681 if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) || (compressed_size > 1))
682 {
683 compressed_size += sizeof (scanner_info_t);
684
685 scanner_info_t *info_p;
686
687 if (prev_literal_pool_p != NULL || scanner_context_p->end_arguments_p == NULL)
688 {
689 info_p = scanner_insert_info (context_p, literal_pool_p->source_p, compressed_size);
690 }
691 else
692 {
693 scanner_info_t *start_info_p = scanner_context_p->end_arguments_p;
694 info_p = scanner_insert_info_before (context_p, literal_pool_p->source_p, start_info_p, compressed_size);
695 }
696
697 if (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
698 {
699 no_declarations = PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK;
700 }
701
702 uint8_t *data_p = (uint8_t *) (info_p + 1);
703
704 if (status_flags & SCANNER_LITERAL_POOL_FUNCTION)
705 {
706 info_p->type = SCANNER_TYPE_FUNCTION;
707
708 uint8_t u8_arg = 0;
709
710 if (arguments_required)
711 {
712 u8_arg |= SCANNER_FUNCTION_ARGUMENTS_NEEDED;
713
714 if (no_declarations < PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
715 {
716 no_declarations++;
717 }
718
719 #if ENABLED (JERRY_ES2015)
720 const uint16_t is_unmapped = SCANNER_LITERAL_POOL_IS_STRICT | SCANNER_LITERAL_POOL_ARGUMENTS_UNMAPPED;
721 #else /* !ENABLED (JERRY_ES2015) */
722 const uint16_t is_unmapped = SCANNER_LITERAL_POOL_IS_STRICT;
723 #endif /* ENABLED (JERRY_ES2015) */
724
725 if (status_flags & is_unmapped)
726 {
727 arguments_required = false;
728 }
729 else
730 {
731 u8_arg |= SCANNER_FUNCTION_MAPPED_ARGUMENTS;
732 }
733 }
734
735 #if ENABLED (JERRY_ES2015)
736 if (status_flags & SCANNER_LITERAL_POOL_ASYNC)
737 {
738 u8_arg |= SCANNER_FUNCTION_ASYNC;
739
740 if (status_flags & SCANNER_LITERAL_POOL_FUNCTION_STATEMENT)
741 {
742 u8_arg |= SCANNER_FUNCTION_STATEMENT;
743 }
744 }
745
746 if (status_flags & SCANNER_LITERAL_POOL_CAN_EVAL)
747 {
748 u8_arg |= SCANNER_FUNCTION_LEXICAL_ENV_NEEDED;
749 }
750 #endif /* ENABLED (JERRY_ES2015) */
751
752 info_p->u8_arg = u8_arg;
753 info_p->u16_arg = (uint16_t) no_declarations;
754 }
755 else
756 {
757 info_p->type = SCANNER_TYPE_BLOCK;
758
759 JERRY_ASSERT (prev_literal_pool_p != NULL);
760 }
761
762 parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
763 prev_source_p = literal_pool_p->source_p - 1;
764 no_declarations = literal_pool_p->no_declarations;
765
766 while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
767 {
768 if (JERRY_UNLIKELY (no_declarations > PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK)
769 || (!(literal_p->type & SCANNER_LITERAL_IS_LOCAL)
770 && (!(literal_p->type & (SCANNER_LITERAL_IS_VAR | SCANNER_LITERAL_IS_ARG))
771 || !(status_flags & SCANNER_LITERAL_POOL_FUNCTION))))
772 {
773 continue;
774 }
775
776 if (literal_p->length == 0)
777 {
778 *data_p++ = SCANNER_STREAM_TYPE_HOLE;
779 continue;
780 }
781
782 no_declarations++;
783
784 uint8_t type = SCANNER_STREAM_TYPE_VAR;
785
786 if (literal_p->type & SCANNER_LITERAL_IS_FUNC)
787 {
788 no_declarations++;
789 type = SCANNER_STREAM_TYPE_FUNC;
790
791 if (literal_p->type & SCANNER_LITERAL_IS_ARG)
792 {
793 type = SCANNER_STREAM_TYPE_ARG_FUNC;
794
795 #if ENABLED (JERRY_ES2015)
796 if (literal_p->type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
797 {
798 type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC;
799 }
800 #endif /* ENABLED (JERRY_ES2015) */
801 }
802 }
803 else if (literal_p->type & SCANNER_LITERAL_IS_ARG)
804 {
805 type = SCANNER_STREAM_TYPE_ARG;
806
807 #if ENABLED (JERRY_ES2015)
808 if (literal_p->type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
809 {
810 type = SCANNER_STREAM_TYPE_DESTRUCTURED_ARG;
811 }
812
813 if (literal_p->type & SCANNER_LITERAL_IS_VAR)
814 {
815 type = (uint8_t) (type + 1);
816
817 JERRY_ASSERT (type == SCANNER_STREAM_TYPE_ARG_VAR
818 || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR);
819 }
820 #endif /* ENABLED (JERRY_ES2015) */
821 }
822 #if ENABLED (JERRY_ES2015)
823 else if (literal_p->type & SCANNER_LITERAL_IS_LET)
824 {
825 if (!(literal_p->type & SCANNER_LITERAL_IS_CONST))
826 {
827 type = SCANNER_STREAM_TYPE_LET;
828
829 if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && (literal_p->type & SCANNER_LITERAL_NO_REG))
830 {
831 literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
832 }
833 }
834 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
835 else if (prev_literal_pool_p == NULL)
836 {
837 type = SCANNER_STREAM_TYPE_IMPORT;
838 }
839 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
840 else
841 {
842 type = SCANNER_STREAM_TYPE_LOCAL;
843 }
844 }
845 else if (literal_p->type & SCANNER_LITERAL_IS_CONST)
846 {
847 type = SCANNER_STREAM_TYPE_CONST;
848
849 if ((status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) && (literal_p->type & SCANNER_LITERAL_NO_REG))
850 {
851 literal_p->type |= SCANNER_LITERAL_EARLY_CREATE;
852 }
853 }
854
855 if (literal_p->type & SCANNER_LITERAL_EARLY_CREATE)
856 {
857 type |= SCANNER_STREAM_NO_REG | SCANNER_STREAM_EARLY_CREATE;
858 }
859 #endif /* ENABLED (JERRY_ES2015) */
860
861 if (literal_p->has_escape)
862 {
863 type |= SCANNER_STREAM_HAS_ESCAPE;
864 }
865
866 if ((literal_p->type & SCANNER_LITERAL_NO_REG)
867 || (arguments_required && (literal_p->type & SCANNER_LITERAL_IS_ARG)))
868 {
869 type |= SCANNER_STREAM_NO_REG;
870 }
871
872 data_p[0] = type;
873 data_p[1] = (uint8_t) literal_p->length;
874 data_p += 3;
875
876 intptr_t diff = (intptr_t) (literal_p->char_p - prev_source_p);
877
878 if (diff >= 1 && diff <= UINT8_MAX)
879 {
880 data_p[-1] = (uint8_t) diff;
881 }
882 else if (diff >= -UINT8_MAX && diff <= UINT16_MAX)
883 {
884 if (diff < 0)
885 {
886 diff = -diff;
887 }
888
889 data_p[-3] |= SCANNER_STREAM_UINT16_DIFF;
890 data_p[-1] = (uint8_t) diff;
891 data_p[0] = (uint8_t) (diff >> 8);
892 data_p += 1;
893 }
894 else
895 {
896 data_p[-1] = 0;
897 memcpy (data_p, &literal_p->char_p, sizeof (const uint8_t *));
898 data_p += sizeof (const uint8_t *);
899 }
900
901 prev_source_p = literal_p->char_p + literal_p->length;
902 }
903
904 data_p[0] = SCANNER_STREAM_TYPE_END;
905
906 JERRY_ASSERT (((uint8_t *) info_p) + compressed_size == data_p + 1);
907 }
908
909 if (!(status_flags & SCANNER_LITERAL_POOL_FUNCTION)
910 && prev_literal_pool_p->no_declarations < no_declarations)
911 {
912 prev_literal_pool_p->no_declarations = (uint16_t) no_declarations;
913 }
914
915 if ((status_flags & SCANNER_LITERAL_POOL_FUNCTION) && prev_literal_pool_p != NULL)
916 {
917 if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IS_STRICT)
918 {
919 context_p->status_flags |= PARSER_IS_STRICT;
920 }
921 else
922 {
923 context_p->status_flags &= (uint32_t) ~PARSER_IS_STRICT;
924 }
925
926 #if ENABLED (JERRY_ES2015)
927 if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_GENERATOR)
928 {
929 context_p->status_flags |= PARSER_IS_GENERATOR_FUNCTION;
930 }
931 else
932 {
933 context_p->status_flags &= (uint32_t) ~PARSER_IS_GENERATOR_FUNCTION;
934 }
935
936 if (prev_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_ASYNC)
937 {
938 context_p->status_flags |= PARSER_IS_ASYNC_FUNCTION;
939 }
940 else
941 {
942 context_p->status_flags &= (uint32_t) ~PARSER_IS_ASYNC_FUNCTION;
943 }
944 #endif /* ENABLED (JERRY_ES2015) */
945 }
946
947 scanner_context_p->active_literal_pool_p = literal_pool_p->prev_p;
948
949 parser_list_free (&literal_pool_p->literal_pool);
950 scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
951 } /* scanner_pop_literal_pool */
952
953 /**
954 * Filter out the arguments from a literal pool.
955 */
956 void
scanner_filter_arguments(parser_context_t * context_p,scanner_context_t * scanner_context_p)957 scanner_filter_arguments (parser_context_t *context_p, /**< context */
958 scanner_context_t *scanner_context_p) /**< scanner context */
959 {
960 /* Fast case: check whether all literals are arguments. */
961 scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
962 scanner_literal_pool_t *prev_literal_pool_p = literal_pool_p->prev_p;
963 parser_list_iterator_t literal_iterator;
964 lexer_lit_location_t *literal_p;
965 bool can_eval = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_CAN_EVAL) != 0;
966 bool has_arguments = (literal_pool_p->status_flags & SCANNER_LITERAL_POOL_NO_ARGUMENTS) == 0;
967
968 if (can_eval && prev_literal_pool_p != NULL)
969 {
970 prev_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
971 }
972
973 literal_pool_p->status_flags &= (uint16_t) ~SCANNER_LITERAL_POOL_CAN_EVAL;
974
975 parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
976
977 while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
978 {
979 #if ENABLED (JERRY_ES2015)
980 if (can_eval || (literal_p->type & SCANNER_LITERAL_EARLY_CREATE))
981 {
982 literal_p->type |= SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE;
983 }
984 #else /* !ENABLED (JERRY_ES2015) */
985 if (can_eval)
986 {
987 literal_p->type |= SCANNER_LITERAL_NO_REG;
988 }
989 #endif /* ENABLED (JERRY_ES2015) */
990
991 uint8_t type = literal_p->type;
992
993 if (!(type & SCANNER_LITERAL_IS_ARG) && !(has_arguments && scanner_literal_is_arguments (literal_p)))
994 {
995 break;
996 }
997
998 #if ENABLED (JERRY_ES2015)
999 if (type & (SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG))
1000 {
1001 break;
1002 }
1003 #endif /* ENABLED (JERRY_ES2015) */
1004 }
1005
1006 if (literal_p == NULL)
1007 {
1008 return;
1009 }
1010
1011 scanner_literal_pool_t *new_literal_pool_p;
1012
1013 new_literal_pool_p = (scanner_literal_pool_t *) scanner_malloc (context_p, sizeof (scanner_literal_pool_t));
1014
1015 new_literal_pool_p->prev_p = literal_pool_p;
1016 scanner_context_p->active_literal_pool_p = new_literal_pool_p;
1017
1018 *new_literal_pool_p = *literal_pool_p;
1019 parser_list_init (&new_literal_pool_p->literal_pool,
1020 sizeof (lexer_lit_location_t),
1021 (uint32_t) ((128 - sizeof (void *)) / sizeof (lexer_lit_location_t)));
1022
1023 parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1024
1025 #if ENABLED (JERRY_ES2015)
1026 /* Destructured args are placed after the other arguments because of register assignments. */
1027 bool has_destructured_arg = false;
1028 #endif /* ENABLED (JERRY_ES2015) */
1029
1030 while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1031 {
1032 uint8_t type = literal_p->type;
1033
1034 if ((type & SCANNER_LITERAL_IS_ARG) || (has_arguments && scanner_literal_is_arguments (literal_p)))
1035 {
1036 #if ENABLED (JERRY_ES2015)
1037 if (can_eval || (literal_p->type & SCANNER_LITERAL_EARLY_CREATE))
1038 {
1039 type |= SCANNER_LITERAL_NO_REG | SCANNER_LITERAL_EARLY_CREATE;
1040 literal_p->type = type;
1041 }
1042
1043 if (type & (SCANNER_LITERAL_IS_DESTRUCTURED_ARG | SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG))
1044 {
1045 has_destructured_arg = true;
1046
1047 if (type & SCANNER_LITERAL_IS_DESTRUCTURED_ARG)
1048 {
1049 continue;
1050 }
1051
1052 type &= (uint8_t) ~SCANNER_LITERAL_IS_ARROW_DESTRUCTURED_ARG;
1053 type |= SCANNER_LITERAL_IS_DESTRUCTURED_ARG;
1054
1055 literal_p->type = type;
1056 continue;
1057 }
1058 #else /* !ENABLED (JERRY_ES2015) */
1059 if (can_eval)
1060 {
1061 literal_p->type |= SCANNER_LITERAL_NO_REG;
1062 }
1063 #endif /* ENABLED (JERRY_ES2015) */
1064
1065 lexer_lit_location_t *new_literal_p;
1066 new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool);
1067 *new_literal_p = *literal_p;
1068 }
1069 else if (prev_literal_pool_p != NULL)
1070 {
1071 /* Propagate literal to upper level. */
1072 lexer_lit_location_t *literal_location_p = scanner_add_custom_literal (context_p,
1073 prev_literal_pool_p,
1074 literal_p);
1075 type |= SCANNER_LITERAL_NO_REG;
1076
1077 #if ENABLED (JERRY_ES2015)
1078 type |= SCANNER_LITERAL_IS_USED;
1079 #endif /* ENABLED (JERRY_ES2015) */
1080
1081 literal_location_p->type |= type;
1082 }
1083 }
1084
1085 #if ENABLED (JERRY_ES2015)
1086 if (has_destructured_arg)
1087 {
1088 parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1089
1090 while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1091 {
1092 const uint8_t expected_flags = SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_IS_DESTRUCTURED_ARG;
1093
1094 if ((literal_p->type & expected_flags) == expected_flags)
1095 {
1096 lexer_lit_location_t *new_literal_p;
1097 new_literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &new_literal_pool_p->literal_pool);
1098 *new_literal_p = *literal_p;
1099 }
1100 }
1101 }
1102 #endif /* ENABLED (JERRY_ES2015) */
1103
1104 new_literal_pool_p->prev_p = prev_literal_pool_p;
1105
1106 parser_list_free (&literal_pool_p->literal_pool);
1107 scanner_free (literal_pool_p, sizeof (scanner_literal_pool_t));
1108 } /* scanner_filter_arguments */
1109
1110 /**
1111 * Add any literal to the specified literal pool.
1112 *
1113 * @return pointer to the literal
1114 */
1115 lexer_lit_location_t *
scanner_add_custom_literal(parser_context_t * context_p,scanner_literal_pool_t * literal_pool_p,const lexer_lit_location_t * literal_location_p)1116 scanner_add_custom_literal (parser_context_t *context_p, /**< context */
1117 scanner_literal_pool_t *literal_pool_p, /**< literal pool */
1118 const lexer_lit_location_t *literal_location_p) /**< literal */
1119 {
1120 parser_list_iterator_t literal_iterator;
1121 parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1122 lexer_lit_location_t *literal_p;
1123
1124 const uint8_t *char_p = literal_location_p->char_p;
1125 prop_length_t length = literal_location_p->length;
1126
1127 if (JERRY_LIKELY (!literal_location_p->has_escape))
1128 {
1129 while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1130 {
1131 if (literal_p->length == length)
1132 {
1133 if (JERRY_LIKELY (!literal_p->has_escape))
1134 {
1135 if (memcmp (literal_p->char_p, char_p, length) == 0)
1136 {
1137 return literal_p;
1138 }
1139 }
1140 else if (lexer_compare_identifier_to_string (literal_p, char_p, length))
1141 {
1142 /* The non-escaped version is preferred. */
1143 literal_p->char_p = char_p;
1144 literal_p->has_escape = 0;
1145 return literal_p;
1146 }
1147 }
1148 }
1149 }
1150 else
1151 {
1152 while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1153 {
1154 if (lexer_compare_identifiers (context_p, literal_p, literal_location_p))
1155 {
1156 return literal_p;
1157 }
1158 }
1159 }
1160
1161 literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool);
1162 *literal_p = *literal_location_p;
1163
1164 literal_p->type = 0;
1165
1166 return literal_p;
1167 } /* scanner_add_custom_literal */
1168
1169 /**
1170 * Add the current literal token to the current literal pool.
1171 *
1172 * @return pointer to the literal
1173 */
1174 inline lexer_lit_location_t * JERRY_ATTR_ALWAYS_INLINE
scanner_add_literal(parser_context_t * context_p,scanner_context_t * scanner_context_p)1175 scanner_add_literal (parser_context_t *context_p, /**< context */
1176 scanner_context_t *scanner_context_p) /**< scanner context */
1177 {
1178 return scanner_add_custom_literal (context_p,
1179 scanner_context_p->active_literal_pool_p,
1180 &context_p->token.lit_location);
1181 } /* scanner_add_literal */
1182
1183 /**
1184 * Add the current literal token to the current literal pool and
1185 * set SCANNER_LITERAL_NO_REG if it is inside a with statement.
1186 *
1187 * @return pointer to the literal
1188 */
1189 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_add_reference(parser_context_t * context_p,scanner_context_t * scanner_context_p)1190 scanner_add_reference (parser_context_t *context_p, /**< context */
1191 scanner_context_t *scanner_context_p) /**< scanner context */
1192 {
1193 lexer_lit_location_t *lit_location_p = scanner_add_custom_literal (context_p,
1194 scanner_context_p->active_literal_pool_p,
1195 &context_p->token.lit_location);
1196 #if ENABLED (JERRY_ES2015)
1197 lit_location_p->type |= SCANNER_LITERAL_IS_USED;
1198 #endif /* ENABLED (JERRY_ES2015) */
1199
1200 if (scanner_context_p->active_literal_pool_p->status_flags & SCANNER_LITERAL_POOL_IN_WITH)
1201 {
1202 lit_location_p->type |= SCANNER_LITERAL_NO_REG;
1203 }
1204
1205 scanner_detect_eval_call (context_p, scanner_context_p);
1206 } /* scanner_add_reference */
1207
1208 /**
1209 * Append an argument to the literal pool. If the argument is already present, make it a "hole".
1210 *
1211 * @return newly created literal
1212 */
1213 lexer_lit_location_t *
scanner_append_argument(parser_context_t * context_p,scanner_context_t * scanner_context_p)1214 scanner_append_argument (parser_context_t *context_p, /**< context */
1215 scanner_context_t *scanner_context_p) /**< scanner context */
1216 {
1217 scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
1218 parser_list_iterator_t literal_iterator;
1219 parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1220 lexer_lit_location_t *literal_location_p = &context_p->token.lit_location;
1221 lexer_lit_location_t *literal_p;
1222
1223 const uint8_t *char_p = literal_location_p->char_p;
1224 prop_length_t length = literal_location_p->length;
1225
1226 if (JERRY_LIKELY (!context_p->token.lit_location.has_escape))
1227 {
1228 while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1229 {
1230 if (literal_p->length == length)
1231 {
1232 if (JERRY_LIKELY (!literal_p->has_escape))
1233 {
1234 if (memcmp (literal_p->char_p, char_p, length) == 0)
1235 {
1236 break;
1237 }
1238 }
1239 else if (lexer_compare_identifier_to_string (literal_p, char_p, length))
1240 {
1241 break;
1242 }
1243 }
1244 }
1245 }
1246 else
1247 {
1248 while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1249 {
1250 if (lexer_compare_identifiers (context_p, literal_p, literal_location_p))
1251 {
1252 break;
1253 }
1254 }
1255 }
1256
1257 uint8_t literal_type = SCANNER_LITERAL_IS_ARG;
1258
1259 if (literal_p != NULL)
1260 {
1261 literal_p->length = 0;
1262
1263 #if ENABLED (JERRY_ES2015)
1264 if (literal_p->type & SCANNER_LITERAL_IS_USED)
1265 {
1266 literal_type = SCANNER_LITERAL_IS_ARG | SCANNER_LITERAL_EARLY_CREATE;
1267 }
1268 #endif /* ENABLED (JERRY_ES2015) */
1269 }
1270
1271 literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool);
1272
1273 *literal_p = context_p->token.lit_location;
1274 literal_p->type = literal_type;
1275
1276 return literal_p;
1277 } /* scanner_append_argument */
1278
1279 /**
1280 * Check whether an eval call is performed and update the status flags accordingly.
1281 */
1282 void
scanner_detect_eval_call(parser_context_t * context_p,scanner_context_t * scanner_context_p)1283 scanner_detect_eval_call (parser_context_t *context_p, /**< context */
1284 scanner_context_t *scanner_context_p) /**< scanner context */
1285 {
1286 if (context_p->token.keyword_type == LEXER_KEYW_EVAL
1287 && lexer_check_next_character (context_p, LIT_CHAR_LEFT_PAREN))
1288 {
1289 scanner_context_p->active_literal_pool_p->status_flags |= SCANNER_LITERAL_POOL_CAN_EVAL;
1290 }
1291 } /* scanner_detect_eval_call */
1292
1293 #if ENABLED (JERRY_ES2015)
1294
1295 /**
1296 * Find a let/const declaration of a given literal.
1297 *
1298 * @return true - if the literal is found, false - otherwise
1299 */
1300 bool
scanner_scope_find_let_declaration(parser_context_t * context_p,lexer_lit_location_t * literal_p)1301 scanner_scope_find_let_declaration (parser_context_t *context_p, /**< context */
1302 lexer_lit_location_t *literal_p) /**< literal */
1303 {
1304 ecma_string_t *name_p;
1305
1306 if (JERRY_LIKELY (!literal_p->has_escape))
1307 {
1308 name_p = ecma_new_ecma_string_from_utf8 (literal_p->char_p, literal_p->length);
1309 }
1310 else
1311 {
1312 uint8_t *destination_p = (uint8_t *) scanner_malloc (context_p, literal_p->length);
1313
1314 lexer_convert_ident_to_cesu8 (destination_p, literal_p->char_p, literal_p->length);
1315
1316 name_p = ecma_new_ecma_string_from_utf8 (destination_p, literal_p->length);
1317 scanner_free (destination_p, literal_p->length);
1318 }
1319
1320 ecma_object_t *lex_env_p = JERRY_CONTEXT (vm_top_context_p)->lex_env_p;
1321
1322 while (lex_env_p->type_flags_refs & ECMA_OBJECT_FLAG_BLOCK)
1323 {
1324 if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
1325 {
1326 ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
1327
1328 if (property_p != NULL && ecma_is_property_enumerable (*property_p))
1329 {
1330 ecma_deref_ecma_string (name_p);
1331 return true;
1332 }
1333 }
1334
1335 JERRY_ASSERT (lex_env_p->u2.outer_reference_cp != JMEM_CP_NULL);
1336 lex_env_p = ECMA_GET_NON_NULL_POINTER (ecma_object_t, lex_env_p->u2.outer_reference_cp);
1337 }
1338
1339 if (ecma_get_lex_env_type (lex_env_p) == ECMA_LEXICAL_ENVIRONMENT_DECLARATIVE)
1340 {
1341 ecma_property_t *property_p = ecma_find_named_property (lex_env_p, name_p);
1342
1343 if (property_p != NULL && ecma_is_property_enumerable (*property_p))
1344 {
1345 ecma_deref_ecma_string (name_p);
1346 return true;
1347 }
1348 }
1349
1350 ecma_deref_ecma_string (name_p);
1351 return false;
1352 } /* scanner_scope_find_let_declaration */
1353
1354 /**
1355 * Throws an error for invalid var statements.
1356 */
1357 void
scanner_detect_invalid_var(parser_context_t * context_p,scanner_context_t * scanner_context_p,lexer_lit_location_t * var_literal_p)1358 scanner_detect_invalid_var (parser_context_t *context_p, /**< context */
1359 scanner_context_t *scanner_context_p, /**< scanner context */
1360 lexer_lit_location_t *var_literal_p) /**< var literal */
1361 {
1362 if (var_literal_p->type & SCANNER_LITERAL_IS_LOCAL
1363 && !(var_literal_p->type & (SCANNER_LITERAL_IS_FUNC | SCANNER_LITERAL_IS_ARG))
1364 && (var_literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL)
1365 {
1366 scanner_raise_redeclaration_error (context_p);
1367 }
1368
1369 scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
1370 const uint8_t *char_p = var_literal_p->char_p;
1371 prop_length_t length = var_literal_p->length;
1372
1373 while (!(literal_pool_p->status_flags & SCANNER_LITERAL_POOL_FUNCTION))
1374 {
1375 literal_pool_p = literal_pool_p->prev_p;
1376
1377 parser_list_iterator_t literal_iterator;
1378 parser_list_iterator_init (&literal_pool_p->literal_pool, &literal_iterator);
1379 lexer_lit_location_t *literal_p;
1380
1381 if (JERRY_LIKELY (!context_p->token.lit_location.has_escape))
1382 {
1383 while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1384 {
1385 if (literal_p->type & SCANNER_LITERAL_IS_LOCAL
1386 && !(literal_p->type & SCANNER_LITERAL_IS_ARG)
1387 && (literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL
1388 && literal_p->length == length)
1389 {
1390 if (JERRY_LIKELY (!literal_p->has_escape))
1391 {
1392 if (memcmp (literal_p->char_p, char_p, length) == 0)
1393 {
1394 scanner_raise_redeclaration_error (context_p);
1395 return;
1396 }
1397 }
1398 else if (lexer_compare_identifier_to_string (literal_p, char_p, length))
1399 {
1400 scanner_raise_redeclaration_error (context_p);
1401 return;
1402 }
1403 }
1404 }
1405 }
1406 else
1407 {
1408 while ((literal_p = (lexer_lit_location_t *) parser_list_iterator_next (&literal_iterator)) != NULL)
1409 {
1410 if (literal_p->type & SCANNER_LITERAL_IS_LOCAL
1411 && !(literal_p->type & SCANNER_LITERAL_IS_ARG)
1412 && (literal_p->type & SCANNER_LITERAL_IS_LOCAL) != SCANNER_LITERAL_IS_LOCAL
1413 && lexer_compare_identifiers (context_p, literal_p, var_literal_p))
1414 {
1415 scanner_raise_redeclaration_error (context_p);
1416 return;
1417 }
1418 }
1419 }
1420 }
1421
1422 if ((context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)
1423 && scanner_scope_find_let_declaration (context_p, var_literal_p))
1424 {
1425 scanner_raise_redeclaration_error (context_p);
1426 }
1427 } /* scanner_detect_invalid_var */
1428
1429 /**
1430 * Throws an error for invalid let statements.
1431 */
1432 void
scanner_detect_invalid_let(parser_context_t * context_p,lexer_lit_location_t * let_literal_p)1433 scanner_detect_invalid_let (parser_context_t *context_p, /**< context */
1434 lexer_lit_location_t *let_literal_p) /**< let literal */
1435 {
1436 if (let_literal_p->type & (SCANNER_LITERAL_IS_ARG
1437 | SCANNER_LITERAL_IS_VAR
1438 | SCANNER_LITERAL_IS_LOCAL))
1439 {
1440 scanner_raise_redeclaration_error (context_p);
1441 }
1442
1443 if (let_literal_p->type & SCANNER_LITERAL_IS_FUNC)
1444 {
1445 let_literal_p->type &= (uint8_t) ~SCANNER_LITERAL_IS_FUNC;
1446 }
1447 } /* scanner_detect_invalid_let */
1448
1449 /**
1450 * Push the values required for class declaration parsing.
1451 */
1452 void
scanner_push_class_declaration(parser_context_t * context_p,scanner_context_t * scanner_context_p,uint8_t stack_mode)1453 scanner_push_class_declaration (parser_context_t *context_p, /**< context */
1454 scanner_context_t *scanner_context_p, /* scanner context */
1455 uint8_t stack_mode) /**< stack mode */
1456 {
1457 JERRY_ASSERT (context_p->token.type == LEXER_KEYW_CLASS);
1458
1459 parser_stack_push_uint8 (context_p, stack_mode);
1460 scanner_source_start_t source_start;
1461 source_start.source_p = context_p->source_p;
1462
1463 parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t));
1464 parser_stack_push_uint8 (context_p, SCAN_STACK_IMPLICIT_CLASS_CONSTRUCTOR);
1465 scanner_context_p->mode = SCAN_MODE_CLASS_DECLARATION;
1466
1467 lexer_next_token (context_p);
1468 } /* scanner_push_class_declaration */
1469
1470 /**
1471 * Push the values required for destructuring assignment or binding parsing.
1472 */
1473 void
scanner_push_destructuring_pattern(parser_context_t * context_p,scanner_context_t * scanner_context_p,uint8_t binding_type,bool is_nested)1474 scanner_push_destructuring_pattern (parser_context_t *context_p, /**< context */
1475 scanner_context_t *scanner_context_p, /**< scanner context */
1476 uint8_t binding_type, /**< type of destructuring binding pattern */
1477 bool is_nested) /**< nested declaration */
1478 {
1479 JERRY_ASSERT (binding_type != SCANNER_BINDING_NONE || !is_nested);
1480
1481 scanner_source_start_t source_start;
1482 source_start.source_p = context_p->source_p;
1483
1484 parser_stack_push (context_p, &source_start, sizeof (scanner_source_start_t));
1485 parser_stack_push_uint8 (context_p, scanner_context_p->binding_type);
1486 scanner_context_p->binding_type = binding_type;
1487
1488 if (SCANNER_NEEDS_BINDING_LIST (binding_type))
1489 {
1490 scanner_binding_list_t *binding_list_p;
1491 binding_list_p = (scanner_binding_list_t *) scanner_malloc (context_p, sizeof (scanner_binding_list_t));
1492
1493 binding_list_p->prev_p = scanner_context_p->active_binding_list_p;
1494 binding_list_p->items_p = NULL;
1495 binding_list_p->is_nested = is_nested;
1496
1497 scanner_context_p->active_binding_list_p = binding_list_p;
1498 }
1499 } /* scanner_push_destructuring_pattern */
1500
1501 /**
1502 * Pop binding list.
1503 */
1504 void
scanner_pop_binding_list(scanner_context_t * scanner_context_p)1505 scanner_pop_binding_list (scanner_context_t *scanner_context_p) /**< scanner context */
1506 {
1507 scanner_binding_list_t *binding_list_p = scanner_context_p->active_binding_list_p;
1508 scanner_binding_item_t *item_p = binding_list_p->items_p;
1509 scanner_binding_list_t *prev_binding_list_p = binding_list_p->prev_p;
1510 bool is_nested = binding_list_p->is_nested;
1511
1512 scanner_free (binding_list_p, sizeof (scanner_binding_list_t));
1513 scanner_context_p->active_binding_list_p = prev_binding_list_p;
1514
1515 JERRY_ASSERT (binding_list_p != NULL);
1516
1517 if (!is_nested)
1518 {
1519 while (item_p != NULL)
1520 {
1521 scanner_binding_item_t *next_p = item_p->next_p;
1522
1523 JERRY_ASSERT (item_p->literal_p->type & (SCANNER_LITERAL_IS_LOCAL | SCANNER_LITERAL_IS_ARG));
1524
1525 scanner_free (item_p, sizeof (scanner_binding_item_t));
1526 item_p = next_p;
1527 }
1528 return;
1529 }
1530
1531 JERRY_ASSERT (prev_binding_list_p != NULL);
1532
1533 while (item_p != NULL)
1534 {
1535 scanner_binding_item_t *next_p = item_p->next_p;
1536
1537 item_p->next_p = prev_binding_list_p->items_p;
1538 prev_binding_list_p->items_p = item_p;
1539
1540 item_p = next_p;
1541 }
1542 } /* scanner_pop_binding_list */
1543
1544 /**
1545 * Append a hole into the literal pool.
1546 */
1547 void
scanner_append_hole(parser_context_t * context_p,scanner_context_t * scanner_context_p)1548 scanner_append_hole (parser_context_t *context_p, scanner_context_t *scanner_context_p)
1549 {
1550 scanner_literal_pool_t *literal_pool_p = scanner_context_p->active_literal_pool_p;
1551
1552 lexer_lit_location_t *literal_p;
1553 literal_p = (lexer_lit_location_t *) parser_list_append (context_p, &literal_pool_p->literal_pool);
1554
1555 literal_p->char_p = NULL;
1556 literal_p->length = 0;
1557 literal_p->type = SCANNER_LITERAL_IS_ARG;
1558 literal_p->has_escape = 0;
1559 } /* scanner_append_hole */
1560
1561 #endif /* ENABLED (JERRY_ES2015) */
1562
1563 /**
1564 * Reverse the scanner info chain after the scanning is completed.
1565 */
1566 void
scanner_reverse_info_list(parser_context_t * context_p)1567 scanner_reverse_info_list (parser_context_t *context_p) /**< context */
1568 {
1569 scanner_info_t *scanner_info_p = context_p->next_scanner_info_p;
1570 scanner_info_t *last_scanner_info_p = NULL;
1571
1572 if (scanner_info_p->type == SCANNER_TYPE_END)
1573 {
1574 return;
1575 }
1576
1577 do
1578 {
1579 scanner_info_t *next_scanner_info_p = scanner_info_p->next_p;
1580 scanner_info_p->next_p = last_scanner_info_p;
1581
1582 last_scanner_info_p = scanner_info_p;
1583 scanner_info_p = next_scanner_info_p;
1584 }
1585 while (scanner_info_p->type != SCANNER_TYPE_END);
1586
1587 context_p->next_scanner_info_p->next_p = scanner_info_p;
1588 context_p->next_scanner_info_p = last_scanner_info_p;
1589 } /* scanner_reverse_info_list */
1590
1591 /**
1592 * Release unused scanner info blocks.
1593 * This should happen only if an error is occured.
1594 */
1595 void
scanner_cleanup(parser_context_t * context_p)1596 scanner_cleanup (parser_context_t *context_p) /**< context */
1597 {
1598 if (context_p->skipped_scanner_info_p != NULL)
1599 {
1600 context_p->skipped_scanner_info_end_p->next_p = context_p->next_scanner_info_p;
1601 context_p->next_scanner_info_p = context_p->skipped_scanner_info_p;
1602 context_p->skipped_scanner_info_p = NULL;
1603 }
1604
1605 scanner_info_t *scanner_info_p = context_p->next_scanner_info_p;
1606
1607 while (scanner_info_p != NULL)
1608 {
1609 scanner_info_t *next_scanner_info_p = scanner_info_p->next_p;
1610
1611 size_t size = sizeof (scanner_info_t);
1612
1613 switch (scanner_info_p->type)
1614 {
1615 case SCANNER_TYPE_END:
1616 {
1617 scanner_info_p = context_p->active_scanner_info_p;
1618 continue;
1619 }
1620 case SCANNER_TYPE_FUNCTION:
1621 case SCANNER_TYPE_BLOCK:
1622 {
1623 size = scanner_get_stream_size (scanner_info_p, sizeof (scanner_info_t));
1624 break;
1625 }
1626 case SCANNER_TYPE_WHILE:
1627 case SCANNER_TYPE_FOR_IN:
1628 #if ENABLED (JERRY_ES2015)
1629 case SCANNER_TYPE_FOR_OF:
1630 #endif /* ENABLED (JERRY_ES2015) */
1631 case SCANNER_TYPE_CASE:
1632 #if ENABLED (JERRY_ES2015)
1633 case SCANNER_TYPE_INITIALIZER:
1634 #endif /* ENABLED (JERRY_ES2015) */
1635 {
1636 size = sizeof (scanner_location_info_t);
1637 break;
1638 }
1639 case SCANNER_TYPE_FOR:
1640 {
1641 size = sizeof (scanner_for_info_t);
1642 break;
1643 }
1644 case SCANNER_TYPE_SWITCH:
1645 {
1646 scanner_release_switch_cases (((scanner_switch_info_t *) scanner_info_p)->case_p);
1647 size = sizeof (scanner_switch_info_t);
1648 break;
1649 }
1650 default:
1651 {
1652 #if ENABLED (JERRY_ES2015)
1653 JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS
1654 || scanner_info_p->type == SCANNER_TYPE_LET_EXPRESSION
1655 || scanner_info_p->type == SCANNER_TYPE_CLASS_CONSTRUCTOR
1656 || scanner_info_p->type == SCANNER_TYPE_ERR_REDECLARED
1657 || scanner_info_p->type == SCANNER_TYPE_ERR_ASYNC_FUNCTION);
1658 #else /* !ENABLED (JERRY_ES2015) */
1659 JERRY_ASSERT (scanner_info_p->type == SCANNER_TYPE_END_ARGUMENTS);
1660 #endif /* ENABLED (JERRY_ES2015) */
1661 break;
1662 }
1663 }
1664
1665 scanner_free (scanner_info_p, size);
1666 scanner_info_p = next_scanner_info_p;
1667 }
1668
1669 context_p->next_scanner_info_p = NULL;
1670 context_p->active_scanner_info_p = NULL;
1671 } /* scanner_cleanup */
1672
1673 /**
1674 * Checks whether a context needs to be created for a block.
1675 *
1676 * @return true - if context is needed,
1677 * false - otherwise
1678 */
1679 bool
scanner_is_context_needed(parser_context_t * context_p,parser_check_context_type_t check_type)1680 scanner_is_context_needed (parser_context_t *context_p, /**< context */
1681 parser_check_context_type_t check_type) /**< context type */
1682 {
1683 scanner_info_t *info_p = context_p->next_scanner_info_p;
1684 const uint8_t *data_p = (const uint8_t *) (info_p + 1);
1685
1686 JERRY_UNUSED (check_type);
1687
1688 #if ENABLED (JERRY_ES2015)
1689 JERRY_ASSERT ((check_type == PARSER_CHECK_BLOCK_CONTEXT ? info_p->type == SCANNER_TYPE_BLOCK
1690 : info_p->type == SCANNER_TYPE_FUNCTION));
1691
1692 uint32_t scope_stack_reg_top = (check_type != PARSER_CHECK_GLOBAL_CONTEXT ? context_p->scope_stack_reg_top
1693 : 0);
1694 #else /* !ENABLED (JERRY_ES2015) */
1695 JERRY_ASSERT (check_type == PARSER_CHECK_BLOCK_CONTEXT);
1696 JERRY_ASSERT (info_p->type == SCANNER_TYPE_BLOCK);
1697
1698 uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top;
1699 #endif /* !JERRY_NDEBUG */
1700
1701 while (data_p[0] != SCANNER_STREAM_TYPE_END)
1702 {
1703 uint8_t data = data_p[0];
1704
1705 #if ENABLED (JERRY_ES2015)
1706 uint32_t type = data & SCANNER_STREAM_TYPE_MASK;
1707
1708 if (JERRY_UNLIKELY (type == SCANNER_STREAM_TYPE_HOLE))
1709 {
1710 JERRY_ASSERT (check_type == PARSER_CHECK_FUNCTION_CONTEXT);
1711 data_p++;
1712 continue;
1713 }
1714
1715 #ifndef JERRY_NDEBUG
1716 if (check_type == PARSER_CHECK_BLOCK_CONTEXT)
1717 {
1718 JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR
1719 || type == SCANNER_STREAM_TYPE_LET
1720 || type == SCANNER_STREAM_TYPE_CONST
1721 || type == SCANNER_STREAM_TYPE_LOCAL
1722 || type == SCANNER_STREAM_TYPE_FUNC);
1723 }
1724 else if (check_type == PARSER_CHECK_GLOBAL_CONTEXT)
1725 {
1726 /* FIXME: a private declarative lexical environment should always be present
1727 * for modules. Remove SCANNER_STREAM_TYPE_IMPORT after it is implemented. */
1728 JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR
1729 || type == SCANNER_STREAM_TYPE_LET
1730 || type == SCANNER_STREAM_TYPE_CONST
1731 || type == SCANNER_STREAM_TYPE_FUNC
1732 || type == SCANNER_STREAM_TYPE_IMPORT);
1733
1734 /* Only let/const can be stored in registers */
1735 JERRY_ASSERT ((data & SCANNER_STREAM_NO_REG)
1736 || (type == SCANNER_STREAM_TYPE_FUNC && (context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL))
1737 || type == SCANNER_STREAM_TYPE_LET
1738 || type == SCANNER_STREAM_TYPE_CONST);
1739 }
1740 else
1741 {
1742 JERRY_ASSERT (check_type == PARSER_CHECK_FUNCTION_CONTEXT);
1743
1744 JERRY_ASSERT (type == SCANNER_STREAM_TYPE_VAR
1745 || type == SCANNER_STREAM_TYPE_LET
1746 || type == SCANNER_STREAM_TYPE_CONST
1747 || type == SCANNER_STREAM_TYPE_LOCAL
1748 || type == SCANNER_STREAM_TYPE_ARG
1749 || type == SCANNER_STREAM_TYPE_ARG_VAR
1750 || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG
1751 || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR
1752 || type == SCANNER_STREAM_TYPE_ARG_FUNC
1753 || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC
1754 || type == SCANNER_STREAM_TYPE_FUNC);
1755 }
1756 #endif /* !JERRY_NDEBUG */
1757
1758 #else /* !ENABLED (JERRY_ES2015) */
1759 JERRY_ASSERT ((data & SCANNER_STREAM_TYPE_MASK) == SCANNER_STREAM_TYPE_VAR);
1760 #endif /* ENABLED (JERRY_ES2015) */
1761
1762 if (!(data & SCANNER_STREAM_UINT16_DIFF))
1763 {
1764 if (data_p[2] != 0)
1765 {
1766 data_p += 2 + 1;
1767 }
1768 else
1769 {
1770 data_p += 2 + 1 + sizeof (const uint8_t *);
1771 }
1772 }
1773 else
1774 {
1775 data_p += 2 + 2;
1776 }
1777
1778 #if ENABLED (JERRY_ES2015)
1779 if (JERRY_UNLIKELY (check_type == PARSER_CHECK_GLOBAL_CONTEXT)
1780 && (type == SCANNER_STREAM_TYPE_VAR
1781 || (type == SCANNER_STREAM_TYPE_FUNC && !(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL))
1782 || type == SCANNER_STREAM_TYPE_IMPORT))
1783 {
1784 continue;
1785 }
1786
1787 if (JERRY_UNLIKELY (check_type == PARSER_CHECK_FUNCTION_CONTEXT))
1788 {
1789 if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)
1790 || type == SCANNER_STREAM_TYPE_ARG_VAR
1791 || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR)
1792 {
1793 /* The return value is true, if the variable is stored in the lexical environment
1794 * or all registers have already been used for function arguments. This can be
1795 * inprecise in the latter case, but this is a very rare corner case. A more
1796 * sophisticated check would require to decode the literal. */
1797 if ((data & SCANNER_STREAM_NO_REG)
1798 || scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
1799 {
1800 return true;
1801 }
1802 continue;
1803 }
1804
1805 if (SCANNER_STREAM_TYPE_IS_ARG (type))
1806 {
1807 continue;
1808 }
1809 }
1810 #endif /* ENABLED (JERRY_ES2015) */
1811
1812 if ((data & SCANNER_STREAM_NO_REG)
1813 || scope_stack_reg_top >= PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
1814 {
1815 return true;
1816 }
1817
1818 scope_stack_reg_top++;
1819 }
1820
1821 return false;
1822 } /* scanner_is_context_needed */
1823
1824 #if ENABLED (JERRY_ES2015)
1825
1826 /**
1827 * Try to scan/parse the ".target" part in the "new.target" expression.
1828 *
1829 * Upon exiting with "true" the current token will point to the "target"
1830 * literal.
1831 *
1832 * If the "target" literal is not after the "new." then a scanner/parser
1833 * error will be raised.
1834 *
1835 * @returns true if the ".target" part was found
1836 * false if there is no "." after the new.
1837 */
1838 bool
scanner_try_scan_new_target(parser_context_t * context_p)1839 scanner_try_scan_new_target (parser_context_t *context_p) /**< parser/scanner context */
1840 {
1841 JERRY_ASSERT (context_p->token.type == LEXER_KEYW_NEW);
1842
1843 if (lexer_check_next_character (context_p, LIT_CHAR_DOT))
1844 {
1845 lexer_next_token (context_p);
1846 if (context_p->token.type != LEXER_DOT)
1847 {
1848 parser_raise_error (context_p, PARSER_ERR_INVALID_CHARACTER);
1849 }
1850
1851 lexer_next_token (context_p);
1852 if (!lexer_token_is_identifier (context_p, "target", 6))
1853 {
1854 parser_raise_error (context_p, PARSER_ERR_NEW_TARGET_EXPECTED);
1855 }
1856
1857 return true;
1858 }
1859 return false;
1860 } /* scanner_try_scan_new_target */
1861
1862 #endif /* ENABLED (JERRY_ES2015) */
1863
1864 /**
1865 * Description of "arguments" literal string.
1866 */
1867 const lexer_lit_location_t lexer_arguments_literal =
1868 {
1869 (const uint8_t *) "arguments", 9, LEXER_IDENT_LITERAL, false
1870 };
1871
1872 /**
1873 * Create an unused literal.
1874 */
1875 static void
scanner_create_unused_literal(parser_context_t * context_p,uint8_t status_flags)1876 scanner_create_unused_literal (parser_context_t *context_p, /**< context */
1877 uint8_t status_flags) /**< initial status flags */
1878 {
1879 if (JERRY_UNLIKELY (context_p->literal_count >= PARSER_MAXIMUM_NUMBER_OF_LITERALS))
1880 {
1881 parser_raise_error (context_p, PARSER_ERR_LITERAL_LIMIT_REACHED);
1882 }
1883
1884 lexer_literal_t *literal_p = (lexer_literal_t *) parser_list_append (context_p, &context_p->literal_pool);
1885
1886 literal_p->type = LEXER_UNUSED_LITERAL;
1887 literal_p->status_flags = status_flags;
1888
1889 context_p->literal_count++;
1890 } /* scanner_create_unused_literal */
1891
1892 #if ENABLED (JERRY_ES2015)
1893 /**
1894 * Emit checks for redeclared bindings in the global lexical scope.
1895 */
1896 void
scanner_check_variables(parser_context_t * context_p)1897 scanner_check_variables (parser_context_t *context_p) /**< context */
1898 {
1899 scanner_info_t *info_p = context_p->next_scanner_info_p;
1900 const uint8_t *next_data_p = (const uint8_t *) (info_p + 1);
1901 lexer_lit_location_t literal;
1902
1903 JERRY_ASSERT (info_p->type == SCANNER_TYPE_FUNCTION);
1904
1905 literal.char_p = info_p->source_p - 1;
1906
1907 while (next_data_p[0] != SCANNER_STREAM_TYPE_END)
1908 {
1909 uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK;
1910 const uint8_t *data_p = next_data_p;
1911
1912 JERRY_ASSERT (type != SCANNER_STREAM_TYPE_HOLE
1913 && !SCANNER_STREAM_TYPE_IS_ARG (type)
1914 && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type));
1915 JERRY_ASSERT (data_p[0] & SCANNER_STREAM_NO_REG);
1916
1917 if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
1918 {
1919 if (data_p[2] != 0)
1920 {
1921 literal.char_p += data_p[2];
1922 next_data_p += 2 + 1;
1923 }
1924 else
1925 {
1926 memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *));
1927 next_data_p += 2 + 1 + sizeof (const uint8_t *);
1928 }
1929 }
1930 else
1931 {
1932 int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
1933
1934 if (diff <= UINT8_MAX)
1935 {
1936 diff = -diff;
1937 }
1938
1939 literal.char_p += diff;
1940 next_data_p += 2 + 2;
1941 }
1942
1943 literal.length = data_p[1];
1944 literal.type = LEXER_IDENT_LITERAL;
1945 literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
1946
1947 lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
1948 literal.char_p += data_p[1];
1949
1950 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
1951 if (type == SCANNER_STREAM_TYPE_IMPORT)
1952 {
1953 continue;
1954 }
1955 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
1956
1957 context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED;
1958
1959 uint16_t opcode;
1960 if (type == SCANNER_STREAM_TYPE_VAR || type == SCANNER_STREAM_TYPE_FUNC)
1961 {
1962 opcode = CBC_CHECK_VAR;
1963 }
1964 else
1965 {
1966 opcode = CBC_CHECK_LET;
1967 }
1968
1969 parser_emit_cbc_literal (context_p, opcode, context_p->lit_object.index);
1970 }
1971
1972 parser_flush_cbc (context_p);
1973 } /* scanner_check_variables */
1974 #endif /* ENABLED (JERRY_ES2015) */
1975
1976 /**
1977 * Create and/or initialize var/let/const/function/etc. variables.
1978 */
1979 void
scanner_create_variables(parser_context_t * context_p,uint32_t option_flags)1980 scanner_create_variables (parser_context_t *context_p, /**< context */
1981 uint32_t option_flags) /**< combination of scanner_create_variables_flags_t bits */
1982 {
1983 scanner_info_t *info_p = context_p->next_scanner_info_p;
1984 const uint8_t *next_data_p = (const uint8_t *) (info_p + 1);
1985 uint8_t info_type = info_p->type;
1986 uint8_t info_u8_arg = info_p->u8_arg;
1987 lexer_lit_location_t literal;
1988 parser_scope_stack_t *scope_stack_p;
1989 parser_scope_stack_t *scope_stack_end_p;
1990
1991 JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION || info_type == SCANNER_TYPE_BLOCK);
1992 JERRY_ASSERT (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)
1993 || !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY));
1994 JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION
1995 || !(option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_ARGS | SCANNER_CREATE_VARS_IS_FUNCTION_BODY)));
1996
1997 if (info_type == SCANNER_TYPE_FUNCTION && !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY))
1998 {
1999 JERRY_ASSERT (context_p->scope_stack_p == NULL);
2000
2001 size_t stack_size = info_p->u16_arg * sizeof (parser_scope_stack_t);
2002 context_p->scope_stack_size = info_p->u16_arg;
2003
2004 scope_stack_p = NULL;
2005
2006 if (stack_size > 0)
2007 {
2008 scope_stack_p = (parser_scope_stack_t *) parser_malloc (context_p, stack_size);
2009 }
2010
2011 context_p->scope_stack_p = scope_stack_p;
2012 scope_stack_end_p = scope_stack_p + context_p->scope_stack_size;
2013 }
2014 else
2015 {
2016 JERRY_ASSERT (context_p->scope_stack_p != NULL || context_p->scope_stack_size == 0);
2017
2018 scope_stack_p = context_p->scope_stack_p;
2019 scope_stack_end_p = scope_stack_p + context_p->scope_stack_size;
2020 scope_stack_p += context_p->scope_stack_top;
2021 }
2022
2023 uint32_t scope_stack_reg_top = context_p->scope_stack_reg_top;
2024
2025 literal.char_p = info_p->source_p - 1;
2026
2027 while (next_data_p[0] != SCANNER_STREAM_TYPE_END)
2028 {
2029 uint32_t type = next_data_p[0] & SCANNER_STREAM_TYPE_MASK;
2030 const uint8_t *data_p = next_data_p;
2031
2032 JERRY_ASSERT ((option_flags & (SCANNER_CREATE_VARS_IS_FUNCTION_BODY | SCANNER_CREATE_VARS_IS_FUNCTION_ARGS))
2033 || (type != SCANNER_STREAM_TYPE_HOLE
2034 && !SCANNER_STREAM_TYPE_IS_ARG (type)
2035 && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type)));
2036
2037 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2038 JERRY_ASSERT (type != SCANNER_STREAM_TYPE_IMPORT || (data_p[0] & SCANNER_STREAM_NO_REG));
2039 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2040
2041 if (type == SCANNER_STREAM_TYPE_HOLE)
2042 {
2043 next_data_p++;
2044
2045 if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
2046 {
2047 continue;
2048 }
2049
2050 if (info_u8_arg & SCANNER_FUNCTION_MAPPED_ARGUMENTS)
2051 {
2052 scanner_create_unused_literal (context_p, LEXER_FLAG_FUNCTION_ARGUMENT);
2053 }
2054
2055 if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
2056 {
2057 scope_stack_reg_top++;
2058 }
2059 continue;
2060 }
2061
2062 JERRY_ASSERT (context_p->scope_stack_size != 0);
2063
2064 if (!(data_p[0] & SCANNER_STREAM_UINT16_DIFF))
2065 {
2066 if (data_p[2] != 0)
2067 {
2068 literal.char_p += data_p[2];
2069 next_data_p += 2 + 1;
2070 }
2071 else
2072 {
2073 memcpy (&literal.char_p, data_p + 2 + 1, sizeof (const uint8_t *));
2074 next_data_p += 2 + 1 + sizeof (const uint8_t *);
2075 }
2076 }
2077 else
2078 {
2079 int32_t diff = ((int32_t) data_p[2]) | ((int32_t) data_p[3]) << 8;
2080
2081 if (diff <= UINT8_MAX)
2082 {
2083 diff = -diff;
2084 }
2085
2086 literal.char_p += diff;
2087 next_data_p += 2 + 2;
2088 }
2089
2090 if (SCANNER_STREAM_TYPE_IS_ARG (type))
2091 {
2092 if (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
2093 {
2094 #if ENABLED (JERRY_ES2015)
2095 if ((context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)
2096 && (type == SCANNER_STREAM_TYPE_ARG_VAR || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR))
2097 {
2098 literal.length = data_p[1];
2099 literal.type = LEXER_IDENT_LITERAL;
2100 literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
2101
2102 /* Literal must be exists. */
2103 lexer_construct_literal_object (context_p, &literal, LEXER_IDENT_LITERAL);
2104
2105 if (context_p->lit_object.index < PARSER_REGISTER_START)
2106 {
2107 parser_emit_cbc_ext_literal_from_token (context_p, CBC_EXT_COPY_FROM_ARG);
2108 }
2109 }
2110 #endif /* ENABLED (JERRY_ES2015) */
2111
2112 literal.char_p += data_p[1];
2113 continue;
2114 }
2115 }
2116 else if ((option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS)
2117 && !SCANNER_STREAM_TYPE_IS_ARG_FUNC (type))
2118 {
2119 /* Function arguments must come first. */
2120 break;
2121 }
2122
2123 literal.length = data_p[1];
2124 literal.type = LEXER_IDENT_LITERAL;
2125 literal.has_escape = (data_p[0] & SCANNER_STREAM_HAS_ESCAPE) ? 1 : 0;
2126
2127 lexer_construct_literal_object (context_p, &literal, LEXER_NEW_IDENT_LITERAL);
2128 literal.char_p += data_p[1];
2129
2130 if (SCANNER_STREAM_TYPE_IS_ARG_FUNC (type) && (option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY))
2131 {
2132 JERRY_ASSERT (scope_stack_p >= context_p->scope_stack_p + 2);
2133 JERRY_ASSERT (context_p->status_flags & PARSER_IS_FUNCTION);
2134 #if ENABLED (JERRY_ES2015)
2135 JERRY_ASSERT (!(context_p->status_flags & PARSER_FUNCTION_IS_PARSING_ARGS));
2136 #endif /* ENABLED (JERRY_ES2015) */
2137
2138 parser_scope_stack_t *function_map_p = scope_stack_p - 2;
2139 uint16_t literal_index = context_p->lit_object.index;
2140
2141 while (literal_index != function_map_p->map_from)
2142 {
2143 function_map_p--;
2144
2145 JERRY_ASSERT (function_map_p >= context_p->scope_stack_p);
2146 }
2147
2148 JERRY_ASSERT (function_map_p[1].map_from == PARSER_SCOPE_STACK_FUNC);
2149
2150 cbc_opcode_t opcode = CBC_SET_VAR_FUNC;
2151
2152 #if ENABLED (JERRY_ES2015)
2153 if (JERRY_UNLIKELY (context_p->status_flags & PARSER_LEXICAL_BLOCK_NEEDED)
2154 && (function_map_p[0].map_to & PARSER_SCOPE_STACK_REGISTER_MASK) == 0)
2155 {
2156 opcode = CBC_INIT_ARG_OR_FUNC;
2157 }
2158 #endif /* ENABLED (JERRY_ES2015) */
2159
2160 parser_emit_cbc_literal_value (context_p,
2161 (uint16_t) opcode,
2162 function_map_p[1].map_to,
2163 scanner_decode_map_to (function_map_p));
2164 continue;
2165 }
2166
2167 if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
2168 {
2169 JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
2170 parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
2171 }
2172
2173 scope_stack_p->map_from = context_p->lit_object.index;
2174
2175 #if ENABLED (JERRY_ES2015)
2176 if (info_type == SCANNER_TYPE_FUNCTION)
2177 {
2178 if (type != SCANNER_STREAM_TYPE_LET
2179 #if ENABLED (JERRY_ES2015_MODULE_SYSTEM)
2180 && type != SCANNER_STREAM_TYPE_IMPORT
2181 #endif /* ENABLED (JERRY_ES2015_MODULE_SYSTEM) */
2182 && type != SCANNER_STREAM_TYPE_CONST)
2183 {
2184 context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_GLOBAL;
2185 }
2186 }
2187 #endif /* ENABLED (JERRY_ES2015) */
2188
2189 uint16_t map_to;
2190 uint16_t func_init_opcode = CBC_INIT_ARG_OR_FUNC;
2191
2192 if (!(data_p[0] & SCANNER_STREAM_NO_REG)
2193 && scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
2194 {
2195 map_to = (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top);
2196
2197 #if ENABLED (JERRY_ES2015)
2198 scope_stack_p->map_to = (uint16_t) (scope_stack_reg_top + 1);
2199 #else /* !ENABLED (JERRY_ES2015) */
2200 scope_stack_p->map_to = map_to;
2201 #endif /* ENABLED (JERRY_ES2015) */
2202
2203 scope_stack_reg_top++;
2204 #if ENABLED (JERRY_ES2015)
2205 switch (type)
2206 {
2207 case SCANNER_STREAM_TYPE_CONST:
2208 {
2209 scope_stack_p->map_to |= PARSER_SCOPE_STACK_IS_CONST_REG;
2210 /* FALLTHRU */
2211 }
2212 case SCANNER_STREAM_TYPE_LET:
2213 case SCANNER_STREAM_TYPE_ARG:
2214 case SCANNER_STREAM_TYPE_ARG_VAR:
2215 case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
2216 case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
2217 case SCANNER_STREAM_TYPE_ARG_FUNC:
2218 case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
2219 {
2220 scope_stack_p->map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY;
2221 break;
2222 }
2223 }
2224
2225 func_init_opcode = CBC_SET_VAR_FUNC;
2226 #endif /* ENABLED (JERRY_ES2015) */
2227 }
2228 else
2229 {
2230 context_p->lit_object.literal_p->status_flags |= LEXER_FLAG_USED;
2231 map_to = context_p->lit_object.index;
2232
2233 #if ENABLED (JERRY_ES2015)
2234 uint16_t scope_stack_map_to = 0;
2235 #else /* !ENABLED (JERRY_ES2015) */
2236 scope_stack_p->map_to = map_to;
2237 #endif /* ENABLED (JERRY_ES2015) */
2238
2239 if (info_type == SCANNER_TYPE_FUNCTION)
2240 {
2241 context_p->status_flags |= PARSER_LEXICAL_ENV_NEEDED;
2242 }
2243
2244 switch (type)
2245 {
2246 #if ENABLED (JERRY_ES2015)
2247 case SCANNER_STREAM_TYPE_LET:
2248 case SCANNER_STREAM_TYPE_CONST:
2249 case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG:
2250 case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR:
2251 case SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC:
2252 {
2253 scope_stack_map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY;
2254
2255 if (!(data_p[0] & SCANNER_STREAM_EARLY_CREATE))
2256 {
2257 break;
2258 }
2259 scope_stack_map_to |= PARSER_SCOPE_STACK_IS_LOCAL_CREATED;
2260 /* FALLTHRU */
2261 }
2262 case SCANNER_STREAM_TYPE_LOCAL:
2263 #endif /* ENABLED (JERRY_ES2015) */
2264 case SCANNER_STREAM_TYPE_VAR:
2265 {
2266 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2267 context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
2268 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2269
2270 #if ENABLED (JERRY_ES2015)
2271 uint16_t opcode;
2272
2273 switch (type)
2274 {
2275 case SCANNER_STREAM_TYPE_LET:
2276 {
2277 opcode = CBC_CREATE_LET;
2278 break;
2279 }
2280 case SCANNER_STREAM_TYPE_CONST:
2281 {
2282 opcode = CBC_CREATE_CONST;
2283 break;
2284 }
2285 case SCANNER_STREAM_TYPE_VAR:
2286 {
2287 opcode = CBC_CREATE_VAR;
2288
2289 if (option_flags & SCANNER_CREATE_VARS_IS_SCRIPT)
2290 {
2291 opcode = CBC_CREATE_VAR_EVAL;
2292
2293 if (context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT)
2294 {
2295 opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_CREATE_VAR_EVAL);
2296 }
2297 }
2298 break;
2299 }
2300 default:
2301 {
2302 JERRY_ASSERT (type == SCANNER_STREAM_TYPE_LOCAL
2303 || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG
2304 || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_VAR
2305 || type == SCANNER_STREAM_TYPE_DESTRUCTURED_ARG_FUNC);
2306
2307 opcode = CBC_CREATE_LOCAL;
2308 break;
2309 }
2310 }
2311 #else /* !ENABLED (JERRY_ES2015) */
2312 uint16_t opcode = ((option_flags & SCANNER_CREATE_VARS_IS_SCRIPT) ? CBC_CREATE_VAR_EVAL
2313 : CBC_CREATE_VAR);
2314 #endif /* ENABLED (JERRY_ES2015) */
2315
2316 parser_emit_cbc_literal (context_p, opcode, map_to);
2317 break;
2318 }
2319 case SCANNER_STREAM_TYPE_ARG:
2320 #if ENABLED (JERRY_ES2015)
2321 case SCANNER_STREAM_TYPE_ARG_VAR:
2322 #endif /* ENABLED (JERRY_ES2015) */
2323 case SCANNER_STREAM_TYPE_ARG_FUNC:
2324 {
2325 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2326 context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
2327 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2328
2329 #if ENABLED (JERRY_ES2015)
2330 scope_stack_map_to |= PARSER_SCOPE_STACK_NO_FUNCTION_COPY;
2331
2332 /* Argument initializers of functions with mapped arguments (e.g. function f(a,b,a) {}) are
2333 * generated here. The other initializers are handled by parser_parse_function_arguments(). */
2334 if (info_u8_arg & SCANNER_FUNCTION_MAPPED_ARGUMENTS)
2335 {
2336 #endif /* ENABLED (JERRY_ES2015) */
2337 parser_emit_cbc_literal_value (context_p,
2338 CBC_INIT_ARG_OR_FUNC,
2339 (uint16_t) (PARSER_REGISTER_START + scope_stack_reg_top),
2340 map_to);
2341 #if ENABLED (JERRY_ES2015)
2342 }
2343 else if (data_p[0] & SCANNER_STREAM_EARLY_CREATE)
2344 {
2345 parser_emit_cbc_literal (context_p, CBC_CREATE_LOCAL, map_to);
2346 scope_stack_map_to |= PARSER_SCOPE_STACK_IS_LOCAL_CREATED;
2347 }
2348 #endif /* ENABLED (JERRY_ES2015) */
2349
2350 if (scope_stack_reg_top < PARSER_MAXIMUM_NUMBER_OF_REGISTERS)
2351 {
2352 scope_stack_reg_top++;
2353 }
2354 break;
2355 }
2356 }
2357
2358 #if ENABLED (JERRY_ES2015)
2359 scope_stack_p->map_to = scope_stack_map_to;
2360 #endif /* ENABLED (JERRY_ES2015) */
2361 }
2362
2363 scope_stack_p++;
2364
2365 if (!SCANNER_STREAM_TYPE_IS_FUNCTION (type))
2366 {
2367 continue;
2368 }
2369
2370 if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
2371 {
2372 JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
2373 parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
2374 }
2375
2376 #if ENABLED (JERRY_PARSER_DUMP_BYTE_CODE)
2377 context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
2378 #endif /* ENABLED (JERRY_PARSER_DUMP_BYTE_CODE) */
2379
2380 if (!SCANNER_STREAM_TYPE_IS_ARG_FUNC (type))
2381 {
2382 if (func_init_opcode == CBC_INIT_ARG_OR_FUNC && (option_flags & SCANNER_CREATE_VARS_IS_SCRIPT))
2383 {
2384 #if ENABLED (JERRY_ES2015)
2385 literal.char_p -= data_p[1];
2386 if (!(context_p->global_status_flags & ECMA_PARSE_DIRECT_EVAL)
2387 || !scanner_scope_find_let_declaration (context_p, &literal))
2388 {
2389 func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL;
2390
2391 if (context_p->global_status_flags & ECMA_PARSE_FUNCTION_CONTEXT)
2392 {
2393 func_init_opcode = PARSER_TO_EXT_OPCODE (CBC_EXT_CREATE_VAR_FUNC_EVAL);
2394 }
2395 }
2396 literal.char_p += data_p[1];
2397 #else /* !ENABLED (JERRY_ES2015) */
2398 func_init_opcode = CBC_CREATE_VAR_FUNC_EVAL;
2399 #endif /* ENABLED (JERRY_ES2015) */
2400 }
2401
2402 parser_emit_cbc_literal_value (context_p, func_init_opcode, context_p->literal_count, map_to);
2403 }
2404
2405 scope_stack_p->map_from = PARSER_SCOPE_STACK_FUNC;
2406 scope_stack_p->map_to = context_p->literal_count;
2407 scope_stack_p++;
2408
2409 scanner_create_unused_literal (context_p, 0);
2410 }
2411
2412 if (info_type == SCANNER_TYPE_FUNCTION
2413 && !(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_BODY)
2414 && (info_u8_arg & SCANNER_FUNCTION_ARGUMENTS_NEEDED))
2415 {
2416 JERRY_ASSERT (info_type == SCANNER_TYPE_FUNCTION);
2417
2418 if (JERRY_UNLIKELY (scope_stack_p >= scope_stack_end_p))
2419 {
2420 JERRY_ASSERT (context_p->scope_stack_size == PARSER_MAXIMUM_DEPTH_OF_SCOPE_STACK);
2421 parser_raise_error (context_p, PARSER_ERR_SCOPE_STACK_LIMIT_REACHED);
2422 }
2423
2424 context_p->status_flags |= PARSER_ARGUMENTS_NEEDED | PARSER_LEXICAL_ENV_NEEDED;
2425
2426 lexer_construct_literal_object (context_p, &lexer_arguments_literal, lexer_arguments_literal.type);
2427
2428 scope_stack_p->map_from = context_p->lit_object.index;
2429 #if ENABLED (JERRY_ES2015)
2430 scope_stack_p->map_to = 0;
2431 #else /* !ENABLED (JERRY_ES2015) */
2432 scope_stack_p->map_to = context_p->lit_object.index;
2433 #endif /* ENABLED (JERRY_ES2015) */
2434 scope_stack_p++;
2435 }
2436
2437 context_p->scope_stack_top = (uint16_t) (scope_stack_p - context_p->scope_stack_p);
2438 context_p->scope_stack_reg_top = (uint16_t) scope_stack_reg_top;
2439
2440 #if ENABLED (JERRY_ES2015)
2441 if (info_type == SCANNER_TYPE_FUNCTION)
2442 {
2443 context_p->scope_stack_global_end = context_p->scope_stack_top;
2444 }
2445 #endif /* ENABLED (JERRY_ES2015) */
2446
2447 if (context_p->register_count < scope_stack_reg_top)
2448 {
2449 context_p->register_count = (uint16_t) scope_stack_reg_top;
2450 }
2451
2452 if (!(option_flags & SCANNER_CREATE_VARS_IS_FUNCTION_ARGS))
2453 {
2454 scanner_release_next (context_p, (size_t) (next_data_p + 1 - ((const uint8_t *) info_p)));
2455 }
2456 parser_flush_cbc (context_p);
2457 } /* scanner_create_variables */
2458
2459 /**
2460 * Get location from context.
2461 */
2462 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_get_location(scanner_location_t * location_p,parser_context_t * context_p)2463 scanner_get_location (scanner_location_t *location_p, /**< location */
2464 parser_context_t *context_p) /**< context */
2465 {
2466 location_p->source_p = context_p->source_p;
2467 location_p->line = context_p->line;
2468 location_p->column = context_p->column;
2469 } /* scanner_get_location */
2470
2471 /**
2472 * Set context location.
2473 */
2474 inline void JERRY_ATTR_ALWAYS_INLINE
scanner_set_location(parser_context_t * context_p,scanner_location_t * location_p)2475 scanner_set_location (parser_context_t *context_p, /**< context */
2476 scanner_location_t *location_p) /**< location */
2477 {
2478 context_p->source_p = location_p->source_p;
2479 context_p->line = location_p->line;
2480 context_p->column = location_p->column;
2481 } /* scanner_set_location */
2482
2483 /**
2484 * Get the real map_to value.
2485 */
2486 inline uint16_t JERRY_ATTR_ALWAYS_INLINE
scanner_decode_map_to(parser_scope_stack_t * stack_item_p)2487 scanner_decode_map_to (parser_scope_stack_t *stack_item_p) /**< scope stack item */
2488 {
2489 JERRY_ASSERT (stack_item_p->map_from != PARSER_SCOPE_STACK_FUNC);
2490
2491 #if ENABLED (JERRY_ES2015)
2492 uint16_t value = (stack_item_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK);
2493 return (value == 0) ? stack_item_p->map_from : (uint16_t) (value + (PARSER_REGISTER_START - 1));
2494 #else /* !ENABLED (JERRY_ES2015) */
2495 return stack_item_p->map_to;
2496 #endif /* ENABLED (JERRY_ES2015) */
2497 } /* scanner_decode_map_to */
2498
2499 #if ENABLED (JERRY_ES2015)
2500
2501 /**
2502 * Checks whether the literal is a const in the current scope.
2503 *
2504 * @return true if the literal is a const, false otherwise
2505 */
2506 bool
scanner_literal_is_const_reg(parser_context_t * context_p,uint16_t literal_index)2507 scanner_literal_is_const_reg (parser_context_t *context_p, /**< context */
2508 uint16_t literal_index) /**< literal index */
2509 {
2510 if (literal_index < PARSER_REGISTER_START)
2511 {
2512 /* Re-assignment of non-register const bindings are detected elsewhere. */
2513 return false;
2514 }
2515
2516 parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top;
2517
2518 literal_index = (uint16_t) (literal_index - (PARSER_REGISTER_START - 1));
2519
2520 do
2521 {
2522 /* Registers must be found in the scope stack. */
2523 JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p);
2524 scope_stack_p--;
2525 }
2526 while (literal_index != (scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK));
2527
2528 return (scope_stack_p->map_to & PARSER_SCOPE_STACK_IS_CONST_REG) != 0;
2529 } /* scanner_literal_is_const_reg */
2530
2531 /**
2532 * Checks whether the literal is created before.
2533 *
2534 * @return true if the literal is created before, false otherwise
2535 */
2536 bool
scanner_literal_is_created(parser_context_t * context_p,uint16_t literal_index)2537 scanner_literal_is_created (parser_context_t *context_p, /**< context */
2538 uint16_t literal_index) /**< literal index */
2539 {
2540 JERRY_ASSERT (literal_index < PARSER_REGISTER_START);
2541
2542 parser_scope_stack_t *scope_stack_p = context_p->scope_stack_p + context_p->scope_stack_top;
2543
2544 do
2545 {
2546 /* These literals must be found in the scope stack. */
2547 JERRY_ASSERT (scope_stack_p > context_p->scope_stack_p);
2548 scope_stack_p--;
2549 }
2550 while (literal_index != scope_stack_p->map_from);
2551
2552 JERRY_ASSERT ((scope_stack_p->map_to & PARSER_SCOPE_STACK_REGISTER_MASK) == 0);
2553
2554 return (scope_stack_p->map_to & PARSER_SCOPE_STACK_IS_LOCAL_CREATED) != 0;
2555 } /* scanner_literal_is_created */
2556
2557 #endif /* ENABLED (JERRY_ES2015) */
2558
2559 /**
2560 * @}
2561 * @}
2562 * @}
2563 */
2564
2565 #endif /* ENABLED (JERRY_PARSER) */
2566