Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
616913e
Move zval.u2.next to Bucket
iluuu1994 Jun 6, 2026
3775fb8
Move zval.u2.lineno
iluuu1994 Jun 6, 2026
4f23c90
Move zval.u2.constant_flags
iluuu1994 Jun 6, 2026
b1730d7
Move zval.u2.num_args
iluuu1994 Jun 7, 2026
e39509b
Move zval.u2.cache_slot
iluuu1994 Jun 7, 2026
f323116
Move zval.u2.guard
iluuu1994 Jun 7, 2026
d041fd4
Move zval.u2.opline_num
iluuu1994 Jun 7, 2026
0a6e499
Move zval.u2.fe_pos and zval.u2.fe_iter_idx
iluuu1994 Jun 7, 2026
4deb290
Remove ZEND_EXTRA_VALUE for PoC
iluuu1994 Jun 8, 2026
0f4b07f
Avoid Z_EXTRA in ext/spl/spl_dllist.c
iluuu1994 Jun 8, 2026
172595d
Avoid Z_EXTRA in array_map()
iluuu1994 Jun 8, 2026
c7c91c4
Move offset for ZEND_INIT_FCALL_OFFSET
iluuu1994 Jun 9, 2026
1c22769
Move offset for ZEND_TYPE_ASSERT
iluuu1994 Jun 9, 2026
6b71c9d
Move Z_EXTRA for stable sorting to Bucket.stable_index
iluuu1994 Jun 9, 2026
295bbc1
Drop Z_EXTRA INI_ZVAL_IS_NUMBER
iluuu1994 Jun 9, 2026
ccce3b9
Move IS_PROP_UNINIT and IS_PROP_LAZY
iluuu1994 Jun 10, 2026
26033d0
Move IS_PROP_REINITABLE to auxiliary data structure
iluuu1994 Jun 10, 2026
8bc027d
Remove remaining Z_PROP_FLAG things
iluuu1994 Jun 10, 2026
951d0ae
Move VAR_WAKEUP_FLAG and VAR_UNSERIALIZE_FLAG
iluuu1994 Jun 10, 2026
53d81f3
Fully remove u2
iluuu1994 Jun 10, 2026
0fed76f
Avoid Z_TYPE_INFO_P and Z_* lval
iluuu1994 Jun 10, 2026
acedb89
Move call_info to zend_execute_data
iluuu1994 Jun 11, 2026
bd0eb72
Wip
iluuu1994 Jun 11, 2026
95fa75a
Basic support for .gdbinit
iluuu1994 Jun 12, 2026
dc37863
Fixes
iluuu1994 Jun 12, 2026
e16338b
Support default + bench exts for testing symfony demo
iluuu1994 Jun 12, 2026
7ad5a05
Fix Zend/zend_vm_execute.h ref promotion
iluuu1994 Jun 12, 2026
274b061
Dirty support for spl array iterator
iluuu1994 Jun 12, 2026
04012c7
Debug int overflow check
iluuu1994 Jun 12, 2026
1b1fbd9
Make run-tests.php ignore tests that fail with "Unsupported int range"
iluuu1994 Jun 12, 2026
7759492
Simplify sccp changes
iluuu1994 Jun 12, 2026
9fb1c14
Fix sccp
iluuu1994 Jun 12, 2026
127c056
Shift pointers by 16 bits
iluuu1994 Jun 13, 2026
89c939c
Comprehensive sccp fix
iluuu1994 Jun 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 22 additions & 16 deletions .gdbinit
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
set $Z_PTR_SHIFT = 16
set $Z_TYPE_INFO_MASK = 0x3f
set $Z_TYPE_MASK = 0x0f
set $Z_TYPE_SHIFT = 6

define set_ts
set $tsrm_ls = $arg0
end
Expand Down Expand Up @@ -84,7 +89,7 @@ define dump_bt

set $callFrameSize = (sizeof(zend_execute_data) + sizeof(zval) - 1) / sizeof(zval)

set $count = $ex->This.u2.num_args
set $count = $ex->num_args
set $arg = 0
while $arg < $count
if $arg > 0
Expand Down Expand Up @@ -160,11 +165,11 @@ end

define ____printzv_contents
set $zvalue = $arg0
set $type = $zvalue->u1.v.type
set $type = ($zvalue->u32.a & $Z_TYPE_MASK)

# 15 == IS_INDIRECT
if $type > 5 && $type < 12
printf "(refcount=%d) ", $zvalue->value.counted->gc.refcount
printf "(refcount=%d) ", ((zend_refcounted*)($zvalue->ptr >> $Z_PTR_SHIFT))->gc.refcount
end

if $type == 0
Expand All @@ -180,19 +185,19 @@ define ____printzv_contents
printf "bool: true"
end
if $type == 4
printf "long: %ld", $zvalue->value.lval
printf "long: %ld", ((int64_t)$zvalue->u64 - ((int64_t)$zvalue->u64 & $Z_TYPE_INFO_MASK)) / (1 << $Z_TYPE_SHIFT)
end
if $type == 5
printf "double: %f", $zvalue->value.dval
printf "double: %f", (double)*(float*)&$zvalue->u32.b
end
if $type == 6
printf "string: %s", (char*)$zvalue->value.str->val
printf "string: %s", (char*)((zend_string*)($zvalue->ptr >> $Z_PTR_SHIFT))->val
end
if $type == 7
printf "array: "
if ! $arg1
set $ind = $ind + 1
____print_ht $zvalue->value.arr 1
____print_ht ((HashTable*)($zvalue->ptr >> $Z_PTR_SHIFT)) 1
set $ind = $ind - 1
set $i = $ind
while $i > 0
Expand Down Expand Up @@ -243,21 +248,21 @@ define ____printzv_contents
set $type = 0
end
if $type == 9
printf "resource: #%d", $zvalue->value.res->handle
printf "resource: #%d", ((zend_resource*)($zvalue->ptr >> $Z_PTR_SHIFT))->handle
end
if $type == 10
printf "reference: "
____printzv &$zvalue->value.ref->val $arg1
____printzv &((zend_reference*)($zvalue->ptr >> $Z_PTR_SHIFT))->val $arg1
end
if $type == 11
printf "CONSTANT_AST"
end
if $type == 12
printf "indirect: "
____printzv $zvalue->value.zv $arg1
____printzv ((zval*)($zvalue->ptr >> $Z_PTR_SHIFT)) $arg1
end
if $type == 13
printf "pointer: %p", $zvalue->value.ptr
printf "pointer: %p", ((void*)($zvalue->ptr >> $Z_PTR_SHIFT))
end
if $type == 15
printf "_ERROR"
Expand Down Expand Up @@ -341,7 +346,8 @@ define ____print_ht
set $h = $bucket->h
end
set $n = $ind
if $val->u1.v.type > 0
set $type = ($val->u32.a & $Z_TYPE_MASK)
if $type > 0
while $n > 0
printf " "
set $n = $n - 1
Expand All @@ -351,7 +357,7 @@ define ____print_ht
____print_str (char*)$key->val $key->len
printf " => "
else
printf "%d => ", $h
printf "%ld => ", $h
end
if $arg1 == 0
printf "%p\n", $val
Expand All @@ -361,14 +367,14 @@ define ____print_ht
____printzv $zval 1
end
if $arg1 == 2
printf "%s\n", (char*)$val->value.ptr
printf "%s\n", ((char*)($zvalue->ptr >> $Z_PTR_SHIFT))
end
if $arg1 == 3
set $func = (zend_function*)$val->value.ptr
set $func = ((zend_function*)($zvalue->ptr >> $Z_PTR_SHIFT))
printf "\"%s\"\n", (char*)$func->common.function_name->val
end
if $arg1 == 4
set $const = (zend_constant *)$val->value.ptr
set $const = ((zend_constant*)($zvalue->ptr >> $Z_PTR_SHIFT))
____printzv $const 1
end
end
Expand Down
15 changes: 7 additions & 8 deletions Zend/Optimizer/block_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,11 +245,10 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
if (!Z_REFCOUNTED(ZEND_OP1_LITERAL(last_op))) {
zend_string *tmp = zend_string_alloc(l, 0);
memcpy(ZSTR_VAL(tmp), Z_STRVAL(ZEND_OP1_LITERAL(last_op)), old_len);
Z_STR(ZEND_OP1_LITERAL(last_op)) = tmp;
ZVAL_STR(&ZEND_OP1_LITERAL(last_op), tmp);
} else {
Z_STR(ZEND_OP1_LITERAL(last_op)) = zend_string_extend(Z_STR(ZEND_OP1_LITERAL(last_op)), l, 0);
ZVAL_STR(&ZEND_OP1_LITERAL(last_op), zend_string_extend(Z_STR(ZEND_OP1_LITERAL(last_op)), l, 0));
}
Z_TYPE_INFO(ZEND_OP1_LITERAL(last_op)) = IS_STRING_EX;
memcpy(Z_STRVAL(ZEND_OP1_LITERAL(last_op)) + old_len, Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)));
Z_STRVAL(ZEND_OP1_LITERAL(last_op))[l] = '\0';
zval_ptr_dtor_nogc(&ZEND_OP1_LITERAL(opline));
Expand Down Expand Up @@ -498,7 +497,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
}
}
break;

case ZEND_BOOL:
case ZEND_BOOL_NOT:
optimize_bool:
Expand Down Expand Up @@ -739,11 +738,10 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
if (!Z_REFCOUNTED(ZEND_OP2_LITERAL(src))) {
zend_string *tmp = zend_string_alloc(l, 0);
memcpy(ZSTR_VAL(tmp), Z_STRVAL(ZEND_OP2_LITERAL(src)), old_len);
Z_STR(ZEND_OP2_LITERAL(src)) = tmp;
ZVAL_STR(&ZEND_OP2_LITERAL(src), tmp);
} else {
Z_STR(ZEND_OP2_LITERAL(src)) = zend_string_extend(Z_STR(ZEND_OP2_LITERAL(src)), l, 0);
ZVAL_STR(&ZEND_OP2_LITERAL(src), zend_string_extend(Z_STR(ZEND_OP2_LITERAL(src)), l, 0));
}
Z_TYPE_INFO(ZEND_OP2_LITERAL(src)) = IS_STRING_EX;
memcpy(Z_STRVAL(ZEND_OP2_LITERAL(src)) + old_len, Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)));
Z_STRVAL(ZEND_OP2_LITERAL(src))[l] = '\0';
zval_ptr_dtor_str(&ZEND_OP2_LITERAL(opline));
Expand Down Expand Up @@ -1068,7 +1066,8 @@ static void assemble_code_blocks(const zend_cfg *cfg, zend_op_array *op_array, z
ZEND_ASSERT(b->successors_count == (opline->opcode == ZEND_MATCH ? 1 : 2) + zend_hash_num_elements(jumptable));

ZEND_HASH_FOREACH_VAL(jumptable, zv) {
Z_LVAL_P(zv) = ZEND_OPLINE_TO_OFFSET(opline, new_opcodes + blocks[b->successors[s++]].start);
// Use raw access for jumptables? Would avoid a shr.
ZVAL_LONG(zv, ZEND_OPLINE_TO_OFFSET(opline, new_opcodes + blocks[b->successors[s++]].start));
} ZEND_HASH_FOREACH_END();
opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, new_opcodes + blocks[b->successors[s++]].start);
break;
Expand Down
23 changes: 12 additions & 11 deletions Zend/Optimizer/compact_literals.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
LITERAL_INFO(opline->op1.constant, 1);
}
if (opline->op2_type == IS_CONST) {
if (Z_EXTRA(op_array->literals[opline->op2.constant]) == ZEND_EXTRA_VALUE) {
LITERAL_INFO(opline->op2.constant, 2);
} else {
LITERAL_INFO(opline->op2.constant, 1);
}
LITERAL_INFO(opline->op2.constant, 1);
}
break;
default:
Expand Down Expand Up @@ -352,9 +348,10 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
i++;
}
break;
case IS_DOUBLE:
case IS_DOUBLE: {
ZEND_ASSERT(info[i].num_related == 1);
key = zend_string_init((char*)&Z_DVAL(op_array->literals[i]), sizeof(double), 0);
double d = Z_DVAL(op_array->literals[i]);
key = zend_string_init((char*)&d, sizeof(double), 0);
bias_key(key, 200);
if ((pos = zend_hash_find(&hash, key))) {
map[i] = Z_LVAL_P(pos);
Expand All @@ -370,6 +367,7 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
}
zend_string_release_ex(key, 0);
break;
}
case IS_STRING: {
key = create_str_cache_key(&op_array->literals[i], info[i].num_related);
if ((pos = zend_hash_find(&hash, key)) != NULL) {
Expand Down Expand Up @@ -544,12 +542,15 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
case ZEND_INIT_FCALL_BY_NAME:
case ZEND_INIT_NS_FCALL_BY_NAME:
// op2 func
if (func_slot[opline->op2.constant] >= 0) {
// FIXME: Compact for op2_type == IS_UNDEF.
if (opline->op2_type == IS_CONST && func_slot[opline->op2.constant] >= 0) {
opline->result.num = func_slot[opline->op2.constant];
} else {
opline->result.num = cache_size;
cache_size += sizeof(void *);
func_slot[opline->op2.constant] = opline->result.num;
if (opline->op2_type == IS_CONST) {
func_slot[opline->op2.constant] = opline->result.num;
}
}
break;
case ZEND_INIT_METHOD_CALL:
Expand Down Expand Up @@ -759,9 +760,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
zval *val = &op_array->literals[opline->op2.constant];

if (Z_TYPE_P(val) == IS_CONSTANT_AST) {
/* Ensure zval is aligned to 8 bytes */
/* Ensure cache slot is aligned to 8 bytes */
op_array->cache_size = ZEND_MM_ALIGNED_SIZE_EX(op_array->cache_size, 8);
Z_CACHE_SLOT_P(val) = op_array->cache_size;
opline->extended_value = op_array->cache_size;
op_array->cache_size += sizeof(zval);
}
} else if (opline->opcode != ZEND_RECV) {
Expand Down
6 changes: 6 additions & 0 deletions Zend/Optimizer/compact_vars.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ void zend_optimizer_compact_vars(zend_op_array *op_array) {
num--;
zend_bitset_incl(used_vars, VAR_NUM(opline->result.var) + num);
}
} else if (opline->opcode == ZEND_FE_RESET_R || opline->opcode == ZEND_FE_RESET_RW) {
/* FE_RESET reserves the slot right after the result to hold the foreach
* iteration position (Z_FE_POS_P/Z_FE_ITER_P). Keep it so it isn't
* dropped, and -- since used temps are renumbered in index order -- it
* stays immediately after the loop variable. */
zend_bitset_incl(used_vars, VAR_NUM(opline->result.var) + 1);
}
}
}
Expand Down
26 changes: 13 additions & 13 deletions Zend/Optimizer/dfa_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ static void zend_ssa_replace_control_link(zend_op_array *op_array, zend_ssa *ssa
zval *zv;
ZEND_HASH_FOREACH_VAL(jumptable, zv) {
if (ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(zv)) == old->start) {
Z_LVAL_P(zv) = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, dst->start);
ZVAL_LONG(zv, ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, dst->start));
}
} ZEND_HASH_FOREACH_END();
if (ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value) == old->start) {
Expand Down Expand Up @@ -1109,7 +1109,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
// op_1: ASSIGN ? -> #v [use_as_double], long(?) => ASSIGN ? -> #v, double(?)

zval *zv = CT_CONSTANT_EX(op_array, opline->op2.constant);
ZEND_ASSERT(Z_TYPE_INFO_P(zv) == IS_LONG);
ZEND_ASSERT(Z_TYPE_P(zv) == IS_LONG);
ZVAL_DOUBLE(&tmp, zval_get_double(zv));
opline->op2.constant = zend_optimizer_add_literal(op_array, &tmp);

Expand All @@ -1120,7 +1120,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
// op_1: QM_ASSIGN #v [use_as_double], long(?) => QM_ASSIGN #v, double(?)

zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
ZEND_ASSERT(Z_TYPE_INFO_P(zv) == IS_LONG);
ZEND_ASSERT(Z_TYPE_P(zv) == IS_LONG);
ZVAL_DOUBLE(&tmp, zval_get_double(zv));
opline->op1.constant = zend_optimizer_add_literal(op_array, &tmp);
}
Expand All @@ -1139,7 +1139,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);

if ((OP2_INFO() & MAY_BE_ANY) == MAY_BE_DOUBLE
&& Z_TYPE_INFO_P(zv) == IS_LONG) {
&& Z_TYPE_P(zv) == IS_LONG) {

// op_1: #v.? = ADD long(?), #?.? [double] => #v.? = ADD double(?), #?.? [double]

Expand All @@ -1151,10 +1151,10 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
zv = CT_CONSTANT_EX(op_array, opline->op1.constant);

if (((OP2_INFO() & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG
&& Z_TYPE_INFO_P(zv) == IS_LONG
&& Z_TYPE_P(zv) == IS_LONG
&& Z_LVAL_P(zv) == 0)
|| ((OP2_INFO() & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_DOUBLE
&& Z_TYPE_INFO_P(zv) == IS_DOUBLE
&& Z_TYPE_P(zv) == IS_DOUBLE
&& Z_DVAL_P(zv) == 0.0)) {

// op_1: #v.? = ADD 0, #?.? [double,long] => #v.? = QM_ASSIGN #?.?
Expand All @@ -1173,9 +1173,9 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
&& (OP2_INFO() & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_LONG|MAY_BE_DOUBLE))) == 0) {
zv = CT_CONSTANT_EX(op_array, opline->op1.constant);

if ((Z_TYPE_INFO_P(zv) == IS_LONG
if ((Z_TYPE_P(zv) == IS_LONG
&& Z_LVAL_P(zv) == 2)
|| (Z_TYPE_INFO_P(zv) == IS_DOUBLE
|| (Z_TYPE_P(zv) == IS_DOUBLE
&& Z_DVAL_P(zv) == 2.0
&& !(OP2_INFO() & MAY_BE_LONG))) {

Expand All @@ -1192,7 +1192,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
zval *zv = CT_CONSTANT_EX(op_array, opline->op2.constant);

if ((OP1_INFO() & MAY_BE_ANY) == MAY_BE_DOUBLE
&& Z_TYPE_INFO_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) == IS_LONG) {
&& Z_TYPE_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) == IS_LONG) {

// op_1: #v.? = ADD #?.? [double], long(?) => #v.? = ADD #?.? [double], double(?)

Expand All @@ -1202,10 +1202,10 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
}
if (opline->opcode == ZEND_ADD || opline->opcode == ZEND_SUB) {
if (((OP1_INFO() & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG
&& Z_TYPE_INFO_P(zv) == IS_LONG
&& Z_TYPE_P(zv) == IS_LONG
&& Z_LVAL_P(zv) == 0)
|| ((OP1_INFO() & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_DOUBLE
&& Z_TYPE_INFO_P(zv) == IS_DOUBLE
&& Z_TYPE_P(zv) == IS_DOUBLE
&& Z_DVAL_P(zv) == 0.0)) {

// op_1: #v.? = ADD #?.? [double,long], 0 => #v.? = QM_ASSIGN #?.?
Expand All @@ -1218,9 +1218,9 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
&& (OP1_INFO() & ((MAY_BE_ANY|MAY_BE_UNDEF)-(MAY_BE_LONG|MAY_BE_DOUBLE))) == 0) {
zv = CT_CONSTANT_EX(op_array, opline->op2.constant);

if ((Z_TYPE_INFO_P(zv) == IS_LONG
if ((Z_TYPE_P(zv) == IS_LONG
&& Z_LVAL_P(zv) == 2)
|| (Z_TYPE_INFO_P(zv) == IS_DOUBLE
|| (Z_TYPE_P(zv) == IS_DOUBLE
&& Z_DVAL_P(zv) == 2.0
&& !(OP1_INFO() & MAY_BE_LONG))) {

Expand Down
26 changes: 26 additions & 0 deletions Zend/Optimizer/optimize_temp_vars_5.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ void zend_optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_c
} else {
if (map_T[currT] == INVALID_VAR) {
int use_new_var = 0;
/* The foreach loop variable occupies two consecutive temporaries:
* the loop variable and, in the next slot, the iteration position
* (Z_FE_POS_P/Z_FE_ITER_P), which is never referenced as an operand.
* Reserve them as a consecutive pair so the position slot is neither
* reused for another temporary nor separated from the loop variable. */
bool needs_pair = opline->opcode == ZEND_FE_FETCH_R
|| opline->opcode == ZEND_FE_FETCH_RW
|| opline->opcode == ZEND_FE_FREE;

/* Code in "finally" blocks may modify temporary variables.
* We allocate new temporaries for values that need to
Expand Down Expand Up @@ -125,6 +133,19 @@ void zend_optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_c
if (use_new_var) {
i = ++max;
zend_bitset_incl(taken_T, i);
if (needs_pair) {
zend_bitset_incl(taken_T, ++max);
}
} else if (needs_pair) {
/* Find a consecutive pair of free slots above the live set. */
int var = max;
while (var >= 0 && !zend_bitset_in(taken_T, var)) {
var--;
}
max = MAX(max, var + 2);
i = var + 1;
zend_bitset_incl(taken_T, i);
zend_bitset_incl(taken_T, i + 1);
} else {
GET_AVAILABLE_T();
}
Expand Down Expand Up @@ -164,6 +185,11 @@ void zend_optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_c
num--;
zend_bitset_excl(taken_T, map_T[currT]+num);
}
} else if (opline->opcode == ZEND_FE_RESET_R
|| opline->opcode == ZEND_FE_RESET_RW) {
/* Free the foreach iteration-position slot paired with the loop
* variable (reserved at FE_FETCH/FE_FREE above). */
zend_bitset_excl(taken_T, map_T[currT] + 1);
}
}
}
Expand Down
Loading