@@ -1361,13 +1361,15 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1361
1361
level = 0 ;
1362
1362
for (;;p ++ ) {
1363
1363
if (p -> op == ZEND_JIT_TRACE_VM ) {
1364
- uint8_t orig_op1_type , op1_type , op2_type , op3_type ;
1364
+ uint8_t orig_op1_type , orig_op2_type , op1_type , op2_type , op3_type ;
1365
+ // zend_class_entry *op1_ce = NULL;
1366
+ zend_class_entry * op2_ce = NULL ;
1365
1367
1366
1368
// TODO: range inference ???
1367
1369
opline = p -> opline ;
1368
1370
1369
1371
op1_type = orig_op1_type = p -> op1_type ;
1370
- op2_type = p -> op2_type ;
1372
+ op2_type = orig_op2_type = p -> op2_type ;
1371
1373
op3_type = p -> op3_type ;
1372
1374
if (op1_type & (IS_TRACE_REFERENCE |IS_TRACE_INDIRECT )) {
1373
1375
op1_type = IS_UNKNOWN ;
@@ -1383,11 +1385,11 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1383
1385
}
1384
1386
1385
1387
if ((p + 1 )-> op == ZEND_JIT_TRACE_OP1_TYPE ) {
1386
- // TODO: support for recorded classes ???
1388
+ // op1_ce = (zend_class_entry*)(p+1)->ce;
1387
1389
p ++ ;
1388
1390
}
1389
1391
if ((p + 1 )-> op == ZEND_JIT_TRACE_OP2_TYPE ) {
1390
- // TODO: support for recorded classes ???
1392
+ op2_ce = ( zend_class_entry * )( p + 1 ) -> ce ;
1391
1393
p ++ ;
1392
1394
}
1393
1395
@@ -1701,6 +1703,11 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
1701
1703
}
1702
1704
ADD_OP1_TRACE_GUARD ();
1703
1705
break ;
1706
+ case ZEND_INIT_DYNAMIC_CALL :
1707
+ if (orig_op2_type == IS_OBJECT && op2_ce == zend_ce_closure ) {
1708
+ ADD_OP2_TRACE_GUARD ();
1709
+ }
1710
+ break ;
1704
1711
default :
1705
1712
break ;
1706
1713
}
@@ -3361,8 +3368,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
3361
3368
uint8_t op2_type = p -> op2_type ;
3362
3369
uint8_t op3_type = p -> op3_type ;
3363
3370
uint8_t orig_op1_type = op1_type ;
3371
+ uint8_t orig_op2_type = op2_type ;
3364
3372
zend_bool op1_indirect ;
3365
3373
zend_class_entry * op1_ce = NULL ;
3374
+ zend_class_entry * op2_ce = NULL ;
3366
3375
3367
3376
opline = p -> opline ;
3368
3377
if (op1_type & (IS_TRACE_REFERENCE |IS_TRACE_INDIRECT )) {
@@ -3383,7 +3392,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
3383
3392
p ++ ;
3384
3393
}
3385
3394
if ((p + 1 )-> op == ZEND_JIT_TRACE_OP2_TYPE ) {
3386
- // TODO: support for recorded classes ???
3395
+ op2_ce = ( zend_class_entry * )( p + 1 ) -> ce ;
3387
3396
p ++ ;
3388
3397
}
3389
3398
@@ -4970,8 +4979,17 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
4970
4979
goto jit_failure ;
4971
4980
}
4972
4981
goto done ;
4973
- case ZEND_INIT_METHOD_CALL :
4974
4982
case ZEND_INIT_DYNAMIC_CALL :
4983
+ if (orig_op2_type == IS_OBJECT && op2_ce == zend_ce_closure ) {
4984
+ op2_info = OP2_INFO ();
4985
+ CHECK_OP2_TRACE_TYPE ();
4986
+ if (!zend_jit_init_closure_call (& dasm_state , opline , op_array_ssa -> cfg .map ? op_array_ssa -> cfg .map [opline - op_array -> opcodes ] : -1 , op_array , ssa , ssa_op , frame -> call_level , p + 1 )) {
4987
+ goto jit_failure ;
4988
+ }
4989
+ goto done ;
4990
+ }
4991
+ /* break missing intentionally */
4992
+ case ZEND_INIT_METHOD_CALL :
4975
4993
if (!zend_jit_trace_handler (& dasm_state , op_array , opline , zend_may_throw (opline , ssa_op , op_array , ssa ), p + 1 )) {
4976
4994
goto jit_failure ;
4977
4995
}
@@ -6058,7 +6076,7 @@ static void zend_jit_dump_exit_info(zend_jit_trace_info *t)
6058
6076
if (t -> exit_info [i ].flags & ZEND_JIT_EXIT_RESTORE_CALL ) {
6059
6077
fprintf (stderr , "/CALL" );
6060
6078
}
6061
- if (t -> exit_info [i ].flags & ZEND_JIT_EXIT_POLYMORPHISM ) {
6079
+ if (t -> exit_info [i ].flags & ( ZEND_JIT_EXIT_POLYMORPHISM | ZEND_JIT_EXIT_DYNAMIC_CALL ) ) {
6062
6080
fprintf (stderr , "/POLY" );
6063
6081
}
6064
6082
if (t -> exit_info [i ].flags & ZEND_JIT_EXIT_FREE_OP1 ) {
@@ -6398,7 +6416,7 @@ int ZEND_FASTCALL zend_jit_trace_hot_side(zend_execute_data *execute_data, uint3
6398
6416
int ret = 0 ;
6399
6417
uint32_t trace_num ;
6400
6418
zend_jit_trace_rec trace_buffer [ZEND_JIT_TRACE_MAX_LENGTH ];
6401
- zend_bool is_megamorphic = 0 ;
6419
+ uint32_t is_megamorphic = 0 ;
6402
6420
uint32_t polymorphism = 0 ;
6403
6421
6404
6422
trace_num = ZEND_JIT_TRACE_NUM ;
@@ -6427,15 +6445,18 @@ int ZEND_FASTCALL zend_jit_trace_hot_side(zend_execute_data *execute_data, uint3
6427
6445
goto abort ;
6428
6446
}
6429
6447
6430
- if (EX (call )
6431
- && JIT_G (max_polymorphic_calls ) > 0
6432
- && (zend_jit_traces [parent_num ].exit_info [exit_num ].flags & ZEND_JIT_EXIT_POLYMORPHISM )) {
6433
- if (zend_jit_traces [parent_num ].polymorphism >= JIT_G (max_polymorphic_calls ) - 1 ) {
6434
- is_megamorphic = 1 ;
6435
- } else if (!zend_jit_traces [parent_num ].polymorphism ) {
6436
- polymorphism = 1 ;
6437
- } else if (exit_num == 0 ) {
6438
- polymorphism = zend_jit_traces [parent_num ].polymorphism + 1 ;
6448
+ if (JIT_G (max_polymorphic_calls ) > 0 ) {
6449
+ if ((zend_jit_traces [parent_num ].exit_info [exit_num ].flags & ZEND_JIT_EXIT_DYNAMIC_CALL )
6450
+ || ((zend_jit_traces [parent_num ].exit_info [exit_num ].flags & ZEND_JIT_EXIT_POLYMORPHISM )
6451
+ && EX (call ))) {
6452
+ if (zend_jit_traces [parent_num ].polymorphism >= JIT_G (max_polymorphic_calls ) - 1 ) {
6453
+ is_megamorphic = zend_jit_traces [parent_num ].exit_info [exit_num ].flags &
6454
+ (ZEND_JIT_EXIT_DYNAMIC_CALL | ZEND_JIT_EXIT_POLYMORPHISM );
6455
+ } else if (!zend_jit_traces [parent_num ].polymorphism ) {
6456
+ polymorphism = 1 ;
6457
+ } else if (exit_num == 0 ) {
6458
+ polymorphism = zend_jit_traces [parent_num ].polymorphism + 1 ;
6459
+ }
6439
6460
}
6440
6461
}
6441
6462
0 commit comments