php-src/sapi/phpdbg/tests
Arnaud Le Blanc 76d7c616bb
Pass opline as argument to opcode handlers in CALL VM
This changes the signature of opcode handlers in the CALL VM so that the opline
is passed directly via arguments. This reduces the number of memory operations
on EX(opline), and makes the CALL VM considerably faster.

Additionally, this unifies the CALL and HYBRID VMs a bit, as EX(opline) is now
handled in the same way in both VMs.

This is a part of GH-17849.

Currently we have two VMs:

 * HYBRID: Used when compiling with GCC. execute_data and opline are global
   register variables
 * CALL: Used when compiling with something else. execute_data is passed as
   opcode handler arg, but opline is passed via execute_data->opline
   (EX(opline)).

The Call VM looks like this:

    while (1) {
        ret = execute_data->opline->handler(execute_data);
        if (UNEXPECTED(ret != 0)) {
            if (ret > 0) { // returned by ZEND_VM_ENTER() / ZEND_VM_LEAVE()
                execute_data = EG(current_execute_data);
            } else {       // returned by ZEND_VM_RETURN()
                return;
            }
        }
    }

    // example op handler
    int ZEND_INIT_FCALL_SPEC_CONST_HANDLER(zend_execute_data *execute_data) {
        // load opline
        const zend_op *opline = execute_data->opline;

        // instruction execution

        // dispatch
        // ZEND_VM_NEXT_OPCODE():
        execute_data->opline++;
        return 0; // ZEND_VM_CONTINUE()
    }

Opcode handlers return a positive value to signal that the loop must load a
new execute_data from EG(current_execute_data), typically when entering
or leaving a function.

Here I make the following changes:

 * Pass opline as opcode handler argument
 * Return next opline from opcode handlers
 * ZEND_VM_ENTER / ZEND_VM_LEAVE return opline|(1<<0) to signal that
   execute_data must be reloaded from EG(current_execute_data)

This gives us:

    while (1) {
        opline = opline->handler(execute_data, opline);
        if (UNEXPECTED((uintptr_t) opline & ZEND_VM_ENTER_BIT) {
            opline = opline & ~ZEND_VM_ENTER_BIT;
            if (opline != 0) { // ZEND_VM_ENTER() / ZEND_VM_LEAVE()
                execute_data = EG(current_execute_data);
            } else {           // ZEND_VM_RETURN()
                return;
            }
        }
    }

    // example op handler
    const zend_op * ZEND_INIT_FCALL_SPEC_CONST_HANDLER(zend_execute_data *execute_data, const zend_op *opline) {
        // opline already loaded

        // instruction execution

        // dispatch
        // ZEND_VM_NEXT_OPCODE():
        return ++opline;
    }

bench.php is 23% faster on Linux / x86_64, 18% faster on MacOS / M1.

Symfony Demo is 2.8% faster.

When using the HYBRID VM, JIT'ed code stores execute_data/opline in two fixed
callee-saved registers and rarely touches EX(opline), just like the VM.

Since the registers are callee-saved, the JIT'ed code doesn't have to
save them before calling other functions, and can assume they always
contain execute_data/opline. The code also avoids saving/restoring them in
prologue/epilogue, as execute_ex takes care of that (JIT'ed code is called
exclusively from there).

The CALL VM can now use a fixed register for execute_data/opline as well, but
we can't rely on execute_ex to save the registers for us as it may use these
registers itself. So we have to save/restore the two registers in JIT'ed code
prologue/epilogue.

Closes GH-17952
2025-04-15 18:51:54 +02:00
..
bug73615
gh12962 Fix GH-12962: Double free of init_file in phpdbg_prompt.c 2023-12-17 11:46:02 +01:00
basic_run.phpt Use EXPECT instead of EXPECTF when possible 2018-02-20 21:53:48 +01:00
breakpoints_001.phpt Drop all JIT related XFAILS from phpdbg test suite 2020-11-30 15:24:15 +01:00
breakpoints_002.phpt Drop all JIT related XFAILS from phpdbg test suite 2020-11-30 15:24:15 +01:00
breakpoints_003.phpt Drop all JIT related XFAILS from phpdbg test suite 2020-11-30 15:24:15 +01:00
breakpoints_004.phpt Drop all JIT related XFAILS from phpdbg test suite 2020-11-30 15:24:15 +01:00
breakpoints_005.phpt Sync leading and final newlines in *.phpt sections 2018-10-15 04:33:09 +02:00
breakpoints_006.phpt Sync leading and final newlines in *.phpt sections 2018-10-15 04:33:09 +02:00
breakpoints_007.phpt Sync leading and final newlines in *.phpt sections 2018-10-15 04:33:09 +02:00
breakpoints_008.phpt Sync leading and final newlines in *.phpt sections 2018-10-15 04:33:09 +02:00
breakpoints_009.phpt PHPDBG: fix bug parsing 3-word opcodes 2021-04-22 10:11:26 +02:00
bug73615.phpt Fix GH-10489: run-tests.php does not escape path when building cmd (#10560) 2023-02-25 14:02:06 +00:00
bug73704.phpt
bug73794.phpt
bug73927.phpt Drop all JIT related XFAILS from phpdbg test suite 2020-11-30 15:24:15 +01:00
bug76801.phpt fix bug #76801: phpdbg too many open files error 2019-03-23 09:47:49 +01:00
bug78297.phpt Close PHP tags in tests 2023-10-18 17:34:10 +02:00
bug81135.phpt Fix #81135 unknown help topic in phpdbg fails assertion 2021-06-13 22:19:14 +02:00
clean_001.phpt
clear_001.phpt
delimiter.phpt Use EXPECT instead of EXPECTF when possible 2018-02-20 21:53:48 +01:00
empty.inc fix bug #76801: phpdbg too many open files error 2019-03-23 09:47:49 +01:00
exceptions_001.phpt Include the source location in Closure names (#13550) 2024-04-12 18:21:13 +02:00
exceptions_002.phpt Include the source location in Closure names (#13550) 2024-04-12 18:21:13 +02:00
exceptions_003.phpt replace phpdbg custom opcode dumper with O+ dump (#7227) 2021-07-13 15:32:14 +02:00
finish_leave_001.phpt Drop all JIT related XFAILS from phpdbg test suite 2020-11-30 15:24:15 +01:00
generator_run.phpt
gh10715.phpt Fix GH-14553: Bug in phpdbg8.3 (also 8.1 and 8.2) echo output - trimmed at NULL byte (?) 2024-07-04 18:43:42 +02:00
gh12675.phpt Fix GH-12675: MEMORY_LEAK in phpdbg_prompt.c 2023-11-15 21:59:55 +01:00
gh12962.phpt Use getenv to prevent undefined key warning 2024-01-15 20:15:04 +01:00
gh13681.phpt Fix GH-13681: segfault when adding watchpoint fails. 2024-06-17 17:45:53 +01:00
gh13827.phpt Include the source location in Closure names (#13550) 2024-04-12 18:21:13 +02:00
gh13931.phpt Fix GH-13931: Applying zero offset to null pointer in Zend/zend_opcode.c 2024-04-15 19:39:05 +02:00
gh14553.phpt Fix GH-14553: Bug in phpdbg8.3 (also 8.1 and 8.2) echo output - trimmed at NULL byte (?) 2024-07-04 18:43:42 +02:00
gh15208.phpt Fix GH-15208: Segfault with breakpoint map and phpdbg_clear() 2024-11-26 22:26:37 +01:00
gh15210_001.phpt Add necessary SKIPIFs to new phpdbg tests 2024-08-10 01:10:01 +02:00
gh15210_002.phpt Add necessary SKIPIFs to new phpdbg tests 2024-08-10 01:10:01 +02:00
gh15268.phpt Fix GH-15268: heap buffer overflow in phpdbg (zend_hash_num_elements() Zend/zend_hash.h) 2024-08-08 20:35:20 +02:00
gh15901.phpt Fix GH-15901: phpdbg: Assertion failure on i funcs 2024-09-18 23:48:31 +02:00
gh16174.phpt Fix GH-16174: Empty string is an invalid expression for phpdbg-ev 2024-10-10 01:45:37 +02:00
gh16181.phpt Fix GH-16181: phpdbg: exit in exception handler reports fatal error 2024-10-03 11:36:13 +02:00
include.inc
include_once_001.phpt fix bug #76801: phpdbg too many open files error 2019-03-23 09:47:49 +01:00
include_once_002.phpt fix bug #76801: phpdbg too many open files error 2019-03-23 09:47:49 +01:00
info_001.phpt Restrict allowed usages of $GLOBALS 2021-01-06 12:46:24 +01:00
info_002.phpt Drop all JIT related XFAILS from phpdbg test suite 2020-11-30 15:24:15 +01:00
match_breakpoints_001.phpt Adjust assignment line number for match 2020-09-08 00:08:18 +02:00
match_breakpoints_002.phpt Adjust assignment line number for match 2020-09-08 00:08:18 +02:00
match_breakpoints_003.phpt Adjust assignment line number for match 2020-09-08 00:08:18 +02:00
match_breakpoints_004.phpt Adjust assignment line number for match 2020-09-08 00:08:18 +02:00
next_001.phpt replace phpdbg custom opcode dumper with O+ dump (#7227) 2021-07-13 15:32:14 +02:00
normal_exit.phpt
phpdbg_break_next.phpt Drop all JIT related XFAILS from phpdbg test suite 2020-11-30 15:24:15 +01:00
phpdbg_get_executable_stream_wrapper.inc
phpdbg_get_executable_stream_wrapper.phpt Deprecate implicit nullable parameter types (#12959) 2024-03-13 21:40:26 +01:00
phpdbg_oplog_001.phpt Update phpdbg oplog test 2019-05-29 17:05:01 +02:00
phpdbg_oplog_002.phpt Fix 'can not' in error messages 2021-10-05 09:51:58 +01:00
print_001.phpt Merge branch 'PHP-8.2' into PHP-8.3 2024-04-05 14:12:08 +02:00
print_002.phpt Fix opcache dump varying tmps 2024-04-05 14:11:41 +02:00
register_function.phpt Fix crashes in function registration + test 2025-01-06 21:30:34 +01:00
register_function_leak.phpt Fix memory leak in phpdbg calling registered function 2025-01-30 19:28:26 +01:00
run_001.phpt
run_002.phpt Drop all JIT related XFAILS from phpdbg test suite 2020-11-30 15:24:15 +01:00
set_exception_handler.phpt Drop all JIT related XFAILS from phpdbg test suite 2020-11-30 15:24:15 +01:00
stdin_001.phpt Use EXPECT instead of EXPECTF when possible 2018-02-20 21:53:48 +01:00
stepping_001.phpt replace phpdbg custom opcode dumper with O+ dump (#7227) 2021-07-13 15:32:14 +02:00
watch_001.phpt Improve tests on 32bit 2022-06-29 14:04:40 +02:00
watch_002.phpt Improve tests on 32bit 2022-06-29 14:04:40 +02:00
watch_003.phpt Improve tests on 32bit 2022-06-29 14:04:40 +02:00
watch_004.phpt Improve tests on 32bit 2022-06-29 14:04:40 +02:00
watch_005.phpt Drop all JIT related XFAILS from phpdbg test suite 2020-11-30 15:24:15 +01:00
watch_006.phpt Pass opline as argument to opcode handlers in CALL VM 2025-04-15 18:51:54 +02:00
watch_007.phpt Fix phpdbg segmentation fault in case of malformed input 2023-01-17 14:12:49 +00:00