@@ -579,6 +579,122 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
579
579
}
580
580
}
581
581
582
+ if (ZEND_FUNC_INFO (op_array )) {
583
+ zend_func_info * func_info = ZEND_FUNC_INFO (op_array );
584
+
585
+ if (func_info -> callee_info ) {
586
+ zend_call_info * call_info = func_info -> callee_info ;
587
+ static zend_function * in_array_function = NULL ;
588
+
589
+ if (!in_array_function ) {
590
+ in_array_function = zend_hash_str_find_ptr (CG (function_table ), "in_array" , sizeof ("in_array" )- 1 );
591
+ }
592
+ do {
593
+ if (call_info -> callee_func == in_array_function
594
+ && (call_info -> caller_init_opline -> extended_value == 2
595
+ || (call_info -> caller_init_opline -> extended_value == 3
596
+ && (call_info -> caller_call_opline - 1 )-> opcode == ZEND_SEND_VAL
597
+ && (call_info -> caller_call_opline - 1 )-> op1_type == IS_CONST ))) {
598
+
599
+ zend_op * send_array ;
600
+ zend_op * send_needly ;
601
+ zend_bool strict = 0 ;
602
+
603
+ if (call_info -> caller_init_opline -> extended_value == 2 ) {
604
+ send_array = call_info -> caller_call_opline - 1 ;
605
+ send_needly = call_info -> caller_call_opline - 2 ;
606
+ } else {
607
+ if (zend_is_true (CT_CONSTANT_EX (op_array , (call_info -> caller_call_opline - 1 )-> op1 .constant ))) {
608
+ strict = 1 ;
609
+ }
610
+ send_array = call_info -> caller_call_opline - 2 ;
611
+ send_needly = call_info -> caller_call_opline - 3 ;
612
+ }
613
+
614
+ if (send_array -> opcode == ZEND_SEND_VAL
615
+ && send_array -> op1_type == IS_CONST
616
+ && Z_TYPE_P (CT_CONSTANT_EX (op_array , send_array -> op1 .constant )) == IS_ARRAY
617
+ && (send_needly -> opcode == ZEND_SEND_VAL
618
+ || send_needly -> opcode == ZEND_SEND_VAR )
619
+ ) {
620
+ int ok = 1 ;
621
+
622
+ HashTable * src = Z_ARRVAL_P (CT_CONSTANT_EX (op_array , send_array -> op1 .constant ));
623
+ HashTable * dst ;
624
+ zval * val , tmp ;
625
+ zend_ulong idx ;
626
+
627
+ ZVAL_TRUE (& tmp );
628
+ dst = emalloc (sizeof (HashTable ));
629
+ zend_hash_init (dst , zend_hash_num_elements (src ), NULL , ZVAL_PTR_DTOR , 0 );
630
+ if (strict ) {
631
+ ZEND_HASH_FOREACH_VAL (src , val ) {
632
+ if (Z_TYPE_P (val ) == IS_STRING ) {
633
+ zend_hash_add (dst , Z_STR_P (val ), & tmp );
634
+ } else if (Z_TYPE_P (val ) == IS_LONG ) {
635
+ zend_hash_index_add (dst , Z_LVAL_P (val ), & tmp );
636
+ } else {
637
+ zend_array_destroy (dst );
638
+ ok = 0 ;
639
+ break ;
640
+ }
641
+ } ZEND_HASH_FOREACH_END ();
642
+ } else {
643
+ ZEND_HASH_FOREACH_VAL (src , val ) {
644
+ if (Z_TYPE_P (val ) != IS_STRING || ZEND_HANDLE_NUMERIC (Z_STR_P (val ), idx )) {
645
+ zend_array_destroy (dst );
646
+ ok = 0 ;
647
+ break ;
648
+ }
649
+ zend_hash_add (dst , Z_STR_P (val ), & tmp );
650
+ } ZEND_HASH_FOREACH_END ();
651
+ }
652
+
653
+ if (ok ) {
654
+ uint32_t op_num = send_needly - op_array -> opcodes ;
655
+ zend_ssa_op * ssa_op = ssa -> ops + op_num ;
656
+
657
+ if (ssa_op -> op1_use >= 0 ) {
658
+ /* Reconstruct SSA */
659
+ int var_num = ssa_op -> op1_use ;
660
+ zend_ssa_var * var = ssa -> vars + var_num ;
661
+
662
+ ZEND_ASSERT (ssa_op -> op1_def < 0 );
663
+ zend_ssa_unlink_use_chain (ssa , op_num , ssa_op -> op1_use );
664
+ ssa_op -> op1_use = -1 ;
665
+ ssa_op -> op1_use_chain = -1 ;
666
+ op_num = call_info -> caller_call_opline - op_array -> opcodes ;
667
+ ssa_op = ssa -> ops + op_num ;
668
+ ssa_op -> op1_use = var_num ;
669
+ ssa_op -> op1_use_chain = var -> use_chain ;
670
+ var -> use_chain = op_num ;
671
+ }
672
+
673
+ ZVAL_ARR (& tmp , dst );
674
+
675
+ /* Update opcode */
676
+ call_info -> caller_call_opline -> opcode = ZEND_IN_ARRAY ;
677
+ call_info -> caller_call_opline -> extended_value = strict ;
678
+ call_info -> caller_call_opline -> op1_type = send_needly -> op1_type ;
679
+ call_info -> caller_call_opline -> op1 .num = send_needly -> op1 .num ;
680
+ call_info -> caller_call_opline -> op2_type = IS_CONST ;
681
+ call_info -> caller_call_opline -> op2 .constant = zend_optimizer_add_literal (op_array , & tmp );
682
+ if (call_info -> caller_init_opline -> extended_value == 3 ) {
683
+ MAKE_NOP (call_info -> caller_call_opline - 1 );
684
+ }
685
+ MAKE_NOP (call_info -> caller_init_opline );
686
+ MAKE_NOP (send_needly );
687
+ MAKE_NOP (send_array );
688
+ remove_nops = 1 ;
689
+
690
+ }
691
+ }
692
+ }
693
+ call_info = call_info -> next_callee ;
694
+ } while (call_info );
695
+ }
696
+ }
697
+
582
698
if (remove_nops ) {
583
699
zend_ssa_remove_nops (op_array , ssa );
584
700
}
0 commit comments