patch 7.4.2273
Problem:    getwininfo() and getbufinfo() are inefficient.
Solution:   Do not make a copy of all window/buffer-local options.  Make it
            possible to get them with gettabwinvar() or getbufvar().
diff --git a/src/eval.c b/src/eval.c
index 350173a..a8835b1 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -8470,9 +8470,23 @@
 		  || switch_win(&oldcurwin, &oldtabpage, win, tp, TRUE) == OK)
 #endif
 	{
-	    if (*varname == '&')	/* window-local-option */
+	    if (*varname == '&')
 	    {
-		if (get_option_tv(&varname, rettv, 1) == OK)
+		if (varname[1] == NUL)
+		{
+		    /* get all window-local options in a dict */
+		    dict_T	*opts = get_winbuf_options(FALSE);
+
+		    if (opts != NULL)
+		    {
+			rettv->v_type = VAR_DICT;
+			rettv->vval.v_dict = opts;
+			++opts->dv_refcount;
+			done = TRUE;
+		    }
+		}
+		else if (get_option_tv(&varname, rettv, 1) == OK)
+		    /* window-local-option */
 		    done = TRUE;
 	    }
 	    else
diff --git a/src/evalfunc.c b/src/evalfunc.c
index 1a2ea86..7ccf524 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -3921,7 +3921,6 @@
 get_buffer_info(buf_T *buf)
 {
     dict_T	*dict;
-    dict_T	*opts;
     tabpage_T	*tp;
     win_T	*wp;
     list_T	*windows;
@@ -3945,11 +3944,6 @@
     /* Get a reference to buffer variables */
     dict_add_dict(dict, "variables", buf->b_vars);
 
-    /* Copy buffer options */
-    opts = get_winbuf_options(TRUE);
-    if (opts != NULL)
-	dict_add_dict(dict, "options", opts);
-
     /* List of windows displaying this buffer */
     windows = list_alloc();
     if (windows != NULL)
@@ -4156,9 +4150,23 @@
 	save_curbuf = curbuf;
 	curbuf = buf;
 
-	if (*varname == '&')	/* buffer-local-option */
+	if (*varname == '&')
 	{
-	    if (get_option_tv(&varname, rettv, TRUE) == OK)
+	    if (varname[1] == NUL)
+	    {
+		/* get all buffer-local options in a dict */
+		dict_T	*opts = get_winbuf_options(TRUE);
+
+		if (opts != NULL)
+		{
+		    rettv->v_type = VAR_DICT;
+		    rettv->vval.v_dict = opts;
+		    ++opts->dv_refcount;
+		    done = TRUE;
+		}
+	    }
+	    else if (get_option_tv(&varname, rettv, TRUE) == OK)
+		/* buffer-local-option */
 		done = TRUE;
 	}
 	else if (STRCMP(varname, "changedtick") == 0)
@@ -5112,7 +5120,6 @@
 get_win_info(win_T *wp, short tpnr, short winnr)
 {
     dict_T	*dict;
-    dict_T	*opts;
 
     dict = dict_alloc();
     if (dict == NULL)
@@ -5131,14 +5138,9 @@
 	    (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL), NULL);
 #endif
 
-    /* Make a reference to window variables */
+    /* Add a reference to window variables */
     dict_add_dict(dict, "variables", wp->w_vars);
 
-    /* Copy window options */
-    opts = get_winbuf_options(FALSE);
-    if (opts != NULL)
-	dict_add_dict(dict, "options", opts);
-
     return dict;
 }
 #endif
diff --git a/src/testdir/test_bufwintabinfo.vim b/src/testdir/test_bufwintabinfo.vim
index 1c88cf5..5c916e2 100644
--- a/src/testdir/test_bufwintabinfo.vim
+++ b/src/testdir/test_bufwintabinfo.vim
@@ -18,7 +18,6 @@
     let b:editor = 'vim'
     let l = getbufinfo('%')
     call assert_equal(bufnr('%'), l[0].bufnr)
-    call assert_equal(8, l[0].options.tabstop)
     call assert_equal('vim', l[0].variables.editor)
     call assert_notequal(-1, index(l[0].windows, bufwinid('%')))
 
@@ -49,9 +48,6 @@
     call assert_equal(winbufnr(2), winlist[1].bufnr)
     call assert_equal(winheight(2), winlist[1].height)
     call assert_equal(1, winlist[2].winnr)
-    if has('signs')
-      call assert_equal('auto', winlist[0].options.signcolumn)
-    endif
     call assert_equal(2, winlist[3].tabnr)
     call assert_equal('green', winlist[2].variables.signal)
     call assert_equal(winwidth(1), winlist[0].width)
@@ -83,3 +79,25 @@
     call assert_false(winlist[2].loclist)
     wincmd t | only
 endfunction
+
+function Test_get_buf_options()
+  let opts = getbufvar(bufnr('%'), '&')
+  call assert_equal(v:t_dict, type(opts))
+  call assert_equal(8, opts.tabstop)
+endfunc
+
+function Test_get_win_options()
+  let opts = getwinvar(1, '&')
+  call assert_equal(v:t_dict, type(opts))
+  call assert_equal(0, opts.linebreak)
+  if has('signs')
+    call assert_equal('auto', opts.signcolumn)
+  endif
+
+  let opts = gettabwinvar(1, 1, '&')
+  call assert_equal(v:t_dict, type(opts))
+  call assert_equal(0, opts.linebreak)
+  if has('signs')
+    call assert_equal('auto', opts.signcolumn)
+  endif
+endfunc
diff --git a/src/version.c b/src/version.c
index 8f435db..4a19097 100644
--- a/src/version.c
+++ b/src/version.c
@@ -764,6 +764,8 @@
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2273,
+/**/
     2272,
 /**/
     2271,