Skip to content

Commit 5cf307d

Browse files
committed
JIT/AArch64: INIT_FCALL and DO_FCALL support for optimized function code-generation (1204/1205)
1 parent 391d2fa commit 5cf307d

File tree

1 file changed

+122
-15
lines changed

1 file changed

+122
-15
lines changed

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 122 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@
3131
|.define CARG4, x3
3232
|.define CARG5, x4
3333
|.define CARG6, x5
34+
|.define CARG1w, w0
35+
|.define CARG2w, w1
36+
|.define CARG3w, w2
37+
|.define CARG4w, w3
38+
|.define CARG5w, w4
39+
|.define CARG6w, w5
3440
|.define RETVALx, x0
3541
|.define RETVALw, w0
3642
|.define FCARG1x, x0
@@ -1447,7 +1453,16 @@ static int zend_jit_cannot_add_element_stub(dasm_State **Dst)
14471453
static int zend_jit_undefined_function_stub(dasm_State **Dst)
14481454
{
14491455
|->undefined_function:
1450-
| brk #0 // TODO
1456+
| ldr REG0, EX->opline
1457+
| movz CARG1, #0
1458+
| LOAD_ADDR CARG2, "Call to undefined function %s()"
1459+
| ldr CARG3w, [REG0, #offsetof(zend_op, op2.constant)]
1460+
| sxtw CARG3, CARG3w
1461+
| add REG0, REG0, CARG3
1462+
| ldr CARG3, [REG0]
1463+
| add CARG3, CARG3, #offsetof(zend_string, val)
1464+
| EXT_CALL zend_throw_error, REG0
1465+
| b ->exception_handler
14511466
return 1;
14521467
}
14531468

@@ -4836,7 +4851,7 @@ static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t
48364851
if (!func
48374852
&& trace
48384853
&& trace->op == ZEND_JIT_TRACE_INIT_CALL) {
4839-
| brk #0 // TODO: Tracing mode. ASLR?
4854+
func = (zend_function*)trace->func;
48404855
}
48414856

48424857
if (opline->opcode == ZEND_INIT_FCALL
@@ -4845,7 +4860,7 @@ static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t
48454860
/* load constant address later */
48464861
} else if (func && op_array == &func->op_array) {
48474862
/* recursive call */
4848-
| brk #0 // TODO
4863+
| ldr REG0, EX->func
48494864
} else {
48504865
| // if (CACHED_PTR(opline->result.num))
48514866
| ldr REG0, EX->run_time_cache
@@ -4857,15 +4872,21 @@ static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t
48574872
&& func
48584873
&& func->type == ZEND_USER_FUNCTION
48594874
&& (func->op_array.fn_flags & ZEND_ACC_IMMUTABLE)) {
4860-
| brk #0 // TODO
4875+
| LOAD_ADDR FCARG1x, func
4876+
| EXT_CALL zend_jit_init_func_run_time_cache_helper, REG0
4877+
| ldr REG1, EX->run_time_cache
4878+
| mov REG0, RETVALx
4879+
| str REG0, [REG1, #opline->result.num]
4880+
| b >3
48614881
} else {
48624882
zval *zv = RT_CONSTANT(opline, opline->op2);
48634883

48644884
if (opline->opcode == ZEND_INIT_FCALL) {
48654885
| LOAD_ADDR FCARG1x, Z_STR_P(zv);
48664886
| EXT_CALL zend_jit_find_func_helper, REG0
48674887
} else if (opline->opcode == ZEND_INIT_FCALL_BY_NAME) {
4868-
| brk #0 // TODO
4888+
| LOAD_ADDR FCARG1x, Z_STR_P(zv + 1);
4889+
| EXT_CALL zend_jit_find_func_helper, REG0
48694890
} else if (opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
48704891
| LOAD_ADDR FCARG1x, zv;
48714892
| EXT_CALL zend_jit_find_ns_func_helper, REG0
@@ -4882,7 +4903,8 @@ static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t
48824903
} else {
48834904
| cbnz REG0, >3
48844905
| // SAVE_OPLINE();
4885-
| brk #0 // TODO: invalid func address.
4906+
| SET_EX_OPLINE opline, REG0
4907+
| b ->undefined_function
48864908
}
48874909
}
48884910
|.code
@@ -5175,12 +5197,10 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
51755197

51765198
prev_opline = opline - 1;
51775199
while (prev_opline->opcode == ZEND_EXT_FCALL_BEGIN || prev_opline->opcode == ZEND_TICKS) {
5178-
| brk #0 // TODO
51795200
prev_opline--;
51805201
}
51815202
if (prev_opline->opcode == ZEND_SEND_UNPACK || prev_opline->opcode == ZEND_SEND_ARRAY ||
51825203
prev_opline->opcode == ZEND_CHECK_UNDEF_ARGS) {
5183-
| brk #0 // TODO
51845204
unknown_num_args = 1;
51855205
}
51865206

@@ -5196,7 +5216,6 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
51965216
if (!func) {
51975217
/* resolve function at run time */
51985218
} else if (func->type == ZEND_USER_FUNCTION) {
5199-
| brk #0 // TODO
52005219
ZEND_ASSERT(opline->opcode != ZEND_DO_ICALL);
52015220
call_num_args = call_info->num_args;
52025221
} else if (func->type == ZEND_INTERNAL_FUNCTION) {
@@ -5312,19 +5331,32 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
53125331
if (func && op_array == &func->op_array) {
53135332
/* recursive call */
53145333
if (trace || func->op_array.cache_size > sizeof(void*)) {
5315-
| brk #0 // TODO
5334+
| ldr REG2, EX->run_time_cache
5335+
| str REG2, EX:RX->run_time_cache
53165336
}
53175337
} else {
53185338
if (func) {
5319-
| brk #0 // TODO
5339+
| ldr REG0, EX:RX->func
53205340
}
53215341
| ldr REG2, [REG0, #offsetof(zend_op_array, run_time_cache__ptr)]
53225342
// Always defined as ZEND_MAP_PTR_KIND_PTR_OR_OFFSET. See Zend/zend_map_ptr.h.
53235343
#if ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR
53245344
| ldr REG2, [REG2]
53255345
#elif ZEND_MAP_PTR_KIND == ZEND_MAP_PTR_KIND_PTR_OR_OFFSET
53265346
if (func && !(func->op_array.fn_flags & ZEND_ACC_CLOSURE)) {
5327-
| brk #0 // TODO
5347+
if (ZEND_MAP_PTR_IS_OFFSET(func->op_array.run_time_cache)) {
5348+
| MEM_LOAD_OP_ZTS add, ldr, REG2, compiler_globals, map_ptr_base, REG1, TMP1
5349+
} else if ((func->op_array.fn_flags & ZEND_ACC_IMMUTABLE)
5350+
&& (!func->op_array.scope || (func->op_array.scope->ce_flags & ZEND_ACC_LINKED))) {
5351+
| MEM_LOAD_OP_ZTS add, ldr, REG2, compiler_globals, map_ptr_base, REG1, TMP1
5352+
} else {
5353+
/* the called op_array may be not persisted yet */
5354+
| tst REG2, #1
5355+
| beq >1
5356+
| MEM_LOAD_OP_ZTS add, ldr, REG2, compiler_globals, map_ptr_base, REG1, TMP1
5357+
|1:
5358+
| ldr REG2, [REG2]
5359+
}
53285360
} else {
53295361
| tst REG2, #1
53305362
| beq >1
@@ -5345,11 +5377,82 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
53455377

53465378
| // opline = op_array->opcodes;
53475379
if (func && !unknown_num_args) {
5348-
| brk #0 // TODO
5380+
for (i = call_num_args; i < func->op_array.last_var; i++) {
5381+
uint32_t n = EX_NUM_TO_VAR(i);
5382+
| // ZVAL_UNDEF(EX_VAR(n))
5383+
| str wzr, [RX, #(n + offsetof(zval,u1.type_info))]
5384+
}
5385+
5386+
if (call_num_args <= func->op_array.num_args) {
5387+
if (!trace || (trace->op == ZEND_JIT_TRACE_END
5388+
&& trace->stop == ZEND_JIT_TRACE_STOP_INTERPRETER)) {
5389+
uint32_t num_args;
5390+
5391+
if ((func->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0) {
5392+
if (trace) {
5393+
num_args = 0;
5394+
} else if (call_info) {
5395+
num_args = skip_valid_arguments(op_array, ssa, call_info);
5396+
} else {
5397+
num_args = call_num_args;
5398+
}
5399+
} else {
5400+
num_args = call_num_args;
5401+
}
5402+
if (zend_accel_in_shm(func->op_array.opcodes)) {
5403+
| LOAD_IP_ADDR (func->op_array.opcodes + num_args)
5404+
} else {
5405+
| ldr REG0, EX->func
5406+
if (GCC_GLOBAL_REGS) {
5407+
| ldr IP, [REG0, #offsetof(zend_op_array, opcodes)]
5408+
if (num_args) {
5409+
| add IP, IP, #(num_args * sizeof(zend_op))
5410+
}
5411+
} else {
5412+
| ldr REG1, [REG0, #offsetof(zend_op_array, opcodes)]
5413+
if (num_args) {
5414+
| add REG1, REG1, #(num_args * sizeof(zend_op))
5415+
}
5416+
| str REG1, EX->opline
5417+
}
5418+
}
5419+
5420+
if (!trace && op_array == &func->op_array) {
5421+
/* recursive call */
5422+
if (ZEND_OBSERVER_ENABLED) {
5423+
| SAVE_IP
5424+
| mov CARG1, FP
5425+
| EXT_CALL zend_observer_fcall_begin, REG0
5426+
}
5427+
#ifdef CONTEXT_THREADED_JIT
5428+
| brk #0 // TODO
5429+
#else
5430+
| b =>num_args
5431+
#endif
5432+
return 1;
5433+
}
5434+
}
5435+
} else {
5436+
if (!trace || (trace->op == ZEND_JIT_TRACE_END
5437+
&& trace->stop == ZEND_JIT_TRACE_STOP_INTERPRETER)) {
5438+
if (func && zend_accel_in_shm(func->op_array.opcodes)) {
5439+
| LOAD_IP_ADDR (func->op_array.opcodes)
5440+
} else if (GCC_GLOBAL_REGS) {
5441+
| ldr IP, [REG0, #offsetof(zend_op_array, opcodes)]
5442+
} else {
5443+
| ldr CARG1, [REG0, #offsetof(zend_op_array, opcodes)]
5444+
| str CARG1, EX->opline
5445+
}
5446+
}
5447+
if (!GCC_GLOBAL_REGS) {
5448+
| mov CARG1, FP
5449+
}
5450+
| EXT_CALL zend_jit_copy_extra_args_helper, REG0
5451+
}
53495452
} else {
53505453
| // opline = op_array->opcodes
53515454
if (func && zend_accel_in_shm(func->op_array.opcodes)) {
5352-
| brk #0 // TODO
5455+
| LOAD_IP_ADDR (func->op_array.opcodes)
53535456
} else if (GCC_GLOBAL_REGS) {
53545457
| ldr IP, [REG0, #offsetof(zend_op_array, opcodes)]
53555458
} else {
@@ -5358,6 +5461,10 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
53585461
}
53595462
if (func) {
53605463
| brk #0 // TODO
5464+
| // num_args = EX_NUM_ARGS();
5465+
| ldr REG1w, [FP, #offsetof(zend_execute_data, This.u2.num_args)]
5466+
| // if (UNEXPECTED(num_args > first_extra_arg))
5467+
| cmp REG1w, #(func->op_array.num_args)
53615468
} else {
53625469
| // first_extra_arg = op_array->num_args;
53635470
| ldr REG2w, [REG0, #offsetof(zend_op_array, num_args)]
@@ -5387,7 +5494,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
53875494
|1:
53885495
| // if (EXPECTED((int)num_args < op_array->last_var)) {
53895496
if (func) {
5390-
| brk #0 // TODO
5497+
| movz REG2w, #(func->op_array.last_var)
53915498
} else {
53925499
| ldr REG2w, [REG0, #offsetof(zend_op_array, last_var)]
53935500
}

0 commit comments

Comments
 (0)