File 0536-Do-not-allocate-new-bitstring-binary-on-empty-append.patch of Package erlang

From faf6b3809544f40043b82552742572b6fa9bb339 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20Valim?= <jose.valim@plataformatec.com.br>
Date: Thu, 13 Dec 2018 14:21:16 +0100
Subject: [PATCH 1/2] Do not allocate new bitstring/binary on empty append

---
 erts/emulator/beam/erl_bits.c             | 37 ++++++++++++++++++++++---------
 erts/emulator/test/bs_construct_SUITE.erl | 14 ++++++++++--
 2 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c
index e82c776e70..051feb5977 100644
--- a/erts/emulator/beam/erl_bits.c
+++ b/erts/emulator/beam/erl_bits.c
@@ -1331,6 +1331,10 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
 	}
     }
 
+    if (build_size_in_bits == 0) {
+	goto return_bin;
+    }
+
     if((ERTS_UINT_MAX - build_size_in_bits) < erts_bin_offset) {
         c_p->freason = SYSTEM_LIMIT;
         return THE_NON_VALUE;
@@ -1388,16 +1392,6 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
 	Uint bitsize;
 	Eterm* hp;
 
-	/*
-	 * Allocate heap space.
-	 */
-	heap_need = PROC_BIN_SIZE + ERL_SUB_BIN_SIZE + extra_words;
-	if (c_p->stop - c_p->htop < heap_need) {
-	    (void) erts_garbage_collect(c_p, heap_need, reg, live+1);
-	    bin = reg[live];
-	}
-	hp = c_p->htop;
-
 	/*
 	 * Calculate sizes. The size of the new binary, is the sum of the
 	 * build size and the size of the old binary. Allow some room
@@ -1412,6 +1406,19 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
 	    }
 	}
 
+	if (build_size_in_bits == 0) {
+	    goto return_bin;
+	}
+
+	/*
+	 * Allocate heap space.
+	 */
+	heap_need = PROC_BIN_SIZE + ERL_SUB_BIN_SIZE + extra_words;
+	if (c_p->stop - c_p->htop < heap_need) {
+	    (void) erts_garbage_collect(c_p, heap_need, reg, live+1);
+	}
+	hp = c_p->htop;
+
         if((ERTS_UINT_MAX - build_size_in_bits) < erts_bin_offset) {
             c_p->freason = SYSTEM_LIMIT;
             return THE_NON_VALUE;
@@ -1471,6 +1478,16 @@ erts_bs_append(Process* c_p, Eterm* reg, Uint live, Eterm build_size_term,
 
 	return make_binary(sb);
     }
+
+ return_bin:
+    {
+	if (c_p->stop - c_p->htop < extra_words) {
+	    reg[live] = bin;
+	    (void) erts_garbage_collect(c_p, extra_words, reg, live+1);
+	    bin = reg[live];
+	}
+	return bin;
+    }
 }
 
 Eterm
diff --git a/erts/emulator/test/bs_construct_SUITE.erl b/erts/emulator/test/bs_construct_SUITE.erl
index ce50bcdd86..ad05cb3689 100644
--- a/erts/emulator/test/bs_construct_SUITE.erl
+++ b/erts/emulator/test/bs_construct_SUITE.erl
@@ -26,7 +26,7 @@
          init_per_suite/1, end_per_suite/1,
 	 test1/1, test2/1, test3/1, test4/1, test5/1, testf/1,
 	 not_used/1, in_guard/1,
-	 mem_leak/1, coerce_to_float/1, bjorn/1,
+	 mem_leak/1, coerce_to_float/1, bjorn/1, append_empty_is_same/1,
 	 huge_float_field/1, huge_binary/1, system_limit/1, badarg/1,
 	 copy_writable_binary/1, kostis/1, dynamic/1, bs_add/1,
 	 otp_7422/1, zero_width/1, bad_append/1, bs_add_overflow/1]).
@@ -39,7 +39,7 @@ suite() ->
 
 all() -> 
     [test1, test2, test3, test4, test5, testf, not_used,
-     in_guard, mem_leak, coerce_to_float, bjorn,
+     in_guard, mem_leak, coerce_to_float, bjorn, append_empty_is_same,
      huge_float_field, huge_binary, system_limit, badarg,
      copy_writable_binary, kostis, dynamic, bs_add, otp_7422, zero_width,
      bad_append, bs_add_overflow].
@@ -520,6 +520,16 @@ do_more(Bin, Sz) ->
 do_something() ->
     throw(blurf).
 
+append_empty_is_same(Config) when is_list(Config) ->
+    NonWritableBin = <<"123">>,
+    true = erts_debug:same(NonWritableBin, append(NonWritableBin, <<>>)),
+    WritableBin = <<(id(<<>>))/binary,0,1,2,3,4,5,6,7>>,
+    true = erts_debug:same(WritableBin, append(WritableBin, <<>>)),
+    ok.
+
+append(A, B) ->
+    <<A/binary, B/binary>>.
+
 huge_float_field(Config) when is_list(Config) ->
     {'EXIT',{badarg,_}} = (catch <<0.0:9/float-unit:8>>),
     huge_float_check(catch <<0.0:67108865/float-unit:64>>),
-- 
2.16.4

openSUSE Build Service is sponsored by