@@ -635,7 +635,6 @@ static void* dasm_labels[zend_lb_MAX];
635635|| if (Z_LVAL_P(Z_ZV(addr)) == 0) {
636636| mov Rx(reg), xzr
637637|| } else {
638- | brk #0 // TODO: test
639638| LOAD_64BIT_VAL Rx(reg), Z_LVAL_P(Z_ZV(addr))
640639|| }
641640|| } else if (Z_MODE(addr) == IS_MEM_ZVAL) {
@@ -1001,7 +1000,7 @@ static void* dasm_labels[zend_lb_MAX];
10011000|| } else if (type == IS_ARRAY) {
10021001|| if ((var_info) & (MAY_BE_ARRAY_KEY_STRING|MAY_BE_ARRAY_OF_STRING|MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_REF)) {
10031002|| if (opline && ((var_info) & (MAY_BE_ARRAY_OF_ARRAY|MAY_BE_ARRAY_OF_OBJECT|MAY_BE_ARRAY_OF_RESOURCE|MAY_BE_ARRAY_OF_REF))) {
1004- | brk #0 // TODO
1003+ | SET_EX_OPLINE opline, tmp_reg
10051004|| }
10061005| EXT_CALL zend_array_destroy, tmp_reg
10071006|| } else {
@@ -3344,7 +3343,39 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
33443343 }
33453344
33463345 if (op2_info & MAY_BE_STRING) {
3347- | brk #0 // TODO
3346+ |3:
3347+ if (op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - (MAY_BE_LONG|MAY_BE_STRING))) {
3348+ | // if (EXPECTED(Z_TYPE_P(dim) == IS_STRING))
3349+ | brk #0 // TODO
3350+ | IF_NOT_ZVAL_TYPE op2_addr, IS_STRING, >3, TMP1w, TMP2
3351+ }
3352+ | // offset_key = Z_STR_P(dim);
3353+ | GET_ZVAL_LVAL ZREG_FCARG2x, op2_addr, TMP1
3354+ | // retval = zend_hash_find(ht, offset_key);
3355+ switch (type) {
3356+ case BP_JIT_IS:
3357+ | brk #0 // TODO
3358+ break;
3359+ case BP_VAR_R:
3360+ case BP_VAR_IS:
3361+ case BP_VAR_UNSET:
3362+ | brk #0 // TODO
3363+ break;
3364+ case BP_VAR_RW:
3365+ | brk #0 // TODO
3366+ break;
3367+ case BP_VAR_W:
3368+ if (opline->op2_type != IS_CONST) {
3369+ | brk #0 // TODO
3370+ | EXT_CALL zend_jit_symtable_lookup_w, REG0
3371+ } else {
3372+ | EXT_CALL zend_hash_lookup, REG0
3373+ }
3374+ | mov REG0, RETVALx
3375+ break;
3376+ default:
3377+ ZEND_UNREACHABLE();
3378+ }
33483379 }
33493380
33503381 if (type == BP_JIT_IS && (op2_info & (MAY_BE_LONG|MAY_BE_STRING))) {
@@ -3443,7 +3474,20 @@ static int zend_jit_simple_assign(dasm_State **Dst,
34433474 } else {
34443475 zend_jit_addr ref_addr;
34453476
3446- | brk #0
3477+ if (in_cold) {
3478+ | brk #0 // TODO
3479+ | IF_NOT_ZVAL_TYPE val_addr, IS_REFERENCE, >1, TMP1w, TMP2
3480+ } else {
3481+ | IF_ZVAL_TYPE val_addr, IS_REFERENCE, >1, TMP1w, TMP2
3482+ |.cold_code
3483+ |1:
3484+ }
3485+ | brk #0 // TODO
3486+ if (in_cold) {
3487+ |1:
3488+ } else {
3489+ |.code
3490+ }
34473491 }
34483492 }
34493493
@@ -3595,13 +3639,14 @@ static int zend_jit_assign_to_variable(dasm_State **Dst,
35953639 if (RC_MAY_BE_N(var_info) && (var_info & (MAY_BE_ARRAY|MAY_BE_OBJECT)) != 0) {
35963640 | bne >4
35973641 } else {
3598- | brk #0 // TODO
3642+ | bne >8
35993643 }
3600- | brk #0
36013644 | ZVAL_DTOR_FUNC var_info, opline, TMP1
36023645 if (in_cold || (RC_MAY_BE_N(var_info) && (var_info & (MAY_BE_ARRAY|MAY_BE_OBJECT)) != 0)) {
36033646 if (check_exception) {
3604- | brk #0 // TODO
3647+ | MEM_LOAD_CMP_ZTS ldr, xzr, executor_globals, exception, REG0, TMP1
3648+ | beq >8
3649+ | b ->exception_handler
36053650 } else {
36063651 | brk #0 // TODO
36073652 }
@@ -4380,7 +4425,30 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con
43804425 }
43814426 if (opline->opcode == ZEND_INIT_METHOD_CALL) {
43824427 | // Z_PTR(call->This) = obj;
4383- | brk #0 // TODO
4428+ | ldr REG1, T1
4429+ | str REG1, EX:RX->This.value.ptr
4430+ if (opline->op1_type == IS_UNUSED || use_this) {
4431+ | // call->call_info |= ZEND_CALL_HAS_THIS;
4432+ if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
4433+ | brk #0 // TODO
4434+ } else {
4435+ | brk #0 // TODO
4436+ }
4437+ } else {
4438+ if (opline->op1_type == IS_CV) {
4439+ | // GC_ADDREF(obj);
4440+ | GC_ADDREF REG1, TMP1w
4441+ }
4442+ | // call->call_info |= ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS;
4443+ if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
4444+ | brk #0 // TODO
4445+ } else {
4446+ | ldr TMP1w, EX:RX->This.u1.type_info
4447+ | LOAD_32BIT_VAL TMP2w, (ZEND_CALL_HAS_THIS | ZEND_CALL_RELEASE_THIS)
4448+ | orr TMP1w, TMP1w, TMP2w
4449+ | str TMP1w, EX:RX->This.u1.type_info
4450+ }
4451+ }
43844452 } else if (!is_closure) {
43854453 | // Z_CE(call->This) = called_scope;
43864454 | str xzr, EX:RX->This.value.ptr
@@ -4700,7 +4768,183 @@ static int zend_jit_init_method_call(dasm_State **Dst,
47004768 ZEND_ASSERT(opline->op2_type == IS_CONST);
47014769 ZEND_ASSERT(op1_info & MAY_BE_OBJECT);
47024770
4703- | brk #0 // TODO
4771+ function_name = RT_CONSTANT(opline, opline->op2);
4772+
4773+ if (info) {
4774+ call_info = info->callee_info;
4775+ while (call_info && call_info->caller_init_opline != opline) {
4776+ call_info = call_info->next_callee;
4777+ }
4778+ if (call_info && call_info->callee_func && !call_info->is_prototype) {
4779+ func = call_info->callee_func;
4780+ }
4781+ }
4782+
4783+ if (polymorphic_side_trace) {
4784+ /* function is passed in r0 from parent_trace */
4785+ } else {
4786+ if (opline->op1_type == IS_UNUSED || use_this) {
4787+ zend_jit_addr this_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, offsetof(zend_execute_data, This));
4788+
4789+ | brk #0 // TODO
4790+ | GET_ZVAL_PTR FCARG1x, this_addr, TMP1
4791+ } else {
4792+ if (op1_info & MAY_BE_REF) {
4793+ if (opline->op1_type == IS_CV) {
4794+ if (Z_REG(op1_addr) != ZREG_FCARG1x || Z_OFFSET(op1_addr) != 0) {
4795+ | LOAD_ZVAL_ADDR FCARG1x, op1_addr
4796+ }
4797+ | ZVAL_DEREF FCARG1x, op1_info, TMP1w
4798+ op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1x, 0);
4799+ } else {
4800+ /* Hack: Convert reference to regular value to simplify JIT code */
4801+ ZEND_ASSERT(Z_REG(op1_addr) == ZREG_FP);
4802+ | brk #0 // TODO
4803+ }
4804+ }
4805+ if (op1_info & ((MAY_BE_UNDEF|MAY_BE_ANY)- MAY_BE_OBJECT)) {
4806+ if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
4807+ int32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_TO_VM);
4808+ const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
4809+
4810+ if (!exit_addr) {
4811+ return 0;
4812+ }
4813+ | brk #0 // TODO
4814+ } else {
4815+ | IF_NOT_ZVAL_TYPE op1_addr, IS_OBJECT, >1, TMP1w, TMP2
4816+ |.cold_code
4817+ |1:
4818+ | brk #0 // TODO: currently not jump to cold code.
4819+ if (Z_REG(op1_addr) != ZREG_FCARG1x || Z_OFFSET(op1_addr) != 0) {
4820+ | LOAD_ZVAL_ADDR FCARG1x, op1_addr
4821+ }
4822+ | SET_EX_OPLINE opline, REG0
4823+ if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !use_this) {
4824+ | EXT_CALL zend_jit_invalid_method_call_tmp, REG0
4825+ } else {
4826+ | EXT_CALL zend_jit_invalid_method_call, REG0
4827+ }
4828+ | b ->exception_handler
4829+ |.code
4830+ }
4831+ }
4832+ | GET_ZVAL_PTR FCARG1x, op1_addr, TMP1
4833+ }
4834+
4835+ if (delayed_call_chain) {
4836+ if (!zend_jit_save_call_chain(Dst, delayed_call_level)) {
4837+ return 0;
4838+ }
4839+ }
4840+
4841+ | str FCARG1x, T1 // save
4842+
4843+ if (func) {
4844+ | // fbc = CACHED_PTR(opline->result.num + sizeof(void*));
4845+ | brk #0 // TODO
4846+ } else {
4847+ | // if (CACHED_PTR(opline->result.num) == obj->ce)) {
4848+ | ldr REG0, EX->run_time_cache
4849+ | LOAD_32BIT_VAL TMP1w, opline->result.num
4850+ | add TMP1, REG0, TMP1
4851+ | ldr REG2, [TMP1]
4852+ | ldr TMP1, [FCARG1x, #offsetof(zend_object, ce)]
4853+ | cmp REG2, TMP1
4854+ | bne >1
4855+ | brk #0 // TODO: currently jump to label 1.
4856+ | // fbc = CACHED_PTR(opline->result.num + sizeof(void*));
4857+ | LOAD_32BIT_VAL TMP1w, (opline->result.num + sizeof(void*))
4858+ | add TMP1, TMP1, REG0
4859+ | ldr REG0, [TMP1]
4860+ }
4861+
4862+ |.cold_code
4863+ |1:
4864+ | LOAD_ADDR FCARG2x, function_name
4865+ | mov CARG3, sp
4866+ | SET_EX_OPLINE opline, REG0
4867+ if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) && !use_this) {
4868+ | brk #0 // TODO
4869+ | EXT_CALL zend_jit_find_method_tmp_helper, REG0
4870+ } else {
4871+ | EXT_CALL zend_jit_find_method_helper, REG0
4872+ }
4873+ | mov REG0, RETVALx
4874+ | cbnz REG0, >2
4875+ | b ->exception_handler
4876+ |.code
4877+ |2:
4878+ }
4879+
4880+ if (!func
4881+ && trace
4882+ && trace->op == ZEND_JIT_TRACE_INIT_CALL
4883+ && trace->func
4884+ ) {
4885+ int32_t exit_point;
4886+ const void *exit_addr;
4887+
4888+ exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_METHOD_CALL);
4889+ exit_addr = zend_jit_trace_get_exit_addr(exit_point);
4890+ if (!exit_addr) {
4891+ return 0;
4892+ }
4893+
4894+ func = (zend_function*)trace->func;
4895+
4896+ if (func->type == ZEND_USER_FUNCTION &&
4897+ (!(func->common.fn_flags & ZEND_ACC_IMMUTABLE) ||
4898+ (func->common.fn_flags & ZEND_ACC_CLOSURE) ||
4899+ !func->common.function_name)) {
4900+ const zend_op *opcodes = func->op_array.opcodes;
4901+
4902+ | brk #0 // TODO
4903+ } else {
4904+ | brk #0 // TODO
4905+ }
4906+ }
4907+
4908+ if (!func) {
4909+ | // if (fbc->common.fn_flags & ZEND_ACC_STATIC) {
4910+ | ldr TMP1w, [REG0, #offsetof(zend_function, common.fn_flags)]
4911+ || ZEND_ASSERT(ZEND_ACC_STATIC <= MAX_IMM12);
4912+ | tst TMP1w, #ZEND_ACC_STATIC
4913+ | bne >1
4914+ |.cold_code
4915+ |1:
4916+ }
4917+
4918+ if (!func || (func->common.fn_flags & ZEND_ACC_STATIC) != 0) {
4919+ | brk #0 // TODO
4920+ }
4921+
4922+ if (!func) {
4923+ | brk #0 // TODO
4924+ | b >9
4925+ |.code
4926+ }
4927+
4928+ if (!func || (func->common.fn_flags & ZEND_ACC_STATIC) == 0) {
4929+ if (!zend_jit_push_call_frame(Dst, opline, NULL, func, 0, use_this, stack_check)) {
4930+ return 0;
4931+ }
4932+ }
4933+
4934+ if (!func) {
4935+ |9:
4936+ }
4937+ zend_jit_start_reuse_ip();
4938+
4939+ if (zend_jit_needs_call_chain(call_info, b, op_array, ssa, ssa_op, opline, trace)) {
4940+ if (!zend_jit_save_call_chain(Dst, call_level)) {
4941+ return 0;
4942+ }
4943+ } else {
4944+ delayed_call_chain = 1;
4945+ delayed_call_level = call_level;
4946+ }
4947+
47044948 return 1;
47054949}
47064950
@@ -5502,15 +5746,27 @@ static int zend_jit_leave_func(dasm_State **Dst,
55025746 return 0;
55035747 }
55045748 }
5505- | brk #0 // TODO: test
5749+ | // OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
5750+ | ldr FCARG1x, EX->func
5751+ | sub FCARG1x, FCARG1x, #sizeof(zend_object)
5752+ | OBJ_RELEASE ZREG_FCARG1x, >4, ZREG_TMP1, ZREG_TMP2
5753+ |4:
55065754 } else if (may_need_release_this) {
55075755 if (!left_frame) {
55085756 left_frame = 1;
55095757 if (!zend_jit_leave_frame(Dst)) {
55105758 return 0;
55115759 }
55125760 }
5513- | brk #0 // TODO: test
5761+ | // if (call_info & ZEND_CALL_RELEASE_THIS)
5762+ | LOAD_32BIT_VAL TMP1w, ZEND_CALL_RELEASE_THIS
5763+ | tst FCARG1w, TMP1w
5764+ | beq >4
5765+ | // zend_object *object = Z_OBJ(execute_data->This);
5766+ | ldr FCARG1x, EX->This.value.obj
5767+ | // OBJ_RELEASE(object);
5768+ | OBJ_RELEASE ZREG_FCARG1x, >4, ZREG_TMP1, ZREG_TMP2
5769+ |4:
55145770 // TODO: avoid EG(excption) check for $this->foo() calls
55155771 may_throw = 1;
55165772 }
@@ -5846,7 +6102,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
58466102 }
58476103
58486104 if (op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_ARRAY))) {
5849- | brk #7
6105+ | brk #0 // TODO
58506106 }
58516107
58526108#ifdef ZEND_JIT_USE_RC_INFERENCE
0 commit comments