@@ -653,6 +653,66 @@ static int zend_jit_trace_add_phis(zend_jit_trace_rec *trace_buffer, uint32_t ss
653
653
return ssa_vars_count ;
654
654
}
655
655
656
+ static int zend_jit_trace_add_call_phis (zend_jit_trace_rec * trace_buffer , uint32_t ssa_vars_count , zend_ssa * tssa , zend_jit_trace_stack * stack )
657
+ {
658
+ zend_ssa_phi * prev = NULL ;
659
+ const zend_op_array * op_array = trace_buffer -> op_array ;
660
+ const zend_op * opline = trace_buffer [1 ].opline ;
661
+ int count = opline - op_array -> opcodes ;
662
+ int i ;
663
+
664
+ for (i = 0 ; i < count ; i ++ ) {
665
+ zend_ssa_phi * phi = zend_arena_calloc (& CG (arena ), 1 ,
666
+ ZEND_MM_ALIGNED_SIZE (sizeof (zend_ssa_phi )) +
667
+ ZEND_MM_ALIGNED_SIZE (sizeof (int ) * 2 ) +
668
+ sizeof (void * ) * 2 );
669
+ phi -> sources = (int * )(((char * )phi ) + ZEND_MM_ALIGNED_SIZE (sizeof (zend_ssa_phi )));
670
+ phi -> sources [0 ] = STACK_VAR (stack , i );
671
+ phi -> sources [1 ] = -1 ;
672
+ phi -> use_chains = (zend_ssa_phi * * )(((char * )phi -> sources ) + ZEND_MM_ALIGNED_SIZE (sizeof (int ) * 2 ));
673
+ phi -> pi = -1 ;
674
+ phi -> var = i ;
675
+ phi -> ssa_var = ssa_vars_count ;
676
+ SET_STACK_VAR (stack , i , ssa_vars_count );
677
+ ssa_vars_count ++ ;
678
+ phi -> block = 1 ;
679
+ if (prev ) {
680
+ prev -> next = phi ;
681
+ } else {
682
+ tssa -> blocks [1 ].phis = phi ;
683
+ }
684
+ prev = phi ;
685
+ }
686
+ return ssa_vars_count ;
687
+ }
688
+
689
+ static int zend_jit_trace_add_ret_phis (zend_jit_trace_rec * trace_buffer , uint32_t ssa_vars_count , zend_ssa * tssa , zend_jit_trace_stack * stack )
690
+ {
691
+ const zend_op * opline = trace_buffer [1 ].opline - 1 ;
692
+ int i ;
693
+
694
+ if (RETURN_VALUE_USED (opline )) {
695
+ zend_ssa_phi * phi = zend_arena_calloc (& CG (arena ), 1 ,
696
+ ZEND_MM_ALIGNED_SIZE (sizeof (zend_ssa_phi )) +
697
+ ZEND_MM_ALIGNED_SIZE (sizeof (int ) * 2 ) +
698
+ sizeof (void * ) * 2 );
699
+
700
+ i = EX_VAR_TO_NUM (opline -> result .var );
701
+ phi -> sources = (int * )(((char * )phi ) + ZEND_MM_ALIGNED_SIZE (sizeof (zend_ssa_phi )));
702
+ phi -> sources [0 ] = STACK_VAR (stack , i );
703
+ phi -> sources [1 ] = -1 ;
704
+ phi -> use_chains = (zend_ssa_phi * * )(((char * )phi -> sources ) + ZEND_MM_ALIGNED_SIZE (sizeof (int ) * 2 ));
705
+ phi -> pi = -1 ;
706
+ phi -> var = i ;
707
+ phi -> ssa_var = ssa_vars_count ;
708
+ SET_STACK_VAR (stack , i , ssa_vars_count );
709
+ ssa_vars_count ++ ;
710
+ phi -> block = 1 ;
711
+ tssa -> blocks [1 ].phis = phi ;
712
+ }
713
+ return ssa_vars_count ;
714
+ }
715
+
656
716
static int zend_jit_trace_copy_ssa_var_info (const zend_op_array * op_array , const zend_ssa * ssa , const zend_op * * tssa_opcodes , zend_ssa * tssa , int ssa_var )
657
717
{
658
718
int var , use ;
@@ -1084,7 +1144,9 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1084
1144
tssa -> blocks = zend_arena_calloc (& CG (arena ), 2 , sizeof (zend_ssa_block ));
1085
1145
tssa -> cfg .predecessors = zend_arena_calloc (& CG (arena ), 2 , sizeof (int ));
1086
1146
1087
- if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
1147
+ if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
1148
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
1149
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET ) {
1088
1150
tssa -> cfg .blocks_count = 2 ;
1089
1151
tssa -> cfg .edges_count = 2 ;
1090
1152
@@ -1136,6 +1198,10 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1136
1198
// TODO: For tracing, it's possible, to create pseudo Phi functions
1137
1199
// at the end of loop, without this additional pass (like LuaJIT) ???
1138
1200
ssa_vars_count = zend_jit_trace_add_phis (trace_buffer , ssa_vars_count , tssa , stack );
1201
+ } else if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL ) {
1202
+ ssa_vars_count = zend_jit_trace_add_call_phis (trace_buffer , ssa_vars_count , tssa , stack );
1203
+ } else if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET ) {
1204
+ ssa_vars_count = zend_jit_trace_add_ret_phis (trace_buffer , ssa_vars_count , tssa , stack );
1139
1205
}
1140
1206
1141
1207
p = trace_buffer + ZEND_JIT_TRACE_START_REC_SIZE ;
@@ -1213,7 +1279,9 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1213
1279
i ++ ;
1214
1280
}
1215
1281
1216
- if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
1282
+ if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
1283
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
1284
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET ) {
1217
1285
/* Update Phi sources */
1218
1286
zend_ssa_phi * phi = tssa -> blocks [1 ].phis ;
1219
1287
@@ -1352,7 +1420,9 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1352
1420
}
1353
1421
}
1354
1422
1355
- if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
1423
+ if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
1424
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
1425
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET ) {
1356
1426
/* Propagate initial value through Phi functions */
1357
1427
zend_ssa_phi * phi = tssa -> blocks [1 ].phis ;
1358
1428
@@ -1978,7 +2048,9 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1978
2048
while (q -> op == ZEND_JIT_TRACE_INIT_CALL ) {
1979
2049
q ++ ;
1980
2050
}
1981
- if (q -> op == ZEND_JIT_TRACE_VM ) {
2051
+ if (q -> op == ZEND_JIT_TRACE_VM
2052
+ || (q -> op == ZEND_JIT_TRACE_END
2053
+ && q -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET )) {
1982
2054
const zend_op * opline = q -> opline - 1 ;
1983
2055
if (opline -> result_type != IS_UNUSED ) {
1984
2056
ssa_var_info [
@@ -2038,7 +2110,9 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
2038
2110
}
2039
2111
}
2040
2112
2041
- if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
2113
+ if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
2114
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
2115
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET ) {
2042
2116
/* Propagate guards through Phi sources */
2043
2117
zend_ssa_phi * phi = tssa -> blocks [1 ].phis ;
2044
2118
@@ -2248,7 +2322,9 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
2248
2322
}
2249
2323
}
2250
2324
2251
- if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
2325
+ if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
2326
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
2327
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET ) {
2252
2328
zend_ssa_phi * phi = ssa -> blocks [1 ].phis ;
2253
2329
2254
2330
while (phi ) {
@@ -2546,7 +2622,9 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
2546
2622
}
2547
2623
}
2548
2624
2549
- if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
2625
+ if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
2626
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
2627
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET ) {
2550
2628
zend_ssa_phi * phi = ssa -> blocks [1 ].phis ;
2551
2629
2552
2630
while (phi ) {
@@ -2558,12 +2636,14 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
2558
2636
phi = phi -> next ;
2559
2637
}
2560
2638
2561
- for (i = 0 ; i < op_array -> last_var ; i ++ ) {
2562
- if (start [i ] >= 0 && !ssa -> vars [i ].phi_use_chain ) {
2563
- end [i ] = idx ;
2564
- flags [i ] &= ~ZREG_LAST_USE ;
2565
- } else {
2566
- zend_jit_close_var (stack , i , start , end , flags , idx );
2639
+ if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
2640
+ for (i = 0 ; i < op_array -> last_var ; i ++ ) {
2641
+ if (start [i ] >= 0 && !ssa -> vars [i ].phi_use_chain ) {
2642
+ end [i ] = idx ;
2643
+ flags [i ] &= ~ZREG_LAST_USE ;
2644
+ } else {
2645
+ zend_jit_close_var (stack , i , start , end , flags , idx );
2646
+ }
2567
2647
}
2568
2648
}
2569
2649
} else {
@@ -2650,7 +2730,9 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
2650
2730
}
2651
2731
}
2652
2732
2653
- if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
2733
+ if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
2734
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
2735
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET ) {
2654
2736
zend_ssa_phi * phi = ssa -> blocks [1 ].phis ;
2655
2737
2656
2738
while (phi ) {
@@ -2815,7 +2897,9 @@ static zend_lifetime_interval** zend_jit_trace_allocate_registers(zend_jit_trace
2815
2897
}
2816
2898
2817
2899
/* SSA resolution */
2818
- if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
2900
+ if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
2901
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
2902
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET ) {
2819
2903
zend_ssa_phi * phi = ssa -> blocks [1 ].phis ;
2820
2904
2821
2905
while (phi ) {
@@ -3402,7 +3486,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
3402
3486
ZEND_UNREACHABLE ();
3403
3487
// SET_STACK_TYPE(stack, i, STACK_TYPE(parent_stack, i));
3404
3488
} else if ((info & MAY_BE_GUARD ) != 0
3405
- && trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
3489
+ && (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
3490
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
3491
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET )
3406
3492
&& (ssa -> vars [i ].use_chain != -1
3407
3493
|| (ssa -> vars [i ].phi_use_chain
3408
3494
&& !(ssa -> var_info [ssa -> vars [i ].phi_use_chain -> ssa_var ].type & MAY_BE_GUARD )))) {
@@ -3422,7 +3508,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
3422
3508
}
3423
3509
3424
3510
if ((info & MAY_BE_PACKED_GUARD ) != 0
3425
- && trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
3511
+ && (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
3512
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
3513
+ || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET )
3426
3514
&& ssa -> vars [i ].use_chain != -1 ) {
3427
3515
if (!zend_jit_packed_guard (& dasm_state , opline , EX_NUM_TO_VAR (i ), info )) {
3428
3516
goto jit_failure ;
@@ -6304,20 +6392,19 @@ static void zend_jit_dump_trace(zend_jit_trace_rec *trace_buffer, zend_ssa *tssa
6304
6392
if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
6305
6393
|| trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
6306
6394
|| trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET ) {
6395
+ zend_ssa_phi * p = tssa -> blocks [1 ].phis ;
6396
+
6307
6397
fprintf (stderr , "LOOP:\n" );
6308
- if (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP ) {
6309
- zend_ssa_phi * p = tssa -> blocks [1 ].phis ;
6310
-
6311
- while (p ) {
6312
- fprintf (stderr , " ;" );
6313
- zend_dump_ssa_var (op_array , tssa , p -> ssa_var , 0 , p -> var , ZEND_DUMP_RC_INFERENCE );
6314
- fprintf (stderr , " = Phi(" );
6315
- zend_dump_ssa_var (op_array , tssa , p -> sources [0 ], 0 , p -> var , ZEND_DUMP_RC_INFERENCE );
6316
- fprintf (stderr , ", " );
6317
- zend_dump_ssa_var (op_array , tssa , p -> sources [1 ], 0 , p -> var , ZEND_DUMP_RC_INFERENCE );
6318
- fprintf (stderr , ")\n" );
6319
- p = p -> next ;
6320
- }
6398
+
6399
+ while (p ) {
6400
+ fprintf (stderr , " ;" );
6401
+ zend_dump_ssa_var (op_array , tssa , p -> ssa_var , 0 , p -> var , ZEND_DUMP_RC_INFERENCE );
6402
+ fprintf (stderr , " = Phi(" );
6403
+ zend_dump_ssa_var (op_array , tssa , p -> sources [0 ], 0 , p -> var , ZEND_DUMP_RC_INFERENCE );
6404
+ fprintf (stderr , ", " );
6405
+ zend_dump_ssa_var (op_array , tssa , p -> sources [1 ], 0 , p -> var , ZEND_DUMP_RC_INFERENCE );
6406
+ fprintf (stderr , ")\n" );
6407
+ p = p -> next ;
6321
6408
}
6322
6409
}
6323
6410
}
0 commit comments