File 0733-erts-Fix-reduction-counting-in-binary-match-BIFs.patch of Package erlang

From c4239549ad9378ea6db30065ab1756c7d6724858 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20H=C3=B6gberg?= <john@erlang.org>
Date: Tue, 16 May 2023 11:21:33 +0200
Subject: [PATCH 2/2] erts: Fix reduction counting in binary match BIFs

---
 erts/emulator/beam/erl_bif_binary.c | 31 ++++++++++++++---------------
 1 file changed, 15 insertions(+), 16 deletions(-)

diff --git a/erts/emulator/beam/erl_bif_binary.c b/erts/emulator/beam/erl_bif_binary.c
index 884cf792db..453a091b1e 100644
--- a/erts/emulator/beam/erl_bif_binary.c
+++ b/erts/emulator/beam/erl_bif_binary.c
@@ -646,7 +646,7 @@ static BFReturn ac_find_first_match(BinaryFindContext *ctx, byte *haystack)
     register Uint reds = *reductions;
 
     while (i < len) {
-	if (--reds == 0) {
+	if (reds == 0) {
 	    state->q = q;
 	    state->pos = i;
 	    state->len = len;
@@ -655,6 +655,8 @@ static BFReturn ac_find_first_match(BinaryFindContext *ctx, byte *haystack)
 	    return BF_RESTART;
 	}
 
+    reds--;
+
 	while (q->g[haystack[i]] == NULL && q->h != q) {
 	    q = q->h;
 	}
@@ -844,23 +846,22 @@ static BFReturn bm_find_first_match(BinaryFindContext *ctx, byte *haystack)
     Sint mem_read = len - needle_last - j;
 
     if (mem_read <= 0) {
-	return BF_NOT_FOUND;
+        return BF_NOT_FOUND;
     }
-    mem_read = MIN(mem_read, reds * MC_LOOP_FACTOR);
+
+    /* Save at least one reduction for the loop below. */
+    mem_read = MIN(mem_read, 1 + (reds - 1) * MC_LOOP_FACTOR);
     ASSERT(mem_read > 0);
 
     pos_pointer = memchr(&haystack[j + needle_last], needle[needle_last], mem_read);
     if (pos_pointer == NULL) {
-	reds -= mem_read / MC_LOOP_FACTOR;
-	j += mem_read;
+        reds -= mem_read / MC_LOOP_FACTOR;
+        j += mem_read;
     } else {
-	reds -= (pos_pointer - &haystack[j]) / MC_LOOP_FACTOR;
-	j = pos_pointer - haystack - needle_last;
+        reds -= (pos_pointer - &haystack[j]) / MC_LOOP_FACTOR;
+        j = pos_pointer - haystack - needle_last;
     }
 
-    // Ensure we have at least one reduction before entering the loop
-    ++reds;
-
     for(;;) {
 	if (j > len - blen) {
 	    *reductions = reds;
@@ -934,7 +935,8 @@ static BFReturn bm_find_all_non_overlapping(BinaryFindContext *ctx, byte *haysta
 	    if(mem_read <= 0) {
 		goto done;
 	    }
-	    mem_read = MIN(mem_read, reds * MC_LOOP_FACTOR);
+            /* Save at least one reduction for the loop below. */
+	    mem_read = MIN(mem_read, 1 + (reds - 1) * MC_LOOP_FACTOR);
 	    ASSERT(mem_read > 0);
 	    pos_pointer = memchr(&haystack[j + needle_last], needle[needle_last], mem_read);
 	    if (pos_pointer == NULL) {
@@ -944,8 +946,6 @@ static BFReturn bm_find_all_non_overlapping(BinaryFindContext *ctx, byte *haysta
 		reds -= (pos_pointer - &haystack[j]) / MC_LOOP_FACTOR;
 		j = pos_pointer - haystack - needle_last;
 	    }
-	    // Ensure we have at least one reduction when resuming the loop
-	    ++reds;
 	}
 	if (j > len - blen) {
 	    goto done;
@@ -1463,7 +1463,6 @@ static BFReturn do_binary_find(Process *p, Eterm subject, BinaryFindContext **ct
 	    }
 	    erts_free_aligned_binary_bytes(temp_alloc);
 	    *res_term = THE_NON_VALUE;
-	    BUMP_ALL_REDS(p);
 	    return BF_RESTART;
 	} else {
 	    *res_term = ctx->found(p, subject, &ctx);
@@ -1474,7 +1473,6 @@ static BFReturn do_binary_find(Process *p, Eterm subject, BinaryFindContext **ct
 	    if (is_first_call) {
 		erts_set_gc_state(p, 0);
 	    }
-	    BUMP_ALL_REDS(p);
 	    return BF_RESTART;
 	}
 	if (ctx->search->done != NULL) {
@@ -1494,7 +1492,6 @@ static BFReturn do_binary_find(Process *p, Eterm subject, BinaryFindContext **ct
 	    if (is_first_call) {
 		erts_set_gc_state(p, 0);
 	    }
-	    BUMP_ALL_REDS(p);
 	    return BF_RESTART;
 	}
 	if (ctx->search->done != NULL) {
@@ -1555,6 +1552,7 @@ binary_match(Process *p, Eterm arg1, Eterm arg2, Eterm arg3, Uint flags)
     case BF_OK:
 	BIF_RET(result);
     case BF_RESTART:
+        BUMP_ALL_REDS(p);
 	ASSERT(result == THE_NON_VALUE && ctx->trap_term != result && ctx->pat_term != result);
 	BIF_TRAP3(&binary_find_trap_export, p, arg1, ctx->trap_term, ctx->pat_term);
     default:
@@ -1616,6 +1614,7 @@ binary_split(Process *p, Eterm arg1, Eterm arg2, Eterm arg3)
     case BF_OK:
 	BIF_RET(result);
     case BF_RESTART:
+        BUMP_ALL_REDS(p);
 	ASSERT(result == THE_NON_VALUE && ctx->trap_term != result && ctx->pat_term != result);
 	BIF_TRAP3(&binary_find_trap_export, p, arg1, ctx->trap_term, ctx->pat_term);
     default:
-- 
2.35.3

openSUSE Build Service is sponsored by