File 1032-erts-Remove-deprecated-creator-pid-from-funs.patch of Package erlang

From aef9de493883b03eadf00aabda505563ef515057 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Mon, 22 May 2023 18:24:38 +0200
Subject: [PATCH 2/2] erts: Remove deprecated "creator pid" from funs

To stay backwards compatible for another release, erlang:fun_info/1
will return the pid of the `init` process.
---
 erts/emulator/beam/copy.c                     | 190 ++--
 erts/emulator/beam/emu/emu_load.c             |   5 +-
 erts/emulator/beam/erl_bif_info.c             |   2 +-
 erts/emulator/beam/erl_fun.c                  |   4 +-
 erts/emulator/beam/erl_fun.h                  |  10 +-
 erts/emulator/beam/erl_gc.h                   |   2 +-
 erts/emulator/beam/erl_process_dump.c         |   1 -
 erts/emulator/beam/erl_term.h                 |   2 +-
 erts/emulator/beam/external.c                 |  17 +-
 erts/emulator/beam/generators.tab             |   2 +-
 erts/emulator/beam/jit/asm_load.c             |   5 +-
 erts/emulator/test/erts_debug_SUITE.erl       |   2 +-
 erts/emulator/test/fun_SUITE.erl              |   8 +-
 .../emulator/test/trace_call_memory_SUITE.erl |   2 +-
 lib/stdlib/test/lists_SUITE.erl               | 845 +-----------------
 15 files changed, 141 insertions(+), 956 deletions(-)

diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c
index a22317f6c1..5a5ca58bcf 100644
--- a/erts/emulator/beam/copy.c
+++ b/erts/emulator/beam/copy.c
@@ -139,20 +139,24 @@ Uint size_object_x(Eterm obj, erts_literal_area_t *litopt)
 		    break;
 		case FUN_SUBTAG:
 		    {
-			Eterm* bptr = fun_val(obj);
-			ErlFunThing* funp = (ErlFunThing *) bptr;
-			unsigned eterms = 1 /* creator */ + funp->num_free;
-			unsigned sz = thing_arityval(hdr);
-			sum += 1 /* header */ + sz + eterms;
-			bptr += 1 /* header */ + sz;
-			while (eterms-- > 1) {
-			  obj = *bptr++;
-			  if (!IS_CONST(obj)) {
-			    ESTACK_PUSH(s, obj);
-			  }
-			}
-			obj = *bptr;
-			break;
+                        const ErlFunThing* funp = (ErlFunThing*)fun_val(obj);
+
+                        ASSERT(ERL_FUN_SIZE == (1 + thing_arityval(hdr)));
+                        sum += ERL_FUN_SIZE + funp->num_free;
+
+                        for (int i = 1; i < funp->num_free; i++) {
+                            obj = funp->env[i];
+                            if (!IS_CONST(obj)) {
+                                ESTACK_PUSH(s, obj);
+                            }
+                        }
+
+                        if (funp->num_free > 0) {
+                            obj = funp->env[0];
+                            break;
+                        }
+
+                        goto pop_next;
 		    }
 		case MAP_SUBTAG:
 		    switch (MAP_HEADER_TYPE(hdr)) {
@@ -389,17 +393,18 @@ Uint size_shared(Eterm obj)
 		goto pop_next;
 	    }
 	    case FUN_SUBTAG: {
-		ErlFunThing* funp = (ErlFunThing *) ptr;
-		unsigned eterms = 1 /* creator */ + funp->num_free;
-		unsigned sz = thing_arityval(hdr);
-		sum += 1 /* header */ + sz + eterms;
-		ptr += 1 /* header */ + sz;
-		while (eterms-- > 0) {
-		    obj = *ptr++;
-		    if (!IS_CONST(obj)) {
-			EQUEUE_PUT(s, obj);
-		    }
-		}
+                const ErlFunThing* funp = (ErlFunThing *) ptr;
+
+                ASSERT(ERL_FUN_SIZE == (1 + thing_arityval(hdr)));
+                sum += ERL_FUN_SIZE + funp->num_free;
+
+                for (int i = 0; i < funp->num_free; i++) {
+                    obj = funp->env[i];
+                    if (!IS_CONST(obj)) {
+                        EQUEUE_PUT(s, obj);
+                    }
+                }
+
 		goto pop_next;
 	    }
 	    case SUB_BINARY_SUBTAG: {
@@ -551,16 +556,14 @@ cleanup:
 		goto cleanup_next;
 	    }
 	    case FUN_SUBTAG: {
-		ErlFunThing* funp = (ErlFunThing *) ptr;
-		unsigned eterms = 1 /* creator */ + funp->num_free;
-		unsigned sz = thing_arityval(hdr);
-		ptr += 1 /* header */ + sz;
-		while (eterms-- > 0) {
-		    obj = *ptr++;
-		    if (!IS_CONST(obj)) {
-			EQUEUE_PUT_UNCHECKED(s, obj);
-		    }
-		}
+                const ErlFunThing *funp = (ErlFunThing *) ptr;
+
+                for (int i = 0; i < funp->num_free; i++) {
+                    obj = funp->env[i];
+                    if (!IS_CONST(obj)) {
+                        EQUEUE_PUT_UNCHECKED(s, obj);
+                    }
+                }
 		goto cleanup_next;
 	    }
             case MAP_SUBTAG:
@@ -865,24 +868,26 @@ Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap,
 		break;
 	    case FUN_SUBTAG:
 		{
-		    ErlFunThing* funp = (ErlFunThing *) objp;
+                    const ErlFunThing *src_fun = (const ErlFunThing *)objp;
+                    ErlFunThing *dst_fun = (ErlFunThing *)htop;
 
-		    i =  thing_arityval(hdr) + 2 + funp->num_free;
-		    tp = htop;
-		    while (i--)  {
-			*htop++ = *objp++;
-		    }
-		    funp = (ErlFunThing *) tp;
+                    *dst_fun = *src_fun;
 
-                    if (is_local_fun(funp)) {
-                        funp->next = off_heap->first;
-                        off_heap->first = (struct erl_off_heap_header*) funp;
-                        erts_refc_inc(&funp->entry.fun->refc, 2);
-                    } else {
-                        ASSERT(is_external_fun(funp) && funp->next == NULL);
+                    for (int i = 0; i < src_fun->num_free; i++) {
+                        dst_fun->env[i] = src_fun->env[i];
                     }
 
-		    *argp = make_fun(tp);
+                    ASSERT(&htop[ERL_FUN_SIZE] == &dst_fun->env[0]);
+                    htop = &dst_fun->env[dst_fun->num_free];
+                    *argp = make_fun(dst_fun);
+
+                    if (is_local_fun(dst_fun)) {
+                        dst_fun->next = off_heap->first;
+                        off_heap->first = (struct erl_off_heap_header*)dst_fun;
+                        erts_refc_inc(&dst_fun->entry.fun->refc, 2);
+                    } else {
+                        ASSERT(is_external_fun(dst_fun) && dst_fun->next == NULL);
+                    }
 		}
 		break;
 	    case EXTERNAL_PID_SUBTAG:
@@ -1117,7 +1122,6 @@ Uint copy_shared_calculate(Eterm obj, erts_shcopy_t *info)
 {
     Uint sum;
     Uint e;
-    unsigned sz;
     Eterm* ptr;
     Eterm *lit_purge_ptr = info->lit_purge_ptr;
     Uint lit_purge_sz = info->lit_purge_sz;
@@ -1259,17 +1263,18 @@ Uint copy_shared_calculate(Eterm obj, erts_shcopy_t *info)
 		goto pop_next;
 	    }
 	    case FUN_SUBTAG: {
-		ErlFunThing* funp = (ErlFunThing *) ptr;
-		unsigned eterms = 1 /* creator */ + funp->num_free;
-		sz = thing_arityval(hdr);
-		sum += 1 /* header */ + sz + eterms;
-		ptr += 1 /* header */ + sz;
-		while (eterms-- > 0) {
-		    obj = *ptr++;
-		    if (!IS_CONST(obj)) {
-			EQUEUE_PUT(s, obj);
-		    }
-		}
+                const ErlFunThing* funp = (ErlFunThing *) ptr;
+
+                ASSERT(ERL_FUN_SIZE == (1 + thing_arityval(hdr)));
+                sum += ERL_FUN_SIZE + funp->num_free;
+
+                for (int i = 0; i < funp->num_free; i++) {
+                    obj = funp->env[i];
+                    if (!IS_CONST(obj)) {
+                        EQUEUE_PUT(s, obj);
+                    }
+                }
+
 		goto pop_next;
 	    }
 	    case SUB_BINARY_SUBTAG: {
@@ -1596,32 +1601,36 @@ Uint copy_shared_perform_x(Eterm obj, Uint size, erts_shcopy_t *info,
 		goto cleanup_next;
 	    }
 	    case FUN_SUBTAG: {
-		ErlFunThing* funp = (ErlFunThing *) ptr;
-		unsigned eterms = 1 /* creator */ + funp->num_free;
-		sz = thing_arityval(hdr);
-		funp = (ErlFunThing *) hp;
-		*resp = make_fun(hp);
-		*hp++ = hdr;
-		ptr++;
-		while (sz-- > 0) {
-		    *hp++ = *ptr++;
-		}
-		while (eterms-- > 0) {
-		    obj = *ptr++;
-		    if (IS_CONST(obj)) {
-			*hp++ = obj;
-		    } else {
-			EQUEUE_PUT_UNCHECKED(s, obj);
-			*hp++ = HEAP_ELEM_TO_BE_FILLED;
-		    }
-		}
+                const ErlFunThing *src_fun = (const ErlFunThing *)ptr;
+                ErlFunThing *dst_fun = (ErlFunThing *)hp;
+
+                *dst_fun = *src_fun;
+
+                /* The header of the source fun may have been clobbered,
+                 * restore it. */
+                dst_fun->thing_word = hdr;
 
-                if (is_local_fun(funp)) {
-                    funp->next = off_heap->first;
-                    off_heap->first = (struct erl_off_heap_header*) funp;
-                    erts_refc_inc(&funp->entry.fun->refc, 2);
+                for (int i = 0; i < src_fun->num_free; i++) {
+                    obj = src_fun->env[i];
+
+                    if (!IS_CONST(obj)) {
+                        EQUEUE_PUT_UNCHECKED(s, obj);
+                        obj = HEAP_ELEM_TO_BE_FILLED;
+                    }
+
+                    dst_fun->env[i] = obj;
+                }
+
+                ASSERT(&hp[ERL_FUN_SIZE] == &dst_fun->env[0]);
+                hp = &dst_fun->env[dst_fun->num_free];
+                *resp = make_fun(dst_fun);
+
+                if (is_local_fun(dst_fun)) {
+                    dst_fun->next = off_heap->first;
+                    off_heap->first = (struct erl_off_heap_header*) dst_fun;
+                    erts_refc_inc(&dst_fun->entry.fun->refc, 2);
                 } else {
-                    ASSERT(is_external_fun(funp) && funp->next == NULL);
+                    ASSERT(is_external_fun(dst_fun) && dst_fun->next == NULL);
                 }
 
 		goto cleanup_next;
@@ -1827,10 +1836,11 @@ Uint copy_shared_perform_x(Eterm obj, Uint size, erts_shcopy_t *info,
 			    hscan++;
 			    break;
 			case FUN_SUBTAG: {
-			    ErlFunThing* funp = (ErlFunThing *) hscan;
-			    hscan += 1 + thing_arityval(*hscan);
-			    remaining = 1 + funp->num_free;
-			    break;
+                            const ErlFunThing* funp = (ErlFunThing *) hscan;
+                            ASSERT(ERL_FUN_SIZE == (1 + thing_arityval(*hscan)));
+                            hscan += ERL_FUN_SIZE;
+                            remaining = funp->num_free;
+                            break;
 			}
 			case MAP_SUBTAG:
                             switch (MAP_HEADER_TYPE(*hscan)) {
@@ -2170,7 +2180,7 @@ move_one_frag(Eterm** hpp, ErlHeapFragment* frag, ErlOffHeap* off_heap, int lite
                 break;
             case FUN_SUBTAG:
                 {
-                    ErlFunThing *funp = (ErlFunThing*)hdr;
+                    const ErlFunThing *funp = (ErlFunThing *) hdr;
 
                     if (is_local_fun(funp)) {
                         hdr->next = off_heap->first;
diff --git a/erts/emulator/beam/emu/emu_load.c b/erts/emulator/beam/emu/emu_load.c
index 8395a87076..9a078410d0 100644
--- a/erts/emulator/beam/emu/emu_load.c
+++ b/erts/emulator/beam/emu/emu_load.c
@@ -665,15 +665,14 @@ void beam_load_finalize_code(LoaderState* stp, struct erl_module_instance* inst_
                 literal = beamfile_get_literal(&stp->beam,
                                                stp->lambda_literals[i]);
                 funp = (ErlFunThing *)fun_val(literal);
-                ASSERT(funp->creator == am_external);
+                ASSERT(funp->external == 1);
 
                 funp->entry.fun = fun_entry;
 
                 funp->next = literal_area->off_heap;
                 literal_area->off_heap = (struct erl_off_heap_header *)funp;
 
-                ASSERT(erts_init_process_id != ERTS_INVALID_PID);
-                funp->creator = erts_init_process_id;
+                funp->external = 0;
 
                 erts_refc_inc(&fun_entry->refc, 2);
             }
diff --git a/erts/emulator/beam/erl_bif_info.c b/erts/emulator/beam/erl_bif_info.c
index 4ba368ec7c..127fb84330 100644
--- a/erts/emulator/beam/erl_bif_info.c
+++ b/erts/emulator/beam/erl_bif_info.c
@@ -3674,7 +3674,7 @@ fun_info_2(BIF_ALIST_2)
         hp = HAlloc(p, 3);
         break;
     case am_pid:
-        val = is_local_fun(funp) ? funp->creator : am_undefined;
+        val = is_local_fun(funp) ? erts_init_process_id : am_undefined;
         hp = HAlloc(p, 3);
         break;
     case am_module:
diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c
index ae6116ec19..cdac196472 100644
--- a/erts/emulator/beam/erl_fun.c
+++ b/erts/emulator/beam/erl_fun.c
@@ -308,7 +308,7 @@ ErlFunThing *erts_new_export_fun_thing(Eterm **hpp, Export *exp, int arity)
     funp->next = NULL;
     funp->entry.exp = exp;
     funp->num_free = 0;
-    funp->creator = am_external;
+    funp->external = 1;
     funp->arity = arity;
 
 #ifdef DEBUG
@@ -335,7 +335,7 @@ ErlFunThing *erts_new_local_fun_thing(Process *p, ErlFunEntry *fe,
     MSO(p).first = (struct erl_off_heap_header*) funp;
     funp->entry.fun = fe;
     funp->num_free = num_free;
-    funp->creator = p->common.id;
+    funp->external = 0;
     funp->arity = arity;
 
 #ifdef DEBUG
diff --git a/erts/emulator/beam/erl_fun.h b/erts/emulator/beam/erl_fun.h
index 4c9ff5cda1..05d27da442 100644
--- a/erts/emulator/beam/erl_fun.h
+++ b/erts/emulator/beam/erl_fun.h
@@ -59,10 +59,10 @@ typedef struct erl_fun_thing {
          * pointer to improve performance. */
         ErtsDispatchable *disp;
 
-        /* Pointer to function entry, valid iff `creator != am_external`.*/
+        /* Pointer to function entry, valid iff `external == 0`.*/
         ErlFunEntry *fun;
 
-        /* Pointer to export entry, valid iff `creator == am_external`.*/
+        /* Pointer to export entry, valid iff `external == 1`.*/
         Export *exp;
     } entry;
 
@@ -71,14 +71,14 @@ typedef struct erl_fun_thing {
 
     byte arity;             /* The _apparent_ arity of the fun. */
     byte num_free;          /* Number of free variables (in env). */
+    byte external;          /* Whether this is an external fun or not */
 
     /* -- The following may be compound Erlang terms ---------------------- */
-    Eterm creator;          /* Pid of creator process (contains node). */
     Eterm env[];            /* Environment (free variables). */
 } ErlFunThing;
 
-#define is_local_fun(FunThing) ((FunThing)->creator != am_external)
-#define is_external_fun(FunThing) ((FunThing)->creator == am_external)
+#define is_local_fun(FunThing) ((FunThing)->external == 0)
+#define is_external_fun(FunThing) ((FunThing)->external != 0)
 
 /* ERL_FUN_SIZE does _not_ include space for the environment which is a
  * C99-style flexible array */
diff --git a/erts/emulator/beam/erl_gc.h b/erts/emulator/beam/erl_gc.h
index c1760562c9..2b21f9e7be 100644
--- a/erts/emulator/beam/erl_gc.h
+++ b/erts/emulator/beam/erl_gc.h
@@ -82,7 +82,7 @@ ERTS_GLB_INLINE Eterm* move_boxed(Eterm *ERTS_RESTRICT ptr, Eterm hdr, Eterm **h
         if (is_flatmap_header(hdr)) nelts+=flatmap_get_size(ptr) + 1;
         else nelts += hashmap_bitcount(MAP_HEADER_VAL(hdr));
     break;
-    case FUN_SUBTAG: nelts+=((ErlFunThing*)(ptr))->num_free+1; break;
+    case FUN_SUBTAG: nelts+=((ErlFunThing*)(ptr))->num_free; break;
     }
     gval    = make_boxed(htop);
     *orig   = gval;
diff --git a/erts/emulator/beam/erl_term.h b/erts/emulator/beam/erl_term.h
index 03211a6acd..fa06ba5afe 100644
--- a/erts/emulator/beam/erl_term.h
+++ b/erts/emulator/beam/erl_term.h
@@ -387,7 +387,7 @@ _ET_DECLARE_CHECKED(Eterm*,binary_val,Wterm)
 #define HEADER_PROC_BIN	_make_header(PROC_BIN_SIZE-1,_TAG_HEADER_REFC_BIN)
 
 /* fun objects */
-#define HEADER_FUN              _make_header(ERL_FUN_SIZE-2,_TAG_HEADER_FUN)
+#define HEADER_FUN              _make_header(ERL_FUN_SIZE-1,_TAG_HEADER_FUN)
 #define is_fun_header(x)        ((x) == HEADER_FUN)
 #define make_fun(x)             make_boxed((Eterm*)(x))
 #define is_any_fun(x)           (is_boxed((x)) && is_fun_header(*boxed_val((x))))
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 081ce23e49..085d9ba603 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -3893,7 +3893,7 @@ enc_term_int(TTBEncodeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj, byte* ep,
                     ep = enc_atom(acmp, fe->module, ep, dflags);
                     ep = enc_term(acmp, make_small(fe->old_index), ep, dflags, off_heap);
                     ep = enc_term(acmp, make_small(fe->old_uniq), ep, dflags, off_heap);
-                    ep = enc_pid(acmp, funp->creator, ep, dflags);
+                    ep = enc_pid(acmp, erts_init_process_id, ep, dflags);
 
                     for (ei = funp->num_free-1; ei >= 0; ei--) {
                         WSTACK_PUSH2(s, ENC_TERM, (UWord) funp->env[ei]);
@@ -4981,6 +4981,7 @@ dec_term_atom_common:
 		hp += num_free;
 		funp->thing_word = HEADER_FUN;
 		funp->num_free = num_free;
+		funp->external = 0;
 		*objp = make_fun(funp);
 
 		/* Module */
@@ -5006,6 +5007,15 @@ dec_term_atom_common:
 		}
 		old_uniq = unsigned_val(temp);
 
+                /* Creator pid, discarded */
+                if ((ep = dec_term(edep, factory, ep, &temp, NULL,
+                                   internal_nc)) == NULL) {
+                    goto error;
+                }
+                if (!is_pid(temp)) {
+                    goto error;
+                }
+
 		/*
 		 * It is safe to link the fun into the fun list only when
 		 * no more validity tests can fail.
@@ -5024,9 +5034,6 @@ dec_term_atom_common:
 		    funp->env[i] = (Eterm) next;
 		    next = funp->env + i;
 		}
-		/* Creator */
-		funp->creator = (Eterm) next;
-		next = &(funp->creator);
 		break;
 	    }
 	case ATOM_INTERNAL_REF2:
@@ -5586,7 +5593,7 @@ encode_size_struct_int(TTBSizeContext* ctx, ErtsAtomCacheMap *acmp, Eterm obj,
                 if (is_local_fun(funp)) {
                     result += 20+1+1+4;	/* New ID + Tag */
                     result += 4; /* Length field (number of free variables */
-                    result += encode_pid_size(acmp, funp->creator, dflags);
+                    result += encode_pid_size(acmp, erts_init_process_id, dflags);
                     result += encode_atom_size(acmp, funp->entry.fun->module, dflags);
                     result += 2 * (1+4);	/* Index, Uniq */
                     if (funp->num_free > 1) {
diff --git a/erts/emulator/beam/generators.tab b/erts/emulator/beam/generators.tab
index a737228c44..ae806e2062 100644
--- a/erts/emulator/beam/generators.tab
+++ b/erts/emulator/beam/generators.tab
@@ -323,7 +323,7 @@ MakeLiteralLambda(Op, Index, DstType, DstVal) {
         funp->next = NULL;
         funp->arity = entry->arity;
         funp->num_free = 0;
-        funp->creator = am_external;
+        funp->external = 1;
 
         literal = beamfile_add_literal(&S->beam, make_fun(tmp_hp), 0);
         S->lambda_literals[$Index] = literal;
diff --git a/erts/emulator/beam/jit/asm_load.c b/erts/emulator/beam/jit/asm_load.c
index 023f084051..f6e1f1c6ab 100644
--- a/erts/emulator/beam/jit/asm_load.c
+++ b/erts/emulator/beam/jit/asm_load.c
@@ -997,15 +997,14 @@ void beam_load_finalize_code(LoaderState *stp,
                 literal = beamfile_get_literal(&stp->beam,
                                                stp->lambda_literals[i]);
                 funp = (ErlFunThing *)fun_val(literal);
-                ASSERT(funp->creator == am_external);
+                ASSERT(funp->external == 1);
 
                 funp->entry.fun = fun_entry;
 
                 funp->next = literal_area->off_heap;
                 literal_area->off_heap = (struct erl_off_heap_header *)funp;
 
-                ASSERT(erts_init_process_id != ERTS_INVALID_PID);
-                funp->creator = erts_init_process_id;
+                funp->external = 0;
 
                 erts_refc_inc(&fun_entry->refc, 2);
             }
diff --git a/erts/emulator/test/erts_debug_SUITE.erl b/erts/emulator/test/erts_debug_SUITE.erl
index 2149eac41b..3240b800d6 100644
--- a/erts/emulator/test/erts_debug_SUITE.erl
+++ b/erts/emulator/test/erts_debug_SUITE.erl
@@ -82,7 +82,7 @@ test_size(Config) when is_list(Config) ->
 
     %% Fun environment size = 0 (the smallest fun possible)
     SimplestFun = fun() -> ok end,
-    FunSz0 = 5,
+    FunSz0 = 4,
     FunSz0 = do_test_size(SimplestFun),
 
     %% Fun environment size = 1
diff --git a/erts/emulator/test/fun_SUITE.erl b/erts/emulator/test/fun_SUITE.erl
index 0f8e7af926..10cfc53a97 100644
--- a/erts/emulator/test/fun_SUITE.erl
+++ b/erts/emulator/test/fun_SUITE.erl
@@ -838,8 +838,7 @@ id(X) ->
     X.
 
 spawn_call(Node, AFun) ->
-    Parent = self(),
-    Init = erlang:whereis(init),
+    Self = self(),
     Pid = spawn_link(Node,
 		     fun() ->
 			     receive
@@ -850,10 +849,7 @@ spawn_call(Node, AFun) ->
 						_ -> lists:seq(0, Arity-1)
 					    end,
 				     Res = apply(Fun, Args),
-                     case erlang:fun_info(Fun, pid) of
-                        {pid,Init} -> Parent ! {result,Res};
-                        {pid,Creator} -> Creator ! {result,Res}
-                     end
+                                     Self ! {result,Res}
 			     end
 		     end),
     Pid ! {AFun,AFun,AFun},
diff --git a/erts/emulator/test/trace_call_memory_SUITE.erl b/erts/emulator/test/trace_call_memory_SUITE.erl
index 59d1873e49..a18dbdabf1 100644
--- a/erts/emulator/test/trace_call_memory_SUITE.erl
+++ b/erts/emulator/test/trace_call_memory_SUITE.erl
@@ -309,7 +309,7 @@ spawn_memory_lambda(Config) when is_list(Config) ->
     receive {'DOWN', MRef, process, Pid, _} -> ok end,
     1 = erlang:trace(self(), false, [all]),
     %% 16-elements list translates into 34-words for spawn, and 6 more words for apply itself
-    {call_memory, [{Pid, 1, 40}]} = erlang:trace_info({erlang, apply, 2}, call_memory).
+    {call_memory, [{Pid, 1, 39}]} = erlang:trace_info({erlang, apply, 2}, call_memory).
 
 spawn_memory_internal(Array) ->
     Array.
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index 59f2e8bd03..7a73e1bc82 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -39,20 +39,14 @@
 	 sublist_2/1, sublist_3/1, sublist_2_e/1, sublist_3_e/1,
 	 flatten_1/1, flatten_2/1, flatten_1_e/1, flatten_2_e/1,
 	 dropwhile/1, takewhile/1,
-	 sort_1/1, sort_2/1, sort_stable/1, merge/1, rmerge/1, sort_rand/1,
-	 usort_1/1, usort_2/1, usort_stable/1, umerge/1, rumerge/1,usort_rand/1,
+	 sort_1/1, sort_2/1, merge/1, rmerge/1, sort_rand/1,
+	 usort_1/1, usort_2/1, umerge/1, rumerge/1,usort_rand/1,
 	 keymerge/1, rkeymerge/1,
-	 keysort_1/1, keysort_i/1, keysort_stable/1,
+	 keysort_1/1, keysort_i/1,
 	 keysort_rand/1, keysort_error/1,
 	 ukeymerge/1, rukeymerge/1,
-	 ukeysort_1/1, ukeysort_i/1, ukeysort_stable/1,
+	 ukeysort_1/1, ukeysort_i/1,
 	 ukeysort_rand/1, ukeysort_error/1,
-	 funmerge/1, rfunmerge/1,
-	 funsort_1/1, funsort_stable/1, funsort_rand/1,
-	 funsort_error/1,
-	 ufunmerge/1, rufunmerge/1,
-	 ufunsort_1/1, ufunsort_stable/1, ufunsort_rand/1,
-	 ufunsort_error/1,
 	 uniq_1/1, uniq_2/1,
 	 zip_unzip/1, zip_unzip3/1, zipwith/1, zipwith3/1,
 	 zip_fail/1, zip_trim/1, zip_pad/1,
@@ -73,9 +67,6 @@
 
 -export([sort_loop/0, sort_loop/1, sloop/1]).
 
-%% Internal export.
--export([make_fun/1]).
-
 %%
 %% all/1
 %%
@@ -91,8 +82,6 @@ all() ->
      {group, keysort},
      {group, ukeysort},
      {group, uniq},
-     {group, funsort},
-     {group, ufunsort},
      {group, sublist},
      {group, flatten},
      {group, seq},
@@ -103,22 +92,16 @@ all() ->
 groups() -> 
     [{append, [parallel], [append_1, append_2]},
      {usort, [parallel],
-      [umerge, rumerge, usort_1, usort_2, usort_rand, usort_stable]},
+      [umerge, rumerge, usort_1, usort_2, usort_rand]},
      {keysort, [parallel],
       [keymerge, rkeymerge, keysort_1, keysort_rand,
-       keysort_i, keysort_stable, keysort_error]},
+       keysort_i, keysort_error]},
      {key, [parallel], [keymember, keysearch_keyfind, keystore,
 			keytake, keyreplace]},
      {sort,[parallel],[merge, rmerge, sort_1, sort_2, sort_rand]},
      {ukeysort, [parallel],
       [ukeymerge, rukeymerge, ukeysort_1, ukeysort_rand,
-       ukeysort_i, ukeysort_stable, ukeysort_error]},
-     {funsort, [parallel],
-      [funmerge, rfunmerge, funsort_1, funsort_stable,
-       funsort_error, funsort_rand]},
-     {ufunsort, [parallel],
-      [ufunmerge, rufunmerge, ufunsort_1, ufunsort_stable,
-       ufunsort_error, ufunsort_rand]},
+       ukeysort_i, ukeysort_error]},
      {seq, [parallel], [seq_loop, seq_2, seq_3, seq_2_e, seq_3_e]},
      {sublist, [parallel],
       [sublist_2, sublist_3, sublist_2_e, sublist_3_e]},
@@ -647,21 +630,6 @@ sort_rand(Config) when is_list(Config) ->
     ok = check(biglist(10000)),
     ok.
 
-%% sort/1 was really stable for a while - the order of equal elements
-%% was kept - but since the performance suffered a bit, this "feature"
-%% was removed.
-
-%% sort/1 should be stable for equal terms.
-sort_stable(Config) when is_list(Config) ->
-    ok = check_stability(bigfunlist(10)),
-    ok = check_stability(bigfunlist(100)),
-    ok = check_stability(bigfunlist(1000)),
-    case erlang:system_info(modified_timing_level) of
-	undefined -> ok = check_stability(bigfunlist(10000));
-	_ -> ok
-    end,
-    ok.
-
 stable_lists_spec() ->
     %% [{SortedList, KeysThatHaveEquals}]
     [{[0.0, 0], [0]},
@@ -681,23 +649,6 @@ check_order(A, [B | L]) when A =< B ->
 check_order(_A, _L) ->
     no.
 
-%% The check that sort/1 is stable is no longer used.
-%% Equal elements are no longer always kept in order.
-check_stability(L) ->
-    S = lists:sort(L),
-    LP = explicit_pid(L),
-    SP = explicit_pid(S),
-    check_sorted(1, 2, LP, SP).
-
-explicit_pid(L) ->
-    lists:reverse(expl_pid(L, [])).
-
-expl_pid([{I,F} | T], L) when is_function(F) ->
-    expl_pid(T, [{I,fun_pid(F)} | L]);
-expl_pid([], L) ->
-    L.
-
-
 usort_1(Conf) when is_list(Conf) ->
     usort(fun lists:usort/1).
 
@@ -944,18 +895,6 @@ usort_rand(Config) when is_list(Config) ->
     ok = ucheck(ubiglist(10000)),
     ok.
 
-%% usort/1 should keep the first duplicate.
-usort_stable(Config) when is_list(Config) ->
-    ok = ucheck_stability(bigfunlist(3)),
-    ok = ucheck_stability(bigfunlist(10)),
-    ok = ucheck_stability(bigfunlist(100)),
-    ok = ucheck_stability(bigfunlist(1000)),
-    case erlang:system_info(modified_timing_level) of
-	undefined -> ok = ucheck_stability(bigfunlist(10000));
-	_ -> ok
-    end,
-    ok.
-
 test_stable_usort(ListsUSort, StableList, Xs) ->
     StableUList = ulist(StableList),
     StableElements =
@@ -975,13 +914,6 @@ ucheck_order(A, [B | L]) when A < B ->
 ucheck_order(_A, _L) ->
     no.
 
-%% Check that usort/1 is stable and correct relative ukeysort/2.
-ucheck_stability(L) ->
-    S = no_dups(lsort(L)),
-    U = lists:usort(L),
-    check_stab(L, U, S, "usort/1", "ukeysort/2").
-
-
 %% Key merge two lists.
 keymerge(Config) when is_list(Config) ->
 
@@ -1105,18 +1037,6 @@ keysort_1(Config) when is_list(Config) ->
 
     ok.
 
-%% keysort should be stable
-keysort_stable(Config) when is_list(Config) ->
-    ok = keysort_check(1, [{1,b},{1,c}], [{1,b},{1,c}]),
-    ok = keysort_check(1, [{1,c},{1,b}], [{1,c},{1,b}]),
-    ok = keysort_check(1,
-		       [{1,c},{1,b},{2,x},{3,p},{2,a}],
-		       [{1,c},{1,b},{2,x},{2,a},{3,p}]),
-    ok = keysort_check(1,
-		       [{1,a},{1,b},{1,a},{1,a}],
-		       [{1,a},{1,b},{1,a},{1,a}]),
-    ok.
-
 %% Create two variants of tuple lists with keys from StableKeys.
 %% The variants are {Key}, and {Key,N++}.
 %%
@@ -1373,27 +1293,6 @@ ukeysort_1(Config) when is_list(Config) ->
 
     ok.
 
-%% ukeysort should keep the first duplicate.
-ukeysort_stable(Config) when is_list(Config) ->
-    ok = ukeysort_check(1, [{1,b},{1,c}], [{1,b}]),
-    ok = ukeysort_check(1, [{1,c},{1,b}], [{1,c}]),
-    ok = ukeysort_check(1,
-			[{1,c},{1,b},{2,x},{3,p},{2,a}],
-			[{1,c},{2,x},{3,p}]),
-
-    ok = ukeysort_check(1, [{1,a},{1,b},{1,b}], [{1,a}]),
-    ok = ukeysort_check(1, [{2,a},{1,b},{2,a}], [{1,b},{2,a}]),
-
-    ok = ukeysort_check_stability(bigfunlist(3)),
-    ok = ukeysort_check_stability(bigfunlist(10)),
-    ok = ukeysort_check_stability(bigfunlist(100)),
-    ok = ukeysort_check_stability(bigfunlist(1000)),
-    case erlang:system_info(modified_timing_level) of
-	undefined -> ok = ukeysort_check_stability(bigfunlist(10000));
-	_ -> ok
-    end,
-    ok.
-
 %% ukeysort should exit when given bad arguments.
 ukeysort_error(Config) when is_list(Config) ->
     {'EXIT', _} = (catch lists:ukeysort(0, [{1,b},{1,c}])),
@@ -1438,13 +1337,6 @@ gen_ukeysort_check(I, Input) ->
 	    erlang:error(gen_ukeysort_check)
     end.
 
-%% Used for checking that the first copy is kept.
-ukeysort_check_stability(L) ->
-    I = 1,
-    U = lists:ukeysort(I, L),
-    S = no_dups_keys(lkeysort(I, L), I),
-    check_stab(L, U, S, "ukeysort/2", "usort/2").
-
 %%% Uniquely keysort a list, check that the returned list is what we
 %%% expected, and that it is actually sorted.
 ukeysort_check(I, Input, Expected) ->
@@ -1483,395 +1375,6 @@ ukeycompare(I, J, A, B) when A =/= B,
 			     element(J, A) =< element(J, B) ->
     ok.
 
-
-
-%% Merge two lists using a fun.
-funmerge(Config) when is_list(Config) ->
-
-    Singleton = id([a, b, c]),
-    Two = [1,2],
-    Six = [1,2,3,4,5,6],
-    F = fun(X, Y) -> X =< Y end,
-
-    %% 2-way merge
-    [] = lists:merge(F, [], []),
-    Two = lists:merge(F, Two, []),
-    Two = lists:merge(F, [], Two),
-    Six = lists:merge(F, [1,3,5], [2,4,6]),
-    Six = lists:merge(F, [2,4,6], [1,3,5]),
-    Six = lists:merge(F, [1,2,3], [4,5,6]),
-    Six = lists:merge(F, [4,5,6], [1,2,3]),
-    Six = lists:merge(F, [1,2,5],[3,4,6]),
-    [1,2,3,5,7] = lists:merge(F, [1,3,5,7], [2]),
-    [1,2,3,4,5,7] = lists:merge(F, [1,3,5,7], [2,4]),
-    [1,2,3,4,5,6,7] = lists:merge(F, [1,3,5,7], [2,4,6]),
-    [1,2,3,5,7] = lists:merge(F, [2], [1,3,5,7]),
-    [1,2,3,4,5,7] = lists:merge(F, [2,4], [1,3,5,7]),
-    [1,2,3,4,5,6,7] = lists:merge(F, [2,4,6], [1,3,5,7]),
-
-    F2 = fun(X,Y) -> element(1,X) =< element(1,Y) end,
-    [{b,2},{c,11},{c,12},{c,21},{c,22},{e,5}] =
-	lists:merge(F2,[{c,11},{c,12},{e,5}], [{b,2},{c,21},{c,22}]),
-
-    true = erts_debug:same(Singleton, lists:merge(F, Singleton, [])),
-    true = erts_debug:same(Singleton, lists:merge(F, [], Singleton)),
-
-    {'EXIT', _} = (catch lists:merge(F, a, b)),
-    {'EXIT', _} = (catch lists:merge(F, a, [])),
-    {'EXIT', _} = (catch lists:merge(F, [], b)),
-    {'EXIT', _} = (catch lists:merge(F, a, [1, 2, 3])),
-    {'EXIT', _} = (catch lists:merge(F, [1, 2, 3], b)),
-
-    ok.
-
-%% Reverse merge two lists using a fun.
-rfunmerge(Config) when is_list(Config) ->
-
-    Singleton = id([a, b, c]),
-    Two = [2,1],
-    Six = [6,5,4,3,2,1],
-    F = fun(X, Y) -> X =< Y end,
-
-    %% 2-way reversed merge
-    [] = lists:rmerge(F, [], []),
-    Two = lists:rmerge(F, Two, []),
-    Two = lists:rmerge(F, [], Two),
-    Six = lists:rmerge(F, [5,3,1], [6,4,2]),
-    Six = lists:rmerge(F, [6,4,2], [5,3,1]),
-    Six = lists:rmerge(F, [3,2,1], [6,5,4]),
-    Six = lists:rmerge(F, [6,5,4], [3,2,1]),
-    Six = lists:rmerge(F, [4,3,2],[6,5,1]),
-    [7,6,5,3,1] = lists:rmerge(F, [7,5,3,1], [6]),
-    [7,6,5,4,3,1] = lists:rmerge(F, [7,5,3,1], [6,4]),
-    [7,6,5,4,3,2,1] = lists:rmerge(F, [7,5,3,1], [6,4,2]),
-    [7,5,3,2,1] = lists:rmerge(F, [2], [7,5,3,1]),
-    [7,5,4,3,2,1] = lists:rmerge(F, [4,2], [7,5,3,1]),
-    [7,6,5,4,3,2,1] = lists:rmerge(F, [6,4,2], [7,5,3,1]),
-
-    F2 = fun(X,Y) -> element(1,X) =< element(1,Y) end,
-    L1 = [{c,11},{c,12},{e,5}],
-    L2 = [{b,2},{c,21},{c,22}],
-    true =
-	lists:merge(F2, L1, L2) == 
-	lists:reverse(lists:rmerge(F2,lists:reverse(L1), lists:reverse(L2))),
-
-    true = erts_debug:same(Singleton, lists:rmerge(F, Singleton, [])),
-    true = erts_debug:same(Singleton, lists:rmerge(F, [], Singleton)),
-
-    {'EXIT', _} = (catch lists:rmerge(F, a, b)),
-    {'EXIT', _} = (catch lists:rmerge(F, a, [])),
-    {'EXIT', _} = (catch lists:rmerge(F, [], b)),
-    {'EXIT', _} = (catch lists:rmerge(F, a, [1, 2, 3])),
-    {'EXIT', _} = (catch lists:rmerge(F, [1, 2, 3], b)),
-
-    ok.
-
-
-funsort_1(Config) when is_list(Config) ->
-    ok = funsort_check(1, [], []),
-    ok = funsort_check(1, [{a,b}], [{a,b}]),
-    ok = funsort_check(1, [{a,b},{a,b}], [{a,b},{a,b}]),
-    ok = funsort_check(1, [{a,b},{b,c}], [{a,b},{b,c}]),
-    ok = funsort_check(1, [{b,c},{a,b}], [{a,b},{b,c}]),
-    ok = funsort_check(1,
-		       [{1,e},{3,f},{2,y},{0,z},{x,14}],
-		       [{0,z},{1,e},{2,y},{3,f},{x,14}]),
-    F = funsort_fun(1),
-
-    [{b,1},{c,1}] = lists:sort(F, [{c,1},{b,1}]),
-    [{a,0},{b,2},{c,3},{d,4}] =
-	lists:sort(F, [{d,4},{c,3},{b,2},{a,0}]),
-    [{a,0},{b,1},{b,2},{c,1}] =
-	lists:sort(F, [{c,1},{b,1},{b,2},{a,0}]),
-    [{a,0},{b,1},{b,2},{c,1},{d,4}] =
-	lists:sort(F, [{c,1},{b,1},{b,2},{a,0},{d,4}]),
-
-    SFun = fun(L) -> fun(X) -> funsort_check(1, X, L) end end,
-    L1 = [{1,a},{1,a},{2,b},{2,b},{3,c},{4,d},{5,e},{6,f}],
-    lists:foreach(SFun(L1), perms(L1)),
-
-    ok.
-
-%% sort/2 should be stable.
-funsort_stable(Config) when is_list(Config) ->
-    ok = funsort_check(1, [{1,b},{1,c}], [{1,b},{1,c}]),
-    ok = funsort_check(1, [{1,c},{1,b}], [{1,c},{1,b}]),
-    ok = funsort_check(1,
-		       [{1,c},{1,b},{2,x},{3,p},{2,a}],
-		       [{1,c},{1,b},{2,x},{2,a},{3,p}]),
-    ok.
-
-%% sort/2 should exit when given bad arguments.
-funsort_error(Config) when is_list(Config) ->
-    {'EXIT', _} = (catch lists:sort(1, [{1,b} , {1,c}])),
-    {'EXIT', _} = (catch lists:sort(fun(X,Y) -> X =< Y end,
-				    [{1,b} | {1,c}])),
-    ok.
-
-%% sort/2 on big randomized lists.
-funsort_rand(Config) when is_list(Config) ->
-    ok = funsort_check3(1, biglist(10)),
-    ok = funsort_check3(1, biglist(100)),
-    ok = funsort_check3(1, biglist(1000)),
-    ok = funsort_check3(1, biglist(10000)),
-    ok.
-
-%% Do a keysort
-funsort(I, L) ->
-    lists:sort(funsort_fun(I), L).
-
-funsort_check3(I, Input) ->
-    check_sorted(I, 3, Input, funsort(I, Input)).
-
-%%% Keysort a list, check that the returned list is what we expected,
-%%% and that it is actually sorted.
-funsort_check(I, Input, Expected) ->
-    Expected = funsort(I, Input),
-    check_sorted(I, Input, Expected).
-
-
-%% Merge two lists while removing duplicates using a fun.
-ufunmerge(Conf) when is_list(Conf) ->
-
-    Singleton = id([a, b, c]),
-    Two = [1,2],
-    Six = [1,2,3,4,5,6],
-    F = fun(X, Y) -> X =< Y end,
-
-    %% 2-way unique merge
-    [] = lists:umerge(F, [], []),
-    Two = lists:umerge(F, Two, []),
-    Two = lists:umerge(F, [], Two),
-    Six = lists:umerge(F, [1,3,5], [2,4,6]),
-    Six = lists:umerge(F, [2,4,6], [1,3,5]),
-    Six = lists:umerge(F, [1,2,3], [4,5,6]),
-    Six = lists:umerge(F, [4,5,6], [1,2,3]),
-    Six = lists:umerge(F, [1,2,5],[3,4,6]),
-    [1,2,3,5,7] = lists:umerge(F, [1,3,5,7], [2]),
-    [1,2,3,4,5,7] = lists:umerge(F, [1,3,5,7], [2,4]),
-    [1,2,3,4,5,6,7] = lists:umerge(F, [1,3,5,7], [2,4,6]),
-    [1,2,3,5,7] = lists:umerge(F, [2], [1,3,5,7]),
-    [1,2,3,4,5,7] = lists:umerge(F, [2,4], [1,3,5,7]),
-    [1,2,3,4,5,6,7] = lists:umerge(F, [2,4,6], [1,3,5,7]),
-
-    [1,2,3,5,7] = lists:umerge(F, [1,2,3,5,7], [2]),
-    [1,2,3,4,5,7] = lists:umerge(F, [1,2,3,4,5,7], [2,4]),
-    [1,2,3,4,5,6,7] = lists:umerge(F, [1,3,5,6,7], [2,4,6]),
-    [1,2,3,5,7] = lists:umerge(F, [2], [1,2,3,5,7]),
-    [1,2,3,4,5,7] = lists:umerge(F, [2,4], [1,2,3,4,5,7]),
-    [1,2,3,4,5,6,7] = lists:umerge(F, [2,4,6], [1,2,3,4,5,6,7]),
-
-    L1 = [{a,1},{a,3},{a,5},{a,7}],
-    L2 = [{b,1},{b,3},{b,5},{b,7}],
-    F2 = fun(X,Y) -> element(2,X) =< element(2,Y) end,
-    L1 = lists:umerge(F2, L1, L2),
-    [{b,2},{e,5},{c,11},{c,12},{c,21},{c,22}] =
-	lists:umerge(F2, [{e,5},{c,11},{c,12}], [{b,2},{c,21},{c,22}]),
-
-    true = erts_debug:same(Singleton, lists:umerge(F, Singleton, [])),
-    true = erts_debug:same(Singleton, lists:umerge(F, [], Singleton)),
-
-    {'EXIT', _} = (catch lists:umerge(F, a, b)),
-    {'EXIT', _} = (catch lists:umerge(F, a, [])),
-    {'EXIT', _} = (catch lists:umerge(F, [], b)),
-    {'EXIT', _} = (catch lists:umerge(F, a, [1, 2, 3])),
-    {'EXIT', _} = (catch lists:umerge(F, [1, 2, 3], b)),
-
-    ok.
-
-%% Reverse merge two lists while removing duplicates using a fun.
-rufunmerge(Conf) when is_list(Conf) ->
-    Singleton = id([a, b, c]),
-    Two = [2,1],
-    Six = [6,5,4,3,2,1],
-    F = fun(X, Y) -> X =< Y end,
-
-    %% 2-way reversed unique merge
-    [] = lists:rumerge(F, [], []),
-    Two = lists:rumerge(F, Two, []),
-    Two = lists:rumerge(F, [], Two),
-    Six = lists:rumerge(F, [5,3,1], [6,4,2]),
-    Six = lists:rumerge(F, [6,4,2], [5,3,1]),
-    Six = lists:rumerge(F, [3,2,1], [6,5,4]),
-    Six = lists:rumerge(F, [6,5,4], [3,2,1]),
-    Six = lists:rumerge(F, [4,3,2],[6,5,1]),
-    [7,6,5,3,1] = lists:rumerge(F, [7,5,3,1], [6]),
-    [7,6,5,4,3,1] = lists:rumerge(F, [7,5,3,1], [6,4]),
-    [7,6,5,4,3,2,1] = lists:rumerge(F, [7,5,3,1], [6,4,2]),
-    [7,5,3,2,1] = lists:rumerge(F, [2], [7,5,3,1]),
-    [7,5,4,3,2,1] = lists:rumerge(F, [4,2], [7,5,3,1]),
-    [7,6,5,4,3,2,1] = lists:rumerge(F, [6,4,2], [7,5,3,1]),
-
-    [7,6,5,3,1] = lists:rumerge(F, [7,6,5,3,1], [6]),
-    [7,6,5,4,3,1] = lists:rumerge(F, [7,6,5,4,3,1], [6,4]),
-    [7,6,5,4,3,2,1] = lists:rumerge(F, [7,6,5,4,3,2,1], [6,4,2]),
-    [7,5,3,2,1] = lists:rumerge(F, [2], [7,5,3,2,1]),
-    [7,5,4,3,2,1] = lists:rumerge(F, [4,2], [7,5,4,3,2,1]),
-    [7,6,5,4,3,2,1] = lists:rumerge(F, [6,4,2], [7,6,5,4,3,2,1]),
-
-    F2 = fun(X,Y) -> element(1,X) =< element(1,Y) end,
-    L1 = [{1,a},{1,b},{1,a}],
-    L2 = [{1,a},{1,b},{1,a}],
-    true = lists:umerge(F2, L1, L2) ==
-	lists:reverse(lists:rumerge(F, lists:reverse(L2), lists:reverse(L1))),
-
-    L3 = [{c,11},{c,12},{e,5}],
-    L4 = [{b,2},{c,21},{c,22}],
-    true =
-	lists:umerge(F2, L3, L4) == 
-	lists:reverse(lists:rumerge(F2,lists:reverse(L3), lists:reverse(L4))),
-
-    true = erts_debug:same(Singleton, lists:rumerge(F, Singleton, [])),
-    true = erts_debug:same(Singleton, lists:rumerge(F, [], Singleton)),
-
-    {'EXIT', _} = (catch lists:rumerge(F, a, b)),
-    {'EXIT', _} = (catch lists:rumerge(F, a, [])),
-    {'EXIT', _} = (catch lists:rumerge(F, [], b)),
-    {'EXIT', _} = (catch lists:rumerge(F, a, [1, 2, 3])),
-    {'EXIT', _} = (catch lists:rumerge(F, [1, 2, 3], b)),
-
-    ok.
-
-ufunsort_1(Config) when is_list(Config) ->
-    ok = ufunsort_check(1, [], []),
-    ok = ufunsort_check(1, [{a,b}], [{a,b}]),
-    ok = ufunsort_check(1, [{a,b},{a,b}], [{a,b}]),
-    ok = ufunsort_check(1, [{a,b},{b,c}], [{a,b},{b,c}]),
-    ok = ufunsort_check(1, [{b,c},{a,b}], [{a,b},{b,c}]),
-    ok = ufunsort_check(1,
-			[{1,e},{3,f},{2,y},{0,z},{x,14}],
-			[{0,z},{1,e},{2,y},{3,f},{x,14}]),
-    ok = ufunsort_check(1,
-			[{1,a},{2,b},{3,c},{2,b},{1,a},{2,b},{3,c},
-			 {2,b},{1,a}],
-			[{1,a},{2,b},{3,c}]),
-    ok = ufunsort_check(1,
-			[{1,a},{1,a},{1,b},{1,b},{1,a},{2,a}],
-			[{1,a},{2,a}]),
-
-    F = funsort_fun(1),
-    L1 = [{1,a},{1,b},{1,a}],
-    L2 = [{1,a},{1,b},{1,a}],
-    ok = ufunsort_check(1, lists:keymerge(1, L1, L2),
-			lists:umerge(F, lists:usort(F, L1),
-				     lists:usort(F, L2))),
-    L3 = [{1,a},{1,b},{1,a},{2,a}],
-    ok = ufunsort_check(1, lists:keymerge(1, L3, L2),
-			lists:umerge(F, lists:usort(F, L3),
-				     lists:usort(F, L2))),
-    L4 = [{1,b},{1,a}],
-    ok = ufunsort_check(1, lists:keymerge(1, L1, L4),
-			lists:umerge(F, lists:usort(F, L1),
-				     lists:usort(F, L4))),
-    L5 = [{1,a},{1,b},{1,a},{2,a}],
-    ok = ufunsort_check(1, lists:keymerge(1, L5, []),
-			lists:umerge(F, lists:usort(F, L5), [])),
-    L6 = [{3,a}],
-    ok = ufunsort_check(1, lists:keymerge(1, L5, L6),
-			lists:umerge(F, lists:usort(F, L5),
-				     lists:usort(F, L6))),
-
-    [{b,1},{c,1}] = lists:usort(F, [{c,1},{c,1},{b,1}]),
-    [{a,0},{b,2},{c,3},{d,4}] =
-	lists:usort(F, [{d,4},{c,3},{b,2},{b,2},{a,0}]),
-    [{a,0},{b,1},{c,1}] =
-	lists:usort(F, [{c,1},{b,1},{b,1},{b,2},{b,2},{a,0}]),
-    [{a,0},{b,1},{c,1},{d,4}] =
-	lists:usort(F, [{c,1},{b,1},{b,2},{a,0},{a,0},{d,4},{d,4}]),
-
-    SFun = fun(L) -> fun(X) -> ufunsort_check(1, X, L) end end,
-    PL = [{1,a},{2,b},{3,c},{4,d},{5,e},{6,f}],
-    Ps = perms([{1,a},{2,b},{3,c},{4,d},{5,e},{6,f},{2,b},{1,a}]),
-    lists:foreach(SFun(PL), Ps),
-
-    ok.
-
-%% usort/2 should be stable.
-ufunsort_stable(Config) when is_list(Config) ->
-    ok = ufunsort_check(1, [{1,b},{1,c}], [{1,b}]),
-    ok = ufunsort_check(1, [{1,c},{1,b}], [{1,c}]),
-    ok = ufunsort_check(1,
-			[{1,c},{1,b},{2,x},{3,p},{2,a}],
-			[{1,c},{2,x},{3,p}]),
-
-    ok = ufunsort_check_stability(bigfunlist(10)),
-    ok = ufunsort_check_stability(bigfunlist(100)),
-    ok = ufunsort_check_stability(bigfunlist(1000)),
-    case erlang:system_info(modified_timing_level) of
-	undefined -> ok = ufunsort_check_stability(bigfunlist(10000));
-	_ -> ok
-    end,
-    ok.
-
-%% usort/2 should exit when given bad arguments.
-ufunsort_error(Config) when is_list(Config) ->
-    {'EXIT', _} = (catch lists:usort(1, [{1,b} , {1,c}])),
-    {'EXIT', _} = (catch lists:usort(fun(X,Y) -> X =< Y end,
-				     [{1,b} | {1,c}])),
-    ok.
-
-%% usort/2 on big randomized lists.
-ufunsort_rand(Config) when is_list(Config) ->
-    ok = ufunsort_check3(1, biglist(10)),
-    ok = ufunsort_check3(1, biglist(100)),
-    ok = ufunsort_check3(1, biglist(1000)),
-    ok = ufunsort_check3(1, biglist(10000)),
-
-    ok = gen_ufunsort_check(1, ubiglist(100)),
-    ok = gen_ufunsort_check(1, ubiglist(1000)),
-    ok = gen_ufunsort_check(1, ubiglist(10000)),
-    ok.
-
-%% Check that usort/2 is stable and correct relative sort/2.
-gen_ufunsort_check(I, Input) ->
-    U = ufunsort(I, Input),
-    S = funsort(I, Input),
-    case U == no_dups_keys(S, I) of
-	true ->
-	    ok;
-	false ->
-	    io:format("~w~n", [Input]),
-	    erlang:error(gen_ufunsort_check)
-    end.
-
-%% Used for checking that the first copy is kept.
-ufunsort_check_stability(L) ->
-    I = 1,
-    U = ufunsort(I, L),
-    S = no_dups(funsort(I, L)),
-    check_stab(L, U, S, "usort/2", "sort/2").
-
-ufunsort_check3(I, Input) ->
-    ucheck_sorted(I, 3, Input, ufunsort(I, Input)).
-
-%%% Keysort a list, check that the returned list is what we expected,
-%%% and that it is actually sorted.
-ufunsort_check(I, Input, Expected) ->
-    Expected = ufunsort(I, Input),
-    ucheck_sorted(I, Input, Expected).
-
-%% Do a keysort
-ufunsort(I, L) ->
-    lists:usort(funsort_fun(I), L).
-
-funsort_fun(I) ->
-    fun(A, B) when tuple_size(A) >= I, tuple_size(B) >= I ->
-            element(I, A) =< element(I, B)
-    end.
-
-check_stab(L, U, S, US, SS) ->
-    UP = explicit_pid(U),
-    SP = explicit_pid(S),
-    case UP == SP of
-	true ->
-	    ok;
-	false ->
-	    io:format("In: ~w~n", [explicit_pid(L)]),
-	    io:format("~s: ~w~n", [US, UP]),
-	    io:format("~s:  ~w~n", [SS, SP]),
-	    erlang:error(unstable)
-    end.
-
 test_stable_ukeysort(StableKeys, Ks) ->
     StableList_1 = [{K} || K <- StableKeys],
     StableUList_1 = ukeylist(1, StableList_1),
@@ -1908,50 +1411,6 @@ urandom_tuple(N, I) ->
     R2 = randint(I),
     {R1, R2}.
 
-%%%------------------------------------------------------------
-%%% Generate lists of given length, containing 2-tuples with random
-%%% integer elements in the range 0..10 as elements 1. All tuples have
-%%% the same function as element 2, but every function is created in a
-%%% unique process. ==/2 will return 'true' for any pair of functions,
-%%% but erlang:fun_info(Fun, pid) can be used for distinguishing
-%%% functions created in different processes. The pid acts like a
-%%% sequence number.
-
-bigfunlist(N) ->
-    rand:seed(exsplus),
-    bigfunlist_1(N).
-
-bigfunlist_1(N) when N < 30000 -> % Now (R8) max 32000 different pids.
-    case catch bigfunlist(N, 0, []) of
-	{'EXIT', _} ->
-	    bigfunlist_1(N);
-	Reply ->
-	    Reply
-    end.
-
-bigfunlist(0, _P, L) ->
-    lists:reverse(L);
-bigfunlist(N, P, L) ->
-    {E, NP} = random_funtuple(P, 11),
-    bigfunlist(N-1, NP, [E | L]).
-
-random_funtuple(P, N) ->
-    R = randint(N),
-    F = make_fun(),
-    NP = fun_pid(F),
-    true = NP > P,
-    {{R, F}, NP}.
-
-make_fun() ->
-    Pid = spawn(?MODULE, make_fun, [self()]),
-    receive {Pid, Fun} -> Fun end.
-
-make_fun(Pid) ->
-    Pid ! {self(), fun (X) -> {X, Pid} end}.
-
-fun_pid(Fun) ->
-    erlang:fun_info(Fun, pid).
-
 random_tuple(N, Seq) ->
     R1 = randint(N),
     R2 = randint(N),
@@ -1960,19 +1419,6 @@ random_tuple(N, Seq) ->
 randint(N) ->
     trunc(rand:uniform() * N).
 
-%% The first "duplicate" is kept.
-no_dups([]) ->
-    [];
-no_dups([H | T]) ->
-    no_dups(H, T, []).
-
-no_dups(H, [H1 | T], L) when H == H1 ->
-    no_dups(H, T, L);
-no_dups(H, [H1 | T], L) ->
-    no_dups(H1, T, [H | L]);
-no_dups(H, [], L) ->
-    lists:reverse([H | L]).
-
 %% The first "duplicate" is kept.
 no_dups_keys([], _I) ->
     [];
@@ -1994,7 +1440,7 @@ perms(L) ->
 %%%------------------------------------------------------------
 %%% Test the sort routines with randomly generated lists.
 
--record(state, {sort = 0, usort = 0, stable = 0}).
+-record(state, {sort = 0, usort = 0}).
 
 %% Run it interactively. 'stop' or 'info' recognized commands.
 sort_loop() ->
@@ -2037,289 +1483,19 @@ sloop(N, S) ->
 			 BL = biglist(Len, []),
 			 ok = check(BL),
 			 ok = keysort_check3(1, BL),
-			 ok = funsort_check3(1, BL),
 			 S#state{sort = S#state.sort + 1};
 		     1 ->
 			 BL = ubiglist(Len, []),
 			 ok = ucheck(BL),
 			 ok = gen_ukeysort_check(1, BL),
-			 ok = gen_ufunsort_check(1, BL),
-			 S#state{usort = S#state.usort + 1};
-		     2 ->
-			 BL = bigfunlist(Len),
-			 %% ok = check_stability(BL),
-			 ok = ucheck_stability(BL),
-			 ok = ukeysort_check_stability(BL),
-			 ok = ufunsort_check_stability(BL),
-			 S#state{stable = S#state.stable + 1}
+			 S#state{usort = S#state.usort + 1}
 		 end,
 	    sloop(N, NS)
     end.
 
 display_state(S) ->    
     io:format("sort:   ~p~n", [S#state.sort]),
-    io:format("usort:  ~p~n", [S#state.usort]),
-    io:format("stable: ~p~n", [S#state.stable]).
-
-%% This version of sort/1 is really stable; the order of equal
-%% elements is kept. It is used for checking the current
-%% implementation of usort/1 etc.
-
-lsort([X, Y | L] = L0) when X =< Y ->
-    case L of
-	[] -> 
-	    L0;
-	[Z] when Y =< Z ->
-	    L0;
-	[Z] when X =< Z ->
-	    [X, Z, Y];
-	[Z] ->
-	    [Z, X, Y];
-	_ ->
-	    split_1(X, Y, L, [], [])
-    end;
-lsort([X, Y | L]) ->
-    case L of
-	[] ->
-	    [Y, X];
-	[Z] when X =< Z ->
-	    [Y, X | L];
-	[Z] when Y =< Z ->
-	    [Y, Z, X];
-	[Z] ->
-	    [Z, Y, X];
-	_ ->
-	    split_2(X, Y, L, [], [])
-    end;
-lsort([_] = L) ->
-    L;
-lsort([] = L) ->
-    L.
-
-split_1(X, Y, [Z | L], R, Rs) when Z >= Y ->
-    split_1(Y, Z, L, [X | R], Rs);
-split_1(X, Y, [Z | L], R, Rs) when Z >= X ->
-    split_1(Z, Y, L, [X | R], Rs);
-split_1(X, Y, [Z | L], [], Rs) ->
-    split_1(X, Y, L, [Z], Rs);
-split_1(X, Y, [Z | L], R, Rs) ->
-    split_1_1(X, Y, L, R, Rs, Z);
-split_1(X, Y, [], R, Rs) ->
-    rmergel([[Y, X | R] | Rs], [], asc).
-
-split_1_1(X, Y, [Z | L], R, Rs, S) when Z >= Y ->
-    split_1_1(Y, Z, L, [X | R], Rs, S);
-split_1_1(X, Y, [Z | L], R, Rs, S) when Z >= X ->
-    split_1_1(Z, Y, L, [X | R], Rs, S);
-split_1_1(X, Y, [Z | L], R, Rs, S) when S =< Z ->
-    split_1(S, Z, L, [], [[Y, X | R] | Rs]);
-split_1_1(X, Y, [Z | L], R, Rs, S) ->
-    split_1(Z, S, L, [], [[Y, X | R] | Rs]);
-split_1_1(X, Y, [], R, Rs, S) ->
-    rmergel([[S], [Y, X | R] | Rs], [], asc).
-
-split_2(X, Y, [Z | L], R, Rs) when Z < Y ->
-    split_2(Y, Z, L, [X | R], Rs);
-split_2(X, Y, [Z | L], R, Rs) when Z < X ->
-    split_2(Z, Y, L, [X | R], Rs);
-split_2(X, Y, [Z | L], [], Rs) ->
-    split_2(X, Y, L, [Z], Rs);
-split_2(X, Y, [Z | L], R, Rs) ->
-    split_2_1(X, Y, L, R, Rs, Z);
-split_2(X, Y, [], R, Rs) ->
-    mergel([[Y, X | R] | Rs], [], desc).
-
-split_2_1(X, Y, [Z | L], R, Rs, S) when Z < Y ->
-    split_2_1(Y, Z, L, [X | R], Rs, S);
-split_2_1(X, Y, [Z | L], R, Rs, S) when Z < X ->
-    split_2_1(Z, Y, L, [X | R], Rs, S);
-split_2_1(X, Y, [Z | L], R, Rs, S) when S > Z ->
-    split_2(S, Z, L, [], [[Y, X | R] | Rs]);
-split_2_1(X, Y, [Z | L], R, Rs, S) ->
-    split_2(Z, S, L, [], [[Y, X | R] | Rs]);
-split_2_1(X, Y, [], R, Rs, S) ->
-    mergel([[S], [Y, X | R] | Rs], [], desc).
-
-mergel([[] | L], Acc, O) ->
-    mergel(L, Acc, O);
-mergel([T1, [H2 | T2] | L], Acc, asc) ->
-    mergel(L, [merge2_1(T1, H2, T2, []) | Acc], asc);
-mergel([[H2 | T2], T1 | L], Acc, desc) ->
-    mergel(L, [merge2_1(T1, H2, T2, []) | Acc], desc);
-mergel([L], [], _O) ->
-    L;
-mergel([L], Acc, O) ->
-    rmergel([lists:reverse(L, []) | Acc], [], O);
-mergel([], [], _O) ->
-    [];
-mergel([], Acc, O) ->
-    rmergel(Acc, [], O);
-mergel([A, [] | L], Acc, O) ->
-    mergel([A | L], Acc, O);
-mergel([A, B, [] | L], Acc, O) ->
-    mergel([A, B | L], Acc, O).
-
-rmergel([[H2 | T2], T1 | L], Acc, asc) ->
-    rmergel(L, [rmerge2_1(T1, H2, T2, []) | Acc], asc);
-rmergel([T1, [H2 | T2] | L], Acc, desc) ->
-    rmergel(L, [rmerge2_1(T1, H2, T2, []) | Acc], desc);
-rmergel([L], Acc, O) ->
-    mergel([lists:reverse(L, []) | Acc], [], O);
-rmergel([], Acc, O) ->
-    mergel(Acc, [], O).
-
-merge2_1([H1 | T1], H2, T2, M) when H1 =< H2 ->
-    merge2_1(T1, H2, T2, [H1 | M]);
-merge2_1([H1 | T1], H2, T2, M) ->
-    merge2_2(T1, H1, T2, [H2 | M]);
-merge2_1([], H2, T2, M) ->
-    lists:reverse(T2, [H2 | M]).
-
-merge2_2(T1, H1, [H2 | T2], M) when H1 =< H2 ->
-    merge2_1(T1, H2, T2, [H1 | M]);
-merge2_2(T1, H1, [H2 | T2], M) ->
-    merge2_2(T1, H1, T2, [H2 | M]);
-merge2_2(T1, H1, [], M) ->
-    lists:reverse(T1, [H1 | M]).
-
-rmerge2_1([H1 | T1], H2, T2, M) when H1 =< H2 ->
-    rmerge2_2(T1, H1, T2, [H2 | M]);
-rmerge2_1([H1 | T1], H2, T2, M) ->
-    rmerge2_1(T1, H2, T2, [H1 | M]);
-rmerge2_1([], H2, T2, M) ->
-    lists:reverse(T2, [H2 | M]).
-
-rmerge2_2(T1, H1, [H2 | T2], M) when H1 =< H2 ->
-    rmerge2_2(T1, H1, T2, [H2 | M]);
-rmerge2_2(T1, H1, [H2 | T2], M) ->
-    rmerge2_1(T1, H2, T2, [H1 | M]);
-rmerge2_2(T1, H1, [], M) ->
-    lists:reverse(T1, [H1 | M]).
-
-
-
-%% This version of keysort/2 is really stable; the order of equal
-%% elements is kept. It is used for checking the current
-%% implementation of ukeysort/2 etc.
-
-lkeysort(Index, L) when is_integer(Index), Index > 0 ->
-    case L of
-	[] -> L;
-	[_] -> L;
-	[X, Y | T] ->
-	    EX = element(Index, X),
-	    EY = element(Index, Y),
-	    if
-		EX =< EY ->
-		    keysplit_1(Index, X, EX, Y, EY, T, [], []);
-		true ->
-		    keysplit_2(Index, Y, EY, T, [X])
-	    end
-    end.
-
-keysplit_1(I, X, EX, Y, EY, [Z | L], R, Rs) ->
-    EZ = element(I, Z),
-    if 
-	EY =< EZ ->
-	    keysplit_1(I, Y, EY, Z, EZ, L, [X | R], Rs);
-	EX =< EZ ->
-	    keysplit_1(I, Z, EZ, Y, EY, L, [X | R], Rs);
-	true, R == [] ->
-	    keysplit_1(I, X, EX, Y, EY, L, [Z], Rs);
-	true ->
-	    keysplit_1_1(I, X, EX, Y, EY, L, R, Rs, Z, EZ)
-    end;
-keysplit_1(I, X, _EX, Y, _EY, [], R, Rs) ->
-    rkeymergel(I, [[Y, X | R] | Rs], []).
-
-%% One out-of-order element, S.
-keysplit_1_1(I, X, EX, Y, EY, [Z | L], R, Rs, S, ES) ->
-    EZ = element(I, Z),
-    if
-	EY =< EZ ->
-	    keysplit_1_1(I, Y, EY, Z, EZ, L, [X | R], Rs, S, ES);
-	EX =< EZ ->
-	    keysplit_1_1(I, Z, EZ, Y, EY, L, [X | R], Rs, S, ES);
-	ES =< EZ ->
-	    keysplit_1(I, S, ES, Z, EZ, L, [], [[Y, X | R] | Rs]);
-	true ->
-	    keysplit_1(I, Z, EZ, S, ES, L, [], [[Y, X | R] | Rs])
-    end;
-keysplit_1_1(I, X, _EX, Y, _EY, [], R, Rs, S, _ES) ->
-    rkeymergel(I, [[S], [Y, X | R] | Rs], []).
-
-%% Descending.
-keysplit_2(I, Y, EY, [Z | L], R) ->
-    EZ = element(I, Z),
-    if
-	EY =< EZ ->
-            keysplit_1(I, Y, EY, Z, EZ, L, [], [lists:reverse(R, [])]);
-        true ->
-            keysplit_2(I, Z, EZ, L, [Y | R])
-    end;
-keysplit_2(_I, Y, _EY, [], R) ->
-    [Y | R].
-
-keymergel(I, [T1, [H2 | T2] | L], Acc) ->
-    keymergel(I, L, [keymerge2_1(I, T1, element(I, H2), H2, T2, []) | Acc]);
-keymergel(_I, [L], []) ->
-    L;
-keymergel(I, [L], Acc) ->
-    rkeymergel(I, [lists:reverse(L, []) | Acc], []);
-keymergel(I, [], Acc) ->
-    rkeymergel(I, Acc, []).
-
-rkeymergel(I, [[H2 | T2], T1 | L], Acc) ->
-    rkeymergel(I, L, [rkeymerge2_1(I, T1, element(I, H2), H2, T2, []) | Acc]);
-rkeymergel(I, [L], Acc) ->
-    keymergel(I, [lists:reverse(L, []) | Acc], []);
-rkeymergel(I, [], Acc) ->
-    keymergel(I, Acc, []).
-
-keymerge2_1(I, [H1 | T1], E2, H2, T2, M) ->
-    E1 = element(I, H1),
-    if 
-	E1 =< E2 ->
-	    keymerge2_1(I, T1, E2, H2, T2, [H1 | M]);
-	true ->
-	    keymerge2_2(I, T1, E1, H1, T2, [H2 | M])
-    end;
-keymerge2_1(_I, [], _E2, H2, T2, M) ->
-    lists:reverse(T2, [H2 | M]).
-
-keymerge2_2(I, T1, E1, H1, [H2 | T2], M) ->
-    E2 = element(I, H2),
-    if
-	E1 =< E2 ->
-	    keymerge2_1(I, T1, E2, H2, T2, [H1 | M]);
-	true ->
-	    keymerge2_2(I, T1, E1, H1, T2, [H2 | M])
-    end;
-keymerge2_2(_I, T1, _E1, H1, [], M) ->
-    lists:reverse(T1, [H1 | M]).
-
-rkeymerge2_1(I, [H1 | T1], E2, H2, T2, M) ->
-    E1 = element(I, H1),
-    if
-	E1 =< E2 ->
-	    rkeymerge2_2(I, T1, E1, T2, [H2 | M], H1);
-	true ->
-	    rkeymerge2_1(I, T1, E2, H2, T2, [H1 | M])
-    end;
-rkeymerge2_1(_I, [], _E2, H2, T2, M) ->
-    lists:reverse(T2, [H2 | M]).
-
-rkeymerge2_2(I, T1, E1, [H2 | T2], M, H1) ->
-    E2 = element(I, H2),
-    if
-	E1 =< E2 ->
-	    rkeymerge2_2(I, T1, E1, T2, [H2 | M], H1);
-	true ->
-	    rkeymerge2_1(I, T1, E2, H2, T2, [H1 | M])
-    end;
-rkeymerge2_2(_I, T1, _E1, [], M, H1) ->
-    lists:reverse(T1, [H1 | M]).
-
+    io:format("usort:  ~p~n", [S#state.usort]).
 
 %%%------------------------------------------------------------
 
@@ -2543,7 +1719,6 @@ sublist_3_e(Config) when is_list(Config) ->
 
 
 -define(flatten_error1(X), {'EXIT', _} = (catch lists:flatten(X))).
--define(flatten_error2(X,Y), {'EXIT', _} = (catch lists:flatten(X,Y))).
 
 %% Test lists:flatten/1,2 and lists:flatlength/1.
 flatten_1(Config) when is_list(Config) ->
-- 
2.35.3

openSUSE Build Service is sponsored by