@@ -4969,6 +4969,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
4969
4969
4970
4970
if (op2_info & MAY_BE_LONG) {
4971
4971
zend_bool op2_loaded = 0;
4972
+ zend_bool packed_loaded = 0;
4972
4973
4973
4974
if (op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_LONG)) {
4974
4975
| // 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
4995
4996
op2_loaded = 1;
4996
4997
}
4997
4998
if (op1_info & MAY_BE_ARRAY_PACKED) {
4999
+ zend_long val = -1;
5000
+
4998
5001
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));
5000
5003
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;
5040
5005
}
5041
5006
} else {
5042
5007
if (!op2_loaded) {
5043
5008
| // hval = Z_LVAL_P(dim);
5044
5009
| GET_ZVAL_LVAL ZREG_FCARG2a, op2_addr
5045
5010
op2_loaded = 1;
5046
5011
}
5012
+ packed_loaded = 1;
5013
+ }
5014
+ if (packed_loaded) {
5047
5015
| // ZEND_HASH_INDEX_FIND(ht, hval, retval, num_undef);
5048
5016
if (op1_info & MAY_BE_ARRAY_HASH) {
5049
5017
| 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
5052
5020
| // if (EXPECTED((zend_ulong)(_h) < (zend_ulong)(_ht)->nNumUsed))
5053
5021
|.if X64
5054
5022
| 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
+ }
5056
5030
|.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
+ }
5058
5036
|.endif
5059
5037
if (type == BP_JIT_IS) {
5060
5038
if (not_found_exit_addr) {
@@ -5066,27 +5044,34 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
5066
5044
| jbe &exit_addr
5067
5045
} else if (type == BP_VAR_IS && not_found_exit_addr) {
5068
5046
| jbe ¬_found_exit_addr
5047
+ } else if (type == BP_VAR_IS && found_exit_addr) {
5048
+ | jbe >7 // NOT_FOUND
5069
5049
} else {
5070
5050
| jbe >2 // NOT_FOUND
5071
5051
}
5072
5052
| // _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
+ }
5082
5058
} 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)]
5084
5066
}
5085
5067
}
5086
5068
}
5087
5069
switch (type) {
5088
5070
case BP_JIT_IS:
5089
5071
if (op1_info & MAY_BE_ARRAY_HASH) {
5072
+ if (packed_loaded) {
5073
+ | jmp >5
5074
+ }
5090
5075
|4:
5091
5076
if (!op2_loaded) {
5092
5077
| // hval = Z_LVAL_P(dim);
@@ -5102,6 +5087,10 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
5102
5087
if (op2_info & MAY_BE_STRING) {
5103
5088
| jmp >5
5104
5089
}
5090
+ } else if (packed_loaded) {
5091
+ if (op2_info & MAY_BE_STRING) {
5092
+ | jmp >5
5093
+ }
5105
5094
} else if (not_found_exit_addr) {
5106
5095
| jmp ¬_found_exit_addr
5107
5096
} else {
@@ -5111,14 +5100,26 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
5111
5100
case BP_VAR_R:
5112
5101
case BP_VAR_IS:
5113
5102
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))) {
5118
5117
if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
5119
5118
| jmp &exit_addr
5120
5119
} else if (type == BP_VAR_IS && not_found_exit_addr) {
5121
5120
| jmp ¬_found_exit_addr
5121
+ } else if (type == BP_VAR_IS && found_exit_addr) {
5122
+ | jmp >7 // NOT_FOUND
5122
5123
} else {
5123
5124
| jmp >2 // NOT_FOUND
5124
5125
}
@@ -5135,6 +5136,8 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
5135
5136
| jz &exit_addr
5136
5137
} else if (type == BP_VAR_IS && not_found_exit_addr) {
5137
5138
| jz ¬_found_exit_addr
5139
+ } else if (type == BP_VAR_IS && found_exit_addr) {
5140
+ | jz >7 // NOT_FOUND
5138
5141
} else {
5139
5142
| jz >2 // NOT_FOUND
5140
5143
}
@@ -5152,7 +5155,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
5152
5155
break;
5153
5156
case BP_VAR_IS:
5154
5157
case BP_VAR_UNSET:
5155
- if (!not_found_exit_addr) {
5158
+ if (!not_found_exit_addr && !found_exit_addr ) {
5156
5159
| // retval = &EG(uninitialized_zval);
5157
5160
| SET_ZVAL_TYPE_INFO res_addr, IS_NULL
5158
5161
| jmp >9
@@ -5164,6 +5167,9 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
5164
5167
|.code
5165
5168
break;
5166
5169
case BP_VAR_RW:
5170
+ if (packed_loaded) {
5171
+ | IF_NOT_Z_TYPE r0, IS_UNDEF, >8
5172
+ }
5167
5173
|2:
5168
5174
|4:
5169
5175
if (!op2_loaded) {
@@ -5176,12 +5182,16 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
5176
5182
| jz >9
5177
5183
break;
5178
5184
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 ) {
5183
5189
|2:
5184
5190
| //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
+ }
5185
5195
|.if X64
5186
5196
| LOAD_ADDR_ZTS CARG3, executor_globals, uninitialized_zval
5187
5197
|.else
@@ -5198,6 +5208,10 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
5198
5208
}
5199
5209
if (op1_info & MAY_BE_ARRAY_HASH) {
5200
5210
|4:
5211
+ if (!op2_loaded) {
5212
+ | // hval = Z_LVAL_P(dim);
5213
+ | GET_ZVAL_LVAL ZREG_FCARG2a, op2_addr
5214
+ }
5201
5215
| EXT_CALL zend_jit_hash_index_lookup_w, r0
5202
5216
}
5203
5217
break;
@@ -5266,6 +5280,8 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
5266
5280
| jz &exit_addr
5267
5281
} else if (type == BP_VAR_IS && not_found_exit_addr) {
5268
5282
| jz ¬_found_exit_addr
5283
+ } else if (type == BP_VAR_IS && found_exit_addr) {
5284
+ | jz >7 // NOT_FOUND
5269
5285
} else {
5270
5286
| jz >2 // NOT_FOUND
5271
5287
}
@@ -5286,13 +5302,11 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
5286
5302
// zend_error(E_WARNING, "Undefined array key \"%s\"", ZSTR_VAL(offset_key));
5287
5303
| UNDEFINED_INDEX opline
5288
5304
| jmp >9
5289
- } else {
5290
- | jmp &exit_addr
5291
5305
}
5292
5306
break;
5293
5307
case BP_VAR_IS:
5294
5308
case BP_VAR_UNSET:
5295
- if (!not_found_exit_addr) {
5309
+ if (!not_found_exit_addr && !found_exit_addr ) {
5296
5310
| // retval = &EG(uninitialized_zval);
5297
5311
| SET_ZVAL_TYPE_INFO res_addr, IS_NULL
5298
5312
| jmp >9
@@ -10650,7 +10664,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
10650
10664
}
10651
10665
}
10652
10666
| 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)) {
10654
10668
return 0;
10655
10669
}
10656
10670
}
@@ -10795,6 +10809,7 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
10795
10809
| IF_NOT_TYPE dl, type, &res_exit_addr
10796
10810
}
10797
10811
| // ZVAL_COPY
10812
+ |7:
10798
10813
| ZVAL_COPY_VALUE_V res_addr, -1, val_addr, res_info, ZREG_R0, ZREG_R1
10799
10814
if (Z_MODE(res_addr) == IS_MEM_ZVAL) {
10800
10815
if (type < IS_STRING) {
@@ -10921,7 +10936,10 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst,
10921
10936
| EXT_CALL zend_jit_isset_dim_helper, r0
10922
10937
| test r0, r0
10923
10938
| jz >9
10924
- | jmp >8
10939
+ if (op1_info & MAY_BE_ARRAY) {
10940
+ | jmp >8
10941
+ |.code
10942
+ }
10925
10943
} else {
10926
10944
if (op2_info & MAY_BE_UNDEF) {
10927
10945
if (op2_info & MAY_BE_ANY) {
@@ -10931,11 +10949,10 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst,
10931
10949
| EXT_CALL zend_jit_undefined_op_helper, r0
10932
10950
|1:
10933
10951
}
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
+ }
10939
10956
}
10940
10957
}
10941
10958
@@ -10946,40 +10963,42 @@ static int zend_jit_isset_isempty_dim(dasm_State **Dst,
10946
10963
}
10947
10964
#endif
10948
10965
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
10957
10971
}
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;
10965
10975
}
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
+ }
10973
10994
} else {
10974
- ZEND_UNREACHABLE();
10995
+ | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE
10996
+ | jmp >8
10975
10997
}
10976
10998
} else {
10977
- | SET_ZVAL_TYPE_INFO res_addr, IS_TRUE
10978
- | jmp >8
10999
+ | //????
11000
+ | int3
10979
11001
}
10980
- } else {
10981
- | //????
10982
- | int3
10983
11002
}
10984
11003
10985
11004
|9: // not found
0 commit comments