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