Emit EXT_STMT after each pipe stage, and attach the TMP var that holds the intermediary result#19377
Conversation
…s the intermediary result
iluuu1994
left a comment
There was a problem hiding this comment.
Looks ok, but unless you disable optimizations you'll need some opcache changes.
- You'll need to add EXT_STMT to keeps_op1_alive().
- You'll probably need to create a USE for op1 in Zend/Optimizer/zend_ssa.c. Otherwise, if the pipe is optimized away (might happen for CTE-calls) you'll end up with a dead variable as an input.
I'm also confused by this remark:
This however does not work (yet) for the closure wrapped stages as these are handled differently. Ideally they all have a similar DECLARE_LAMBDA_FUNCTION/BIND_LEXICAL/INIT_DYNAMIC_CALL set, but instead PHP creates nested closures instead:
The EXT_STMT call is there after dynamic calls. Does this not suffice? To enter the body of the closure, I presume you'd need step into rather than step over. I don't know exactly how Xdebug handles this, but it seems like that should work.
This example would leak:
function x() {
return range(0, 10);
}
function test($a, $b) {
$a |> $b;
}
test(42, x(...));
because we were missing a FREE in test(). This requires two fixes, namely one in
zend_do_free() to skip over the EXT_STMT usage, and another in
zend_optimize_block() to avoid removing the FREE opcode by removing the result
def of the declaring opcode.
|
To keep a record of what the (unrelated) issue is once this patch get merged, and copied from @TimWolla on Slack:
|
The following script:
Creates the following opcodes for the
testPipes()function (without this patch):If users set a breakpoint on line
4 $result = "Hello World", then Xdebug realises this and moves it to line5. This is because Xdebug only breaks onEXT_STMTlines, and is clever enough to adjust the breakpoint.However, if you then would use "step over" then it would immediately go to line 10, as that's where the next
EXT_STMTop is created. This means it is not possible to inspect the intermediary values being passed from pipe element to pipe element.This patch changes the opcode generation to add additional
EXT_STMTopcodes in between each state:The
EXT_STMTin op 4, 9, 14, and 21 are new, and also have as theirop1value the intermediate pipe value.This allows Xdebug to break here, and show the contents of this hinted variable.
This however does not work (yet) for the closure wrapped stages as these are handled differently. Ideally they all have a similar
DECLARE_LAMBDA_FUNCTION/BIND_LEXICAL/INIT_DYNAMIC_CALLset, but instead PHP creates nested closures instead:I can currently work around this by always breaking upon the return of a user-land closure, but this is not ideal. Instead, I would like to have an EXT_STMT in the original function just like in between
htmlentities/strtolower/str_split).