@@ -12530,6 +12530,136 @@ static int zend_jit_isset_isempty_cv(dasm_State **Dst, const zend_op *opline, ui
12530
12530
return 1;
12531
12531
}
12532
12532
12533
+ static int zend_jit_fe_fetch(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_op *ssa_op, uint32_t op1_info, unsigned int target_label, zend_uchar exit_opcode, const void *exit_addr)
12534
+ {
12535
+ zend_jit_addr op1_addr = OP1_ADDR();
12536
+
12537
+ | // array = EX_VAR(opline->op1.var);
12538
+ | // fe_ht = Z_ARRVAL_P(array);
12539
+ | GET_ZVAL_PTR FCARG2a, op1_addr
12540
+ | // pos = Z_FE_POS_P(array);
12541
+ | mov FCARG1d, dword [FP + opline->op1.var + offsetof(zval, u2.fe_pos)]
12542
+ | // p = fe_ht->arData + pos;
12543
+ |.if X64
12544
+ | movsxd r0, FCARG1d
12545
+ | shl r0, 5
12546
+ |.else
12547
+ | imul r0, FCARG1a, sizeof(Bucket)
12548
+ |.endif
12549
+ | add r0, aword [FCARG2a + offsetof(zend_array, arData)]
12550
+ |1:
12551
+ | // if (UNEXPECTED(pos >= fe_ht->nNumUsed)) {
12552
+ | cmp dword [FCARG2a + offsetof(zend_array, nNumUsed)], FCARG1d
12553
+ | // ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
12554
+ | // ZEND_VM_CONTINUE();
12555
+ if (exit_addr) {
12556
+ if (exit_opcode == ZEND_JMP) {
12557
+ | jbe &exit_addr
12558
+ } else {
12559
+ | jbe >3
12560
+ }
12561
+ } else {
12562
+ | jbe =>target_label
12563
+ }
12564
+ | // pos++;
12565
+ | add FCARG1d, 1
12566
+ | // value_type = Z_TYPE_INFO_P(value);
12567
+ | // if (EXPECTED(value_type != IS_UNDEF)) {
12568
+ | IF_Z_TYPE r0, IS_UNDEF, >2
12569
+ if (!exit_addr || exit_opcode == ZEND_JMP) {
12570
+ | IF_NOT_Z_TYPE r0, IS_INDIRECT, >3
12571
+ } else {
12572
+ | IF_NOT_Z_TYPE r0, IS_INDIRECT, &exit_addr
12573
+ }
12574
+ | // value = Z_INDIRECT_P(value);
12575
+ | GET_Z_PTR FCARG2a, r0
12576
+ | // value_type = Z_TYPE_INFO_P(value);
12577
+ | // if (EXPECTED(value_type != IS_UNDEF)) {
12578
+ if (!exit_addr || exit_opcode == ZEND_JMP) {
12579
+ | IF_NOT_Z_TYPE FCARG2a, IS_UNDEF, >4
12580
+ } else {
12581
+ | IF_NOT_Z_TYPE r0, IS_UNDEF, &exit_addr
12582
+ }
12583
+ | GET_ZVAL_PTR FCARG2a, op1_addr // reload
12584
+ |2:
12585
+ | // p++;
12586
+ | add r0, sizeof(Bucket)
12587
+ | jmp <1
12588
+ |3:
12589
+
12590
+ if (!exit_addr || exit_opcode == ZEND_JMP) {
12591
+ zend_jit_addr val_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG2a, 0);
12592
+ zend_jit_addr var_addr = OP2_ADDR();
12593
+ uint32_t val_info;
12594
+
12595
+ | mov FCARG2a, r0
12596
+ |4:
12597
+ | // Z_FE_POS_P(array) = pos + 1;
12598
+ | mov dword [FP + opline->op1.var + offsetof(zval, u2.fe_pos)], FCARG1d
12599
+
12600
+ if (RETURN_VALUE_USED(opline)) {
12601
+ zend_jit_addr res_addr = RES_ADDR();
12602
+
12603
+ if ((op1_info & MAY_BE_ARRAY_KEY_LONG)
12604
+ && (op1_info & MAY_BE_ARRAY_KEY_STRING)) {
12605
+ | // if (!p->key) {
12606
+ | cmp aword [r0 + offsetof(Bucket, key)], 0
12607
+ | jz >2
12608
+ }
12609
+ if (op1_info & MAY_BE_ARRAY_KEY_STRING) {
12610
+ | // ZVAL_STR_COPY(EX_VAR(opline->result.var), p->key);
12611
+ | mov FCARG1a, aword [r0 + offsetof(Bucket, key)]
12612
+ | SET_ZVAL_PTR res_addr, FCARG1a
12613
+ | test dword [FCARG1a + offsetof(zend_refcounted, gc.u.type_info)], IS_STR_INTERNED
12614
+ | jz >1
12615
+ | SET_ZVAL_TYPE_INFO res_addr, IS_STRING
12616
+ | jmp >3
12617
+ |1:
12618
+ | GC_ADDREF FCARG1a
12619
+ | SET_ZVAL_TYPE_INFO res_addr, IS_STRING_EX
12620
+
12621
+ if (op1_info & MAY_BE_ARRAY_KEY_LONG) {
12622
+ | jmp >3
12623
+ |2:
12624
+ }
12625
+ }
12626
+ if (op1_info & MAY_BE_ARRAY_KEY_LONG) {
12627
+ | // ZVAL_LONG(EX_VAR(opline->result.var), p->h);
12628
+ | mov FCARG1a, aword [r0 + offsetof(Bucket, h)]
12629
+ | SET_ZVAL_LVAL res_addr, FCARG1a
12630
+ | SET_ZVAL_TYPE_INFO res_addr, IS_LONG
12631
+ }
12632
+ |3:
12633
+ }
12634
+
12635
+ val_info = ((op1_info & MAY_BE_ARRAY_OF_ANY) >> MAY_BE_ARRAY_SHIFT);
12636
+ if (val_info & MAY_BE_ARRAY) {
12637
+ val_info |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
12638
+ }
12639
+ if (op1_info & MAY_BE_ARRAY_OF_REF) {
12640
+ val_info |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY |
12641
+ MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
12642
+ } else if (val_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
12643
+ val_info |= MAY_BE_RC1 | MAY_BE_RCN;
12644
+ }
12645
+
12646
+ if (opline->op2_type == IS_CV) {
12647
+ | // zend_assign_to_variable(variable_ptr, value, IS_CV, EX_USES_STRICT_TYPES());
12648
+ if (!zend_jit_assign_to_variable(Dst, opline, var_addr, var_addr, OP2_INFO(), -1, IS_CV, opline->op2, val_addr, val_info, 0, 1)) {
12649
+ return 0;
12650
+ }
12651
+ } else {
12652
+ | // ZVAL_COPY(res, value);
12653
+ | ZVAL_COPY_VALUE var_addr, -1, val_addr, val_info, ZREG_R0, ZREG_FCARG1a
12654
+ if (val_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
12655
+ | TRY_ADDREF op1_info, ah, FCARG1a
12656
+ }
12657
+ }
12658
+ }
12659
+
12660
+ return 1;
12661
+ }
12662
+
12533
12663
static zend_bool zend_jit_noref_guard(dasm_State **Dst, const zend_op *opline, zend_jit_addr var_addr)
12534
12664
{
12535
12665
int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);
0 commit comments