Skip to content

Commit 76d7c61

Browse files
committed
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
1 parent 49891d8 commit 76d7c61

11 files changed

+457
-481
lines changed

Zend/zend_vm_def.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -5656,11 +5656,10 @@ ZEND_VM_HOT_HANDLER(199, ZEND_CHECK_UNDEF_ARGS, UNUSED, UNUSED)
56565656

56575657
ZEND_VM_COLD_HELPER(zend_missing_arg_helper, ANY, ANY)
56585658
{
5659-
#ifdef ZEND_VM_IP_GLOBAL_REG
56605659
USE_OPLINE
56615660

56625661
SAVE_OPLINE();
5663-
#endif
5662+
56645663
zend_missing_arg_error(execute_data);
56655664
HANDLE_EXCEPTION();
56665665
}

Zend/zend_vm_execute.h

+195-177
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Zend/zend_vm_execute.skl

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include "Zend/zend_vm_opcodes.h"
2+
13
{%DEFINES%}
24

35
#if (ZEND_VM_KIND != ZEND_VM_KIND_CALL) && (ZEND_GCC_VERSION >= 4000) && !defined(__clang__)

Zend/zend_vm_gen.php

+55-37
Original file line numberDiff line numberDiff line change
@@ -818,7 +818,7 @@ function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec) {
818818
if (isset($matches[2])) {
819819
// extra args
820820
$args = substr(preg_replace("/,\s*[A-Za-z0-9_]*\s*,\s*([^,)\s]*)\s*/", ", $1", $matches[2]), 2);
821-
return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(" . $args. " ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC))";
821+
return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX " . $args . "))";
822822
}
823823
return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))";
824824
}
@@ -852,7 +852,7 @@ function($matches) use ($spec, $prefix, $op1, $op2, $extra_spec, $name) {
852852
if (isset($matches[2])) {
853853
// extra args
854854
$args = substr(preg_replace("/,\s*[A-Za-z0-9_]*\s*,\s*([^,)\s]*)\s*/", ", $1", $matches[2]), 2);
855-
return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(" . $args. " ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC))";
855+
return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX " . $args . "))";
856856
}
857857
return "ZEND_VM_TAIL_CALL(" . helper_name($matches[1], $spec, $op1, $op2, $extra_spec) . "(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))";
858858
}
@@ -1164,7 +1164,7 @@ function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno,
11641164
out($f, "static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_fastcall $spec_name(ZEND_OPCODE_HANDLER_ARGS)\n");
11651165
} else {
11661166
// Helper with parameter
1167-
out($f, "static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_fastcall $spec_name($param ZEND_OPCODE_HANDLER_ARGS_DC)\n");
1167+
out($f, "static$zend_attributes ZEND_OPCODE_HANDLER_RET$zend_fastcall $spec_name(ZEND_OPCODE_HANDLER_ARGS_EX $param)\n");
11681168
}
11691169
break;
11701170
case ZEND_VM_KIND_SWITCH:
@@ -1870,13 +1870,13 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
18701870
out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
18711871
out($f,"# define ZEND_OPCODE_HANDLER_ARGS void\n");
18721872
out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU\n");
1873-
out($f,"# define ZEND_OPCODE_HANDLER_ARGS_DC\n");
1874-
out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC\n");
1873+
out($f,"# define ZEND_OPCODE_HANDLER_ARGS_EX\n");
1874+
out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX\n");
18751875
out($f,"#else\n");
1876-
out($f,"# define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data\n");
1877-
out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data\n");
1878-
out($f,"# define ZEND_OPCODE_HANDLER_ARGS_DC , ZEND_OPCODE_HANDLER_ARGS\n");
1879-
out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC , ZEND_OPCODE_HANDLER_ARGS_PASSTHRU\n");
1876+
out($f,"# define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data, const zend_op *opline\n");
1877+
out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data, opline\n");
1878+
out($f,"# define ZEND_OPCODE_HANDLER_ARGS_EX ZEND_OPCODE_HANDLER_ARGS, \n");
1879+
out($f,"# define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_EX ZEND_OPCODE_HANDLER_ARGS_PASSTHRU, \n");
18801880
out($f,"#endif\n");
18811881
out($f,"\n");
18821882
out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
@@ -1902,10 +1902,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
19021902
out($f,"# define ZEND_VM_COLD ZEND_COLD ZEND_OPT_SIZE\n");
19031903
}
19041904
out($f,"#else\n");
1905-
out($f,"# define ZEND_OPCODE_HANDLER_RET int\n");
1905+
out($f,"# define ZEND_OPCODE_HANDLER_RET const zend_op *\n");
19061906
out($f,"# define ZEND_VM_TAIL_CALL(call) return call\n");
1907-
out($f,"# define ZEND_VM_CONTINUE() return 0\n");
1908-
out($f,"# define ZEND_VM_RETURN() return -1\n");
1907+
out($f,"# define ZEND_VM_CONTINUE() return opline\n");
1908+
out($f,"# define ZEND_VM_RETURN() return (const zend_op*)ZEND_VM_ENTER_BIT\n");
19091909
if ($kind == ZEND_VM_KIND_HYBRID) {
19101910
out($f,"# define ZEND_VM_HOT\n");
19111911
}
@@ -1914,8 +1914,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
19141914
out($f,"\n");
19151915
out($f,"typedef ZEND_OPCODE_HANDLER_RET (ZEND_FASTCALL *opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS);\n");
19161916
out($f,"\n");
1917-
out($f,"#define DCL_OPLINE\n");
19181917
out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
1918+
out($f,"# define DCL_OPLINE\n");
19191919
out($f,"# define OPLINE opline\n");
19201920
out($f,"# define USE_OPLINE\n");
19211921
out($f,"# define LOAD_OPLINE() opline = EX(opline)\n");
@@ -1924,12 +1924,13 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
19241924
out($f,"# define SAVE_OPLINE() EX(opline) = opline\n");
19251925
out($f,"# define SAVE_OPLINE_EX() SAVE_OPLINE()\n");
19261926
out($f,"#else\n");
1927-
out($f,"# define OPLINE EX(opline)\n");
1928-
out($f,"# define USE_OPLINE const zend_op *opline = EX(opline);\n");
1929-
out($f,"# define LOAD_OPLINE()\n");
1930-
out($f,"# define LOAD_OPLINE_EX()\n");
1931-
out($f,"# define LOAD_NEXT_OPLINE() ZEND_VM_INC_OPCODE()\n");
1932-
out($f,"# define SAVE_OPLINE()\n");
1927+
out($f,"# define DCL_OPLINE const zend_op *opline;\n");
1928+
out($f,"# define OPLINE opline\n");
1929+
out($f,"# define USE_OPLINE\n");
1930+
out($f,"# define LOAD_OPLINE() opline = EX(opline)\n");
1931+
out($f,"# define LOAD_OPLINE_EX() opline = EX(opline)\n");
1932+
out($f,"# define LOAD_NEXT_OPLINE() opline = EX(opline) + 1\n");
1933+
out($f,"# define SAVE_OPLINE() EX(opline) = opline\n");
19331934
out($f,"# define SAVE_OPLINE_EX()\n");
19341935
out($f,"#endif\n");
19351936
out($f,"#define HANDLE_EXCEPTION() ZEND_ASSERT(EG(exception)); LOAD_OPLINE(); ZEND_VM_CONTINUE()\n");
@@ -1943,9 +1944,10 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
19431944
out($f,"# define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; ZEND_VM_ENTER_EX()\n");
19441945
out($f,"# define ZEND_VM_LEAVE() return 2\n");
19451946
out($f,"#else\n");
1946-
out($f,"# define ZEND_VM_ENTER_EX() return 1\n");
1947-
out($f,"# define ZEND_VM_ENTER() return 1\n");
1948-
out($f,"# define ZEND_VM_LEAVE() return 2\n");
1947+
out($f,"# define ZEND_VM_ENTER_BIT 1ULL\n");
1948+
out($f,"# define ZEND_VM_ENTER_EX() return (zend_op*)((uintptr_t)opline | ZEND_VM_ENTER_BIT)\n");
1949+
out($f,"# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n");
1950+
out($f,"# define ZEND_VM_LEAVE() return (zend_op*)((uintptr_t)opline | ZEND_VM_ENTER_BIT)\n");
19491951
out($f,"#endif\n");
19501952
out($f,"#define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
19511953
out($f,"#define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
@@ -2119,12 +2121,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
21192121
}
21202122
break;
21212123
case "ZEND_VM_CONTINUE_LABEL":
2122-
if ($kind == ZEND_VM_KIND_CALL || $kind == ZEND_VM_KIND_HYBRID) {
2123-
// Only SWITCH dispatch method use it
2124-
out($f,"#if !defined(ZEND_VM_FP_GLOBAL_REG) || !defined(ZEND_VM_IP_GLOBAL_REG)\n");
2125-
out($f,$m[1]."\tint ret;".$m[3]."\n");
2126-
out($f,"#endif\n");
2127-
} else if ($kind == ZEND_VM_KIND_SWITCH) {
2124+
if ($kind == ZEND_VM_KIND_SWITCH) {
21282125
// Only SWITCH dispatch method use it
21292126
out($f,"zend_vm_continue:".$m[3]."\n");
21302127
} else {
@@ -2143,16 +2140,17 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
21432140
case ZEND_VM_KIND_HYBRID:
21442141
out($f,"#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)\n");
21452142
out($f, $m[1]."HYBRID_SWITCH()".$m[3]."\n");
2146-
out($f,"#else\n");
2143+
out($f,"#else /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */\n");
21472144
case ZEND_VM_KIND_CALL:
21482145
out($f,"#if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG)\n");
21492146
out($f, $m[1]."((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
21502147
out($f, $m[1]."if (UNEXPECTED(!OPLINE))".$m[3]."\n");
21512148
out($f,"#else\n");
2152-
out($f, $m[1]."if (UNEXPECTED((ret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)) != 0))".$m[3]."\n");
2149+
out($f, $m[1]."opline = ((opcode_handler_t)opline->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
2150+
out($f, $m[1]."if (UNEXPECTED(((uintptr_t)opline & ZEND_VM_ENTER_BIT)))".$m[3]."\n");
21532151
out($f,"#endif\n");
21542152
if ($kind == ZEND_VM_KIND_HYBRID) {
2155-
out($f,"#endif\n");
2153+
out($f,"#endif /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */\n");
21562154
}
21572155
break;
21582156
}
@@ -2168,7 +2166,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
21682166
if ($kind == ZEND_VM_KIND_CALL || $kind == ZEND_VM_KIND_HYBRID) {
21692167
// Executor is defined as a set of functions
21702168
if ($kind == ZEND_VM_KIND_HYBRID) {
2171-
out($f,"#else\n");
2169+
out($f,"#else /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */\n");
21722170
}
21732171
out($f,
21742172
"#ifdef ZEND_VM_FP_GLOBAL_REG\n" .
@@ -2178,18 +2176,19 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
21782176
"# endif\n" .
21792177
$m[1]."return;\n" .
21802178
"#else\n" .
2181-
$m[1]."if (EXPECTED(ret > 0)) {\n" .
2179+
$m[1]."opline = (const zend_op*)((uintptr_t)opline & ~ZEND_VM_ENTER_BIT);\n".
2180+
$m[1]."if (EXPECTED(opline != NULL)) {\n" .
21822181
$m[1]."\texecute_data = EG(current_execute_data);\n".
21832182
$m[1]."\tZEND_VM_LOOP_INTERRUPT_CHECK();\n".
21842183
$m[1]."} else {\n" .
21852184
"# ifdef ZEND_VM_IP_GLOBAL_REG\n" .
21862185
$m[1]."\topline = vm_stack_data.orig_opline;\n" .
2187-
"# endif\n".
2186+
"# endif\n" .
21882187
$m[1]."\treturn;\n".
21892188
$m[1]."}\n".
21902189
"#endif\n");
21912190
if ($kind == ZEND_VM_KIND_HYBRID) {
2192-
out($f,"#endif\n");
2191+
out($f,"#endif /* ZEND_VM_KIND != ZEND_VM_KIND_HYBRID */\n");
21932192
}
21942193
}
21952194
break;
@@ -2335,6 +2334,8 @@ function gen_vm_opcodes_header(
23352334
): string {
23362335
$str = HEADER_TEXT;
23372336
$str .= "#ifndef ZEND_VM_OPCODES_H\n#define ZEND_VM_OPCODES_H\n\n";
2337+
$str .= "#include \"Zend/zend_portability.h\"\n";
2338+
$str .= "\n";
23382339
$str .= "#define ZEND_VM_SPEC\t\t" . ZEND_VM_SPEC . "\n";
23392340
$str .= "#define ZEND_VM_LINES\t\t" . ZEND_VM_LINES . "\n";
23402341
$str .= "#define ZEND_VM_KIND_CALL\t" . ZEND_VM_KIND_CALL . "\n";
@@ -2968,6 +2969,7 @@ function gen_vm($def, $skel) {
29682969
out($f, "\topcode_handler_t handler;\n");
29692970
out($f,"#endif\n");
29702971
}
2972+
out($f, "\tDCL_OPLINE;\n");
29712973
out($f, "\tint ret;\n");
29722974
out($f, "#ifdef ZEND_VM_IP_GLOBAL_REG\n");
29732975
out($f, "\tconst zend_op *orig_opline = opline;\n");
@@ -3001,8 +3003,24 @@ function gen_vm($def, $skel) {
30013003
out($f, "\t\tret = -1;\n");
30023004
out($f, "\t}\n");
30033005
out($f, "#else\n");
3004-
out($f, "\tret = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
3005-
out($f, "\tSAVE_OPLINE();\n");
3006+
out($f, "\topline = ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
3007+
3008+
out($f, "if (UNEXPECTED(((uintptr_t)opline & ZEND_VM_ENTER_BIT))) {\n");
3009+
out($f, "\t\topline = (const zend_op*)((uintptr_t)opline & ~ZEND_VM_ENTER_BIT);\n");
3010+
out($f, "\t\tif (EXPECTED(opline)) {\n");
3011+
out($f, "\t\t\t/* ZEND_VM_ENTER() or ZEND_VM_LEAVE() */\n");
3012+
out($f, "\t\t\tret = EG(current_execute_data) != ex ? (int)(EG(current_execute_data)->prev_execute_data != ex) + 1 : 0;\n");
3013+
out($f, "\t\t\texecute_data = EG(current_execute_data);\n");
3014+
out($f, "\t\t\tSAVE_OPLINE();\n");
3015+
out($f, "\t\t} else {\n");
3016+
out($f, "\t\t\t/* ZEND_VM_RETURN() */\n");
3017+
out($f, "\t\t\tret = -1;\n");
3018+
out($f, "\t\t}\n");
3019+
out($f, "\t} else {\n");
3020+
out($f, "\t\t/* ZEND_VM_CONTINUE() */\n");
3021+
out($f, "\t\tSAVE_OPLINE();\n");
3022+
out($f, "\t\tret = 0;\n");
3023+
out($f, "\t}\n");
30063024
out($f, "#endif\n");
30073025
out($f, "#ifdef ZEND_VM_FP_GLOBAL_REG\n");
30083026
out($f, "\texecute_data = orig_execute_data;\n");

Zend/zend_vm_opcodes.h

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/opcache/jit/zend_jit.c

+18-9
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ static const void *zend_jit_func_trace_counter_handler = NULL;
9898
static const void *zend_jit_ret_trace_counter_handler = NULL;
9999
static const void *zend_jit_loop_trace_counter_handler = NULL;
100100

101-
static int ZEND_FASTCALL zend_runtime_jit(void);
101+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS);
102102

103103
static int zend_jit_trace_op_len(const zend_op *opline);
104104
static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op *opline);
@@ -2871,7 +2871,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
28712871
if (GCC_GLOBAL_REGS) {
28722872
ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit)));
28732873
} else {
2874-
ir_RETURN(ir_CONST_I32(1)); /* ZEND_VM_ENTER */
2874+
zend_jit_vm_enter(jit, jit_IP(jit));
28752875
}
28762876
ir_IF_TRUE(if_hook_enter);
28772877
}
@@ -3074,11 +3074,18 @@ static int zend_real_jit_func(zend_op_array *op_array, zend_script *script, cons
30743074
}
30753075

30763076
/* Run-time JIT handler */
3077-
static int ZEND_FASTCALL zend_runtime_jit(void)
3077+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS)
30783078
{
3079-
zend_execute_data *execute_data = EG(current_execute_data);
3079+
#if GCC_GLOBAL_REGS
3080+
zend_execute_data *execute_data;
3081+
zend_op *opline;
3082+
#else
3083+
const zend_op *orig_opline = opline;
3084+
#endif
3085+
3086+
execute_data = EG(current_execute_data);
30803087
zend_op_array *op_array = &EX(func)->op_array;
3081-
zend_op *opline = op_array->opcodes;
3088+
opline = op_array->opcodes;
30823089
zend_jit_op_array_extension *jit_extension;
30833090
bool do_bailout = 0;
30843091

@@ -3097,7 +3104,7 @@ static int ZEND_FASTCALL zend_runtime_jit(void)
30973104
}
30983105
}
30993106
jit_extension = (zend_jit_op_array_extension*)ZEND_FUNC_INFO(op_array);
3100-
opline->handler = jit_extension->orig_handler;
3107+
((zend_op*)opline)->handler = jit_extension->orig_handler;
31013108

31023109
/* perform real JIT for this function */
31033110
zend_real_jit_func(op_array, NULL, NULL, ZEND_JIT_ON_FIRST_EXEC);
@@ -3116,7 +3123,11 @@ static int ZEND_FASTCALL zend_runtime_jit(void)
31163123
}
31173124

31183125
/* JIT-ed code is going to be called by VM */
3119-
return 0;
3126+
#if GCC_GLOBAL_REGS
3127+
return; // ZEND_VM_CONTINUE
3128+
#else
3129+
return orig_opline; // ZEND_VM_CONTINUE
3130+
#endif
31203131
}
31213132

31223133
void zend_jit_check_funcs(HashTable *function_table, bool is_method) {
@@ -3171,9 +3182,7 @@ void ZEND_FASTCALL zend_jit_hot_func(zend_execute_data *execute_data, const zend
31713182
op_array->opcodes[i].handler = jit_extension->orig_handlers[i];
31723183
}
31733184

3174-
#ifdef HAVE_GCC_GLOBAL_REGS
31753185
EX(opline) = opline;
3176-
#endif
31773186

31783187
/* perform real JIT for this function */
31793188
zend_real_jit_func(op_array, NULL, opline, ZEND_JIT_ON_HOT_COUNTERS);

0 commit comments

Comments
 (0)