Skip to content

Commit 9e8a8e6

Browse files
committed
Use information about recorded classes for speculative FETCH_OBJ optimization
1 parent 0e71446 commit 9e8a8e6

File tree

4 files changed

+46
-6
lines changed

4 files changed

+46
-6
lines changed

ext/opcache/Optimizer/zend_inference.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
/* Bitmask for type inference (zend_ssa_var_info.type) */
2727
#include "zend_type_info.h"
2828

29+
#define MAY_BE_CLASS_GUARD (1<<27) /* needs class guard */
2930
#define MAY_BE_GUARD (1<<28) /* needs type guard */
3031
#define MAY_BE_IN_REG (1<<29) /* value allocated in CPU register */
3132

ext/opcache/jit/zend_jit.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2790,8 +2790,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
27902790
}
27912791
}
27922792
}
2793-
if (!zend_jit_fetch_obj(&dasm_state, opline, op_array,
2794-
op1_info, op1_addr, 0, ce, ce_is_instanceof, 0,
2793+
if (!zend_jit_fetch_obj(&dasm_state, opline, op_array, ssa, ssa_op,
2794+
op1_info, op1_addr, 0, ce, ce_is_instanceof, 0, NULL,
27952795
zend_may_throw(opline, ssa_op, op_array, ssa))) {
27962796
goto jit_failure;
27972797
}

ext/opcache/jit/zend_jit_trace.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2921,6 +2921,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
29212921
uint8_t op3_type = p->op3_type;
29222922
uint8_t orig_op1_type = op1_type;
29232923
zend_bool op1_indirect;
2924+
zend_class_entry *op1_ce = NULL;
29242925

29252926
opline = p->opline;
29262927
if (op1_type & (IS_TRACE_REFERENCE|IS_TRACE_INDIRECT)) {
@@ -2934,7 +2935,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
29342935
}
29352936

29362937
if ((p+1)->op == ZEND_JIT_TRACE_OP1_TYPE) {
2937-
// TODO: support for recorded classes ???
2938+
op1_ce = (zend_class_entry*)(p+1)->ce;
29382939
p++;
29392940
}
29402941
if ((p+1)->op == ZEND_JIT_TRACE_OP2_TYPE) {
@@ -3837,9 +3838,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
38373838
delayed_fetch_this = ssa->var_info[ssa_op->op1_use].delayed_fetch_this;
38383839
}
38393840
}
3840-
if (!zend_jit_fetch_obj(&dasm_state, opline, op_array,
3841+
if (!zend_jit_fetch_obj(&dasm_state, opline, op_array, ssa, ssa_op,
38413842
op1_info, op1_addr, op1_indirect, ce, ce_is_instanceof,
3842-
delayed_fetch_this,
3843+
delayed_fetch_this, op1_ce,
38433844
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, MAY_BE_STRING))) {
38443845
goto jit_failure;
38453846
}

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10898,7 +10898,31 @@ static zend_bool zend_may_be_dynamic_property(zend_class_entry *ce, zend_string
1089810898
return 0;
1089910899
}
1090010900

10901-
static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, uint32_t op1_info, zend_jit_addr op1_addr, zend_bool op1_indirect, zend_class_entry *ce, zend_bool ce_is_instanceof, zend_bool use_this, int may_throw)
10901+
static int zend_jit_class_guard(dasm_State **Dst, const zend_op *opline, zend_class_entry *ce)
10902+
{
10903+
int32_t exit_point = zend_jit_trace_get_exit_point(opline, opline, NULL, 0);
10904+
const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
10905+
10906+
if (!exit_addr) {
10907+
return 0;
10908+
}
10909+
10910+
|.if X64
10911+
|| if (!IS_SIGNED_32BIT(ce)) {
10912+
| mov64 r0, ((ptrdiff_t)ce)
10913+
| cmp aword [FCARG1a + offsetof(zend_object, ce)], r0
10914+
|| } else {
10915+
| cmp aword [FCARG1a + offsetof(zend_object, ce)], ce
10916+
|| }
10917+
|.else
10918+
| cmp aword [FCARG1a + offsetof(zend_object, ce)], ce
10919+
|.endif
10920+
| jne &exit_addr
10921+
10922+
return 1;
10923+
}
10924+
10925+
static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, uint32_t op1_info, zend_jit_addr op1_addr, zend_bool op1_indirect, zend_class_entry *ce, zend_bool ce_is_instanceof, zend_bool use_this, zend_class_entry *trace_ce, int may_throw)
1090210926
{
1090310927
zval *member;
1090410928
zend_property_info *prop_info;
@@ -10950,6 +10974,20 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen
1095010974
| GET_ZVAL_PTR FCARG1a, op1_addr
1095110975
}
1095210976

10977+
if (!prop_info && trace_ce && (trace_ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
10978+
prop_info = zend_get_known_property_info(trace_ce, Z_STR_P(member), opline->op1_type == IS_UNUSED, op_array->filename);
10979+
if (prop_info) {
10980+
if (!(op1_info & MAY_BE_CLASS_GUARD)) {
10981+
if (!zend_jit_class_guard(Dst, opline, trace_ce)) {
10982+
return 0;
10983+
}
10984+
if (ssa->var_info && ssa_op->op1_use >= 0) {
10985+
ssa->var_info[ssa_op->op1_use].type |= MAY_BE_CLASS_GUARD;
10986+
}
10987+
}
10988+
}
10989+
}
10990+
1095310991
if (!prop_info) {
1095410992
| mov r0, EX->run_time_cache
1095510993
| mov r2, aword [r0 + (opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS)]

0 commit comments

Comments
 (0)