File 4623-erts-Use-hash_foreach-instead-of-manual-loop.patch of Package erlang

From 0cf06f07be27de4219743df3098c8cf66b3848c2 Mon Sep 17 00:00:00 2001
From: Lukas Larsson <lukas@erlang.org>
Date: Fri, 9 Aug 2019 14:27:20 +0200
Subject: [PATCH 3/6] erts: Use hash_foreach instead of manual loop

---
 erts/emulator/beam/erl_fun.c  | 91 ++++++++++++++++++++-----------------------
 erts/emulator/beam/index.c    | 45 +++++++++------------
 erts/emulator/beam/register.c | 51 ++++++++++--------------
 3 files changed, 81 insertions(+), 106 deletions(-)

diff --git a/erts/emulator/beam/erl_fun.c b/erts/emulator/beam/erl_fun.c
index 257f9bf5b3..79a1fdb8b9 100644
--- a/erts/emulator/beam/erl_fun.c
+++ b/erts/emulator/beam/erl_fun.c
@@ -171,36 +171,33 @@ erts_erase_fun_entry(ErlFunEntry* fe)
     erts_fun_write_unlock();
 }
 
+struct fun_purge_foreach_args {
+    BeamInstr *start;
+    BeamInstr *end;
+};
+
+static void fun_purge_foreach(ErlFunEntry *fe, struct fun_purge_foreach_args *arg)
+{
+    BeamInstr* addr = fe->address;
+    if (arg->start <= addr && addr < arg->end) {
+        fe->pend_purge_address = addr;
+        ERTS_THR_WRITE_MEMORY_BARRIER;
+        fe->address = unloaded_fun;
+#ifdef HIPE
+        fe->pend_purge_native_address = fe->native_address;
+        hipe_set_closure_stub(fe);
+#endif
+        erts_purge_state_add_fun(fe);
+    }
+}
+
 void
 erts_fun_purge_prepare(BeamInstr* start, BeamInstr* end)
 {
-    int limit;
-    HashBucket** bucket;
-    int i;
+    struct fun_purge_foreach_args args = {start, end};
 
     erts_fun_read_lock();
-    limit = erts_fun_table.size;
-    bucket = erts_fun_table.bucket;
-    for (i = 0; i < limit; i++) {
-	HashBucket* b = bucket[i];
-
-	while (b) {
-	    ErlFunEntry* fe = (ErlFunEntry *) b;
-	    BeamInstr* addr = fe->address;
-
-	    if (start <= addr && addr < end) {
-		fe->pend_purge_address = addr;
-		ERTS_THR_WRITE_MEMORY_BARRIER;
-		fe->address = unloaded_fun;
-#ifdef HIPE
-                fe->pend_purge_native_address = fe->native_address;
-                hipe_set_closure_stub(fe);
-#endif
-		erts_purge_state_add_fun(fe);
-	    }
-	    b = b->next;
-	}
-    }
+    hash_foreach(&erts_fun_table, (HFOREACH_FUN)fun_purge_foreach, &args);
     erts_fun_read_unlock();
 }
 
@@ -250,36 +247,34 @@ erts_fun_purge_complete(ErlFunEntry **funs, Uint no)
     ERTS_THR_WRITE_MEMORY_BARRIER;
 }
 
+struct dump_fun_foreach_args {
+    fmtfn_t to;
+    void *to_arg;
+};
+
+static void
+dump_fun_foreach(ErlFunEntry *fe, struct dump_fun_foreach_args *args)
+{
+    erts_print(args->to, args->to_arg, "=fun\n");
+    erts_print(args->to, args->to_arg, "Module: %T\n", fe->module);
+    erts_print(args->to, args->to_arg, "Uniq: %d\n", fe->old_uniq);
+    erts_print(args->to, args->to_arg, "Index: %d\n",fe->old_index);
+    erts_print(args->to, args->to_arg, "Address: %p\n", fe->address);
+#ifdef HIPE
+    erts_print(args->to, args->to_arg, "Native_address: %p\n", fe->native_address);
+#endif
+    erts_print(args->to, args->to_arg, "Refc: %ld\n", erts_refc_read(&fe->refc, 1));
+}
+
 void
 erts_dump_fun_entries(fmtfn_t to, void *to_arg)
 {
-    int limit;
-    HashBucket** bucket;
-    int i;
+    struct dump_fun_foreach_args args = {to, to_arg};
     int lock = !ERTS_IS_CRASH_DUMPING;
 
-
     if (lock)
 	erts_fun_read_lock();
-    limit = erts_fun_table.size;
-    bucket = erts_fun_table.bucket;
-    for (i = 0; i < limit; i++) {
-	HashBucket* b = bucket[i];
-
-	while (b) {
-	    ErlFunEntry* fe = (ErlFunEntry *) b;
-	    erts_print(to, to_arg, "=fun\n");
-	    erts_print(to, to_arg, "Module: %T\n", fe->module);
-	    erts_print(to, to_arg, "Uniq: %d\n", fe->old_uniq);
-	    erts_print(to, to_arg, "Index: %d\n",fe->old_index);
-	    erts_print(to, to_arg, "Address: %p\n", fe->address);
-#ifdef HIPE
-	    erts_print(to, to_arg, "Native_address: %p\n", fe->native_address);
-#endif
-	    erts_print(to, to_arg, "Refc: %ld\n", erts_refc_read(&fe->refc, 1));
-	    b = b->next;
-	}
-    }
+    hash_foreach(&erts_fun_table, (HFOREACH_FUN)dump_fun_foreach, &args);
     if (lock)
 	erts_fun_read_unlock();
 }
diff --git a/erts/emulator/beam/index.c b/erts/emulator/beam/index.c
index be1771b037..09d3c24424 100644
--- a/erts/emulator/beam/index.c
+++ b/erts/emulator/beam/index.c
@@ -114,35 +114,26 @@ int index_get(IndexTable* t, void* tmpl)
     return -1;
 }
 
-void erts_index_merge(Hash* src, IndexTable* dst)
+static void index_merge_foreach(IndexSlot *p, IndexTable *dst)
 {
-    int limit = src->size;
-    HashBucket** bucket = src->bucket;
-    int i;
-
-    for (i = 0; i < limit; i++) {
-	HashBucket* b = bucket[i];
-	IndexSlot* p;
-	int ix;
-
-	while (b) {
-	    Uint sz;
-	    ix = dst->entries++;
-	    if (ix >= dst->size) {
-		if (ix >= dst->limit) {
-		    erts_exit(ERTS_ERROR_EXIT, "no more index entries in %s (max=%d)\n",
-			     dst->htable.name, dst->limit);
-		}
-		sz = INDEX_PAGE_SIZE*sizeof(IndexSlot*);
-		dst->seg_table[ix>>INDEX_PAGE_SHIFT] = erts_alloc(dst->type, sz);
-		dst->size += INDEX_PAGE_SIZE;
-	    }
-	    p = (IndexSlot*) b;
-	    p->index = ix;
-	    dst->seg_table[ix>>INDEX_PAGE_SHIFT][ix&INDEX_PAGE_MASK] = p;
-	    b = b->next;
-	}
+    Uint sz;
+    int ix = dst->entries++;
+    if (ix >= dst->size) {
+        if (ix >= dst->limit) {
+            erts_exit(ERTS_ERROR_EXIT, "no more index entries in %s (max=%d)\n",
+                      dst->htable.name, dst->limit);
+        }
+        sz = INDEX_PAGE_SIZE*sizeof(IndexSlot*);
+        dst->seg_table[ix>>INDEX_PAGE_SHIFT] = erts_alloc(dst->type, sz);
+        dst->size += INDEX_PAGE_SIZE;
     }
+    p->index = ix;
+    dst->seg_table[ix>>INDEX_PAGE_SHIFT][ix&INDEX_PAGE_MASK] = p;
+}
+
+void erts_index_merge(Hash* src, IndexTable* dst)
+{
+    hash_foreach(src, (HFOREACH_FUN)index_merge_foreach, dst);
 }
 
 void index_erase_latest_from(IndexTable* t, Uint from_ix)
diff --git a/erts/emulator/beam/register.c b/erts/emulator/beam/register.c
index 2b50f5a303..d69632d8c8 100644
--- a/erts/emulator/beam/register.c
+++ b/erts/emulator/beam/register.c
@@ -580,15 +580,24 @@ int process_reg_sz(void)
 
 #include "bif.h"
 
+struct registered_foreach_arg {
+    Eterm res;
+    Eterm *hp;
+};
+
+static void
+registered_foreach(RegProc *reg, struct registered_foreach_arg *arg)
+{
+    arg->res = CONS(arg->hp, reg->name, arg->res);
+    arg->hp += 2;
+}
+
 /* return a list of the registered processes */
 
 BIF_RETTYPE registered_0(BIF_ALIST_0)
 {
-    int i;
-    Eterm res;
+    struct registered_foreach_arg arg;
     Uint need;
-    Eterm* hp;
-    HashBucket **bucket;
     ErtsProcLocks proc_locks = ERTS_PROC_LOCK_MAIN;
 
     ERTS_CHK_HAVE_ONLY_MAIN_PROC_LOCK(BIF_P);
@@ -596,41 +605,21 @@ BIF_RETTYPE registered_0(BIF_ALIST_0)
     if (!proc_locks)
 	erts_proc_lock(BIF_P, ERTS_PROC_LOCK_MAIN);
 
-    bucket = process_reg.bucket;
-
-    /* work out how much heap we need & maybe garb, by scanning through
-       the registered process table */
-    need = 0;
-    for (i = 0; i < process_reg.size; i++) {
-	HashBucket *b = bucket[i];
-	while (b != NULL) {
-	    need += 2;
-	    b = b->next;
-	}
-    }
+    /* work out how much heap we need */
+    need = process_reg.nobjs * 2;
 
     if (need == 0) {
 	reg_read_unlock();
 	BIF_RET(NIL);
     }
 
-    hp = HAlloc(BIF_P, need);
-     
-     /* scan through again and make the list */ 
-    res = NIL;
+    /* scan through again and make the list */
+    arg.hp = HAlloc(BIF_P, need);
+    arg.res = NIL;
 
-    for (i = 0; i < process_reg.size; i++) {
-	HashBucket *b = bucket[i];
-	while (b != NULL) {
-	    RegProc *reg = (RegProc *) b;
-
-	    res = CONS(hp, reg->name, res);
-	    hp += 2;
-	    b = b->next;
-	}
-    }
+    hash_foreach(&process_reg, (HFOREACH_FUN)registered_foreach, &arg);
 
     reg_read_unlock();
 
-    BIF_RET(res);
+    BIF_RET(arg.res);
 }
-- 
2.16.4

openSUSE Build Service is sponsored by