Skip to content

Commit c5ded13

Browse files
committed
JIT: Code generation for ROPE_INIT, ROPE_ADD and ROPE_END with STRING operands
1 parent 425c2e3 commit c5ded13

File tree

6 files changed

+133
-0
lines changed

6 files changed

+133
-0
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3899,6 +3899,17 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
38993899
goto jit_failure;
39003900
}
39013901
goto done;
3902+
case ZEND_ROPE_INIT:
3903+
case ZEND_ROPE_ADD:
3904+
case ZEND_ROPE_END:
3905+
op2_info = OP2_INFO();
3906+
if ((op2_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_STRING) {
3907+
break;
3908+
}
3909+
if (!zend_jit_rope(&dasm_state, opline, op2_info)) {
3910+
goto jit_failure;
3911+
}
3912+
goto done;
39023913
default:
39033914
break;
39043915
}

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13953,6 +13953,48 @@ static int zend_jit_in_array(dasm_State **Dst, const zend_op *opline, uint32_t o
1395313953
return 1;
1395413954
}
1395513955

13956+
static int zend_jit_rope(dasm_State **Dst, const zend_op *opline, uint32_t op2_info)
13957+
{
13958+
uint32_t offset;
13959+
13960+
offset = (opline->opcode == ZEND_ROPE_INIT) ?
13961+
opline->result.var :
13962+
opline->op1.var + opline->extended_value * sizeof(zend_string*);
13963+
13964+
if (opline->op2_type == IS_CONST) {
13965+
zval *zv = RT_CONSTANT(opline, opline->op2);
13966+
zend_string *str;
13967+
13968+
ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
13969+
str = Z_STR_P(zv);
13970+
| LOAD_ADDR REG0, str
13971+
| MEM_ACCESS_64_WITH_UOFFSET str, REG0, FP, offset, TMP1
13972+
} else {
13973+
zend_jit_addr op2_addr = OP2_ADDR();
13974+
13975+
ZEND_ASSERT((op2_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_STRING);
13976+
13977+
| GET_ZVAL_PTR REG1, op2_addr, TMP1
13978+
| MEM_ACCESS_64_WITH_UOFFSET str, REG1, FP, offset, TMP1
13979+
if (opline->op2_type == IS_CV) {
13980+
| GET_ZVAL_TYPE_INFO REG0w, op2_addr, TMP1
13981+
| TRY_ADDREF op2_info, REG0w, REG1, TMP1w
13982+
}
13983+
}
13984+
13985+
if (opline->opcode == ZEND_ROPE_END) {
13986+
zend_jit_addr res_addr = RES_ADDR();
13987+
13988+
| ADD_SUB_64_WITH_CONST add, FCARG1x, FP, opline->op1.var, TMP1
13989+
| LOAD_32BIT_VAL FCARG2w, opline->extended_value
13990+
| EXT_CALL zend_jit_rope_end, TMP1
13991+
| SET_ZVAL_PTR res_addr, RETVALx, TMP1
13992+
| SET_ZVAL_TYPE_INFO res_addr, IS_STRING_EX, TMP1w, TMP2
13993+
}
13994+
13995+
return 1;
13996+
}
13997+
1395613998
static bool zend_jit_noref_guard(dasm_State **Dst, const zend_op *opline, zend_jit_addr var_addr)
1395713999
{
1395814000
int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);

ext/opcache/jit/zend_jit_disasm.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,7 @@ static int zend_jit_disasm_init(void)
693693
REGISTER_HELPER(zend_jit_pre_dec_obj_helper);
694694
REGISTER_HELPER(zend_jit_post_inc_obj_helper);
695695
REGISTER_HELPER(zend_jit_post_dec_obj_helper);
696+
REGISTER_HELPER(zend_jit_rope_end);
696697
#if (PHP_VERSION_ID <= 80100) && (SIZEOF_SIZE_T == 4)
697698
REGISTER_HELPER(zval_jit_update_constant_ex);
698699
#endif

ext/opcache/jit/zend_jit_helpers.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2597,3 +2597,24 @@ static void ZEND_FASTCALL zend_jit_free_trampoline_helper(zend_function *func)
25972597
zend_string_release_ex(func->common.function_name, 0);
25982598
zend_free_trampoline(func);
25992599
}
2600+
2601+
static zend_string* ZEND_FASTCALL zend_jit_rope_end(zend_string **rope, uint32_t count)
2602+
{
2603+
zend_string *ret;
2604+
uint32_t i;
2605+
size_t len = 0;
2606+
char *target;
2607+
2608+
for (i = 0; i <= count; i++) {
2609+
len += ZSTR_LEN(rope[i]);
2610+
}
2611+
ret = zend_string_alloc(len, 0);
2612+
target = ZSTR_VAL(ret);
2613+
for (i = 0; i <= count; i++) {
2614+
memcpy(target, ZSTR_VAL(rope[i]), ZSTR_LEN(rope[i]));
2615+
target += ZSTR_LEN(rope[i]);
2616+
zend_string_release_ex(rope[i], 0);
2617+
}
2618+
*target = '\0';
2619+
return ret;
2620+
}

ext/opcache/jit/zend_jit_trace.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,6 +1937,11 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
19371937
ADD_OP1_TRACE_GUARD();
19381938
}
19391939
break;
1940+
case ZEND_ROPE_INIT:
1941+
case ZEND_ROPE_ADD:
1942+
case ZEND_ROPE_END:
1943+
ADD_OP2_TRACE_GUARD();
1944+
break;
19401945
default:
19411946
break;
19421947
}
@@ -5794,6 +5799,18 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
57945799
TRACE_FRAME_SET_UNKNOWN_NUM_ARGS(JIT_G(current_frame)->call);
57955800
}
57965801
break;
5802+
case ZEND_ROPE_INIT:
5803+
case ZEND_ROPE_ADD:
5804+
case ZEND_ROPE_END:
5805+
op2_info = OP2_INFO();
5806+
CHECK_OP2_TRACE_TYPE();
5807+
if ((op2_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_STRING) {
5808+
break;
5809+
}
5810+
if (!zend_jit_rope(&dasm_state, opline, op2_info)) {
5811+
goto jit_failure;
5812+
}
5813+
goto done;
57975814
default:
57985815
break;
57995816
}

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14798,6 +14798,47 @@ static int zend_jit_in_array(dasm_State **Dst, const zend_op *opline, uint32_t o
1479814798
return 1;
1479914799
}
1480014800

14801+
static int zend_jit_rope(dasm_State **Dst, const zend_op *opline, uint32_t op2_info)
14802+
{
14803+
uint32_t offset;
14804+
14805+
offset = (opline->opcode == ZEND_ROPE_INIT) ?
14806+
opline->result.var :
14807+
opline->op1.var + opline->extended_value * sizeof(zend_string*);
14808+
14809+
if (opline->op2_type == IS_CONST) {
14810+
zval *zv = RT_CONSTANT(opline, opline->op2);
14811+
zend_string *str;
14812+
14813+
ZEND_ASSERT(Z_TYPE_P(zv) == IS_STRING);
14814+
str = Z_STR_P(zv);
14815+
| ADDR_STORE aword [FP + offset], str, r0
14816+
} else {
14817+
zend_jit_addr op2_addr = OP2_ADDR();
14818+
14819+
ZEND_ASSERT((op2_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_STRING);
14820+
14821+
| GET_ZVAL_PTR r1, op2_addr
14822+
| mov aword [FP + offset], r1
14823+
if (opline->op2_type == IS_CV) {
14824+
| GET_ZVAL_TYPE_INFO eax, op2_addr
14825+
| TRY_ADDREF op2_info, ah, r1
14826+
}
14827+
}
14828+
14829+
if (opline->opcode == ZEND_ROPE_END) {
14830+
zend_jit_addr res_addr = RES_ADDR();
14831+
14832+
| lea FCARG1a, [FP + opline->op1.var]
14833+
| mov FCARG2d, opline->extended_value
14834+
| EXT_CALL zend_jit_rope_end, r0
14835+
| SET_ZVAL_PTR res_addr, r0
14836+
| SET_ZVAL_TYPE_INFO res_addr, IS_STRING_EX
14837+
}
14838+
14839+
return 1;
14840+
}
14841+
1480114842
static bool zend_jit_noref_guard(dasm_State **Dst, const zend_op *opline, zend_jit_addr var_addr)
1480214843
{
1480314844
int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);

0 commit comments

Comments
 (0)