diff -r e11fcef66289 src/eval.c
--- a/src/eval.c	Wed Jun 25 22:55:38 2014 +0200
+++ b/src/eval.c	Thu Jun 26 20:12:20 2014 +0900
@@ -17328,6 +17328,7 @@
     _RTLENTRYF
 #endif
 	item_compare2 __ARGS((const void *s1, const void *s2));
+static int item_compare_stable __ARGS((const void *s1, const void *s2));
 
 static int	item_compare_ic;
 static int	item_compare_numeric;
@@ -17418,6 +17419,25 @@
     return res;
 }
 
+/* struct for stable sort */
+typedef struct sdata_S {
+    listitem_T	*li;
+    int	i;		/* original position in the list */
+} sdata_T;
+
+    static int
+item_compare_stable(s1, s2)
+    const void	*s1;
+    const void	*s2;
+{
+    int ret;
+    if(item_compare_func)
+        ret = item_compare2(&((sdata_T *)s1)->li, &((sdata_T *)s2)->li);
+    else
+        ret = item_compare(&((sdata_T *)s1)->li, &((sdata_T *)s2)->li);
+    return ret==0 ? ((sdata_T *)s1)->i - ((sdata_T *)s2)->i : ret;
+}
+
 /*
  * "sort({list})" function
  */
@@ -17429,7 +17449,6 @@
 {
     list_T	*l;
     listitem_T	*li;
-    listitem_T	**ptrs;
     long	len;
     long	i;
 
@@ -17496,29 +17515,32 @@
 	    }
 	}
 
-	/* Make an array with each entry pointing to an item in the List. */
-	ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
-	if (ptrs == NULL)
-	    return;
-
 	i = 0;
 	if (sort)
 	{
-	    /* sort(): ptrs will be the list to sort */
-	    for (li = l->lv_first; li != NULL; li = li->li_next)
-		ptrs[i++] = li;
+	    sdata_T *sdata;
+	    sdata = (sdata_T *)alloc((int)(len * sizeof(sdata_T)));
+	    if (sdata == NULL)
+		return;
+
+	    /* save the original position i along with the item pointer */
+	    for (li = l->lv_first; li != NULL; li = li->li_next) {
+		sdata[i].li = li;
+		sdata[i].i = i;
+		++i;
+	    }
 
 	    item_compare_func_err = FALSE;
 	    /* test the compare function */
 	    if (item_compare_func != NULL
-		    && item_compare2((void *)&ptrs[0], (void *)&ptrs[1])
+		    && item_compare2((void *)&sdata[0].li, (void *)&sdata[1].li)
 							 == ITEM_COMPARE_FAIL)
 		EMSG(_("E702: Sort compare function failed"));
 	    else
 	    {
 		/* Sort the array with item pointers. */
-		qsort((void *)ptrs, (size_t)len, sizeof(listitem_T *),
-		    item_compare_func == NULL ? item_compare : item_compare2);
+		qsort((void *)sdata, (size_t)len, sizeof(sdata_T),
+			item_compare_stable);
 
 		if (!item_compare_func_err)
 		{
@@ -17526,12 +17548,19 @@
 		    l->lv_first = l->lv_last = l->lv_idx_item = NULL;
 		    l->lv_len = 0;
 		    for (i = 0; i < len; ++i)
-			list_append(l, ptrs[i]);
-		}
-	    }
-	}
-	else
-	{
+			list_append(l, sdata[i].li);
+		}
+	    }
+	    vim_free(sdata);
+	}
+	else
+	{
+	    listitem_T	**ptrs;
+	    /* Make an array with each entry pointing to an item in the List. */
+	    ptrs = (listitem_T **)alloc((int)(len * sizeof(listitem_T *)));
+	    if (ptrs == NULL)
+		return;
+
 	    int	(*item_compare_func_ptr)__ARGS((const void *, const void *));
 
 	    /* f_uniq(): ptrs will be a stack of items to remove */
@@ -17567,9 +17596,9 @@
 		    l->lv_len--;
 		}
 	    }
-	}
-
-	vim_free(ptrs);
+	    vim_free(ptrs);
+	}
+
     }
 }
 
