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