@@ -146,7 +146,8 @@ static uint32_t zend_jit_trace_get_exit_point(const zend_op *from_opline, const
146
146
if (stack_size ) {
147
147
stack = JIT_G (current_frame )-> stack ;
148
148
do {
149
- if (STACK_TYPE (stack , stack_size - 1 ) != IS_UNKNOWN ) {
149
+ if (STACK_TYPE (stack , stack_size - 1 ) != IS_UNKNOWN
150
+ || STACK_REG (stack , stack_size - 1 ) != ZREG_NONE ) {
150
151
break ;
151
152
}
152
153
stack_size -- ;
@@ -2832,17 +2833,37 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
2832
2833
goto jit_failure ;
2833
2834
}
2834
2835
} else {
2835
- SET_STACK_REG (stack , i , ZREG_NONE );
2836
+ if (STACK_REG (parent_stack , i ) == ZREG_ZVAL_COPY_R0 ) {
2837
+ SET_STACK_TYPE (stack , i , IS_UNKNOWN );
2838
+ } else {
2839
+ SET_STACK_REG (stack , i , ZREG_NONE );
2840
+ }
2836
2841
if (!zend_jit_store_const (& dasm_state , i , STACK_REG (parent_stack , i ))) {
2837
2842
goto jit_failure ;
2838
2843
}
2839
2844
}
2840
2845
}
2841
2846
}
2842
-
2843
2847
if (zend_jit_traces [parent_trace ].exit_info [exit_num ].flags & ZEND_JIT_EXIT_RESTORE_CALL ) {
2844
2848
zend_jit_save_call_chain (& dasm_state , -1 );
2845
2849
}
2850
+ if (zend_jit_traces [parent_trace ].exit_info [exit_num ].flags & ZEND_JIT_EXIT_FREE_OP2 ) {
2851
+ const zend_op * op = zend_jit_traces [parent_trace ].exit_info [exit_num ].opline - 1 ;
2852
+ if (!zend_jit_free_op (& dasm_state , op , -1 , op -> op2 .var )) {
2853
+ goto jit_failure ;
2854
+ }
2855
+ }
2856
+ if (zend_jit_traces [parent_trace ].exit_info [exit_num ].flags & ZEND_JIT_EXIT_FREE_OP1 ) {
2857
+ const zend_op * op = zend_jit_traces [parent_trace ].exit_info [exit_num ].opline - 1 ;
2858
+ if (!zend_jit_free_op (& dasm_state , op , -1 , op -> op1 .var )) {
2859
+ goto jit_failure ;
2860
+ }
2861
+ }
2862
+ if (zend_jit_traces [parent_trace ].exit_info [exit_num ].flags & (ZEND_JIT_EXIT_FREE_OP1 |ZEND_JIT_EXIT_FREE_OP2 )) {
2863
+ if (!zend_jit_check_exception (& dasm_state )) {
2864
+ goto jit_failure ;
2865
+ }
2866
+ }
2846
2867
}
2847
2868
2848
2869
if (ra
@@ -3750,6 +3771,11 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
3750
3771
(op2_info & (MAY_BE_OBJECT |MAY_BE_RESOURCE |MAY_BE_ARRAY_OF_OBJECT |MAY_BE_ARRAY_OF_RESOURCE |MAY_BE_ARRAY_OF_ARRAY )) != 0 )))) {
3751
3772
goto jit_failure ;
3752
3773
}
3774
+ if ((res_info & MAY_BE_GUARD )
3775
+ && JIT_G (current_frame )
3776
+ && (op1_info & (MAY_BE_ANY |MAY_BE_UNDEF )) == MAY_BE_ARRAY ) {
3777
+ ssa -> var_info [ssa_op -> result_def ].type &= ~MAY_BE_GUARD ;
3778
+ }
3753
3779
goto done ;
3754
3780
case ZEND_ISSET_ISEMPTY_DIM_OBJ :
3755
3781
if ((opline -> extended_value & ZEND_ISEMPTY )) {
@@ -4598,6 +4624,21 @@ static const void *zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_n
4598
4624
4599
4625
opline = zend_jit_traces [trace_num ].exit_info [exit_num ].opline ;
4600
4626
if (opline ) {
4627
+ if (zend_jit_traces [trace_num ].exit_info [exit_num ].flags & ZEND_JIT_EXIT_FREE_OP2 ) {
4628
+ if (!zend_jit_free_op (& dasm_state , (opline - 1 ), -1 , (opline - 1 )-> op2 .var )) {
4629
+ goto jit_failure ;
4630
+ }
4631
+ }
4632
+ if (zend_jit_traces [trace_num ].exit_info [exit_num ].flags & ZEND_JIT_EXIT_FREE_OP1 ) {
4633
+ if (!zend_jit_free_op (& dasm_state , (opline - 1 ), -1 , (opline - 1 )-> op1 .var )) {
4634
+ goto jit_failure ;
4635
+ }
4636
+ }
4637
+ if (zend_jit_traces [trace_num ].exit_info [exit_num ].flags & (ZEND_JIT_EXIT_FREE_OP1 |ZEND_JIT_EXIT_FREE_OP2 )) {
4638
+ if (!zend_jit_check_exception (& dasm_state )) {
4639
+ goto jit_failure ;
4640
+ }
4641
+ }
4601
4642
zend_jit_set_ip (& dasm_state , opline );
4602
4643
if (opline == zend_jit_traces [zend_jit_traces [trace_num ].root ].opline ) {
4603
4644
/* prevent endless loop */
@@ -4995,6 +5036,12 @@ static void zend_jit_dump_exit_info(zend_jit_trace_info *t)
4995
5036
if (t -> exit_info [i ].flags & ZEND_JIT_EXIT_POLYMORPHISM ) {
4996
5037
fprintf (stderr , "/POLY" );
4997
5038
}
5039
+ if (t -> exit_info [i ].flags & ZEND_JIT_EXIT_FREE_OP1 ) {
5040
+ fprintf (stderr , "/FREE_OP1" );
5041
+ }
5042
+ if (t -> exit_info [i ].flags & ZEND_JIT_EXIT_FREE_OP2 ) {
5043
+ fprintf (stderr , "/FREE_OP2" );
5044
+ }
4998
5045
for (j = 0 ; j < stack_size ; j ++ ) {
4999
5046
zend_uchar type = STACK_TYPE (stack , j );
5000
5047
if (type != IS_UNKNOWN ) {
@@ -5005,16 +5052,18 @@ static void zend_jit_dump_exit_info(zend_jit_trace_info *t)
5005
5052
fprintf (stderr , "undef" );
5006
5053
} else {
5007
5054
fprintf (stderr , "%s" , zend_get_type_by_const (type ));
5008
- if ( STACK_REG ( stack , j ) != ZREG_NONE ) {
5009
- if (STACK_REG (stack , j ) < ZREG_NUM ) {
5010
- fprintf ( stderr , "(%s)" , zend_reg_name [ STACK_REG (stack , j )]);
5011
- } else if ( STACK_REG (stack , j ) == ZREG_THIS ) {
5012
- fprintf ( stderr , "(this)" );
5013
- } else {
5014
- fprintf ( stderr , "(const_%d)" , STACK_REG ( stack , j ) - ZREG_NUM );
5015
- }
5055
+ }
5056
+ if (STACK_REG (stack , j ) != ZREG_NONE ) {
5057
+ if ( STACK_REG (stack , j ) < ZREG_NUM ) {
5058
+ fprintf ( stderr , "(%s)" , zend_reg_name [ STACK_REG (stack , j )]);
5059
+ } else if ( STACK_REG ( stack , j ) == ZREG_THIS ) {
5060
+ fprintf ( stderr , "(this)" );
5061
+ } else {
5062
+ fprintf ( stderr , "(const_%d)" , STACK_REG ( stack , j ) - ZREG_NUM );
5016
5063
}
5017
5064
}
5065
+ } else if (STACK_REG (stack , j ) == ZREG_ZVAL_COPY_R0 ) {
5066
+ fprintf (stderr , " zval_copy(%s)" , zend_reg_name [0 ]);
5018
5067
}
5019
5068
}
5020
5069
fprintf (stderr , "\n" );
@@ -5477,14 +5526,41 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf
5477
5526
5478
5527
GC_ADDREF (obj );
5479
5528
ZVAL_OBJ (EX_VAR_NUM (i ), obj );
5529
+ } else if (STACK_REG (stack , i ) == ZREG_NULL ) {
5530
+ ZVAL_NULL (EX_VAR_NUM (i ));
5531
+ } else if (STACK_REG (stack , i ) == ZREG_ZVAL_COPY_R0 ) {
5532
+ zval * val = (zval * )regs -> r [0 ];
5533
+
5534
+ ZVAL_COPY (EX_VAR_NUM (i ), val );
5480
5535
} else {
5481
5536
ZEND_UNREACHABLE ();
5482
5537
}
5483
5538
}
5484
5539
}
5485
5540
5486
5541
opline = t -> exit_info [exit_num ].opline ;
5542
+
5487
5543
if (opline ) {
5544
+ if (t -> exit_info [exit_num ].flags & ZEND_JIT_EXIT_FREE_OP2 ) {
5545
+ ZEND_ASSERT ((opline - 1 )-> opcode == ZEND_FETCH_DIM_R
5546
+ || (opline - 1 )-> opcode == ZEND_FETCH_DIM_IS
5547
+ || (opline - 1 )-> opcode == ZEND_FETCH_DIM_FUNC_ARG );
5548
+ EX (opline ) = opline - 1 ;
5549
+ zval_ptr_dtor_nogc (EX_VAR ((opline - 1 )-> op2 .var ));
5550
+ }
5551
+ if (t -> exit_info [exit_num ].flags & ZEND_JIT_EXIT_FREE_OP1 ) {
5552
+ ZEND_ASSERT ((opline - 1 )-> opcode == ZEND_FETCH_DIM_R
5553
+ || (opline - 1 )-> opcode == ZEND_FETCH_DIM_IS
5554
+ || (opline - 1 )-> opcode == ZEND_FETCH_DIM_FUNC_ARG );
5555
+ EX (opline ) = opline - 1 ;
5556
+ zval_ptr_dtor_nogc (EX_VAR ((opline - 1 )-> op1 .var ));
5557
+ }
5558
+ if (t -> exit_info [exit_num ].flags & (ZEND_JIT_EXIT_FREE_OP1 |ZEND_JIT_EXIT_FREE_OP2 )) {
5559
+ if (EG (exception )) {
5560
+ return 1 ;
5561
+ }
5562
+ }
5563
+
5488
5564
/* Set VM opline to continue interpretation */
5489
5565
EX (opline ) = opline ;
5490
5566
}
0 commit comments