@@ -3234,6 +3234,27 @@ static int zend_jit_type_guard(dasm_State **Dst, const zend_op *opline, uint32_t
32343234 return 1;
32353235}
32363236
3237+ static int zend_jit_packed_guard(dasm_State **Dst, const zend_op *opline, uint32_t var, uint32_t op_info)
3238+ {
3239+ int32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_PACKED_GUARD);
3240+ const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
3241+
3242+ if (!exit_addr) {
3243+ return 0;
3244+ }
3245+
3246+ | GET_ZVAL_LVAL ZREG_FCARG1a, ZEND_ADDR_MEM_ZVAL(ZREG_FP, var)
3247+ if (op_info & MAY_BE_ARRAY_PACKED) {
3248+ | test dword [FCARG1a + offsetof(zend_array, u.flags)], HASH_FLAG_PACKED
3249+ | jz &exit_addr
3250+ } else {
3251+ | test dword [FCARG1a + offsetof(zend_array, u.flags)], HASH_FLAG_PACKED
3252+ | jnz &exit_addr
3253+ }
3254+
3255+ return 1;
3256+ }
3257+
32373258static int zend_jit_trace_handler(dasm_State **Dst, const zend_op_array *op_array, const zend_op *opline, int may_throw, zend_jit_trace_rec *trace)
32383259{
32393260 zend_jit_op_array_trace_extension *jit_extension =
@@ -4953,12 +4974,27 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
49534974 | // if (EXPECTED(Z_TYPE_P(dim) == IS_LONG))
49544975 | IF_NOT_ZVAL_TYPE op2_addr, IS_LONG, >3
49554976 }
4977+ if (op1_info & MAY_BE_PACKED_GUARD) {
4978+ int32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_PACKED_GUARD);
4979+ const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
4980+
4981+ if (!exit_addr) {
4982+ return 0;
4983+ }
4984+ if (op1_info & MAY_BE_ARRAY_PACKED) {
4985+ | test dword [FCARG1a + offsetof(zend_array, u.flags)], HASH_FLAG_PACKED
4986+ | jz &exit_addr
4987+ } else {
4988+ | test dword [FCARG1a + offsetof(zend_array, u.flags)], HASH_FLAG_PACKED
4989+ | jnz &exit_addr
4990+ }
4991+ }
49564992 if (type == BP_VAR_W) {
49574993 | // hval = Z_LVAL_P(dim);
49584994 | GET_ZVAL_LVAL ZREG_FCARG2a, op2_addr
49594995 op2_loaded = 1;
49604996 }
4961- if (( op1_info & MAY_BE_ARRAY_KEY_LONG) && (op1_info & MAY_BE_ARRAY_PACKED) ) {
4997+ if (op1_info & MAY_BE_ARRAY_PACKED) {
49624998 if (Z_MODE(op2_addr) == IS_CONST_ZVAL) {
49634999 zend_long val = Z_LVAL_P(Z_ZV(op2_addr));
49645000 if (val >= 0 && val < HT_MAX_SIZE) {
@@ -5050,7 +5086,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
50505086 }
50515087 switch (type) {
50525088 case BP_JIT_IS:
5053- if (( op1_info & MAY_BE_ARRAY_KEY_LONG) && (op1_info & MAY_BE_ARRAY_HASH) ) {
5089+ if (op1_info & MAY_BE_ARRAY_HASH) {
50545090 |4:
50555091 if (!op2_loaded) {
50565092 | // hval = Z_LVAL_P(dim);
@@ -5076,9 +5112,9 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
50765112 case BP_VAR_IS:
50775113 case BP_VAR_UNSET:
50785114 if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) ||
5079- !( op1_info & MAY_BE_ARRAY_HASH) ||
5080- Z_MODE(op2_addr) != IS_CONST_ZVAL ||
5081- (Z_LVAL_P(Z_ZV(op2_addr)) >= 0 && Z_LVAL_P(Z_ZV(op2_addr)) < HT_MAX_SIZE)) {
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)) )) {
50825118 if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
50835119 | jmp &exit_addr
50845120 } else if (type == BP_VAR_IS && not_found_exit_addr) {
@@ -5087,7 +5123,7 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
50875123 | jmp >2 // NOT_FOUND
50885124 }
50895125 }
5090- if (( op1_info & MAY_BE_ARRAY_KEY_LONG) && (op1_info & MAY_BE_ARRAY_HASH) ) {
5126+ if (op1_info & MAY_BE_ARRAY_HASH) {
50915127 |4:
50925128 if (!op2_loaded) {
50935129 | // hval = Z_LVAL_P(dim);
@@ -5140,20 +5176,27 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
51405176 | jz >9
51415177 break;
51425178 case BP_VAR_W:
5143- |2:
5144- | //retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
5145- |.if X64
5146- | LOAD_ADDR_ZTS CARG3, executor_globals, uninitialized_zval
5147- |.else
5148- | sub r4, 12
5149- | PUSH_ADDR_ZTS executor_globals, uninitialized_zval, r0
5150- |.endif
5151- | EXT_CALL zend_hash_index_add_new, r0
5152- |.if not(X64)
5153- | add r4, 12
5154- |.endif
5155- if (op1_info & MAY_BE_ARRAY_KEY_LONG) {
5156- | jmp >8
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)))) {
5183+ |2:
5184+ | //retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
5185+ |.if X64
5186+ | LOAD_ADDR_ZTS CARG3, executor_globals, uninitialized_zval
5187+ |.else
5188+ | sub r4, 12
5189+ | PUSH_ADDR_ZTS executor_globals, uninitialized_zval, r0
5190+ |.endif
5191+ | EXT_CALL zend_hash_index_add_new, r0
5192+ |.if not(X64)
5193+ | add r4, 12
5194+ |.endif
5195+ if (op1_info & MAY_BE_ARRAY_HASH) {
5196+ | jmp >8
5197+ }
5198+ }
5199+ if (op1_info & MAY_BE_ARRAY_HASH) {
51575200 |4:
51585201 | EXT_CALL zend_jit_hash_index_lookup_w, r0
51595202 }
0 commit comments