Hi!
While investigating an issue with Xdebug and fast_call/fast_ret, I
noticed that the opcodes "associated" with the "finally" statement, are
rolled up in the previous line.
The code:
1 <?php
2 function extractFile()
3 {
4 try {
5 echo "try\n";
6 } catch (Catch1 $e) {
7 echo "catch1\n";
8 } catch (Catch2 $e) {
9 echo "catch2\n";
10 } finally {
11 echo "finally\n";
12 }
13 echo "end\n";
14 }
15
16 extractFile();
17 ?>
Produces:
line #* E I O op fetch ext return
operands
-------------------------------------------------------------------------------------
5 0 E > ECHO
'try%0A'
1 > JMP ->7
6 2 E > > CATCH
'Catch1', !0, ->5
7 3 > ECHO
'catch1%0A'
4 > JMP ->7
8 5 E > > CATCH
'Catch2', !0
9 6 > ECHO
'catch2%0A'
7 > > FAST_CALL ->9
8* JMP ->11
11 9 > ECHO
'finally%0A'
10 > FAST_RET
13 11 > ECHO
'end%0A'
14 12 > RETURN null
The FAST_CALL/JMP instructions should really be linked to line 10. Not
doing so produces confusing results while doing code coverage, where it now
shows that the "echo catch2\n" on line 9 is executed. This is of course not
the case, but the linking of FAST_CALL and JMP to line 9 makes it look like
this. Is it possible to change this so thta the FAST_CALL and JMP are linked
to line 10 instead?
And secondly, I am struggeling with where FAST_CALL and FAST_RET can jump to.
Right now, I have:
https://github.com/derickr/vld/commit/9cf01bba0a1aeef6a261c6c85b238552215a9f0b#diff-286f7620179e1ee0a20e81523d91ff24R1036
+#if PHP_VERSION_ID >= 50500
+ } else if (opcode.opcode == ZEND_FAST_CALL) {
+#if PHP_VERSION_ID >= 70000
+ *jmp1 = VLD_ZNODE_JMP_LINE(opcode.op1, position, base_address);
+#else
+ *jmp1 = ((long) VLD_ZNODE_ELEM(opcode.op1, jmp_addr) - (long)
base_address) / sizeof(zend_op);
+#endif
+ if (opcode.extended_value) {
+ *jmp2 = VLD_ZNODE_ELEM(opcode.op2, opline_num);
+ }
+ return 1;
+ } else if (opcode.opcode == ZEND_FAST_RET) {
+ *jmp1 = position + 1;
+ if (opcode.extended_value) {
+ *jmp2 = VLD_ZNODE_ELEM(opcode.op2, opline_num);
+ }
+ return 1;
+#endif
Which seems to work, although I am unsure about the "+ 1" for FAST_RET.
I also never see anything for opcode.extended_value, and hence the *jmp is
unset. This also returns dumping opcodes with this bit of code (code slightly
lifted from dbg):
https://github.com/derickr/vld/commit/9cf01bba0a1aeef6a261c6c85b238552215a9f0b#diff-286f7620179e1ee0a20e81523d91ff24R684
+#if PHP_VERSION_ID >= 50600
+ switch (op.opcode) {
+ case ZEND_FAST_RET:
+ if (op.extended_value == ZEND_FAST_RET_TO_FINALLY) {
+ fetch_type = "to_finally";
+ } else if (op.extended_value == ZEND_FAST_RET_TO_CATCH)
{
+ fetch_type = "to_catch";
+ }
+ break;
+ case ZEND_FAST_CALL:
+ if (op.extended_value == ZEND_FAST_CALL_FROM_FINALLY)
{
+ fetch_type = "from_finally";
+ }
+ break;
+ }
+#endif
+
Any hints?
cheers,
Derick
--
http://derickrethans.nl | http://xdebug.org
Like Xdebug? Consider a donation: http://xdebug.org/donate.php
twitter: @derickr and @xdebug
Posted with an email client that doesn't mangle email: alpine
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php