summaryrefslogtreecommitdiff
path: root/erts
diff options
context:
space:
mode:
authorSverker Eriksson <sverker@erlang.org>2021-05-06 12:15:05 +0200
committerSverker Eriksson <sverker@erlang.org>2021-05-06 12:16:23 +0200
commita7d4b1a7867ec23edc2c4a41c965b83cfc6afdcb (patch)
tree517faa16b98f7ac5093a077021c915d89ea05c44 /erts
parentc3784253e168e4f7acf301015e5461eacf884e4e (diff)
parentae9b51e15c2f879741679e52f9b3b498195c49e2 (diff)
downloaderlang-a7d4b1a7867ec23edc2c4a41c965b83cfc6afdcb.tar.gz
Merge 'sverker/22/ets-matchspec-stack-bug/OTP-17379'
forward to OTP-23.3.1 as 'sverker/23/ets-matchspec-stack-bug/OTP-17379'
Diffstat (limited to 'erts')
-rw-r--r--erts/emulator/beam/erl_db_util.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index 2087e1c337..658ac44824 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -3837,6 +3837,7 @@ dmc_array(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(UWord) *text,
{
int all_constant = 1;
int textpos = DMC_STACK_NUM(*text);
+ int preventive_bumps = 0;
Uint i;
/*
@@ -3856,13 +3857,35 @@ dmc_array(DMCContext *context, DMCHeap *heap, DMC_STACK_TYPE(UWord) *text,
if (!c && all_constant) {
all_constant = 0;
if (i < nelems - 1) {
+ /* Revert preventive stack bumps as they will now be done again
+ * for real by do_emit_constant() */
+ context->stack_used -= preventive_bumps;
+
dmc_rearrange_constants(context, text, textpos,
p + i + 1, nelems - i - 1);
}
- } else if (c && !all_constant) {
- do_emit_constant(context, text, p[i]);
+ } else if (c) {
+ if (all_constant) {
+ /*
+ * OTP-17379:
+ * All constants so far, but do preventive stack bumps
+ * as the constants may later be converted to matchPushC
+ * by dmc_rearrange_constants above.
+ * Otherwise dmc_expr() may do incorrect stack depth estimation
+ * when it emits instructions for the first non-constant.
+ */
+ ++context->stack_used;
+ ++preventive_bumps;
+ }
+ else {
+ do_emit_constant(context, text, p[i]);
+ }
}
}
+ if (all_constant) {
+ /* Preventive stack bumps not needed */
+ context->stack_used -= preventive_bumps;
+ }
*constant = all_constant;
return retOk;
}