]> granicus.if.org Git - php/commitdiff
Optimize zend_binary_assign_op_dim_helper()
authorDmitry Stogov <dmitry@zend.com>
Wed, 13 Apr 2016 23:35:53 +0000 (02:35 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 13 Apr 2016 23:35:53 +0000 (02:35 +0300)
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index c276fb9f42ef582f66102cd21719d2b1b8f9b248..a23b843bc60e1a65f50892424e9db6c712486a72 100644 (file)
@@ -1669,6 +1669,16 @@ static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_
        return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_W);
 }
 
+static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW(HashTable *ht, const zval *dim)
+{
+       return zend_fetch_dimension_address_inner(ht, dim, IS_TMP_VAR, BP_VAR_RW);
+}
+
+static zend_never_inline zval* ZEND_FASTCALL zend_fetch_dimension_address_inner_RW_CONST(HashTable *ht, const zval *dim)
+{
+       return zend_fetch_dimension_address_inner(ht, dim, IS_CONST, BP_VAR_RW);
+}
+
 static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *container, zval *dim, int dim_type, int type)
 {
     zval *retval;
index 1382729278ae33f01a35d77f4e245f4136473c11..c1f3fad2edd7f921d949564f87529af88414b514 100644 (file)
@@ -766,7 +766,7 @@ ZEND_VM_HELPER(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMPVAR|UNU
 {
        USE_OPLINE
        zend_free_op free_op1, free_op2, free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -778,43 +778,87 @@ ZEND_VM_HELPER(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMPVAR|UNU
                HANDLE_EXCEPTION();
        }
 
-       dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
+       if (OP1_TYPE != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ZEND_VM_C_LABEL(assign_dim_op_array):
+               SEPARATE_ARRAY(container);
+ZEND_VM_C_LABEL(assign_dim_op_new_array):
+               if (OP2_TYPE == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               ZEND_VM_C_GOTO(assign_dim_op_ret_null);
+                       }
+               } else {
+                       dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
 
-       do {
-               if (OP1_TYPE == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (OP1_TYPE != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if (OP2_TYPE == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               ZEND_VM_C_GOTO(assign_dim_op_ret_null);
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, OP2_TYPE);
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (OP1_TYPE != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       ZEND_VM_C_GOTO(assign_dim_op_array);
+                               }
+                       } else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               ZEND_VM_C_GOTO(assign_dim_op_convert_to_array);
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (OP1_TYPE != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+ZEND_VM_C_LABEL(assign_dim_op_convert_to_array):
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       ZEND_VM_C_GOTO(assign_dim_op_new_array);
+                               }
+
+                               if (OP2_TYPE == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       ZEND_VM_C_GOTO(assign_dim_op_convert_to_array);
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+ZEND_VM_C_LABEL(assign_dim_op_ret_null):
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        FREE_OP2();
        FREE_OP(free_op_data1);
@@ -2339,7 +2383,7 @@ ZEND_VM_C_LABEL(assign_dim_convert_to_array):
                        if (OP1_TYPE != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       GET_OP2_ZVAL_PTR(BP_VAR_R);
+                       dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
 ZEND_VM_C_LABEL(assign_dim_error):
                        FREE_UNFETCHED_OP_DATA();
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
index 5420d4f4cd741e69af49192523141cbdcafe41f4..6128e6c4fc045d81e6acc0f9684242eacf5ff475 100644 (file)
@@ -16859,7 +16859,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
 {
        USE_OPLINE
        zend_free_op free_op1, free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -16871,43 +16871,87 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
                HANDLE_EXCEPTION();
        }
 
-       dim = EX_CONSTANT(opline->op2);
+       if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+assign_dim_op_array:
+               SEPARATE_ARRAY(container);
+assign_dim_op_new_array:
+               if (IS_CONST == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               goto assign_dim_op_ret_null;
+                       }
+               } else {
+                       dim = EX_CONSTANT(opline->op2);
 
-       do {
-               if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (IS_VAR != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if (IS_CONST == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               goto assign_dim_op_ret_null;
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST);
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (IS_VAR != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       goto assign_dim_op_array;
+                               }
+                       } else if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               goto assign_dim_op_convert_to_array;
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = EX_CONSTANT(opline->op2);
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (IS_VAR != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+assign_dim_op_convert_to_array:
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       goto assign_dim_op_new_array;
+                               }
+
+                               if (IS_CONST == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       goto assign_dim_op_convert_to_array;
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+assign_dim_op_ret_null:
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        FREE_OP(free_op_data1);
        if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
@@ -18386,7 +18430,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       EX_CONSTANT(opline->op2);
+                       dim = EX_CONSTANT(opline->op2);
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -18492,7 +18536,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       EX_CONSTANT(opline->op2);
+                       dim = EX_CONSTANT(opline->op2);
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -18598,7 +18642,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       EX_CONSTANT(opline->op2);
+                       dim = EX_CONSTANT(opline->op2);
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -18704,7 +18748,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       EX_CONSTANT(opline->op2);
+                       dim = EX_CONSTANT(opline->op2);
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -19927,7 +19971,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
 {
        USE_OPLINE
        zend_free_op free_op1, free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -19939,43 +19983,87 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
                HANDLE_EXCEPTION();
        }
 
-       dim = NULL;
+       if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+assign_dim_op_array:
+               SEPARATE_ARRAY(container);
+assign_dim_op_new_array:
+               if (IS_UNUSED == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               goto assign_dim_op_ret_null;
+                       }
+               } else {
+                       dim = NULL;
 
-       do {
-               if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (IS_VAR != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if (IS_UNUSED == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               goto assign_dim_op_ret_null;
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED);
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (IS_VAR != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       goto assign_dim_op_array;
+                               }
+                       } else if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               goto assign_dim_op_convert_to_array;
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = NULL;
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (IS_VAR != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+assign_dim_op_convert_to_array:
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       goto assign_dim_op_new_array;
+                               }
+
+                               if (IS_UNUSED == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       goto assign_dim_op_convert_to_array;
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+assign_dim_op_ret_null:
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        FREE_OP(free_op_data1);
        if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
@@ -20385,7 +20473,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       NULL;
+                       dim = NULL;
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -20491,7 +20579,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       NULL;
+                       dim = NULL;
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -20597,7 +20685,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       NULL;
+                       dim = NULL;
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -20703,7 +20791,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       NULL;
+                       dim = NULL;
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -21314,7 +21402,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
 {
        USE_OPLINE
        zend_free_op free_op1, free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -21326,43 +21414,87 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
                HANDLE_EXCEPTION();
        }
 
-       dim = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
+       if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+assign_dim_op_array:
+               SEPARATE_ARRAY(container);
+assign_dim_op_new_array:
+               if (IS_CV == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               goto assign_dim_op_ret_null;
+                       }
+               } else {
+                       dim = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
 
-       do {
-               if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (IS_VAR != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if (IS_CV == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               goto assign_dim_op_ret_null;
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV);
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (IS_VAR != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       goto assign_dim_op_array;
+                               }
+                       } else if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               goto assign_dim_op_convert_to_array;
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (IS_VAR != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+assign_dim_op_convert_to_array:
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       goto assign_dim_op_new_array;
+                               }
+
+                               if (IS_CV == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       goto assign_dim_op_convert_to_array;
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+assign_dim_op_ret_null:
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        FREE_OP(free_op_data1);
        if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);};
@@ -22841,7 +22973,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+                       dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -22947,7 +23079,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+                       dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -23053,7 +23185,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+                       dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -23159,7 +23291,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+                       dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -23906,7 +24038,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
 {
        USE_OPLINE
        zend_free_op free_op1, free_op2, free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -23918,43 +24050,87 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
                HANDLE_EXCEPTION();
        }
 
-       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+       if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+assign_dim_op_array:
+               SEPARATE_ARRAY(container);
+assign_dim_op_new_array:
+               if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               goto assign_dim_op_ret_null;
+                       }
+               } else {
+                       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 
-       do {
-               if (IS_VAR == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (IS_VAR != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               goto assign_dim_op_ret_null;
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, (IS_TMP_VAR|IS_VAR));
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (IS_VAR != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       goto assign_dim_op_array;
+                               }
+                       } else if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               goto assign_dim_op_convert_to_array;
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (IS_VAR != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+assign_dim_op_convert_to_array:
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       goto assign_dim_op_new_array;
+                               }
+
+                               if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       goto assign_dim_op_convert_to_array;
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+assign_dim_op_ret_null:
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        zval_ptr_dtor_nogc(free_op2);
        FREE_OP(free_op_data1);
@@ -25438,7 +25614,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+                       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -25544,7 +25720,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+                       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -25650,7 +25826,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+                       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -25756,7 +25932,7 @@ assign_dim_convert_to_array:
                        if (IS_VAR != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+                       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -26426,7 +26602,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
 {
        USE_OPLINE
        zend_free_op free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -26438,43 +26614,87 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
                HANDLE_EXCEPTION();
        }
 
-       dim = EX_CONSTANT(opline->op2);
+       if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+assign_dim_op_array:
+               SEPARATE_ARRAY(container);
+assign_dim_op_new_array:
+               if (IS_CONST == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               goto assign_dim_op_ret_null;
+                       }
+               } else {
+                       dim = EX_CONSTANT(opline->op2);
 
-       do {
-               if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (IS_UNUSED != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if (IS_CONST == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               goto assign_dim_op_ret_null;
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST);
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (IS_UNUSED != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       goto assign_dim_op_array;
+                               }
+                       } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               goto assign_dim_op_convert_to_array;
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = EX_CONSTANT(opline->op2);
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (IS_UNUSED != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+assign_dim_op_convert_to_array:
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       goto assign_dim_op_new_array;
+                               }
+
+                               if (IS_CONST == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       goto assign_dim_op_convert_to_array;
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+assign_dim_op_ret_null:
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        FREE_OP(free_op_data1);
 
@@ -29013,7 +29233,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
 {
        USE_OPLINE
        zend_free_op free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -29025,43 +29245,87 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
                HANDLE_EXCEPTION();
        }
 
-       dim = NULL;
+       if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+assign_dim_op_array:
+               SEPARATE_ARRAY(container);
+assign_dim_op_new_array:
+               if (IS_UNUSED == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               goto assign_dim_op_ret_null;
+                       }
+               } else {
+                       dim = NULL;
 
-       do {
-               if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (IS_UNUSED != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if (IS_UNUSED == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               goto assign_dim_op_ret_null;
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED);
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (IS_UNUSED != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       goto assign_dim_op_array;
+                               }
+                       } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               goto assign_dim_op_convert_to_array;
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = NULL;
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (IS_UNUSED != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+assign_dim_op_convert_to_array:
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       goto assign_dim_op_new_array;
+                               }
+
+                               if (IS_UNUSED == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       goto assign_dim_op_convert_to_array;
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+assign_dim_op_ret_null:
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        FREE_OP(free_op_data1);
 
@@ -29754,7 +30018,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
 {
        USE_OPLINE
        zend_free_op free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -29766,43 +30030,87 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
                HANDLE_EXCEPTION();
        }
 
-       dim = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
+       if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+assign_dim_op_array:
+               SEPARATE_ARRAY(container);
+assign_dim_op_new_array:
+               if (IS_CV == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               goto assign_dim_op_ret_null;
+                       }
+               } else {
+                       dim = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
 
-       do {
-               if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (IS_UNUSED != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if (IS_CV == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               goto assign_dim_op_ret_null;
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV);
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (IS_UNUSED != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       goto assign_dim_op_array;
+                               }
+                       } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               goto assign_dim_op_convert_to_array;
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (IS_UNUSED != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+assign_dim_op_convert_to_array:
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       goto assign_dim_op_new_array;
+                               }
+
+                               if (IS_CV == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       goto assign_dim_op_convert_to_array;
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+assign_dim_op_ret_null:
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        FREE_OP(free_op_data1);
 
@@ -32008,7 +32316,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
 {
        USE_OPLINE
        zend_free_op free_op2, free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -32020,43 +32328,87 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
                HANDLE_EXCEPTION();
        }
 
-       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+       if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+assign_dim_op_array:
+               SEPARATE_ARRAY(container);
+assign_dim_op_new_array:
+               if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               goto assign_dim_op_ret_null;
+                       }
+               } else {
+                       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 
-       do {
-               if (IS_UNUSED == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (IS_UNUSED != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               goto assign_dim_op_ret_null;
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, (IS_TMP_VAR|IS_VAR));
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (IS_UNUSED != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       goto assign_dim_op_array;
+                               }
+                       } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               goto assign_dim_op_convert_to_array;
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (IS_UNUSED != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+assign_dim_op_convert_to_array:
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       goto assign_dim_op_new_array;
+                               }
+
+                               if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       goto assign_dim_op_convert_to_array;
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+assign_dim_op_ret_null:
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        zval_ptr_dtor_nogc(free_op2);
        FREE_OP(free_op_data1);
@@ -36506,7 +36858,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
 {
        USE_OPLINE
        zend_free_op free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -36518,43 +36870,87 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
                HANDLE_EXCEPTION();
        }
 
-       dim = EX_CONSTANT(opline->op2);
+       if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+assign_dim_op_array:
+               SEPARATE_ARRAY(container);
+assign_dim_op_new_array:
+               if (IS_CONST == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               goto assign_dim_op_ret_null;
+                       }
+               } else {
+                       dim = EX_CONSTANT(opline->op2);
 
-       do {
-               if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (IS_CV != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if (IS_CONST == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               goto assign_dim_op_ret_null;
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST);
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (IS_CV != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       goto assign_dim_op_array;
+                               }
+                       } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               goto assign_dim_op_convert_to_array;
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = EX_CONSTANT(opline->op2);
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (IS_CV != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+assign_dim_op_convert_to_array:
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       goto assign_dim_op_new_array;
+                               }
+
+                               if (IS_CONST == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       goto assign_dim_op_convert_to_array;
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+assign_dim_op_ret_null:
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        FREE_OP(free_op_data1);
 
@@ -38285,7 +38681,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       EX_CONSTANT(opline->op2);
+                       dim = EX_CONSTANT(opline->op2);
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -38391,7 +38787,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       EX_CONSTANT(opline->op2);
+                       dim = EX_CONSTANT(opline->op2);
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -38497,7 +38893,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       EX_CONSTANT(opline->op2);
+                       dim = EX_CONSTANT(opline->op2);
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -38603,7 +38999,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       EX_CONSTANT(opline->op2);
+                       dim = EX_CONSTANT(opline->op2);
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -40696,7 +41092,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
 {
        USE_OPLINE
        zend_free_op free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -40708,43 +41104,87 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
                HANDLE_EXCEPTION();
        }
 
-       dim = NULL;
+       if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+assign_dim_op_array:
+               SEPARATE_ARRAY(container);
+assign_dim_op_new_array:
+               if (IS_UNUSED == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               goto assign_dim_op_ret_null;
+                       }
+               } else {
+                       dim = NULL;
 
-       do {
-               if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (IS_CV != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if (IS_UNUSED == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               goto assign_dim_op_ret_null;
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED);
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (IS_CV != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       goto assign_dim_op_array;
+                               }
+                       } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               goto assign_dim_op_convert_to_array;
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = NULL;
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (IS_CV != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+assign_dim_op_convert_to_array:
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       goto assign_dim_op_new_array;
+                               }
+
+                               if (IS_UNUSED == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       goto assign_dim_op_convert_to_array;
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+assign_dim_op_ret_null:
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        FREE_OP(free_op_data1);
 
@@ -41416,7 +41856,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       NULL;
+                       dim = NULL;
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -41522,7 +41962,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       NULL;
+                       dim = NULL;
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -41628,7 +42068,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       NULL;
+                       dim = NULL;
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -41734,7 +42174,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       NULL;
+                       dim = NULL;
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -43073,7 +43513,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
 {
        USE_OPLINE
        zend_free_op free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -43085,43 +43525,87 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
                HANDLE_EXCEPTION();
        }
 
-       dim = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
+       if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+assign_dim_op_array:
+               SEPARATE_ARRAY(container);
+assign_dim_op_new_array:
+               if (IS_CV == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               goto assign_dim_op_ret_null;
+                       }
+               } else {
+                       dim = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
 
-       do {
-               if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (IS_CV != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if (IS_CV == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               goto assign_dim_op_ret_null;
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV);
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (IS_CV != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       goto assign_dim_op_array;
+                               }
+                       } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               goto assign_dim_op_convert_to_array;
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (IS_CV != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+assign_dim_op_convert_to_array:
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       goto assign_dim_op_new_array;
+                               }
+
+                               if (IS_CV == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       goto assign_dim_op_convert_to_array;
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+assign_dim_op_ret_null:
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        FREE_OP(free_op_data1);
 
@@ -44713,7 +45197,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+                       dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -44819,7 +45303,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+                       dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -44925,7 +45409,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+                       dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -45031,7 +45515,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+                       dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -46668,7 +47152,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
 {
        USE_OPLINE
        zend_free_op free_op2, free_op_data1;
-       zval *var_ptr, rv;
+       zval *var_ptr;
        zval *value, *container, *dim;
 
        SAVE_OPLINE();
@@ -46680,43 +47164,87 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
                HANDLE_EXCEPTION();
        }
 
-       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+       if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+assign_dim_op_array:
+               SEPARATE_ARRAY(container);
+assign_dim_op_new_array:
+               if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
+                       var_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval));
+                       if (UNEXPECTED(!var_ptr)) {
+                               zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied");
+                               goto assign_dim_op_ret_null;
+                       }
+               } else {
+                       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 
-       do {
-               if (IS_CV == IS_UNUSED || UNEXPECTED(Z_TYPE_P(container) != IS_ARRAY)) {
-                       if (IS_CV != IS_UNUSED) {
-                               ZVAL_DEREF(container);
+                       if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+                               var_ptr = zend_fetch_dimension_address_inner_RW_CONST(Z_ARRVAL_P(container), dim);
+                       } else {
+                               var_ptr = zend_fetch_dimension_address_inner_RW(Z_ARRVAL_P(container), dim);
                        }
-                       if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
-                               if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(dim) == IS_UNDEF)) {
-                                       dim = GET_OP2_UNDEF_CV(dim, BP_VAR_R);
-                               }
-                               value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
-                               zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
-                               break;
+                       if (UNEXPECTED(!var_ptr)) {
+                               goto assign_dim_op_ret_null;
                        }
+                       ZVAL_DEREF(var_ptr);
+                       SEPARATE_ZVAL_NOREF(var_ptr);
                }
 
-               zend_fetch_dimension_address_RW(&rv, container, dim, (IS_TMP_VAR|IS_VAR));
                value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
 
-               if (UNEXPECTED(Z_ISERROR(rv))) {
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_NULL(EX_VAR(opline->result.var));
+               binary_op(var_ptr, var_ptr, value);
+
+               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                       ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               }
+       } else {
+               if (IS_CV != IS_UNUSED) {
+                       if (EXPECTED(Z_ISREF_P(container))) {
+                               container = Z_REFVAL_P(container);
+                               if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+                                       goto assign_dim_op_array;
+                               }
+                       } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(container) == IS_UNDEF)) {
+                               container = GET_OP1_UNDEF_CV(container, BP_VAR_RW);
+                               goto assign_dim_op_convert_to_array;
                        }
-               } else {
-                       ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT);
-                       var_ptr = Z_INDIRECT(rv);
-                       ZVAL_DEREF(var_ptr);
-                       SEPARATE_ZVAL_NOREF(var_ptr);
+               }
 
-                       binary_op(var_ptr, var_ptr, value);
+               dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 
-                       if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
-                               ZVAL_COPY(EX_VAR(opline->result.var), var_ptr);
+               if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
+                       zend_binary_assign_op_obj_dim(container, dim, value, UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, binary_op);
+               } else if (IS_CV != IS_UNUSED) {
+                       if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+                               if (UNEXPECTED(Z_STRLEN_P(container) == 0)) {
+                                       zval_ptr_dtor_nogc(container);
+assign_dim_op_convert_to_array:
+                                       ZVAL_NEW_ARR(container);
+                                       zend_hash_init(Z_ARRVAL_P(container), 8, NULL, ZVAL_PTR_DTOR, 0);
+                                       goto assign_dim_op_new_array;
+                               }
+
+                               if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
+                                       zend_throw_error(NULL, "[] operator not supported for strings");
+                               } else {
+                                       zend_check_string_offset(dim, BP_VAR_RW);
+                                       zend_wrong_string_offset();
+                               }
+                       } else {
+                               if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) {
+                                       goto assign_dim_op_convert_to_array;
+                               }
+                               if (UNEXPECTED(!Z_ISERROR_P(container))) {
+                                       zend_error(E_WARNING, "Cannot use a scalar value as an array");
+                               }
+assign_dim_op_ret_null:
+                               if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+                                       ZVAL_NULL(EX_VAR(opline->result.var));
+                               }
                        }
+                       value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1);
                }
-       } while (0);
+       }
 
        zval_ptr_dtor_nogc(free_op2);
        FREE_OP(free_op_data1);
@@ -48314,7 +48842,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+                       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -48420,7 +48948,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+                       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -48526,7 +49054,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+                       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 assign_dim_error:
                        zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var));
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
@@ -48632,7 +49160,7 @@ assign_dim_convert_to_array:
                        if (IS_CV != IS_VAR || UNEXPECTED(!Z_ISERROR_P(object_ptr))) {
                                zend_error(E_WARNING, "Cannot use a scalar value as an array");
                        }
-                       _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+                       dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
 assign_dim_error:
 
                        if (UNEXPECTED(RETURN_VALUE_USED(opline))) {