@@ -1136,7 +1136,6 @@ static void* dasm_labels[zend_lb_MAX];
1136
1136
|.macro OBJ_RELEASE, reg, exit_label, tmp_reg1, tmp_reg2
1137
1137
| GC_DELREF Rx(reg), Rw(tmp_reg1)
1138
1138
| bne >1
1139
- | brk #0 // TODO
1140
1139
| // zend_objects_store_del(obj);
1141
1140
|| if (reg != ZREG_FCARG1x) {
1142
1141
| mov FCARG1x, Rx(reg)
@@ -4706,13 +4705,14 @@ static int zend_jit_init_fcall(dasm_State **Dst, const zend_op *opline, uint32_t
4706
4705
} else if (opline->opcode == ZEND_INIT_FCALL_BY_NAME) {
4707
4706
| brk #0 // TODO
4708
4707
} else if (opline->opcode == ZEND_INIT_NS_FCALL_BY_NAME) {
4709
- | brk #0 // TODO
4708
+ | LOAD_ADDR FCARG1x, zv;
4709
+ | EXT_CALL zend_jit_find_ns_func_helper, REG0
4710
4710
} else {
4711
4711
ZEND_UNREACHABLE();
4712
4712
}
4713
4713
| // CACHE_PTR(opline->result.num, fbc);
4714
4714
| ldr REG1, EX->run_time_cache
4715
- | // Get the return value of function zend_jit_find_func_helper
4715
+ | // Get the return value of function zend_jit_find_func_helper/zend_jit_find_ns_func_helper
4716
4716
| mov REG0, RETVALx
4717
4717
| str REG0, [REG1, #opline->result.num]
4718
4718
if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
@@ -5282,7 +5282,38 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
5282
5282
|8:
5283
5283
}
5284
5284
if (opline->opcode == ZEND_DO_FCALL_BY_NAME) {
5285
- | brk #0 // TODO
5285
+ if (!func) {
5286
+ if (trace) {
5287
+ uint32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_TO_VM);
5288
+
5289
+ exit_addr = zend_jit_trace_get_exit_addr(exit_point);
5290
+ if (!exit_addr) {
5291
+ return 0;
5292
+ }
5293
+ | brk #0 // TODO
5294
+ } else {
5295
+ || ZEND_ASSERT(ZEND_ACC_DEPRECATED <= MAX_IMM12);
5296
+ | ldr TMP1w, [REG0, #offsetof(zend_op_array, fn_flags)]
5297
+ | tst TMP1w, #ZEND_ACC_DEPRECATED
5298
+ | bne >1
5299
+ |.cold_code
5300
+ |1:
5301
+ | brk #0 // TODO
5302
+ if (!GCC_GLOBAL_REGS) {
5303
+ | mov FCARG1x, RX
5304
+ }
5305
+ | EXT_CALL zend_jit_deprecated_helper, REG0
5306
+ | and RETVALw, RETVALw, #0xff
5307
+ | cmp RETVALw, #0 // Result is 0 on exception
5308
+ | ldr REG0, EX:RX->func // reload
5309
+ | bne >1
5310
+ | b ->exception_handler
5311
+ |.code
5312
+ |1:
5313
+ }
5314
+ } else if (func->common.fn_flags & ZEND_ACC_DEPRECATED) {
5315
+ | brk #0 // TODO
5316
+ }
5286
5317
}
5287
5318
5288
5319
| // ZVAL_NULL(EX_VAR(opline->result.var));
@@ -5445,7 +5476,17 @@ static int zend_jit_send_val(dasm_State **Dst, const zend_op *opline, uint32_t o
5445
5476
}
5446
5477
| brk #0 // TODO
5447
5478
} else {
5448
- | brk #0 // TODO
5479
+ | ldr REG0, EX:RX->func
5480
+ | ldr TMP1w, [REG0, #offsetof(zend_function, quick_arg_flags)]
5481
+ | LOAD_32BIT_VAL TMP2w, mask
5482
+ | tst TMP1w, TMP2w
5483
+ | bne >1
5484
+ |.cold_code
5485
+ |1:
5486
+ | brk #0 // TODO
5487
+ | SET_EX_OPLINE opline, REG0
5488
+ | b ->throw_cannot_pass_by_ref
5489
+ |.code
5449
5490
}
5450
5491
}
5451
5492
@@ -5504,7 +5545,30 @@ static int zend_jit_send_var(dasm_State **Dst, const zend_op *opline, const zend
5504
5545
} else if (opline->opcode == ZEND_SEND_VAR_NO_REF_EX) {
5505
5546
| brk #0 // TODO
5506
5547
} else if (opline->opcode == ZEND_SEND_FUNC_ARG) {
5507
- | brk #0 // TODO
5548
+ if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE
5549
+ && JIT_G(current_frame)
5550
+ && JIT_G(current_frame)->call
5551
+ && JIT_G(current_frame)->call->func) {
5552
+ if (ARG_SHOULD_BE_SENT_BY_REF(JIT_G(current_frame)->call->func, arg_num)) {
5553
+ if (!zend_jit_send_ref(Dst, opline, op_array, op1_info, 0)) {
5554
+ return 0;
5555
+ }
5556
+ return 1;
5557
+ }
5558
+ } else {
5559
+ | ldr TMP1w, [RX, #offsetof(zend_execute_data, This.u1.type_info)]
5560
+ | LOAD_32BIT_VAL TMP2w, ZEND_CALL_SEND_ARG_BY_REF
5561
+ | tst TMP1w, TMP2w
5562
+ | bne >1
5563
+ |.cold_code
5564
+ |1:
5565
+ | brk #0 // TODO
5566
+ if (!zend_jit_send_ref(Dst, opline, op_array, op1_info, 1)) {
5567
+ return 0;
5568
+ }
5569
+ | b >7
5570
+ |.code
5571
+ }
5508
5572
}
5509
5573
5510
5574
if (op1_info & MAY_BE_UNDEF) {
@@ -5579,7 +5643,42 @@ static int zend_jit_check_func_arg(dasm_State **Dst, const zend_op *opline)
5579
5643
{
5580
5644
uint32_t arg_num = opline->op2.num;
5581
5645
5582
- | brk #0 // TODO
5646
+ if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE
5647
+ && JIT_G(current_frame)
5648
+ && JIT_G(current_frame)->call
5649
+ && JIT_G(current_frame)->call->func) {
5650
+ | brk #0 // TODO
5651
+ } else {
5652
+ // if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
5653
+ uint32_t mask = (ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF) << ((arg_num + 3) * 2);
5654
+
5655
+ if (!zend_jit_reuse_ip(Dst)) {
5656
+ return 0;
5657
+ }
5658
+
5659
+ | ldr REG0, EX:RX->func
5660
+ | ldr TMP1w, [REG0, #offsetof(zend_function, quick_arg_flags)]
5661
+ | LOAD_32BIT_VAL TMP2w, mask
5662
+ | tst TMP1w, TMP2w
5663
+ | bne >1
5664
+ |.cold_code
5665
+ |1:
5666
+ | brk #0 // TODO
5667
+ | // ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
5668
+ | ldr TMP1w, [RX, #offsetof(zend_execute_data, This.u1.type_info)]
5669
+ | LOAD_32BIT_VAL TMP2w, ZEND_CALL_SEND_ARG_BY_REF
5670
+ | orr TMP1w, TMP1w, TMP2w
5671
+ | str TMP1w, [RX, #offsetof(zend_execute_data, This.u1.type_info)]
5672
+ | b >1
5673
+ |.code
5674
+ | // ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
5675
+ | ldr TMP1w, [RX, #offsetof(zend_execute_data, This.u1.type_info)]
5676
+ | LOAD_32BIT_VAL TMP2w, ZEND_CALL_SEND_ARG_BY_REF
5677
+ | mvn TMP2w, TMP2w
5678
+ | and TMP1w, TMP1w, TMP2w
5679
+ | str TMP1w, [RX, #offsetof(zend_execute_data, This.u1.type_info)]
5680
+ |1:
5681
+ }
5583
5682
5584
5683
return 1;
5585
5684
}
@@ -6160,7 +6259,59 @@ static int zend_jit_verify_arg_type(dasm_State **Dst, const zend_op *opline, zen
6160
6259
uint32_t type_mask = ZEND_TYPE_PURE_MASK(arg_info->type) & MAY_BE_ANY;
6161
6260
zend_reg tmp_reg = (type_mask == 0 || is_power_of_two(type_mask)) ? ZREG_FCARG1x : ZREG_REG0;
6162
6261
6163
- | brk #0 // TODO
6262
+ if (ZEND_ARG_SEND_MODE(arg_info)) {
6263
+ | brk #0 // TODO
6264
+ }
6265
+
6266
+ if (type_mask != 0) {
6267
+ if (is_power_of_two(type_mask)) {
6268
+ uint32_t type_code = concrete_type(type_mask);
6269
+ || ZEND_ASSERT(type_code <= MAX_IMM12);
6270
+ | IF_NOT_ZVAL_TYPE res_addr, type_code, >1, TMP1w, TMP2
6271
+ } else {
6272
+ | brk #0 // TODO
6273
+ }
6274
+
6275
+ |.cold_code
6276
+ |1:
6277
+
6278
+ in_cold = 1;
6279
+ }
6280
+
6281
+ | brk #0 // TODO: currently in cold code
6282
+ if (Z_REG(res_addr) != ZREG_FCARG1x || Z_OFFSET(res_addr) != 0) {
6283
+ | brk #0 // TODO
6284
+ | LOAD_ZVAL_ADDR FCARG1x, res_addr
6285
+ }
6286
+ if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
6287
+ | brk #0 // TODO
6288
+ | SET_EX_OPLINE opline, REG0
6289
+ } else {
6290
+ | ADDR_STORE EX->opline, opline, REG0
6291
+ }
6292
+ | LOAD_ADDR FCARG2x, (ptrdiff_t)arg_info
6293
+ | EXT_CALL zend_jit_verify_arg_slow, REG0
6294
+ | mov REG0w, RETVALw
6295
+
6296
+ if (check_exception) {
6297
+ | brk #0 // TODO
6298
+ | and REG0w, REG0w, #0xff
6299
+ | tst REG0w, REG0w
6300
+ if (in_cold) {
6301
+ | bne >1
6302
+ | b ->exception_handler
6303
+ |.code
6304
+ |1:
6305
+ } else {
6306
+ | beq ->exception_handler
6307
+ }
6308
+ } else if (in_cold) {
6309
+ | brk #0 // TODO
6310
+ | b >1
6311
+ |.code
6312
+ |1:
6313
+ }
6314
+
6164
6315
return 1;
6165
6316
}
6166
6317
@@ -6169,7 +6320,51 @@ static int zend_jit_recv(dasm_State **Dst, const zend_op *opline, const zend_op_
6169
6320
uint32_t arg_num = opline->op1.num;
6170
6321
zend_arg_info *arg_info = NULL;
6171
6322
6172
- | brk #0 // TODO
6323
+ if (op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
6324
+ if (EXPECTED(arg_num <= op_array->num_args)) {
6325
+ arg_info = &op_array->arg_info[arg_num-1];
6326
+ } else if (UNEXPECTED(op_array->fn_flags & ZEND_ACC_VARIADIC)) {
6327
+ arg_info = &op_array->arg_info[op_array->num_args];
6328
+ }
6329
+ if (arg_info && !ZEND_TYPE_IS_SET(arg_info->type)) {
6330
+ arg_info = NULL;
6331
+ }
6332
+ }
6333
+
6334
+ if (arg_info || (opline+1)->opcode != ZEND_RECV) {
6335
+ | ldr TMP1w, EX->This.u2.num_args
6336
+ | LOAD_32BIT_VAL TMP2w, arg_num
6337
+ | cmp TMP1w, TMP2w
6338
+ if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
6339
+ int32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_TO_VM);
6340
+ const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
6341
+
6342
+ if (!exit_addr) {
6343
+ return 0;
6344
+ }
6345
+ | brk #0 // TODO
6346
+ } else {
6347
+ | blt >1
6348
+ |.cold_code
6349
+ |1:
6350
+ | brk #0 // TODO
6351
+ |.code
6352
+ }
6353
+ }
6354
+
6355
+ if (arg_info) {
6356
+ if (!zend_jit_verify_arg_type(Dst, opline, arg_info, 1)) {
6357
+ return 0;
6358
+ }
6359
+ }
6360
+
6361
+ if (JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE) {
6362
+ if ((opline+1)->opcode != ZEND_RECV && (opline+1)->opcode != ZEND_RECV_INIT) {
6363
+ | LOAD_IP_ADDR (opline + 1)
6364
+ zend_jit_set_last_valid_opline(opline + 1);
6365
+ }
6366
+ }
6367
+
6173
6368
return 1;
6174
6369
}
6175
6370
0 commit comments