Skip to content

Commit dbcf4a1

Browse files
committed
Use indempotent operation to signal execute_data reloading
This simplies JIT compared to returning -opline, and doesn't require EX(opline) to be in sync.
1 parent 5002b0f commit dbcf4a1

File tree

6 files changed

+45
-36
lines changed

6 files changed

+45
-36
lines changed

Zend/zend_vm_execute.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Zend/zend_vm_gen.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1944,9 +1944,9 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
19441944
out($f,"# define ZEND_VM_ENTER() opline = EG(current_execute_data)->opline; ZEND_VM_ENTER_EX()\n");
19451945
out($f,"# define ZEND_VM_LEAVE() return 2\n");
19461946
out($f,"#else\n");
1947-
out($f,"# define ZEND_VM_ENTER_EX() return (zend_op*)-(uintptr_t)opline\n");
1947+
out($f,"# define ZEND_VM_ENTER_EX() return (zend_op*)((uintptr_t)opline | (1ULL<<63))\n");
19481948
out($f,"# define ZEND_VM_ENTER() execute_data = EG(current_execute_data); LOAD_OPLINE(); ZEND_VM_ENTER_EX()\n");
1949-
out($f,"# define ZEND_VM_LEAVE() return (zend_op*)-(uintptr_t)opline\n");
1949+
out($f,"# define ZEND_VM_LEAVE() return (zend_op*)((uintptr_t)opline | (1ULL<<63))\n");
19501950
out($f,"#endif\n");
19511951
out($f,"#define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU));\n");
19521952
out($f,"#define ZEND_VM_LOOP_INTERRUPT() zend_interrupt_helper".($spec?"_SPEC":"")."(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);\n");
@@ -2181,7 +2181,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
21812181
$m[1]."return;\n" .
21822182
"#else\n" .
21832183
$m[1]."if (EXPECTED(opline != NULL)) {\n" .
2184-
$m[1]."\topline = (zend_op*)-(uintptr_t)opline;\n".
2184+
$m[1]."\topline = (zend_op*)((uintptr_t)opline & ~(1ULL<<63));\n".
21852185
$m[1]."\texecute_data = EG(current_execute_data);\n".
21862186
$m[1]."\tZEND_VM_LOOP_INTERRUPT_CHECK();\n".
21872187
$m[1]."} else {\n" .

ext/opcache/jit/ir/ir_builder.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ extern "C" {
145145
#define ir_MOD_I64(_op1, _op2) ir_BINARY_OP_I64(IR_MOD, (_op1), (_op2))
146146

147147
#define ir_NEG(_type, _op1) ir_UNARY_OP(IR_NEG, (_type), (_op1))
148-
#define ir_NEG_A(_op1) ir_UNARY_OP_A(IR_NEG, (_op1))
149148
#define ir_NEG_C(_op1) ir_UNARY_OP_C(IR_NEG, (_op1))
150149
#define ir_NEG_I8(_op1) ir_UNARY_OP_I8(IR_NEG, (_op1))
151150
#define ir_NEG_I16(_op1) ir_UNARY_OP_I16(IR_NEG, (_op1))

ext/opcache/jit/zend_jit_ir.c

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,6 +1984,16 @@ static int zend_jit_exception_handler_free_op2_stub(zend_jit_ctx *jit)
19841984
return 1;
19851985
}
19861986

1987+
static void zend_jit_vm_enter(zend_jit_ctx *jit, ir_ref to_opline)
1988+
{
1989+
ir_RETURN(ir_OR_A(to_opline, ir_CONST_ADDR((uintptr_t)1ULL<<63)));
1990+
}
1991+
1992+
static void zend_jit_vm_leave(zend_jit_ctx *jit, ir_ref to_opline)
1993+
{
1994+
ir_RETURN(ir_OR_A(to_opline, ir_CONST_ADDR((uintptr_t)1ULL<<63)));
1995+
}
1996+
19871997
static int zend_jit_interrupt_handler_stub(zend_jit_ctx *jit)
19881998
{
19891999
ir_ref if_timeout, if_exception;
@@ -2011,7 +2021,7 @@ static int zend_jit_interrupt_handler_stub(zend_jit_ctx *jit)
20112021
if (GCC_GLOBAL_REGS) {
20122022
ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit)));
20132023
} else {
2014-
ir_RETURN(ir_NEG_A(jit_IP(jit))); // ZEND_VM_ENTER
2024+
zend_jit_vm_enter(jit, jit_IP(jit));
20152025
}
20162026
return 1;
20172027
}
@@ -2212,7 +2222,7 @@ static int zend_jit_leave_throw_stub(zend_jit_ctx *jit)
22122222
// JIT: HANDLE_EXCEPTION()
22132223
ir_IJMP(jit_STUB_ADDR(jit, jit_stub_exception_handler));
22142224
} else {
2215-
ir_RETURN(ir_NEG_A(jit_IP(jit))); // ZEND_VM_LEAVE
2225+
zend_jit_vm_leave(jit, jit_IP(jit));
22162226
}
22172227

22182228
return 1;
@@ -2407,8 +2417,7 @@ static int zend_jit_trace_escape_stub(zend_jit_ctx *jit)
24072417
if (GCC_GLOBAL_REGS) {
24082418
ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit)));
24092419
} else {
2410-
// TODO: tailcall?
2411-
ir_RETURN(ir_NEG_A(jit_IP(jit))); // ZEND_VM_ENTER
2420+
zend_jit_vm_enter(jit, jit_IP(jit));
24122421
}
24132422

24142423
return 1;
@@ -2427,15 +2436,15 @@ static int zend_jit_trace_exit_stub(zend_jit_ctx *jit)
24272436

24282437
ir_IF_TRUE(if_zero);
24292438

2439+
ref = jit_EG(current_execute_data);
2440+
jit_STORE_FP(jit, ir_LOAD_A(ref));
2441+
ref = ir_LOAD_A(jit_EX(opline));
2442+
jit_STORE_IP(jit, ref);
2443+
24302444
if (GCC_GLOBAL_REGS) {
2431-
ref = jit_EG(current_execute_data);
2432-
jit_STORE_FP(jit, ir_LOAD_A(ref));
2433-
ref = ir_LOAD_A(jit_EX(opline));
2434-
jit_STORE_IP(jit, ref);
24352445
ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit)));
24362446
} else {
2437-
ref = ir_LOAD_A(jit_EX(opline));
2438-
ir_RETURN(ir_NEG_A(ref)); // ZEND_VM_ENTER
2447+
zend_jit_vm_enter(jit, ref);
24392448
}
24402449

24412450
ir_IF_FALSE(if_zero);
@@ -2459,12 +2468,7 @@ static int zend_jit_trace_exit_stub(zend_jit_ctx *jit)
24592468
addr = ir_CAST_FC_FUNC(addr);
24602469
#endif
24612470
ref = ir_CALL_2(IR_ADDR, addr, jit_FP(jit), jit_IP(jit));
2462-
// Force reload execute_ex in VM
2463-
ir_ref is_positive = ir_IF(ir_GE(ref, ir_CONST_I32(0)));
2464-
ir_IF_TRUE(is_positive);
2465-
ir_RETURN(ir_NEG_A(ref)); // ZEND_VM_ENTER
2466-
ir_IF_FALSE(is_positive);
2467-
ir_RETURN(ref);
2471+
zend_jit_vm_enter(jit, ref);
24682472
}
24692473

24702474
return 1;
@@ -4214,12 +4218,7 @@ static int zend_jit_tail_handler(zend_jit_ctx *jit, const zend_op *opline)
42144218
|| opline->opcode == ZEND_THROW
42154219
|| opline->opcode == ZEND_VERIFY_NEVER_TYPE)) {
42164220
ir_ref ip = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit));
4217-
// Force reload execute_ex in VM (TODO: check if we actually need this)
4218-
ir_ref is_positive = ir_IF(ir_GE(ip, ir_CONST_I32(0)));
4219-
ir_IF_TRUE(is_positive);
4220-
ir_RETURN(ir_NEG_A(ip)); // ZEND_VM_ENTER
4221-
ir_IF_FALSE(is_positive);
4222-
ir_RETURN(ip);
4221+
zend_jit_vm_enter(jit, ip);
42234222
} else {
42244223
ir_TAILCALL_2(IR_ADDR, ir_CONST_FC_FUNC(handler), jit_FP(jit), jit_IP(jit));
42254224
}
@@ -10448,7 +10447,7 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen
1044810447
if (GCC_GLOBAL_REGS) {
1044910448
ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit)));
1045010449
} else {
10451-
ir_RETURN(ir_NEG_A(jit_IP(jit))); // ZEND_VM_ENTER
10450+
zend_jit_vm_enter(jit, jit_IP(jit));
1045210451
}
1045310452
} while (0);
1045410453

@@ -11216,7 +11215,7 @@ static int zend_jit_leave_func(zend_jit_ctx *jit,
1121611215
if (GCC_GLOBAL_REGS) {
1121711216
ir_TAILCALL(IR_VOID, ir_LOAD_A(jit_IP(jit)));
1121811217
} else {
11219-
ir_RETURN(ir_NEG_A(jit_IP(jit))); // ZEND_VM_LEAVE
11218+
zend_jit_vm_leave(jit, jit_IP(jit));
1122011219
}
1122111220

1122211221
jit->b = -1;
@@ -17346,7 +17345,7 @@ static int zend_jit_trace_return(zend_jit_ctx *jit, bool original_handler, const
1734617345
return 1;
1734717346
}
1734817347
}
17349-
ir_RETURN(ir_NEG_A(jit_IP(jit))); // ZEND_VM_RETURN
17348+
zend_jit_vm_enter(jit, jit_IP(jit));
1735017349
}
1735117350
return 1;
1735217351
}

ext/opcache/jit/zend_jit_vm_helpers.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,14 @@ ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_leave_nested_func_helper(ZEND_OPC
7575
zval_ptr_dtor(EX_VAR(old_opline->result.var));
7676
}
7777
#ifndef HAVE_GCC_GLOBAL_REGS
78-
return (zend_op*)-(uintptr_t)EG(current_execute_data)->opline;
78+
return (zend_op*)((uintptr_t)EG(current_execute_data)->opline | (1ULL<<63));
7979
#endif
8080
} else {
8181
EX(opline)++;
8282
#ifdef HAVE_GCC_GLOBAL_REGS
8383
opline = EX(opline);
8484
#else
85-
return (zend_op*)-(uintptr_t)EX(opline);
85+
return (zend_op*)((uintptr_t)EX(opline) | (1ULL<<63));
8686
#endif
8787
}
8888
}
@@ -372,7 +372,7 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_trace_c
372372
#ifdef HAVE_GCC_GLOBAL_REGS
373373
return;
374374
#else
375-
return opline ? (zend_op*)-(uintptr_t)opline : NULL; // ZEND_VM_ENTER() : ZEND_VM_RETURN()
375+
return opline ? (zend_op*)((uintptr_t)opline | (1ULL<<63)) : NULL; // ZEND_VM_ENTER() : ZEND_VM_RETURN()
376376
#endif
377377
} else {
378378
zend_vm_opcode_handler_t handler = (zend_vm_opcode_handler_t)ZEND_OP_TRACE_INFO(opline, offset)->orig_handler;
@@ -952,8 +952,7 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex,
952952
/* return after interrupt handler */
953953
ZEND_ASSERT(0 && "TODO");
954954
}
955-
opline = (zend_op*)-(uintptr_t)opline;
956-
ZEND_ASSERT((intptr_t)opline > 0);
955+
opline = (zend_op*)((uintptr_t)opline & ~(1ULL<<63));
957956
execute_data = EG(current_execute_data);
958957
#endif
959958

ext/opcache/tests/jit/gh8461-001.inc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,14 @@
11
<?php
2+
23
$x = 0;
4+
5+
class UniqueList
6+
{
7+
const A = 1;
8+
9+
public static function foo()
10+
{
11+
global $x;
12+
$x += self::A;
13+
}
14+
}

0 commit comments

Comments
 (0)