Skip to content

Commit bac054d

Browse files
committed
Check whether expected types are present for compound op jit
zend_jit_long_math_helper() implicitly assumes that the operands MAY_BE_LONG (but can also have additional types). It will normally only be called if this is guaranteed. However, for compound array/object assignment ops this was not check. Generalize the existing check for assign_op to apply to these as well. Of course, we could also make the code support this correctly, but I don't think it makes sense to JIT these if the type we're specializing for is not present. Closes GH-7481.
1 parent 06275d9 commit bac054d

File tree

2 files changed

+48
-71
lines changed

2 files changed

+48
-71
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 37 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2067,6 +2067,32 @@ static zend_lifetime_interval** zend_jit_allocate_registers(const zend_op_array
20672067
return NULL;
20682068
}
20692069

2070+
2071+
static bool zend_jit_supported_binary_op(zend_uchar op, uint32_t op1_info, uint32_t op2_info)
2072+
{
2073+
switch (op) {
2074+
case ZEND_POW:
2075+
case ZEND_DIV:
2076+
// TODO: check for division by zero ???
2077+
return false;
2078+
case ZEND_ADD:
2079+
case ZEND_SUB:
2080+
case ZEND_MUL:
2081+
return (op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE))
2082+
&& (op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE));
2083+
case ZEND_BW_OR:
2084+
case ZEND_BW_AND:
2085+
case ZEND_BW_XOR:
2086+
case ZEND_SL:
2087+
case ZEND_SR:
2088+
case ZEND_MOD:
2089+
return (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG);
2090+
case ZEND_CONCAT:
2091+
return (op1_info & MAY_BE_STRING) && (op2_info & MAY_BE_STRING);
2092+
EMPTY_SWITCH_DEFAULT_CASE()
2093+
}
2094+
}
2095+
20702096
static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op *rt_opline)
20712097
{
20722098
int b, i, end;
@@ -2488,11 +2514,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
24882514
}
24892515
goto done;
24902516
case ZEND_ASSIGN_OP:
2491-
if (opline->extended_value == ZEND_POW
2492-
|| opline->extended_value == ZEND_DIV) {
2493-
// TODO: check for division by zero ???
2494-
break;
2495-
}
24962517
if (opline->op1_type != IS_CV || opline->result_type != IS_UNUSED) {
24972518
break;
24982519
}
@@ -2504,29 +2525,9 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
25042525
if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) {
25052526
break;
25062527
}
2507-
if (opline->extended_value == ZEND_ADD
2508-
|| opline->extended_value == ZEND_SUB
2509-
|| opline->extended_value == ZEND_MUL
2510-
|| opline->extended_value == ZEND_DIV) {
2511-
if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE))
2512-
|| !(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
2513-
break;
2514-
}
2515-
} else if (opline->extended_value == ZEND_BW_OR
2516-
|| opline->extended_value == ZEND_BW_AND
2517-
|| opline->extended_value == ZEND_BW_XOR
2518-
|| opline->extended_value == ZEND_SL
2519-
|| opline->extended_value == ZEND_SR
2520-
|| opline->extended_value == ZEND_MOD) {
2521-
if (!(op1_info & MAY_BE_LONG)
2522-
|| !(op2_info & MAY_BE_LONG)) {
2523-
break;
2524-
}
2525-
} else if (opline->extended_value == ZEND_CONCAT) {
2526-
if (!(op1_info & MAY_BE_STRING)
2527-
|| !(op2_info & MAY_BE_STRING)) {
2528-
break;
2529-
}
2528+
if (!zend_jit_supported_binary_op(
2529+
opline->extended_value, op1_info, op2_info)) {
2530+
break;
25302531
}
25312532
op1_def_info = OP1_DEF_INFO();
25322533
if (!zend_jit_assign_op(&dasm_state, opline,
@@ -2538,17 +2539,16 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
25382539
}
25392540
goto done;
25402541
case ZEND_ASSIGN_DIM_OP:
2541-
if (opline->extended_value == ZEND_POW
2542-
|| opline->extended_value == ZEND_DIV) {
2543-
// TODO: check for division by zero ???
2544-
break;
2545-
}
25462542
if (opline->op1_type != IS_CV || opline->result_type != IS_UNUSED) {
25472543
break;
25482544
}
25492545
if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
25502546
break;
25512547
}
2548+
if (!zend_jit_supported_binary_op(
2549+
opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) {
2550+
break;
2551+
}
25522552
if (!zend_jit_assign_dim_op(&dasm_state, opline,
25532553
OP1_INFO(), OP1_DEF_INFO(), OP1_REG_ADDR(), OP2_INFO(),
25542554
OP1_DATA_INFO(), OP1_DATA_RANGE(),
@@ -2613,11 +2613,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
26132613
}
26142614
goto done;
26152615
case ZEND_ASSIGN_OBJ_OP:
2616-
if (opline->extended_value == ZEND_POW
2617-
|| opline->extended_value == ZEND_DIV) {
2618-
// TODO: check for division by zero ???
2619-
break;
2620-
}
26212616
if (opline->result_type != IS_UNUSED) {
26222617
break;
26232618
}
@@ -2629,6 +2624,10 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
26292624
if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
26302625
break;
26312626
}
2627+
if (!zend_jit_supported_binary_op(
2628+
opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) {
2629+
break;
2630+
}
26322631
ce = NULL;
26332632
ce_is_instanceof = 0;
26342633
if (opline->op1_type == IS_UNUSED) {

ext/opcache/jit/zend_jit_trace.c

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4150,11 +4150,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
41504150
}
41514151
goto done;
41524152
case ZEND_ASSIGN_OP:
4153-
if (opline->extended_value == ZEND_POW
4154-
|| opline->extended_value == ZEND_DIV) {
4155-
// TODO: check for division by zero ???
4156-
break;
4157-
}
41584153
if (opline->op1_type != IS_CV || opline->result_type != IS_UNUSED) {
41594154
break;
41604155
}
@@ -4165,29 +4160,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
41654160
if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) {
41664161
break;
41674162
}
4168-
if (opline->extended_value == ZEND_ADD
4169-
|| opline->extended_value == ZEND_SUB
4170-
|| opline->extended_value == ZEND_MUL
4171-
|| opline->extended_value == ZEND_DIV) {
4172-
if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE))
4173-
|| !(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
4174-
break;
4175-
}
4176-
} else if (opline->extended_value == ZEND_BW_OR
4177-
|| opline->extended_value == ZEND_BW_AND
4178-
|| opline->extended_value == ZEND_BW_XOR
4179-
|| opline->extended_value == ZEND_SL
4180-
|| opline->extended_value == ZEND_SR
4181-
|| opline->extended_value == ZEND_MOD) {
4182-
if (!(op1_info & MAY_BE_LONG)
4183-
|| !(op2_info & MAY_BE_LONG)) {
4184-
break;
4185-
}
4186-
} else if (opline->extended_value == ZEND_CONCAT) {
4187-
if (!(op1_info & MAY_BE_STRING)
4188-
|| !(op2_info & MAY_BE_STRING)) {
4189-
break;
4190-
}
4163+
if (!zend_jit_supported_binary_op(
4164+
opline->extended_value, op1_info, op2_info)) {
4165+
break;
41914166
}
41924167
op1_def_info = OP1_DEF_INFO();
41934168
if (op1_def_info & MAY_BE_GUARD
@@ -4217,6 +4192,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
42174192
if (opline->result_type != IS_UNUSED) {
42184193
break;
42194194
}
4195+
if (!zend_jit_supported_binary_op(
4196+
opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) {
4197+
break;
4198+
}
42204199
op1_info = OP1_INFO();
42214200
op1_addr = OP1_REG_ADDR();
42224201
if (opline->op1_type == IS_VAR) {
@@ -4323,11 +4302,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
43234302
}
43244303
goto done;
43254304
case ZEND_ASSIGN_OBJ_OP:
4326-
if (opline->extended_value == ZEND_POW
4327-
|| opline->extended_value == ZEND_DIV) {
4328-
// TODO: check for division by zero ???
4329-
break;
4330-
}
43314305
if (opline->result_type != IS_UNUSED) {
43324306
break;
43334307
}
@@ -4336,6 +4310,10 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
43364310
|| Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
43374311
break;
43384312
}
4313+
if (!zend_jit_supported_binary_op(
4314+
opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) {
4315+
break;
4316+
}
43394317
ce = NULL;
43404318
ce_is_instanceof = 0;
43414319
delayed_fetch_this = 0;

0 commit comments

Comments
 (0)