@@ -635,7 +635,6 @@ static void* dasm_labels[zend_lb_MAX];
635
635
|| if (Z_LVAL_P(Z_ZV(addr)) == 0) {
636
636
| mov Rx(reg), xzr
637
637
|| } else {
638
- | brk #0 // TODO: test
639
638
| LOAD_64BIT_VAL Rx(reg), Z_LVAL_P(Z_ZV(addr))
640
639
|| }
641
640
|| } else if (Z_MODE(addr) == IS_MEM_ZVAL) {
@@ -1001,7 +1000,7 @@ static void* dasm_labels[zend_lb_MAX];
1001
1000
|| } else if (type == IS_ARRAY) {
1002
1001
|| 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)) {
1003
1002
|| 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
1005
1004
|| }
1006
1005
| EXT_CALL zend_array_destroy, tmp_reg
1007
1006
|| } else {
@@ -3344,7 +3343,39 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
3344
3343
}
3345
3344
3346
3345
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
+ }
3348
3379
}
3349
3380
3350
3381
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,
3443
3474
} else {
3444
3475
zend_jit_addr ref_addr;
3445
3476
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
+ }
3447
3491
}
3448
3492
}
3449
3493
@@ -3595,13 +3639,14 @@ static int zend_jit_assign_to_variable(dasm_State **Dst,
3595
3639
if (RC_MAY_BE_N(var_info) && (var_info & (MAY_BE_ARRAY|MAY_BE_OBJECT)) != 0) {
3596
3640
| bne >4
3597
3641
} else {
3598
- | brk #0 // TODO
3642
+ | bne >8
3599
3643
}
3600
- | brk #0
3601
3644
| ZVAL_DTOR_FUNC var_info, opline, TMP1
3602
3645
if (in_cold || (RC_MAY_BE_N(var_info) && (var_info & (MAY_BE_ARRAY|MAY_BE_OBJECT)) != 0)) {
3603
3646
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
3605
3650
} else {
3606
3651
| brk #0 // TODO
3607
3652
}
@@ -4380,7 +4425,30 @@ static int zend_jit_push_call_frame(dasm_State **Dst, const zend_op *opline, con
4380
4425
}
4381
4426
if (opline->opcode == ZEND_INIT_METHOD_CALL) {
4382
4427
| // 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
+ }
4384
4452
} else if (!is_closure) {
4385
4453
| // Z_CE(call->This) = called_scope;
4386
4454
| str xzr, EX:RX->This.value.ptr
@@ -4700,7 +4768,183 @@ static int zend_jit_init_method_call(dasm_State **Dst,
4700
4768
ZEND_ASSERT(opline->op2_type == IS_CONST);
4701
4769
ZEND_ASSERT(op1_info & MAY_BE_OBJECT);
4702
4770
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
+
4704
4948
return 1;
4705
4949
}
4706
4950
@@ -5502,15 +5746,27 @@ static int zend_jit_leave_func(dasm_State **Dst,
5502
5746
return 0;
5503
5747
}
5504
5748
}
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:
5506
5754
} else if (may_need_release_this) {
5507
5755
if (!left_frame) {
5508
5756
left_frame = 1;
5509
5757
if (!zend_jit_leave_frame(Dst)) {
5510
5758
return 0;
5511
5759
}
5512
5760
}
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:
5514
5770
// TODO: avoid EG(excption) check for $this->foo() calls
5515
5771
may_throw = 1;
5516
5772
}
@@ -5846,7 +6102,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
5846
6102
}
5847
6103
5848
6104
if (op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_ARRAY))) {
5849
- | brk #7
6105
+ | brk #0 // TODO
5850
6106
}
5851
6107
5852
6108
#ifdef ZEND_JIT_USE_RC_INFERENCE
0 commit comments