An example assignment such as:
$x = 10;
doesn't seem to get handled as a simple ref-count incrementing
assignment (in zend_assign_to_variable()). Instead, $x ends up getting a
new "zval" into which a
copy of the RHS (10) is made.
This seems to be because the zval/znode corresponding to the literal 10
is an IS_CONST operand of the assignment opcode. And, during the end of
compilation of a function, the IS_CONST operands in the function's
op_array are patched up as "references" (is_ref is set to 1).
zend_opcode.c:pass_two()
...
while (opline < end) {
if (opline->op1.op_type == IS_CONST) {
opline->op1.u.constant.is_ref = 1;
opline->op1.u.constant.refcount = 2; /* Make sure is_ref won't be
reset */
}
if (opline->op2.op_type == IS_CONST) {
opline->op2.u.constant.is_ref = 1;
opline->op2.u.constant.refcount = 2;
}
...
And zend_assign_to_variable(), when it sees the RHS to be a reference
("is_ref == 1") ends up doing a copy rather than a ref-count
incrementing assignment.
It seems like performance would be better if we didn't mark constant
operands as "references" in pass_two(). But presumably it is required to
handle some cases that'll otherwise break? I am trying to understand
what those cases are. If someone can shed further light on this issue,
it is much appreciated...
regards,
Kannan Muthukkaruppan