Skip to content

Commit 517c30b

Browse files
committed
JIT for FETCH_THIS
1 parent 9c6bda3 commit 517c30b

File tree

6 files changed

+73
-8
lines changed

6 files changed

+73
-8
lines changed

Zend/zend_vm_def.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -970,10 +970,6 @@ ZEND_VM_COLD_HELPER(zend_this_not_in_object_context_helper, ANY, ANY)
970970

971971
SAVE_OPLINE();
972972
zend_throw_error(NULL, "Using $this when not in object context");
973-
if ((opline+1)->opcode == ZEND_OP_DATA) {
974-
FREE_UNFETCHED_OP_DATA();
975-
}
976-
FREE_UNFETCHED_OP2();
977973
UNDEF_RESULT();
978974
HANDLE_EXCEPTION();
979975
}

Zend/zend_vm_execute.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -746,10 +746,6 @@ static zend_never_inline ZEND_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_th
746746

747747
SAVE_OPLINE();
748748
zend_throw_error(NULL, "Using $this when not in object context");
749-
if ((opline+1)->opcode == ZEND_OP_DATA) {
750-
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
751-
}
752-
FREE_UNFETCHED_OP(opline->op2_type, opline->op2.var);
753749
UNDEF_RESULT();
754750
HANDLE_EXCEPTION();
755751
}

ext/opcache/jit/zend_jit.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2812,6 +2812,11 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
28122812
goto jit_failure;
28132813
}
28142814
goto done;
2815+
case ZEND_FETCH_THIS:
2816+
if (!zend_jit_fetch_this(&dasm_state, opline, op_array)) {
2817+
goto jit_failure;
2818+
}
2819+
goto done;
28152820
case ZEND_SWITCH_LONG:
28162821
case ZEND_SWITCH_STRING:
28172822
if (!zend_jit_switch(&dasm_state, opline, op_array, ssa)) {

ext/opcache/jit/zend_jit_internal.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ struct _zend_jit_trace_stack_frame {
344344
#define TRACE_FRAME_MASK_LAST_SEND_BY_VAL 0x00000004
345345
#define TRACE_FRAME_MASK_RETURN_VALUE_USED 0x00000008
346346
#define TRACE_FRAME_MASK_RETURN_VALUE_UNUSED 0x00000010
347+
#define TRACE_FRAME_MASK_THIS_CHECKED 0x00000020
347348

348349

349350
#define TRACE_FRAME_INIT(frame, _func, nested, num_args) do { \
@@ -371,6 +372,8 @@ struct _zend_jit_trace_stack_frame {
371372
((frame)->_info & TRACE_FRAME_MASK_RETURN_VALUE_USED)
372373
#define TRACE_FRAME_IS_RETURN_VALUE_UNUSED(frame) \
373374
((frame)->_info & TRACE_FRAME_MASK_RETURN_VALUE_UNUSED)
375+
#define TRACE_FRAME_IS_THIS_CHECKED(frame) \
376+
((frame)->_info & TRACE_FRAME_MASK_THIS_CHECKED)
374377

375378
#define TRACE_FRAME_SET_RETURN_SSA_VAR(frame, var) do { \
376379
(frame)->_info = var; \
@@ -391,6 +394,9 @@ struct _zend_jit_trace_stack_frame {
391394
(frame)->_info |= TRACE_FRAME_MASK_RETURN_VALUE_UNUSED; \
392395
(frame)->_info &= ~TRACE_FRAME_MASK_RETURN_VALUE_USED; \
393396
} while (0)
397+
#define TRACE_FRAME_SET_THIS_CHECKED(frame) do { \
398+
(frame)->_info |= TRACE_FRAME_MASK_THIS_CHECKED; \
399+
} while (0)
394400

395401
typedef struct _zend_jit_globals {
396402
zend_jit_trace_stack_frame *current_frame;

ext/opcache/jit/zend_jit_trace.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2632,6 +2632,11 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
26322632
goto jit_failure;
26332633
}
26342634
goto done;
2635+
case ZEND_FETCH_THIS:
2636+
if (!zend_jit_fetch_this(&dasm_state, opline, op_array)) {
2637+
goto jit_failure;
2638+
}
2639+
goto done;
26352640
#if 0
26362641
case ZEND_SWITCH_LONG:
26372642
case ZEND_SWITCH_STRING:

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2101,6 +2101,25 @@ static int zend_jit_mod_by_zero_stub(dasm_State **Dst)
21012101
return 1;
21022102
}
21032103

2104+
static int zend_jit_invalid_this_stub(dasm_State **Dst)
2105+
{
2106+
|->invalid_this:
2107+
| UNDEF_OPLINE_RESULT
2108+
|.if X64
2109+
| xor CARG1, CARG1
2110+
| LOAD_ADDR CARG2, "Using $this when not in object context"
2111+
| EXT_CALL zend_throw_error, r0
2112+
|.else
2113+
| sub r4, 8
2114+
| push "Using $this when not in object context"
2115+
| push 0
2116+
| EXT_CALL zend_throw_error, r0
2117+
| add r4, 16
2118+
|.endif
2119+
| jmp ->exception_handler
2120+
return 1;
2121+
}
2122+
21042123
static int zend_jit_double_one_stub(dasm_State **Dst)
21052124
{
21062125
|->one:
@@ -2433,6 +2452,7 @@ static const zend_jit_stub zend_jit_stubs[] = {
24332452
JIT_STUB(undefined_function),
24342453
JIT_STUB(negative_shift),
24352454
JIT_STUB(mod_by_zero),
2455+
JIT_STUB(invalid_this),
24362456
JIT_STUB(trace_halt),
24372457
JIT_STUB(trace_exit),
24382458
JIT_STUB(trace_escape),
@@ -10553,6 +10573,43 @@ static int zend_jit_strlen(dasm_State **Dst, const zend_op *opline, const zend_o
1055310573
return 1;
1055410574
}
1055510575

10576+
static int zend_jit_fetch_this(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array)
10577+
{
10578+
zend_jit_addr res_addr = RES_ADDR();
10579+
10580+
if (zend_jit_trigger == ZEND_JIT_ON_HOT_TRACE) {
10581+
if (!JIT_G(current_frame) ||
10582+
!TRACE_FRAME_IS_THIS_CHECKED(JIT_G(current_frame))) {
10583+
10584+
int32_t exit_point = zend_jit_trace_get_exit_point(opline, opline, NULL);
10585+
const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
10586+
10587+
| cmp byte EX->This.u1.v.type, IS_OBJECT
10588+
| jne &exit_addr
10589+
10590+
if (JIT_G(current_frame)) {
10591+
TRACE_FRAME_SET_THIS_CHECKED(JIT_G(current_frame));
10592+
}
10593+
}
10594+
} else {
10595+
10596+
| cmp byte EX->This.u1.v.type, IS_OBJECT
10597+
| jne >1
10598+
|.cold_code
10599+
|1:
10600+
| SAVE_VALID_OPLINE opline, r0
10601+
| jmp ->invalid_this
10602+
|.code
10603+
}
10604+
10605+
| mov r0, aword EX->This.value.ptr
10606+
| SET_ZVAL_PTR res_addr, r0
10607+
| SET_ZVAL_TYPE_INFO res_addr, IS_OBJECT_EX
10608+
| GC_ADDREF r0
10609+
10610+
return 1;
10611+
}
10612+
1055610613
static int zend_jit_switch(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_ssa *ssa)
1055710614
{
1055810615
HashTable *jumptable = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));

0 commit comments

Comments
 (0)