@@ -4969,6 +4969,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
49694969
49704970 if (op2_info & MAY_BE_LONG) {
49714971 zend_bool op2_loaded = 0;
4972+ zend_bool packed_loaded = 0;
49724973
49734974 if (op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_LONG)) {
49744975 | // if (EXPECTED(Z_TYPE_P(dim) == IS_LONG))
@@ -4995,55 +4996,22 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
49954996 op2_loaded = 1;
49964997 }
49974998 if (op1_info & MAY_BE_ARRAY_PACKED) {
4999+ zend_long val = -1;
5000+
49985001 if (Z_MODE(op2_addr) == IS_CONST_ZVAL) {
4999- zend_long val = Z_LVAL_P(Z_ZV(op2_addr));
5002+ val = Z_LVAL_P(Z_ZV(op2_addr));
50005003 if (val >= 0 && val < HT_MAX_SIZE) {
5001- | // ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
5002- if (op1_info & MAY_BE_ARRAY_HASH) {
5003- | test dword [FCARG1a + offsetof(zend_array, u.flags)], HASH_FLAG_PACKED
5004- | jz >4 // HASH_FIND
5005- }
5006- | // if (EXPECTED((zend_ulong)(_h) < (zend_ulong)(_ht)->nNumUsed))
5007- |.if X64
5008- | movsxd r0, dword [FCARG1a + offsetof(zend_array, nNumUsed)]
5009- if (val == 0) {
5010- | test r0, r0
5011- } else {
5012- | cmp r0, val
5013- }
5014- |.else
5015- | cmp dword [FCARG1a + offsetof(zend_array, nNumUsed)], val
5016- |.endif
5017- if (type == BP_JIT_IS) {
5018- if (not_found_exit_addr) {
5019- | jbe ¬_found_exit_addr
5020- } else {
5021- | jbe >9 // NOT_FOUND
5022- }
5023- } else if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
5024- | jbe &exit_addr
5025- } else if (type == BP_VAR_IS && not_found_exit_addr) {
5026- | jbe ¬_found_exit_addr
5027- } else {
5028- | jbe >2 // NOT_FOUND
5029- }
5030- | // _ret = &_ht->arData[_h].val;
5031- | mov r0, aword [FCARG1a + offsetof(zend_array, arData)]
5032- if (val != 0) {
5033- | add r0, val * sizeof(Bucket)
5034- }
5035- if (type == BP_JIT_IS) {
5036- | jmp >5
5037- } else {
5038- | IF_NOT_Z_TYPE r0, IS_UNDEF, >8
5039- }
5004+ packed_loaded = 1;
50405005 }
50415006 } else {
50425007 if (!op2_loaded) {
50435008 | // hval = Z_LVAL_P(dim);
50445009 | GET_ZVAL_LVAL ZREG_FCARG2a, op2_addr
50455010 op2_loaded = 1;
50465011 }
5012+ packed_loaded = 1;
5013+ }
5014+ if (packed_loaded) {
50475015 | // ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
50485016 if (op1_info & MAY_BE_ARRAY_HASH) {
50495017 | test dword [FCARG1a + offsetof(zend_array, u.flags)], HASH_FLAG_PACKED
@@ -5052,9 +5020,19 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
50525020 | // if (EXPECTED((zend_ulong)(_h) < (zend_ulong)(_ht)->nNumUsed))
50535021 |.if X64
50545022 | movsxd r0, dword [FCARG1a + offsetof(zend_array, nNumUsed)]
5055- | cmp r0, FCARG2a
5023+ if (val == 0) {
5024+ | test r0, r0
5025+ } else if (val > 0 && !op2_loaded) {
5026+ | cmp r0, val
5027+ } else {
5028+ | cmp r0, FCARG2a
5029+ }
50565030 |.else
5057- | cmp dword [FCARG1a + offsetof(zend_array, nNumUsed)], FCARG2a
5031+ if (val >= 0 && !op2_loaded) {
5032+ | cmp dword [FCARG1a + offsetof(zend_array, nNumUsed)], val
5033+ } else {
5034+ | cmp dword [FCARG1a + offsetof(zend_array, nNumUsed)], FCARG2a
5035+ }
50585036 |.endif
50595037 if (type == BP_JIT_IS) {
50605038 if (not_found_exit_addr) {
@@ -5066,27 +5044,34 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
50665044 | jbe &exit_addr
50675045 } else if (type == BP_VAR_IS && not_found_exit_addr) {
50685046 | jbe ¬_found_exit_addr
5047+ } else if (type == BP_VAR_IS && found_exit_addr) {
5048+ | jbe >7 // NOT_FOUND
50695049 } else {
50705050 | jbe >2 // NOT_FOUND
50715051 }
50725052 | // _ret = &_ht->arData[_h].val;
5073- |.if X64
5074- | mov r0, FCARG2a
5075- | shl r0, 5
5076- |.else
5077- | imul r0, FCARG2a, sizeof(Bucket)
5078- |.endif
5079- | add r0, aword [FCARG1a + offsetof(zend_array, arData)]
5080- if (type == BP_JIT_IS) {
5081- | jmp >5
5053+ if (val >= 0) {
5054+ | mov r0, aword [FCARG1a + offsetof(zend_array, arData)]
5055+ if (val != 0) {
5056+ | add r0, val * sizeof(Bucket)
5057+ }
50825058 } else {
5083- | IF_NOT_Z_TYPE r0, IS_UNDEF, >8
5059+ |.if X64
5060+ | mov r0, FCARG2a
5061+ | shl r0, 5
5062+ |.else
5063+ | imul r0, FCARG2a, sizeof(Bucket)
5064+ |.endif
5065+ | add r0, aword [FCARG1a + offsetof(zend_array, arData)]
50845066 }
50855067 }
50865068 }
50875069 switch (type) {
50885070 case BP_JIT_IS:
50895071 if (op1_info & MAY_BE_ARRAY_HASH) {
5072+ if (packed_loaded) {
5073+ | jmp >5
5074+ }
50905075 |4:
50915076 if (!op2_loaded) {
50925077 | // hval = Z_LVAL_P(dim);
@@ -5102,6 +5087,10 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
51025087 if (op2_info & MAY_BE_STRING) {
51035088 | jmp >5
51045089 }
5090+ } else if (packed_loaded) {
5091+ if (op2_info & MAY_BE_STRING) {
5092+ | jmp >5
5093+ }
51055094 } else if (not_found_exit_addr) {
51065095 | jmp ¬_found_exit_addr
51075096 } else {
@@ -5111,14 +5100,26 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
51115100 case BP_VAR_R:
51125101 case BP_VAR_IS:
51135102 case BP_VAR_UNSET:
5114- if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) ||
5115- ((op1_info & MAY_BE_ARRAY_PACKED) &&
5116- (Z_MODE(op2_addr) != IS_CONST_ZVAL ||
5117- (Z_LVAL_P(Z_ZV(op2_addr)) >= 0 && Z_LVAL_P(Z_ZV(op2_addr)) < HT_MAX_SIZE)))) {
5103+ if (packed_loaded) {
5104+ if (op1_info & MAY_BE_ARRAY_HASH) {
5105+ | IF_NOT_Z_TYPE r0, IS_UNDEF, >8
5106+ } else if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
5107+ | IF_Z_TYPE r0, IS_UNDEF, &exit_addr
5108+ } else if (type == BP_VAR_IS && not_found_exit_addr) {
5109+ | IF_Z_TYPE r0, IS_UNDEF, ¬_found_exit_addr
5110+ } else if (type == BP_VAR_IS && found_exit_addr) {
5111+ | IF_Z_TYPE r0, IS_UNDEF, >7 // NOT_FOUND
5112+ } else {
5113+ | IF_Z_TYPE r0, IS_UNDEF, >2 // NOT_FOUND
5114+ }
5115+ }
5116+ if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (packed_loaded && (op1_info & MAY_BE_ARRAY_HASH))) {
51185117 if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
51195118 | jmp &exit_addr
51205119 } else if (type == BP_VAR_IS && not_found_exit_addr) {
51215120 | jmp ¬_found_exit_addr
5121+ } else if (type == BP_VAR_IS && found_exit_addr) {
5122+ | jmp >7 // NOT_FOUND
51225123 } else {
51235124 | jmp >2 // NOT_FOUND
51245125 }
@@ -5135,6 +5136,8 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
51355136 | jz &exit_addr
51365137 } else if (type == BP_VAR_IS && not_found_exit_addr) {
51375138 | jz ¬_found_exit_addr
5139+ } else if (type == BP_VAR_IS && found_exit_addr) {
5140+ | jz >7 // NOT_FOUND
51385141 } else {
51395142 | jz >2 // NOT_FOUND
51405143 }
@@ -5152,7 +5155,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
51525155 break;
51535156 case BP_VAR_IS:
51545157 case BP_VAR_UNSET:
5155- if (!not_found_exit_addr) {
5158+ if (!not_found_exit_addr && !found_exit_addr ) {
51565159 | // retval = &EG(uninitialized_zval);
51575160 | SET_ZVAL_TYPE_INFO res_addr, IS_NULL
51585161 | jmp >9
@@ -5164,6 +5167,9 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
51645167 |.code
51655168 break;
51665169 case BP_VAR_RW:
5170+ if (packed_loaded) {
5171+ | IF_NOT_Z_TYPE r0, IS_UNDEF, >8
5172+ }
51675173 |2:
51685174 |4:
51695175 if (!op2_loaded) {
@@ -5176,12 +5182,16 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
51765182 | jz >9
51775183 break;
51785184 case BP_VAR_W:
5179- if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) ||
5180- ((op1_info & MAY_BE_ARRAY_PACKED) &&
5181- (Z_MODE(op2_addr) != IS_CONST_ZVAL ||
5182- (Z_LVAL_P(Z_ZV(op2_addr)) >= 0 && Z_LVAL_P(Z_ZV(op2_addr)) < HT_MAX_SIZE))) ) {
5185+ if (packed_loaded) {
5186+ | IF_NOT_Z_TYPE r0, IS_UNDEF, >8
5187+ }
5188+ if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || packed_loaded ) {
51835189 |2:
51845190 | //retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
5191+ if (!op2_loaded) {
5192+ | // hval = Z_LVAL_P(dim);
5193+ | GET_ZVAL_LVAL ZREG_FCARG2a, op2_addr
5194+ }
51855195 |.if X64
51865196 | LOAD_ADDR_ZTS CARG3, executor_globals, uninitialized_zval
51875197 |.else
@@ -5198,6 +5208,10 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
51985208 }
51995209 if (op1_info & MAY_BE_ARRAY_HASH) {
52005210 |4:
5211+ if (!op2_loaded) {
5212+ | // hval = Z_LVAL_P(dim);
5213+ | GET_ZVAL_LVAL ZREG_FCARG2a, op2_addr
5214+ }
52015215 | EXT_CALL zend_jit_hash_index_lookup_w, r0
52025216 }
52035217 break;
@@ -5266,6 +5280,8 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
52665280 | jz &exit_addr
52675281 } else if (type == BP_VAR_IS && not_found_exit_addr) {
52685282 | jz ¬_found_exit_addr
5283+ } else if (type == BP_VAR_IS && found_exit_addr) {
5284+ | jz >7 // NOT_FOUND
52695285 } else {
52705286 | jz >2 // NOT_FOUND
52715287 }
@@ -5286,13 +5302,11 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
52865302 // zend_error(E_WARNING, "Undefined array key \"%s\"", ZSTR_VAL(offset_key));
52875303 | UNDEFINED_INDEX opline
52885304 | jmp >9
5289- } else {
5290- | jmp &exit_addr
52915305 }
52925306 break;
52935307 case BP_VAR_IS:
52945308 case BP_VAR_UNSET:
5295- if (!not_found_exit_addr) {
5309+ if (!not_found_exit_addr && !found_exit_addr ) {
52965310 | // retval = &EG(uninitialized_zval);
52975311 | SET_ZVAL_TYPE_INFO res_addr, IS_NULL
52985312 | jmp >9
@@ -10650,7 +10664,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
1065010664 }
1065110665 }
1065210666 | GET_ZVAL_LVAL ZREG_FCARG1a, op1_addr
10653- if (!zend_jit_fetch_dimension_address_inner(Dst, opline, (opline->opcode != ZEND_FETCH_DIM_IS) ? BP_VAR_R : BP_VAR_IS, op1_info, op2_info, NULL , not_found_exit_addr, exit_addr)) {
10667+ if (!zend_jit_fetch_dimension_address_inner(Dst, opline, (opline->opcode != ZEND_FETCH_DIM_IS) ? BP_VAR_R : BP_VAR_IS, op1_info, op2_info, res_exit_addr , not_found_exit_addr, exit_addr)) {
1065410668 return 0;
1065510669 }
1065610670 }
@@ -10795,6 +10809,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
1079510809 | IF_NOT_TYPE dl, type, &res_exit_addr
1079610810 }
1079710811 | // ZVAL_COPY
10812+ |7:
1079810813 | ZVAL_COPY_VALUE_V res_addr, -1, val_addr, res_info, ZREG_R0, ZREG_R1
1079910814 if (Z_MODE(res_addr) == IS_MEM_ZVAL) {
1080010815 if (type < IS_STRING) {
@@ -10921,7 +10936,10 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst,
1092110936 | EXT_CALL zend_jit_isset_dim_helper, r0
1092210937 | test r0, r0
1092310938 | jz >9
10924- | jmp >8
10939+ if (op1_info & MAY_BE_ARRAY) {
10940+ | jmp >8
10941+ |.code
10942+ }
1092510943 } else {
1092610944 if (op2_info & MAY_BE_UNDEF) {
1092710945 if (op2_info & MAY_BE_ANY) {
@@ -10931,11 +10949,10 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst,
1093110949 | EXT_CALL zend_jit_undefined_op_helper, r0
1093210950 |1:
1093310951 }
10934- | jmp >9
10935- }
10936-
10937- if (op1_info & MAY_BE_ARRAY) {
10938- |.code
10952+ if (op1_info & MAY_BE_ARRAY) {
10953+ | jmp >9
10954+ |.code
10955+ }
1093910956 }
1094010957 }
1094110958
@@ -10946,40 +10963,42 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst,
1094610963 }
1094710964#endif
1094810965
10949- |8:
10950- | FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline
10951- if (!op1_avoid_refcounting) {
10952- | FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline
10953- }
10954- if (may_throw) {
10955- if (!zend_jit_check_exception_undef_result(Dst, opline)) {
10956- return 0;
10966+ if (op1_info & (MAY_BE_ARRAY|MAY_BE_STRING|MAY_BE_OBJECT)) {
10967+ |8:
10968+ | FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline
10969+ if (!op1_avoid_refcounting) {
10970+ | FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline
1095710971 }
10958- }
10959- if (!(opline->extended_value & ZEND_ISEMPTY)) {
10960- if (exit_addr) {
10961- if (smart_branch_opcode == ZEND_JMPNZ) {
10962- | jmp &exit_addr
10963- } else {
10964- | jmp >8
10972+ if (may_throw) {
10973+ if (!zend_jit_check_exception_undef_result(Dst, opline)) {
10974+ return 0;
1096510975 }
10966- } else if (smart_branch_opcode) {
10967- if (smart_branch_opcode == ZEND_JMPZ) {
10968- | jmp =>target_label2
10969- } else if (smart_branch_opcode == ZEND_JMPNZ) {
10970- | jmp =>target_label
10971- } else if (smart_branch_opcode == ZEND_JMPZNZ) {
10972- | jmp =>target_label2
10976+ }
10977+ if (!(opline->extended_value & ZEND_ISEMPTY)) {
10978+ if (exit_addr) {
10979+ if (smart_branch_opcode == ZEND_JMPNZ) {
10980+ | jmp &exit_addr
10981+ } else {
10982+ | jmp >8
10983+ }
10984+ } else if (smart_branch_opcode) {
10985+ if (smart_branch_opcode == ZEND_JMPZ) {
10986+ | jmp =>target_label2
10987+ } else if (smart_branch_opcode == ZEND_JMPNZ) {
10988+ | jmp =>target_label
10989+ } else if (smart_branch_opcode == ZEND_JMPZNZ) {
10990+ | jmp =>target_label2
10991+ } else {
10992+ ZEND_UNREACHABLE();
10993+ }
1097310994 } else {
10974- ZEND_UNREACHABLE();
10995+ | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE
10996+ | jmp >8
1097510997 }
1097610998 } else {
10977- | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE
10978- | jmp >8
10999+ | //????
11000+ | int3
1097911001 }
10980- } else {
10981- | //????
10982- | int3
1098311002 }
1098411003
1098511004 |9: // not found
0 commit comments