154154 stream_module :: module (),
155155 stream :: stream (),
156156 offset :: non_neg_integer (),
157- branches :: [{ non_neg_integer (), non_neg_integer (), non_neg_integer ()}],
157+ branches :: #{ integer () | reference () => [{ non_neg_integer (), non_neg_integer ()}]} ,
158158 jump_table_start :: non_neg_integer (),
159159 available_regs :: non_neg_integer (),
160160 used_regs :: non_neg_integer (),
161- labels :: [ {integer () | reference (), integer ()}] ,
161+ labels :: # {integer () | reference () => integer ()},
162162 variant :: non_neg_integer (),
163163 regs :: jit_regs :regs ()
164164}).
@@ -286,12 +286,12 @@ new(Variant, StreamModule, Stream) ->
286286 # state {
287287 stream_module = StreamModule ,
288288 stream = Stream ,
289- branches = [] ,
289+ branches = #{} ,
290290 jump_table_start = 0 ,
291291 offset = StreamModule :offset (Stream ),
292292 available_regs = ? AVAILABLE_REGS_MASK ,
293293 used_regs = 0 ,
294- labels = [] ,
294+ labels = #{} ,
295295 variant = Variant ,
296296 regs = jit_regs :new ()
297297 }.
@@ -465,27 +465,25 @@ patch_branch(StreamModule, Stream, Offset, Type, LabelOffset) ->
465465-spec patch_branches_for_label (
466466 module (),
467467 stream (),
468- integer (),
468+ integer () | reference () ,
469469 non_neg_integer (),
470- [{integer (), non_neg_integer (), any ()}]
471- ) -> {stream (), [{integer (), non_neg_integer (), any ()}]}.
470+ #{integer () | reference () => [{non_neg_integer (), non_neg_integer ()}]}
471+ ) ->
472+ {stream (), #{integer () | reference () => [{non_neg_integer (), non_neg_integer ()}]}}.
472473patch_branches_for_label (StreamModule , Stream , TargetLabel , LabelOffset , Branches ) ->
473- patch_branches_for_label (StreamModule , Stream , TargetLabel , LabelOffset , Branches , []).
474-
475- patch_branches_for_label (_StreamModule , Stream , _TargetLabel , _LabelOffset , [], Acc ) ->
476- {Stream , lists :reverse (Acc )};
477- patch_branches_for_label (
478- StreamModule ,
479- Stream0 ,
480- TargetLabel ,
481- LabelOffset ,
482- [{Label , Offset , Type } | Rest ],
483- Acc
484- ) when Label =:= TargetLabel ->
485- Stream1 = patch_branch (StreamModule , Stream0 , Offset , Type , LabelOffset ),
486- patch_branches_for_label (StreamModule , Stream1 , TargetLabel , LabelOffset , Rest , Acc );
487- patch_branches_for_label (StreamModule , Stream , TargetLabel , LabelOffset , [Branch | Rest ], Acc ) ->
488- patch_branches_for_label (StreamModule , Stream , TargetLabel , LabelOffset , Rest , [Branch | Acc ]).
474+ case Branches of
475+ #{TargetLabel := BrList } ->
476+ Stream1 = lists :foldl (
477+ fun ({Offset , Type }, AccStream ) ->
478+ patch_branch (StreamModule , AccStream , Offset , Type , LabelOffset )
479+ end ,
480+ Stream ,
481+ BrList
482+ ),
483+ {Stream1 , maps :remove (TargetLabel , Branches )};
484+ _ ->
485+ {Stream , Branches }
486+ end .
489487
490488% %-----------------------------------------------------------------------------
491489% % @doc Rewrite stream to update all branches for labels.
@@ -494,19 +492,29 @@ patch_branches_for_label(StreamModule, Stream, TargetLabel, LabelOffset, [Branch
494492% % @return Updated backend state
495493% %-----------------------------------------------------------------------------
496494-spec update_branches (state ()) -> state ().
497- update_branches (# state {branches = []} = State ) ->
498- State ;
499495update_branches (
500496 # state {
501497 stream_module = StreamModule ,
502498 stream = Stream0 ,
503- branches = [{ Label , Offset , Type } | BranchesT ] ,
499+ branches = Branches ,
504500 labels = Labels
505501 } = State
506502) ->
507- {Label , LabelOffset } = lists :keyfind (Label , 1 , Labels ),
508- Stream1 = patch_branch (StreamModule , Stream0 , Offset , Type , LabelOffset ),
509- update_branches (State # state {stream = Stream1 , branches = BranchesT }).
503+ Stream1 = maps :fold (
504+ fun (Label , BrList , AccStream ) ->
505+ #{Label := LabelOffset } = Labels ,
506+ lists :foldl (
507+ fun ({Offset , Type }, AccStream2 ) ->
508+ patch_branch (StreamModule , AccStream2 , Offset , Type , LabelOffset )
509+ end ,
510+ AccStream ,
511+ BrList
512+ )
513+ end ,
514+ Stream0 ,
515+ Branches
516+ ),
517+ State # state {stream = Stream1 , branches = #{}}.
510518
511519% %-----------------------------------------------------------------------------
512520% % @doc Emit a call (call with return) to a primitive with arguments. This
@@ -650,21 +658,22 @@ jump_to_label(
650658 Label
651659) ->
652660 Offset = StreamModule :offset (Stream0 ),
653- case lists : keyfind ( Label , 1 , Labels ) of
654- {Label , LabelOffset } ->
661+ case Labels of
662+ # {Label : = LabelOffset } ->
655663 % Label is already known, emit direct branch without relocation
656664 Rel = LabelOffset - Offset ,
657665 I1 = jit_aarch64_asm :b (Rel ),
658666 Stream1 = StreamModule :append (Stream0 , I1 ),
659667 State # state {stream = Stream1 , regs = jit_regs :unreachable (State # state .regs )};
660- false ->
668+ _ ->
661669 % Label not yet known, emit placeholder and add relocation
662670 I1 = jit_aarch64_asm :b (0 ),
663- Reloc = {Label , Offset , b },
671+ BrEntry = {Offset , b },
672+ ExistingBrs = maps :get (Label , AccBranches , []),
664673 Stream1 = StreamModule :append (Stream0 , I1 ),
665674 State # state {
666675 stream = Stream1 ,
667- branches = [ Reloc | AccBranches ] ,
676+ branches = AccBranches #{ Label => [ BrEntry | ExistingBrs ]} ,
668677 regs = jit_regs :unreachable (State # state .regs )
669678 }
670679 end .
@@ -2354,21 +2363,26 @@ set_continuation_to_label(
23542363 Temp = first_avail (Avail ),
23552364 Offset = StreamModule :offset (Stream0 ),
23562365 Regs1 = jit_regs :invalidate_reg (Regs0 , Temp ),
2357- case lists : keyfind ( Label , 1 , Labels ) of
2358- {Label , LabelOffset } ->
2366+ case Labels of
2367+ # {Label : = LabelOffset } ->
23592368 Rel = LabelOffset - Offset ,
23602369 I1 = jit_aarch64_asm :adr (Temp , Rel ),
23612370 I2 = jit_aarch64_asm :str (Temp , ? JITSTATE_CONTINUATION ),
23622371 Code = <<I1 /binary , I2 /binary >>,
23632372 Stream1 = StreamModule :append (Stream0 , Code ),
23642373 State # state {stream = Stream1 , regs = Regs1 };
2365- false ->
2374+ _ ->
23662375 I1 = jit_aarch64_asm :adr (Temp , 0 ),
2367- Reloc = {Label , Offset , {adr , Temp }},
2376+ BrEntry = {Offset , {adr , Temp }},
23682377 I2 = jit_aarch64_asm :str (Temp , ? JITSTATE_CONTINUATION ),
23692378 Code = <<I1 /binary , I2 /binary >>,
23702379 Stream1 = StreamModule :append (Stream0 , Code ),
2371- State # state {stream = Stream1 , branches = [Reloc | Branches ], regs = Regs1 }
2380+ ExistingBrs = maps :get (Label , Branches , []),
2381+ State # state {
2382+ stream = Stream1 ,
2383+ branches = Branches #{Label => [BrEntry | ExistingBrs ]},
2384+ regs = Regs1
2385+ }
23722386 end .
23732387
23742388% %-----------------------------------------------------------------------------
@@ -2393,12 +2407,19 @@ set_continuation_to_offset(
23932407 OffsetRef = make_ref (),
23942408 Offset = StreamModule :offset (Stream0 ),
23952409 I1 = jit_aarch64_asm :adr (Temp , 0 ),
2396- Reloc = {OffsetRef , Offset , {adr , Temp }},
2410+ BrEntry = {Offset , {adr , Temp }},
23972411 I2 = jit_aarch64_asm :str (Temp , ? JITSTATE_CONTINUATION ),
23982412 Code = <<I1 /binary , I2 /binary >>,
23992413 Stream1 = StreamModule :append (Stream0 , Code ),
24002414 Regs1 = jit_regs :invalidate_reg (Regs0 , Temp ),
2401- {State # state {stream = Stream1 , branches = [Reloc | Branches ], regs = Regs1 }, OffsetRef }.
2415+ {
2416+ State # state {
2417+ stream = Stream1 ,
2418+ branches = Branches #{OffsetRef => [BrEntry ]},
2419+ regs = Regs1
2420+ },
2421+ OffsetRef
2422+ }.
24022423
24032424% %-----------------------------------------------------------------------------
24042425% % @doc Implement a continuation entry point. On AArch64 this is a nop
@@ -2783,20 +2804,24 @@ call_only_or_schedule_next(
27832804 Stream1 = StreamModule :append (Stream0 , <<I1 /binary , I2 /binary , I3 /binary >>),
27842805 BNEOffset = StreamModule :offset (Stream1 ),
27852806
2786- case lists : keyfind ( Label , 1 , Labels ) of
2787- {Label , LabelOffset } ->
2807+ case Labels of
2808+ # {Label : = LabelOffset } ->
27882809 % Label is already known, emit direct branch with calculated offset
27892810 % Calculate relative offset (must be 4-byte aligned)
27902811 Rel = LabelOffset - BNEOffset ,
27912812 I4 = jit_aarch64_asm :bcc (ne , Rel ),
27922813 Stream2 = StreamModule :append (Stream1 , I4 ),
27932814 State1 = State0 # state {stream = Stream2 };
2794- false ->
2815+ _ ->
27952816 % Label not yet known, emit placeholder and add relocation
27962817 I4 = jit_aarch64_asm :bcc (ne , 0 ),
2797- Reloc1 = {Label , BNEOffset , {bcc , ne }},
2818+ BrEntry = {BNEOffset , {bcc , ne }},
2819+ ExistingBrs = maps :get (Label , Branches , []),
27982820 Stream2 = StreamModule :append (Stream1 , I4 ),
2799- State1 = State0 # state {stream = Stream2 , branches = [Reloc1 | Branches ]}
2821+ State1 = State0 # state {
2822+ stream = Stream2 ,
2823+ branches = Branches #{Label => [BrEntry | ExistingBrs ]}
2824+ }
28002825 end ,
28012826 State2 = set_continuation_to_label (State1 , Label ),
28022827 call_primitive_last (State2 , ? PRIM_SCHEDULE_NEXT_CP , [ctx , jit_state ]).
@@ -2894,7 +2919,7 @@ return_labels_and_lines(
28942919) ->
28952920 SortedLabels = lists :keysort (2 , [
28962921 {Label , LabelOffset }
2897- || {Label , LabelOffset } <- Labels , is_integer (Label )
2922+ || {Label , LabelOffset } <- maps : to_list ( Labels ) , is_integer (Label )
28982923 ]),
28992924
29002925 I1 = jit_aarch64_asm :adr (r0 , 8 ),
@@ -3049,10 +3074,10 @@ add_label(
30493074 ),
30503075
30513076 State # state {
3052- stream = Stream2 , branches = RemainingBranches , labels = [ {Label , LabelOffset } | Labels ]
3077+ stream = Stream2 , branches = RemainingBranches , labels = Labels # {Label => LabelOffset }
30533078 };
30543079add_label (# state {labels = Labels } = State , Label , Offset ) ->
3055- State # state {labels = [ {Label , Offset } | Labels ] }.
3080+ State # state {labels = Labels # {Label => Offset }}.
30563081
30573082- ifdef (JIT_DWARF ).
30583083% %-----------------------------------------------------------------------------
0 commit comments