aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/binary.c80
-rw-r--r--erts/emulator/test/binary_SUITE.erl17
2 files changed, 47 insertions, 50 deletions
diff --git a/erts/emulator/beam/binary.c b/erts/emulator/beam/binary.c
index a18228b84a..4ddf59092a 100644
--- a/erts/emulator/beam/binary.c
+++ b/erts/emulator/beam/binary.c
@@ -1153,51 +1153,47 @@ BIF_RETTYPE list_to_bitstring_1(BIF_ALIST_1)
BIF_RETTYPE split_binary_2(BIF_ALIST_2)
{
- Uint pos;
- ErlSubBin* sb1;
- ErlSubBin* sb2;
- size_t orig_size;
- Eterm orig;
- Uint offset;
- Uint bit_offset;
- Uint bit_size;
- Eterm* hp;
+ size_t orig_size, left_size, right_size;
+ Uint byte_offset, bit_offset, bit_size;
+ Uint split_at;
+
+ Eterm *hp, *hp_end;
+ Eterm left, right;
+ Eterm real_bin;
+ Eterm result;
+ byte *bptr;
if (is_not_binary(BIF_ARG_1)) {
- goto error;
- }
- if (!term_to_Uint(BIF_ARG_2, &pos)) {
- goto error;
- }
- if ((orig_size = binary_size(BIF_ARG_1)) < pos) {
- goto error;
+ BIF_ERROR(BIF_P, BADARG);
+ } else if (!term_to_Uint(BIF_ARG_2, &split_at)) {
+ BIF_ERROR(BIF_P, BADARG);
+ } else if ((orig_size = binary_size(BIF_ARG_1)) < split_at) {
+ BIF_ERROR(BIF_P, BADARG);
}
- hp = HAlloc(BIF_P, 2*ERL_SUB_BIN_SIZE+3);
- ERTS_GET_REAL_BIN(BIF_ARG_1, orig, offset, bit_offset, bit_size);
- sb1 = (ErlSubBin *) hp;
- sb1->thing_word = HEADER_SUB_BIN;
- sb1->size = pos;
- sb1->offs = offset;
- sb1->orig = orig;
- sb1->bitoffs = bit_offset;
- sb1->bitsize = 0;
- sb1->is_writable = 0;
- hp += ERL_SUB_BIN_SIZE;
-
- sb2 = (ErlSubBin *) hp;
- sb2->thing_word = HEADER_SUB_BIN;
- sb2->size = orig_size - pos;
- sb2->offs = offset + pos;
- sb2->orig = orig;
- sb2->bitoffs = bit_offset;
- sb2->bitsize = bit_size; /* The extra bits go into the second binary. */
- sb2->is_writable = 0;
- hp += ERL_SUB_BIN_SIZE;
-
- return TUPLE2(hp, make_binary(sb1), make_binary(sb2));
-
- error:
- BIF_ERROR(BIF_P, BADARG);
+
+ left_size = split_at;
+ right_size = orig_size - split_at;
+
+ ERTS_GET_REAL_BIN(BIF_ARG_1, real_bin, byte_offset, bit_offset, bit_size);
+ bptr = binary_bytes(real_bin);
+
+ hp = HAlloc(BIF_P, EXTRACT_SUB_BIN_HEAP_NEED * 2 + 3);
+ hp_end = hp + (EXTRACT_SUB_BIN_HEAP_NEED * 2 + 3);
+
+ left = erts_extract_sub_binary(&hp, real_bin, bptr,
+ byte_offset * 8 + bit_offset,
+ left_size * 8);
+
+ right = erts_extract_sub_binary(&hp, real_bin, bptr,
+ (byte_offset + split_at) * 8 + bit_offset,
+ right_size * 8 + bit_size);
+
+ result = TUPLE2(hp, left, right);
+ hp += 3;
+
+ HRelease(BIF_P, hp_end, hp);
+
+ return result;
}
diff --git a/erts/emulator/test/binary_SUITE.erl b/erts/emulator/test/binary_SUITE.erl
index 4fb339926e..fbd1325c3a 100644
--- a/erts/emulator/test/binary_SUITE.erl
+++ b/erts/emulator/test/binary_SUITE.erl
@@ -1438,7 +1438,8 @@ sleeper() ->
gc_test(Config) when is_list(Config) ->
%% Note: This test is only relevant for REFC binaries.
%% Therefore, we take care that all binaries are REFC binaries.
- B = list_to_binary(lists:seq(0, ?heap_binary_size)),
+ true = 192 > ?heap_binary_size,
+ B = list_to_binary(lists:seq(1, 192)),
Self = self(),
F1 = fun() ->
gc(),
@@ -1447,22 +1448,22 @@ gc_test(Config) when is_list(Config) ->
end,
F = fun() ->
receive go -> ok end,
- {binary,[{_,65,1}]} = process_info(self(), binary),
+ {binary,[{_,192,1}]} = process_info(self(), binary),
gc(),
- {B1,B2} = my_split_binary(B, 4),
+ {B1,B2} = my_split_binary(B, 68),
gc(),
gc(),
{binary,L1} = process_info(self(), binary),
[Binfo1,Binfo2,Binfo3] = L1,
- {_,65,3} = Binfo1 = Binfo2 = Binfo3,
- 65 = size(B),
- 4 = size(B1),
- 61 = size(B2),
+ {_,192,3} = Binfo1 = Binfo2 = Binfo3,
+ 192 = size(B),
+ 68 = size(B1),
+ 124 = size(B2),
F1()
end,
gc(),
gc(),
- 65 = size(B),
+ 192 = size(B),
gc_test1(spawn_opt(erlang, apply, [F,[]], [link,{fullsweep_after,0}])).
gc_test1(Pid) ->