Skip to content

Commit 73c7fa2

Browse files
committed
JIT for FETCH_DIM_W/RW insructions
1 parent 95cf7a0 commit 73c7fa2

File tree

5 files changed

+340
-15
lines changed

5 files changed

+340
-15
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2853,6 +2853,22 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
28532853
goto jit_failure;
28542854
}
28552855
goto done;
2856+
case ZEND_FETCH_DIM_W:
2857+
case ZEND_FETCH_DIM_RW:
2858+
// case ZEND_FETCH_DIM_UNSET:
2859+
case ZEND_FETCH_LIST_W:
2860+
if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
2861+
break;
2862+
}
2863+
if (opline->op1_type != IS_CV) {
2864+
break;
2865+
}
2866+
if (!zend_jit_fetch_dim(&dasm_state, opline,
2867+
OP1_INFO(), OP1_REG_ADDR(), OP2_INFO(), RES_REG_ADDR(),
2868+
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) {
2869+
goto jit_failure;
2870+
}
2871+
goto done;
28562872
case ZEND_ISSET_ISEMPTY_DIM_OBJ:
28572873
if ((opline->extended_value & ZEND_ISEMPTY)) {
28582874
// TODO: support for empty() ???

ext/opcache/jit/zend_jit_disasm_x86.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,9 @@ static int zend_jit_disasm_init(void)
420420
REGISTER_HELPER(zend_jit_fetch_dim_obj_is_helper);
421421
REGISTER_HELPER(zend_jit_fetch_dim_rw_helper);
422422
REGISTER_HELPER(zend_jit_fetch_dim_w_helper);
423+
REGISTER_HELPER(zend_jit_fetch_dim_obj_rw_helper);
424+
REGISTER_HELPER(zend_jit_fetch_dim_obj_w_helper);
425+
// REGISTER_HELPER(zend_jit_fetch_dim_obj_unset_helper);
423426
REGISTER_HELPER(zend_jit_assign_dim_helper);
424427
REGISTER_HELPER(zend_jit_assign_dim_op_helper);
425428
REGISTER_HELPER(zend_jit_fast_assign_concat_helper);

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 87 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,8 @@ static zend_never_inline zend_long zend_check_string_offset(zval *dim/*, int typ
690690
/* For BC reasons we allow errors so that we can warn on leading numeric string */
691691
if (IS_LONG == is_numeric_string_ex(Z_STRVAL_P(dim), Z_STRLEN_P(dim), &offset, NULL,
692692
/* allow errors */ true, NULL, &trailing_data)) {
693-
if (UNEXPECTED(trailing_data) /*&& type != BP_VAR_UNSET*/) {
693+
if (UNEXPECTED(trailing_data)
694+
&& EG(current_execute_data)->opline->opcode != ZEND_FETCH_DIM_UNSET) {
694695
zend_error(E_WARNING, "Illegal string offset \"%s\"", Z_STRVAL_P(dim));
695696
}
696697
return offset;
@@ -850,6 +851,7 @@ static zend_never_inline ZEND_COLD void zend_wrong_string_offset(void)
850851
case ZEND_FETCH_DIM_RW:
851852
case ZEND_FETCH_DIM_FUNC_ARG:
852853
case ZEND_FETCH_DIM_UNSET:
854+
case ZEND_FETCH_LIST_W:
853855
/* TODO: Encode the "reason" into opline->extended_value??? */
854856
var = opline->result.var;
855857
opline++;
@@ -858,9 +860,21 @@ static zend_never_inline ZEND_COLD void zend_wrong_string_offset(void)
858860
while (opline < end) {
859861
if (opline->op1_type == IS_VAR && opline->op1.var == var) {
860862
switch (opline->opcode) {
863+
case ZEND_FETCH_OBJ_W:
864+
case ZEND_FETCH_OBJ_RW:
865+
case ZEND_FETCH_OBJ_FUNC_ARG:
866+
case ZEND_FETCH_OBJ_UNSET:
867+
case ZEND_ASSIGN_OBJ:
861868
case ZEND_ASSIGN_OBJ_OP:
869+
case ZEND_ASSIGN_OBJ_REF:
862870
msg = "Cannot use string offset as an object";
863871
break;
872+
case ZEND_FETCH_DIM_W:
873+
case ZEND_FETCH_DIM_RW:
874+
case ZEND_FETCH_DIM_FUNC_ARG:
875+
case ZEND_FETCH_DIM_UNSET:
876+
case ZEND_FETCH_LIST_W:
877+
case ZEND_ASSIGN_DIM:
864878
case ZEND_ASSIGN_DIM_OP:
865879
msg = "Cannot use string offset as an array";
866880
break;
@@ -878,20 +892,6 @@ static zend_never_inline ZEND_COLD void zend_wrong_string_offset(void)
878892
case ZEND_POST_DEC:
879893
msg = "Cannot increment/decrement string offsets";
880894
break;
881-
case ZEND_FETCH_DIM_W:
882-
case ZEND_FETCH_DIM_RW:
883-
case ZEND_FETCH_DIM_FUNC_ARG:
884-
case ZEND_FETCH_DIM_UNSET:
885-
case ZEND_ASSIGN_DIM:
886-
msg = "Cannot use string offset as an array";
887-
break;
888-
case ZEND_FETCH_OBJ_W:
889-
case ZEND_FETCH_OBJ_RW:
890-
case ZEND_FETCH_OBJ_FUNC_ARG:
891-
case ZEND_FETCH_OBJ_UNSET:
892-
case ZEND_ASSIGN_OBJ:
893-
msg = "Cannot use string offset as an object";
894-
break;
895895
case ZEND_ASSIGN_REF:
896896
case ZEND_ADD_ARRAY_ELEMENT:
897897
case ZEND_INIT_ARRAY:
@@ -914,6 +914,9 @@ static zend_never_inline ZEND_COLD void zend_wrong_string_offset(void)
914914
case ZEND_SEND_FUNC_ARG:
915915
msg = "Only variables can be passed by reference";
916916
break;
917+
case ZEND_FE_RESET_RW:
918+
msg = "Cannot iterate on string offsets by reference";
919+
break;
917920
EMPTY_SWITCH_DEFAULT_CASE();
918921
}
919922
break;
@@ -1014,6 +1017,75 @@ static zend_never_inline void zend_assign_to_string_offset(zval *str, zval *dim,
10141017
}
10151018
}
10161019

1020+
static zend_always_inline void ZEND_FASTCALL zend_jit_fetch_dim_obj_helper(zval *object_ptr, zval *dim, zval *result, int type)
1021+
{
1022+
zval *retval;
1023+
1024+
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
1025+
retval = Z_OBJ_HT_P(object_ptr)->read_dimension(Z_OBJ_P(object_ptr), dim, type, result);
1026+
if (UNEXPECTED(retval == &EG(uninitialized_zval))) {
1027+
zend_class_entry *ce = Z_OBJCE_P(object_ptr);
1028+
1029+
ZVAL_NULL(result);
1030+
zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
1031+
} else if (EXPECTED(retval && Z_TYPE_P(retval) != IS_UNDEF)) {
1032+
if (!Z_ISREF_P(retval)) {
1033+
if (result != retval) {
1034+
ZVAL_COPY(result, retval);
1035+
retval = result;
1036+
}
1037+
if (Z_TYPE_P(retval) != IS_OBJECT) {
1038+
zend_class_entry *ce = Z_OBJCE_P(object_ptr);
1039+
zend_error(E_NOTICE, "Indirect modification of overloaded element of %s has no effect", ZSTR_VAL(ce->name));
1040+
}
1041+
} else if (UNEXPECTED(Z_REFCOUNT_P(retval) == 1)) {
1042+
ZVAL_UNREF(retval);
1043+
}
1044+
if (result != retval) {
1045+
ZVAL_INDIRECT(result, retval);
1046+
}
1047+
} else {
1048+
ZEND_ASSERT(EG(exception) && "read_dimension() returned NULL without exception");
1049+
ZVAL_UNDEF(result);
1050+
}
1051+
} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
1052+
if (!dim) {
1053+
zend_throw_error(NULL, "[] operator not supported for strings");
1054+
} else {
1055+
if (UNEXPECTED(Z_TYPE_P(dim) != IS_LONG)) {
1056+
zend_check_string_offset(dim/*, BP_VAR_RW*/);
1057+
}
1058+
if (!EG(exception)) {
1059+
zend_wrong_string_offset();
1060+
}
1061+
}
1062+
ZVAL_UNDEF(result);
1063+
} else {
1064+
if (type == BP_VAR_UNSET) {
1065+
zend_throw_error(NULL, "Cannot unset offset in a non-array variable");
1066+
ZVAL_UNDEF(result);
1067+
} else {
1068+
zend_throw_error(NULL, "Cannot use a scalar value as an array");
1069+
ZVAL_UNDEF(result);
1070+
}
1071+
}
1072+
}
1073+
1074+
static void ZEND_FASTCALL zend_jit_fetch_dim_obj_w_helper(zval *object_ptr, zval *dim, zval *result)
1075+
{
1076+
zend_jit_fetch_dim_obj_helper(object_ptr, dim, result, BP_VAR_W);
1077+
}
1078+
1079+
static void ZEND_FASTCALL zend_jit_fetch_dim_obj_rw_helper(zval *object_ptr, zval *dim, zval *result)
1080+
{
1081+
zend_jit_fetch_dim_obj_helper(object_ptr, dim, result, BP_VAR_RW);
1082+
}
1083+
1084+
//static void ZEND_FASTCALL zend_jit_fetch_dim_obj_unset_helper(zval *object_ptr, zval *dim, zval *result)
1085+
//{
1086+
// zend_jit_fetch_dim_obj_helper(object_ptr, dim, result, BP_VAR_UNSET);
1087+
//}
1088+
10171089
static void ZEND_FASTCALL zend_jit_assign_dim_helper(zval *object_ptr, zval *dim, zval *value, zval *result)
10181090
{
10191091
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {

ext/opcache/jit/zend_jit_trace.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,6 +1558,16 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
15581558
}
15591559
}
15601560
break;
1561+
case ZEND_FETCH_DIM_W:
1562+
case ZEND_FETCH_DIM_RW:
1563+
// case ZEND_FETCH_DIM_UNSET:
1564+
case ZEND_FETCH_LIST_W:
1565+
if (opline->op1_type != IS_CV) {
1566+
break;
1567+
}
1568+
ADD_OP1_TRACE_GUARD();
1569+
ADD_OP2_TRACE_GUARD();
1570+
break;
15611571
case ZEND_SEND_VAL_EX:
15621572
case ZEND_SEND_VAR_EX:
15631573
case ZEND_SEND_VAR_NO_REF_EX:
@@ -4311,6 +4321,37 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
43114321
goto jit_failure;
43124322
}
43134323
goto done;
4324+
case ZEND_FETCH_DIM_W:
4325+
case ZEND_FETCH_DIM_RW:
4326+
// case ZEND_FETCH_DIM_UNSET:
4327+
case ZEND_FETCH_LIST_W:
4328+
if (opline->op1_type != IS_CV) {
4329+
break;
4330+
}
4331+
op1_info = OP1_INFO();
4332+
op1_addr = OP1_REG_ADDR();
4333+
if (orig_op1_type != IS_UNKNOWN
4334+
&& (orig_op1_type & IS_TRACE_REFERENCE)) {
4335+
if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr,
4336+
!ssa->var_info[ssa_op->op1_use].guarded_reference, 1)) {
4337+
goto jit_failure;
4338+
}
4339+
if (opline->op1_type == IS_CV
4340+
&& zend_jit_var_may_alias(op_array, op_array_ssa, EX_VAR_TO_NUM(opline->op1.var)) == NO_ALIAS) {
4341+
ssa->var_info[ssa_op->op1_use].guarded_reference = 1;
4342+
}
4343+
} else {
4344+
CHECK_OP1_TRACE_TYPE();
4345+
}
4346+
op2_info = OP2_INFO();
4347+
CHECK_OP2_TRACE_TYPE();
4348+
op1_def_info = OP1_DEF_INFO();
4349+
if (!zend_jit_fetch_dim(&dasm_state, opline,
4350+
op1_info, op1_addr, op2_info, RES_REG_ADDR(),
4351+
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) {
4352+
goto jit_failure;
4353+
}
4354+
goto done;
43144355
case ZEND_ISSET_ISEMPTY_DIM_OBJ:
43154356
if ((opline->extended_value & ZEND_ISEMPTY)) {
43164357
// TODO: support for empty() ???

0 commit comments

Comments
 (0)