@@ -445,23 +445,23 @@ re_parse_alternative (re_compiler_ctx_t *re_ctx_p, /**< RegExp compiler context
445
445
} /* re_parse_alternative */
446
446
447
447
static const re_compiled_code_t * re_cache [RE_CACHE_SIZE ];
448
+ static uint8_t re_cache_idx = RE_CACHE_SIZE ;
448
449
449
450
/**
450
451
* Search for the given pattern in the RegExp cache
451
452
*
452
- * @return compiled bytecode - if found
453
- * NULL - otherwise
453
+ * @return index of bytecode in cache - if found
454
+ * RE_CACHE_SIZE - otherwise
454
455
*/
455
- const re_compiled_code_t *
456
+ static uint8_t
456
457
re_find_bytecode_in_cache (ecma_string_t * pattern_str_p , /**< pattern string */
457
- uint16_t flags , /**< flags */
458
- uint32_t * idx ) /**< [out] index */
458
+ uint16_t flags ) /**< flags */
459
459
{
460
- uint32_t free_idx = RE_CACHE_SIZE ;
460
+ uint8_t free_idx = RE_CACHE_SIZE ;
461
461
462
- for (* idx = 0u ; * idx < RE_CACHE_SIZE ; ( * idx ) ++ )
462
+ for (uint8_t idx = 0u ; idx < RE_CACHE_SIZE ; idx ++ )
463
463
{
464
- const re_compiled_code_t * cached_bytecode_p = re_cache [* idx ];
464
+ const re_compiled_code_t * cached_bytecode_p = re_cache [idx ];
465
465
466
466
if (cached_bytecode_p != NULL )
467
467
{
@@ -472,19 +472,18 @@ re_find_bytecode_in_cache (ecma_string_t *pattern_str_p, /**< pattern string */
472
472
&& ecma_compare_ecma_strings (cached_pattern_str_p , pattern_str_p ))
473
473
{
474
474
JERRY_DDLOG ("RegExp is found in cache\n" );
475
- return re_cache [ * idx ] ;
475
+ return idx ;
476
476
}
477
477
}
478
478
else
479
479
{
480
480
/* mark as free, so it can be overridden if the cache is full */
481
- free_idx = * idx ;
481
+ free_idx = idx ;
482
482
}
483
483
}
484
484
485
485
JERRY_DDLOG ("RegExp is NOT found in cache\n" );
486
- * idx = free_idx ;
487
- return NULL ;
486
+ return free_idx ;
488
487
} /* re_find_bytecode_in_cache */
489
488
490
489
/**
@@ -521,6 +520,20 @@ re_compile_bytecode (const re_compiled_code_t **out_bytecode_p, /**< [out] point
521
520
uint16_t flags ) /**< flags */
522
521
{
523
522
ecma_value_t ret_value = ecma_make_simple_value (ECMA_SIMPLE_VALUE_EMPTY );
523
+ uint8_t cache_idx = re_find_bytecode_in_cache (pattern_str_p , flags );
524
+
525
+ if (cache_idx < RE_CACHE_SIZE )
526
+ {
527
+ * out_bytecode_p = re_cache [cache_idx ];
528
+
529
+ if (* out_bytecode_p != NULL )
530
+ {
531
+ ecma_bytecode_ref ((ecma_compiled_code_t * ) * out_bytecode_p );
532
+ return ret_value ;
533
+ }
534
+ }
535
+
536
+ /* not in the RegExp cache, so compile it */
524
537
re_compiler_ctx_t re_ctx ;
525
538
re_ctx .flags = flags ;
526
539
re_ctx .highest_backref = 0 ;
@@ -533,90 +546,93 @@ re_compile_bytecode (const re_compiled_code_t **out_bytecode_p, /**< [out] point
533
546
534
547
re_ctx .bytecode_ctx_p = & bc_ctx ;
535
548
536
- uint32_t cache_idx ;
537
- * out_bytecode_p = re_find_bytecode_in_cache ( pattern_str_p , flags , & cache_idx );
549
+ lit_utf8_size_t pattern_str_size = ecma_string_get_size ( pattern_str_p ) ;
550
+ MEM_DEFINE_LOCAL_ARRAY ( pattern_start_p , pattern_str_size , lit_utf8_byte_t );
538
551
539
- if (* out_bytecode_p != NULL )
540
- {
541
- ecma_bytecode_ref ((ecma_compiled_code_t * ) * out_bytecode_p );
542
- }
543
- else
544
- { /* not in the RegExp cache, so compile it */
545
- lit_utf8_size_t pattern_str_size = ecma_string_get_size (pattern_str_p );
546
- MEM_DEFINE_LOCAL_ARRAY (pattern_start_p , pattern_str_size , lit_utf8_byte_t );
552
+ lit_utf8_size_t sz = ecma_string_to_utf8_string (pattern_str_p , pattern_start_p , pattern_str_size );
553
+ JERRY_ASSERT (sz == pattern_str_size );
547
554
548
- lit_utf8_size_t sz = ecma_string_to_utf8_string (pattern_str_p , pattern_start_p , pattern_str_size );
549
- JERRY_ASSERT (sz == pattern_str_size );
555
+ re_parser_ctx_t parser_ctx ;
556
+ parser_ctx .input_start_p = pattern_start_p ;
557
+ parser_ctx .input_curr_p = pattern_start_p ;
558
+ parser_ctx .input_end_p = pattern_start_p + pattern_str_size ;
559
+ parser_ctx .num_of_groups = -1 ;
560
+ re_ctx .parser_ctx_p = & parser_ctx ;
550
561
551
- re_parser_ctx_t parser_ctx ;
552
- parser_ctx .input_start_p = pattern_start_p ;
553
- parser_ctx .input_curr_p = pattern_start_p ;
554
- parser_ctx .input_end_p = pattern_start_p + pattern_str_size ;
555
- parser_ctx .num_of_groups = -1 ;
556
- re_ctx .parser_ctx_p = & parser_ctx ;
562
+ /* 1. Parse RegExp pattern */
563
+ re_ctx .num_of_captures = 1 ;
564
+ re_append_opcode (& bc_ctx , RE_OP_SAVE_AT_START );
557
565
558
- /* 1. Parse RegExp pattern */
559
- re_ctx .num_of_captures = 1 ;
560
- re_append_opcode (& bc_ctx , RE_OP_SAVE_AT_START );
566
+ ECMA_TRY_CATCH (empty , re_parse_alternative (& re_ctx , true), ret_value );
561
567
562
- ECMA_TRY_CATCH (empty , re_parse_alternative (& re_ctx , true), ret_value );
568
+ /* 2. Check for invalid backreference */
569
+ if (re_ctx .highest_backref >= re_ctx .num_of_captures )
570
+ {
571
+ ret_value = ecma_raise_syntax_error ("Invalid backreference.\n" );
572
+ }
573
+ else
574
+ {
575
+ re_append_opcode (& bc_ctx , RE_OP_SAVE_AND_MATCH );
576
+ re_append_opcode (& bc_ctx , RE_OP_EOF );
577
+
578
+ /* 3. Insert extra informations for bytecode header */
579
+ re_compiled_code_t re_compiled_code ;
580
+
581
+ re_compiled_code .flags = re_ctx .flags | (1u << ECMA_BYTECODE_REF_SHIFT );
582
+ ECMA_SET_NON_NULL_POINTER (re_compiled_code .pattern_cp ,
583
+ ecma_copy_or_ref_ecma_string (pattern_str_p ));
584
+ re_compiled_code .num_of_captures = re_ctx .num_of_captures * 2 ;
585
+ re_compiled_code .num_of_non_captures = re_ctx .num_of_non_captures ;
586
+
587
+ re_bytecode_list_insert (& bc_ctx ,
588
+ 0 ,
589
+ (uint8_t * ) & re_compiled_code ,
590
+ sizeof (re_compiled_code_t ));
591
+ }
563
592
564
- /* 2. Check for invalid backreference */
565
- if (re_ctx .highest_backref >= re_ctx .num_of_captures )
566
- {
567
- ret_value = ecma_raise_syntax_error (ECMA_ERR_MSG ("Invalid backreference.\n" ));
568
- }
569
- else
570
- {
571
- re_append_opcode (& bc_ctx , RE_OP_SAVE_AND_MATCH );
572
- re_append_opcode (& bc_ctx , RE_OP_EOF );
573
-
574
- /* 3. Insert extra informations for bytecode header */
575
- re_compiled_code_t re_compiled_code ;
576
-
577
- re_compiled_code .flags = re_ctx .flags | (1u << ECMA_BYTECODE_REF_SHIFT );
578
- ECMA_SET_NON_NULL_POINTER (re_compiled_code .pattern_cp ,
579
- ecma_copy_or_ref_ecma_string (pattern_str_p ));
580
- re_compiled_code .num_of_captures = re_ctx .num_of_captures * 2 ;
581
- re_compiled_code .num_of_non_captures = re_ctx .num_of_non_captures ;
582
-
583
- re_bytecode_list_insert (& bc_ctx ,
584
- 0 ,
585
- (uint8_t * ) & re_compiled_code ,
586
- sizeof (re_compiled_code_t ));
587
- }
593
+ ECMA_FINALIZE (empty );
588
594
589
- ECMA_FINALIZE ( empty );
595
+ MEM_FINALIZE_LOCAL_ARRAY ( pattern_start_p );
590
596
591
- MEM_FINALIZE_LOCAL_ARRAY (pattern_start_p );
597
+ if (!ecma_is_value_empty (ret_value ))
598
+ {
599
+ /* Compilation failed, free bytecode. */
600
+ JERRY_DDLOG ("RegExp compilation failed!\n" );
601
+ mem_heap_free_block_size_stored (bc_ctx .block_start_p );
602
+ * out_bytecode_p = NULL ;
603
+ }
604
+ else
605
+ {
606
+ #ifdef JERRY_ENABLE_LOG
607
+ re_dump_bytecode (& bc_ctx );
608
+ #endif
592
609
593
- if (!ecma_is_value_empty (ret_value ))
594
- {
595
- /* Compilation failed, free bytecode. */
596
- mem_heap_free_block_size_stored (bc_ctx .block_start_p );
597
- * out_bytecode_p = NULL ;
598
- }
599
- else
600
- {
601
- /* The RegExp bytecode contains at least a RE_OP_SAVE_AT_START opdoce, so it cannot be NULL. */
602
- JERRY_ASSERT (bc_ctx .block_start_p != NULL );
603
- * out_bytecode_p = (re_compiled_code_t * ) bc_ctx .block_start_p ;
610
+ /* The RegExp bytecode contains at least a RE_OP_SAVE_AT_START opdoce, so it cannot be NULL. */
611
+ JERRY_ASSERT (bc_ctx .block_start_p != NULL );
612
+ * out_bytecode_p = (re_compiled_code_t * ) bc_ctx .block_start_p ;
604
613
605
- if (cache_idx < RE_CACHE_SIZE )
614
+ if (cache_idx == RE_CACHE_SIZE )
615
+ {
616
+ if (re_cache_idx == 0u )
606
617
{
607
- ecma_bytecode_ref ((ecma_compiled_code_t * ) * out_bytecode_p );
608
- re_cache [cache_idx ] = * out_bytecode_p ;
618
+ re_cache_idx = RE_CACHE_SIZE ;
609
619
}
610
- else
620
+
621
+ const re_compiled_code_t * cached_bytecode_p = re_cache [-- re_cache_idx ];
622
+ JERRY_DDLOG ("RegExp cache is full! Remove the element on idx: %d\n" , re_cache_idx );
623
+
624
+ if (cached_bytecode_p != NULL )
611
625
{
612
- JERRY_DDLOG ( "RegExp cache is full! Cannot add new bytecode to it." );
626
+ ecma_bytecode_deref (( ecma_compiled_code_t * ) cached_bytecode_p );
613
627
}
628
+
629
+ cache_idx = re_cache_idx ;
614
630
}
615
- }
616
631
617
- #ifdef JERRY_ENABLE_LOG
618
- re_dump_bytecode (& bc_ctx );
619
- #endif
632
+ JERRY_DDLOG ("Insert bytecode into RegExp cache (idx: %d).\n" , cache_idx );
633
+ ecma_bytecode_ref ((ecma_compiled_code_t * ) * out_bytecode_p );
634
+ re_cache [cache_idx ] = * out_bytecode_p ;
635
+ }
620
636
621
637
return ret_value ;
622
638
} /* re_compile_bytecode */
0 commit comments