Skip to content

Commit c179556

Browse files
committed
Optimize matching of little-endian segments
Multiple little-endians segments were handled one at a time. It turns out that it is safe to match out multiple little-endian segments at once, or even any mix of big and little endian segments at once.
1 parent 927c8a5 commit c179556

File tree

2 files changed

+93
-9
lines changed

2 files changed

+93
-9
lines changed

erts/emulator/beam/jit/beam_jit_bs.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -432,16 +432,13 @@ std::vector<BsmSegment> beam_jit_opt_bsm_segments(
432432

433433
if (seg.size > 64) {
434434
read_action_pos = -1;
435-
} else if ((seg.flags & BSF_LITTLE) != 0 && is_common_size) {
436-
seg.action = BsmSegment::action::READ_INTEGER;
437-
read_action_pos = -1;
438435
} else if (read_action_pos < 0 &&
439436
seg.action == BsmSegment::action::GET_INTEGER &&
440437
is_common_size && i + 1 == count) {
441438
seg.action = BsmSegment::action::READ_INTEGER;
442439
read_action_pos = -1;
443440
} else {
444-
if ((seg.flags & BSF_LITTLE) != 0 || read_action_pos < 0 ||
441+
if (read_action_pos < 0 ||
445442
seg.size + segs.at(read_action_pos).size > 64) {
446443
BsmSegment s;
447444

erts/emulator/test/bs_match_int_SUITE.erl

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,10 @@ cmp128(<<I:128>>, I) -> equal;
601601
cmp128(_, _) -> not_equal.
602602

603603
mixed_sizes(_Config) ->
604-
mixed({345,42},
604+
_ = rand:uniform(), %Seed generator
605+
io:format("Seed: ~p", [rand:export_seed()]),
606+
607+
deterministic_mixed({345,42},
605608
fun({A,B}) ->
606609
<<A:9,1:1,B:6>>;
607610
(<<A:9,_:1,B:6>>) ->
@@ -614,21 +617,44 @@ mixed_sizes(_Config) ->
614617
(<<A:16,B:16,C:32,D:22,E:2>>) ->
615618
{A,B,C,D,E}
616619
end),
620+
mixed({27033,59991,16#c001cafe,12345,2},
621+
fun({A,B,C,D,E}) ->
622+
<<A:16/little,B:16/little,C:32/little,
623+
D:22/little,E:2/little>>;
624+
(<<A:16/little,B:16/little,C:32/little,
625+
D:22/little,E:2/little>>) ->
626+
{A,B,C,D,E}
627+
end),
617628

618-
mixed({79,153,17555,50_000,777_000,36#hugebignumber,2222},
629+
deterministic_mixed({79,153,17555,50_000,777_000,36#hugebignumber,2222},
619630
fun({A,B,C,D,E,F,G}) ->
620631
<<A:7,B:8,C:15,0:3,D:17,E:23,F:88,G:13>>;
621632
(<<A:7,B:8,C:15,_:3,D:17,E:23,F:88,G:13>>) ->
622633
{A,B,C,D,E,F,G}
623634
end),
635+
deterministic_mixed({79,153,17555,50_000,777_000,36#hugebignumber,2222},
636+
fun({A,B,C,D,E,F,G}) ->
637+
<<A:7/little,B:8/little,C:15/little,0:3/little,
638+
D:17/little,E:23/little,F:88/little,G:13/little>>;
639+
(<<A:7/little,B:8/little,C:15/little,0:3/little,
640+
D:17/little,E:23/little,F:88/little,G:13/little>>) ->
641+
{A,B,C,D,E,F,G}
642+
end),
643+
deterministic_mixed({79,153,17555,50_000,777_000,36#hugebignumber,2222},
644+
fun({A,B,C,D,E,F,G}) ->
645+
<<A:7/little,B:8/big,C:15/little,0:3/little,
646+
D:17/little,E:23/big,F:88/little,G:13/big>>;
647+
(<<A:7/little,B:8/big,C:15/little,0:3/little,
648+
D:17/little,E:23/big,F:88/little,G:13/big>>) ->
649+
{A,B,C,D,E,F,G}
650+
end),
624651

625652
mixed({16#123456789ABCDEF,13,36#hugenum,979},
626653
fun({A,B,C,D}) ->
627654
<<A:60,B:4,C:50,D:10>>;
628655
(<<A:60,B:4,C:50,D:10>>) ->
629656
{A,B,C,D}
630657
end),
631-
632658
mixed({16#123456789ABCDEF,13,36#hugenum,979},
633659
fun({A,B,C,D}) ->
634660
<<A:60/little,B:4/little,C:50/little,D:10/little>>;
@@ -657,12 +683,20 @@ mixed_sizes(_Config) ->
657683
{A,B,C}
658684
end),
659685

660-
mixed({5,9,38759385,93},
686+
deterministic_mixed({5,9,38759385,93},
661687
fun({A,B,C,D}) ->
662688
<<1:3,A:4,B:5,C:47,D:7>>;
663689
(<<1:3,A:4,B:5,C:47,D:7>>) ->
664690
{A,B,C,D}
665691
end),
692+
deterministic_mixed({5,9,38759385,93},
693+
fun({A,B,C,D}) ->
694+
<<1:3/little,A:4/little,B:5/little,
695+
C:47/little,D:7/little>>;
696+
(<<1:3/little,A:4/little,B:5/little,
697+
C:47/little,D:7/little>>) ->
698+
{A,B,C,D}
699+
end),
666700

667701
mixed({2022,8,22},
668702
fun({A,B,C}) ->
@@ -678,12 +712,62 @@ mixed_sizes(_Config) ->
678712
_ = id(0),
679713
{A,B,C}
680714
end),
715+
716+
%% Additional roundtrip testing without facit.
717+
718+
mixed(fun({A,B,C,D}) ->
719+
<<A:11/little,B:13,C:19/little,D:77/little>>;
720+
(<<A:11/little,B:13,C:19/little,D:77/little>>) ->
721+
{A,B,C,D}
722+
end),
723+
724+
mixed(fun({A,B,C,D,E}) ->
725+
<<A:9/little,B:13,C:35/little,D:7,E:16/little>>;
726+
(<<A:9/little,B:13,C:35/little,D:7,E:16/little>>) ->
727+
{A,B,C,D,E}
728+
end),
729+
730+
mixed(fun({A,B,C,D,E,F,G,H}) ->
731+
<<A:20/little,B:4/little,C:5/little,D:8/little,
732+
E:18,F:42,G:30/little,H:33/little>>;
733+
(<<A:20/little,B:4/little,C:5/little,D:8/little,
734+
E:18,F:42,G:30/little,H:33/little>>) ->
735+
{A,B,C,D,E,F,G,H}
736+
end),
737+
681738
ok.
682739

740+
mixed(F) when is_function(F, 1) ->
741+
NumBits = mixed_bit_size(F, 1),
742+
rand_mixed(NumBits, F).
743+
744+
mixed_bit_size(F, N) when N < 1000 ->
745+
try F(erlang:make_tuple(N, 0)) of
746+
Bits when is_bitstring(Bits) ->
747+
bit_size(Bits)
748+
catch
749+
_:_ ->
750+
mixed_bit_size(F, N + 1)
751+
end.
752+
683753
mixed(Data, F) ->
754+
deterministic_mixed(Data, F),
755+
rand_mixed(bit_size(F(Data)), F).
756+
757+
deterministic_mixed(Data, F) ->
684758
Bin = F(Data),
685759
Data = F(Bin),
686-
true = is_bitstring(Bin).
760+
true = is_bitstring(Bin),
761+
UnalignedBin = make_unaligned_sub_binary(Bin),
762+
Data = F(UnalignedBin),
763+
true = is_bitstring(UnalignedBin).
764+
765+
rand_mixed(NumBits, F) ->
766+
<<Bin:NumBits/bits,_/bits>> = rand:bytes((NumBits + 7) div 8),
767+
Data = F(Bin),
768+
Bin = F(Data),
769+
UnalignedBin = make_unaligned_sub_binary(Bin),
770+
Data = F(UnalignedBin).
687771

688772
signed_integer(Config) when is_list(Config) ->
689773
{no_match,_} = sint(mkbin([])),
@@ -997,4 +1081,7 @@ unit(_Config) ->
9971081
%%% Common utilities.
9981082
%%%
9991083

1084+
make_unaligned_sub_binary(Bin) ->
1085+
erts_debug:unaligned_bitstring(Bin, 3).
1086+
10001087
id(I) -> I.

0 commit comments

Comments
 (0)