ZEND_VM_HANDLER(23, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, SPEC(OP_DATA=CONST|TMP|VAR|CV))
{
	USE_OPLINE
	zend_free_op free_op1;
	zval *object_ptr, *orig_object_ptr;
	zend_free_op free_op2, free_op_data;
	zval *value;
	zval *variable_ptr;
	zval *dim;

	SAVE_OPLINE();
	orig_object_ptr = object_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);

	if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
ZEND_VM_C_LABEL(try_assign_dim_array):
		value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R);
		SEPARATE_ARRAY(object_ptr);
		if (OP2_TYPE == IS_UNUSED) {
			if (OP_DATA_TYPE == IS_CV || OP_DATA_TYPE == IS_VAR) {
				ZVAL_DEREF(value);
			}
			variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), value);
			if (UNEXPECTED(variable_ptr == NULL)) {
				zend_cannot_add_element();
				ZEND_VM_C_GOTO(assign_dim_error);
			} else if (OP_DATA_TYPE == IS_CV) {
				if (Z_REFCOUNTED_P(value)) {
					Z_ADDREF_P(value);
				}
			} else if (OP_DATA_TYPE == IS_VAR) {
				if (value != free_op_data) {
					if (Z_REFCOUNTED_P(value)) {
						Z_ADDREF_P(value);
					}
					FREE_OP_DATA();
				}
			} else if (OP_DATA_TYPE == IS_CONST) {
				if (UNEXPECTED(Z_REFCOUNTED_P(value))) {
					Z_ADDREF_P(value);
				}
			}
		} else {
			dim = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
			if (OP2_TYPE == IS_CONST) {
				variable_ptr = zend_fetch_dimension_address_inner_W_CONST(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC);
			} else {
				variable_ptr = zend_fetch_dimension_address_inner_W(Z_ARRVAL_P(object_ptr), dim EXECUTE_DATA_CC);
			}
			if (UNEXPECTED(variable_ptr == NULL)) {
				ZEND_VM_C_GOTO(assign_dim_error);
			}
			value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE, EX_USES_STRICT_TYPES());
		}
		if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
			ZVAL_COPY(EX_VAR(opline->result.var), value);
		}
	} else {
		if (EXPECTED(Z_ISREF_P(object_ptr))) {
			object_ptr = Z_REFVAL_P(object_ptr);
			if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
				ZEND_VM_C_GOTO(try_assign_dim_array);
			}
		}
		if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
			dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
			value = GET_OP_DATA_ZVAL_PTR_DEREF(BP_VAR_R);

			if (OP2_TYPE == IS_CONST && Z_EXTRA_P(dim) == ZEND_EXTRA_VALUE) {
				dim++;
			}
			zend_assign_to_object_dim(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC);

			FREE_OP_DATA();
		} else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
			if (OP2_TYPE == IS_UNUSED) {
				zend_use_new_element_for_string();
				FREE_UNFETCHED_OP_DATA();
				UNDEF_RESULT();
			} else {
				dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
				value = GET_OP_DATA_ZVAL_PTR_DEREF(BP_VAR_R);
				zend_assign_to_string_offset(object_ptr, dim, value OPLINE_CC EXECUTE_DATA_CC);
				FREE_OP_DATA();
			}
		} else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
			if (Z_ISREF_P(orig_object_ptr)
			 && ZEND_REF_HAS_TYPE_SOURCES(Z_REF_P(orig_object_ptr))
			 && !zend_verify_ref_array_assignable(Z_REF_P(orig_object_ptr))) {
				dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
				FREE_UNFETCHED_OP_DATA();
				UNDEF_RESULT();
			} else {
				ZVAL_ARR(object_ptr, zend_new_array(8));
				ZEND_VM_C_GOTO(try_assign_dim_array);
			}
		} else {
			if (OP1_TYPE != IS_VAR || EXPECTED(!Z_ISERROR_P(object_ptr))) {
				zend_use_scalar_as_array();
			}
			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))) {
				ZVAL_NULL(EX_VAR(opline->result.var));
			}
		}
	}
	if (OP2_TYPE != IS_UNUSED) {
		FREE_OP2();
	}
	FREE_OP1_VAR_PTR();
	/* assign_dim has two opcodes! */
	ZEND_VM_NEXT_OPCODE_EX(1, 2);
}