diff -r 317fd10cf5f0 src/buffer.c
--- a/src/buffer.c	Fri Apr 12 12:18:49 2013 +0200
+++ b/src/buffer.c	Fri Apr 12 22:08:52 2013 +0900
@@ -648,6 +648,9 @@
     buf_T	*buf;
 {
     free_buffer_stuff(buf, TRUE);
+#ifdef FEAT_EVAL
+    dict_unref(buf->b_vars);
+#endif
 #ifdef FEAT_LUA
     lua_buffer_free(buf);
 #endif
@@ -689,8 +692,8 @@
 #endif
     }
 #ifdef FEAT_EVAL
-    vars_clear(&buf->b_vars.dv_hashtab); /* free all internal variables */
-    hash_init(&buf->b_vars.dv_hashtab);
+    vars_clear(&buf->b_vars->dv_hashtab); /* free all internal variables */
+    hash_init(&buf->b_vars->dv_hashtab);
 #endif
 #ifdef FEAT_USR_CMDS
     uc_clear(&buf->b_ucmds);		/* clear local user commands */
@@ -1694,6 +1697,17 @@
 	    vim_free(ffname);
 	    return NULL;
 	}
+#ifdef FEAT_EVAL
+	/* init b: variables */
+	buf->b_vars = dict_alloc();
+	if (buf->b_vars == NULL)
+	{
+	    vim_free(ffname);
+	    vim_free(buf);
+	    return NULL;
+	}
+	init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
+#endif
     }
 
     if (ffname != NULL)
@@ -1778,10 +1792,6 @@
     buf->b_wininfo->wi_fpos.lnum = lnum;
     buf->b_wininfo->wi_win = curwin;
 
-#ifdef FEAT_EVAL
-    /* init b: variables */
-    init_var_dict(&buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
-#endif
 #ifdef FEAT_SYN_HL
     hash_init(&buf->b_s.b_keywtab);
     hash_init(&buf->b_s.b_keywtab_ic);
diff -r 317fd10cf5f0 src/eval.c
--- a/src/eval.c	Fri Apr 12 12:18:49 2013 +0200
+++ b/src/eval.c	Fri Apr 12 22:08:52 2013 +0900
@@ -2131,7 +2131,7 @@
 {
     char_u	numbuf[NUMBUFLEN];
 
-    list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:",
+    list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:",
 								 TRUE, first);
 
     sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
@@ -2146,7 +2146,7 @@
 list_win_vars(first)
     int *first;
 {
-    list_hashtable_vars(&curwin->w_vars.dv_hashtab,
+    list_hashtable_vars(&curwin->w_vars->dv_hashtab,
 						 (char_u *)"w:", TRUE, first);
 }
 
@@ -2158,7 +2158,7 @@
 list_tab_vars(first)
     int *first;
 {
-    list_hashtable_vars(&curtab->tp_vars.dv_hashtab,
+    list_hashtable_vars(&curtab->tp_vars->dv_hashtab,
 						 (char_u *)"t:", TRUE, first);
 }
 #endif
@@ -3948,7 +3948,7 @@
     }
 
     /* b: variables */
-    ht = &curbuf->b_vars.dv_hashtab;
+    ht = &curbuf->b_vars->dv_hashtab;
     if (bdone < ht->ht_used)
     {
 	if (bdone++ == 0)
@@ -3966,7 +3966,7 @@
     }
 
     /* w: variables */
-    ht = &curwin->w_vars.dv_hashtab;
+    ht = &curwin->w_vars->dv_hashtab;
     if (wdone < ht->ht_used)
     {
 	if (wdone++ == 0)
@@ -3980,7 +3980,7 @@
 
 #ifdef FEAT_WINDOWS
     /* t: variables */
-    ht = &curtab->tp_vars.dv_hashtab;
+    ht = &curtab->tp_vars->dv_hashtab;
     if (tdone < ht->ht_used)
     {
 	if (tdone++ == 0)
@@ -6787,16 +6787,16 @@
 
     /* buffer-local variables */
     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
-	set_ref_in_ht(&buf->b_vars.dv_hashtab, copyID);
+	set_ref_in_item(&buf->b_bufvar.di_tv, copyID);
 
     /* window-local variables */
     FOR_ALL_TAB_WINDOWS(tp, wp)
-	set_ref_in_ht(&wp->w_vars.dv_hashtab, copyID);
+	set_ref_in_item(&wp->w_winvar.di_tv, copyID);
 
 #ifdef FEAT_WINDOWS
     /* tabpage-local variables */
     for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
-	set_ref_in_ht(&tp->tp_vars.dv_hashtab, copyID);
+	set_ref_in_item(&tp->tp_winvar.di_tv, copyID);
 #endif
 
     /* global variables */
@@ -11156,7 +11156,7 @@
 		 * find_var_in_ht(). */
 		varname = (char_u *)"b:" + 2;
 	    /* look up the variable */
-	    v = find_var_in_ht(&curbuf->b_vars.dv_hashtab, varname, FALSE);
+	    v = find_var_in_ht(&curbuf->b_vars->dv_hashtab, varname, FALSE);
 	    if (v != NULL)
 		copy_tv(&v->di_tv, rettv);
 	}
@@ -11779,7 +11779,7 @@
     if (tp != NULL && varname != NULL)
     {
 	/* look up the variable */
-	v = find_var_in_ht(&tp->tp_vars.dv_hashtab, varname, FALSE);
+	v = find_var_in_ht(&tp->tp_vars->dv_hashtab, varname, FALSE);
 	if (v != NULL)
 	    copy_tv(&v->di_tv, rettv);
 	else if (argvars[2].v_type != VAR_UNKNOWN)
@@ -11935,7 +11935,7 @@
 		 * find_var_in_ht(). */
 		varname = (char_u *)"w:" + 2;
 	    /* look up the variable */
-	    v = find_var_in_ht(&win->w_vars.dv_hashtab, varname, FALSE);
+	    v = find_var_in_ht(&win->w_vars->dv_hashtab, varname, FALSE);
 	    if (v != NULL)
 		copy_tv(&v->di_tv, rettv);
 	}
@@ -20134,12 +20134,12 @@
 			       || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
 	return NULL;
     if (*name == 'b')				/* buffer variable */
-	return &curbuf->b_vars.dv_hashtab;
+	return &curbuf->b_vars->dv_hashtab;
     if (*name == 'w')				/* window variable */
-	return &curwin->w_vars.dv_hashtab;
+	return &curwin->w_vars->dv_hashtab;
 #ifdef FEAT_WINDOWS
     if (*name == 't')				/* tab page variable */
-	return &curtab->tp_vars.dv_hashtab;
+	return &curtab->tp_vars->dv_hashtab;
 #endif
     if (*name == 'v')				/* v: variable */
 	return &vimvarht;
diff -r 317fd10cf5f0 src/fileio.c
--- a/src/fileio.c	Fri Apr 12 12:18:49 2013 +0200
+++ b/src/fileio.c	Fri Apr 12 22:08:52 2013 +0900
@@ -8955,8 +8955,8 @@
 	    /* Hmm, original window disappeared.  Just use the first one. */
 	    curwin = firstwin;
 # ifdef FEAT_EVAL
-	vars_clear(&aucmd_win->w_vars.dv_hashtab);  /* free all w: variables */
-	hash_init(&aucmd_win->w_vars.dv_hashtab);   /* re-use the hashtab */
+	vars_clear(&aucmd_win->w_vars->dv_hashtab);  /* free all w: variables */
+	hash_init(&aucmd_win->w_vars->dv_hashtab);   /* re-use the hashtab */
 # endif
 #else
 	curwin = aco->save_curwin;
diff -r 317fd10cf5f0 src/structs.h
--- a/src/structs.h	Fri Apr 12 12:18:49 2013 +0200
+++ b/src/structs.h	Fri Apr 12 22:08:52 2013 +0900
@@ -1611,7 +1611,7 @@
 
 #ifdef FEAT_EVAL
     dictitem_T	b_bufvar;	/* variable for "b:" Dictionary */
-    dict_T	b_vars;		/* internal variables, local to buffer */
+    dict_T	*b_vars;	/* internal variables, local to buffer */
 #endif
 
 #if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
@@ -1757,7 +1757,7 @@
     frame_T	    *(tp_snapshot[SNAP_COUNT]);  /* window layout snapshots */
 #ifdef FEAT_EVAL
     dictitem_T	    tp_winvar;	    /* variable for "t:" Dictionary */
-    dict_T	    tp_vars;	    /* internal variables, local to tab page */
+    dict_T	    *tp_vars;	    /* internal variables, local to tab page */
 #endif
 };
 
@@ -2080,7 +2080,7 @@
 
 #ifdef FEAT_EVAL
     dictitem_T	w_winvar;	/* variable for "w:" Dictionary */
-    dict_T	w_vars;		/* internal variables, local to window */
+    dict_T	*w_vars;	/* internal variables, local to window */
 #endif
 
 #if defined(FEAT_RIGHTLEFT) && defined(FEAT_FKMAP)
diff -r 317fd10cf5f0 src/window.c
--- a/src/window.c	Fri Apr 12 12:18:49 2013 +0200
+++ b/src/window.c	Fri Apr 12 22:08:52 2013 +0900
@@ -3457,25 +3457,35 @@
 alloc_tabpage()
 {
     tabpage_T	*tp;
+# ifdef FEAT_GUI
+    int		i;
+# endif
+
 
     tp = (tabpage_T *)alloc_clear((unsigned)sizeof(tabpage_T));
-    if (tp != NULL)
-    {
+    if (tp == NULL)
+	return NULL;
+
+# ifdef FEAT_EVAL
+    /* init t: variables */
+    tp->tp_vars = dict_alloc();
+    if (tp->tp_vars == NULL)
+    {
+	vim_free(tp);
+	return NULL;
+    }
+    init_var_dict(tp->tp_vars, &tp->tp_winvar, VAR_SCOPE);
+# endif
+
 # ifdef FEAT_GUI
-	int	i;
-
-	for (i = 0; i < 3; i++)
-	    tp->tp_prev_which_scrollbars[i] = -1;
+    for (i = 0; i < 3; i++)
+	tp->tp_prev_which_scrollbars[i] = -1;
 # endif
 # ifdef FEAT_DIFF
-	tp->tp_diff_invalid = TRUE;
+    tp->tp_diff_invalid = TRUE;
 # endif
-#ifdef FEAT_EVAL
-	/* init t: variables */
-	init_var_dict(&tp->tp_vars, &tp->tp_winvar, VAR_SCOPE);
-#endif
-	tp->tp_ch_used = p_ch;
-    }
+    tp->tp_ch_used = p_ch;
+
     return tp;
 }
 
@@ -3491,7 +3501,9 @@
     for (idx = 0; idx < SNAP_COUNT; ++idx)
 	clear_snapshot(tp, idx);
 #ifdef FEAT_EVAL
-    vars_clear(&tp->tp_vars.dv_hashtab);	/* free all t: variables */
+    vars_clear(&tp->tp_vars->dv_hashtab);	/* free all t: variables */
+    hash_init(&tp->tp_vars->dv_hashtab);
+    dict_unref(tp->tp_vars);
 #endif
     vim_free(tp);
 }
@@ -4363,71 +4375,79 @@
      * allocate window structure and linesizes arrays
      */
     new_wp = (win_T *)alloc_clear((unsigned)sizeof(win_T));
-    if (new_wp != NULL && win_alloc_lines(new_wp) == FAIL)
+    if (new_wp == NULL)
+	return NULL;
+
+    if (win_alloc_lines(new_wp) == FAIL)
     {
 	vim_free(new_wp);
-	new_wp = NULL;
-    }
-
-    if (new_wp != NULL)
-    {
+	return NULL;
+    }
+
+#ifdef FEAT_EVAL
+    /* init w: variables */
+    new_wp->w_vars = dict_alloc();
+    if (new_wp->w_vars == NULL)
+    {
+	win_free_lsize(new_wp);
+	vim_free(new_wp);
+	return NULL;
+    }
+    init_var_dict(new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE);
+#endif
+
 #ifdef FEAT_AUTOCMD
-	/* Don't execute autocommands while the window is not properly
-	 * initialized yet.  gui_create_scrollbar() may trigger a FocusGained
-	 * event. */
-	block_autocmds();
-#endif
-	/*
-	 * link the window in the window list
-	 */
+    /* Don't execute autocommands while the window is not properly
+     * initialized yet.  gui_create_scrollbar() may trigger a FocusGained
+     * event. */
+    block_autocmds();
+#endif
+    /*
+     * link the window in the window list
+     */
 #ifdef FEAT_WINDOWS
-	if (!hidden)
-	    win_append(after, new_wp);
+    if (!hidden)
+	win_append(after, new_wp);
 #endif
 #ifdef FEAT_VERTSPLIT
-	new_wp->w_wincol = 0;
-	new_wp->w_width = Columns;
-#endif
-
-	/* position the display and the cursor at the top of the file. */
-	new_wp->w_topline = 1;
+    new_wp->w_wincol = 0;
+    new_wp->w_width = Columns;
+#endif
+
+    /* position the display and the cursor at the top of the file. */
+    new_wp->w_topline = 1;
 #ifdef FEAT_DIFF
-	new_wp->w_topfill = 0;
-#endif
-	new_wp->w_botline = 2;
-	new_wp->w_cursor.lnum = 1;
+    new_wp->w_topfill = 0;
+#endif
+    new_wp->w_botline = 2;
+    new_wp->w_cursor.lnum = 1;
 #ifdef FEAT_SCROLLBIND
-	new_wp->w_scbind_pos = 1;
-#endif
-
-	/* We won't calculate w_fraction until resizing the window */
-	new_wp->w_fraction = 0;
-	new_wp->w_prev_fraction_row = -1;
+    new_wp->w_scbind_pos = 1;
+#endif
+
+    /* We won't calculate w_fraction until resizing the window */
+    new_wp->w_fraction = 0;
+    new_wp->w_prev_fraction_row = -1;
 
 #ifdef FEAT_GUI
-	if (gui.in_use)
-	{
-	    gui_create_scrollbar(&new_wp->w_scrollbars[SBAR_LEFT],
-		    SBAR_LEFT, new_wp);
-	    gui_create_scrollbar(&new_wp->w_scrollbars[SBAR_RIGHT],
-		    SBAR_RIGHT, new_wp);
-	}
-#endif
-#ifdef FEAT_EVAL
-	/* init w: variables */
-	init_var_dict(&new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE);
+    if (gui.in_use)
+    {
+	gui_create_scrollbar(&new_wp->w_scrollbars[SBAR_LEFT],
+		SBAR_LEFT, new_wp);
+	gui_create_scrollbar(&new_wp->w_scrollbars[SBAR_RIGHT],
+		SBAR_RIGHT, new_wp);
+    }
 #endif
 #ifdef FEAT_FOLDING
-	foldInitWin(new_wp);
+    foldInitWin(new_wp);
 #endif
 #ifdef FEAT_AUTOCMD
-	unblock_autocmds();
+    unblock_autocmds();
 #endif
 #ifdef FEAT_SEARCH_EXTRA
-	new_wp->w_match_head = NULL;
-	new_wp->w_next_match_id = 4;
-#endif
-    }
+    new_wp->w_match_head = NULL;
+    new_wp->w_next_match_id = 4;
+#endif
     return new_wp;
 }
 
@@ -4488,7 +4508,9 @@
     clear_winopt(&wp->w_allbuf_opt);
 
 #ifdef FEAT_EVAL
-    vars_clear(&wp->w_vars.dv_hashtab);	    /* free all w: variables */
+    vars_clear(&wp->w_vars->dv_hashtab);	/* free all w: variables */
+    hash_init(&wp->w_vars->dv_hashtab);
+    dict_unref(wp->w_vars);
 #endif
 
     if (prevwin == wp)
