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 .
@@ -2386,21 +2395,26 @@ set_continuation_to_label(
23862395 Temp = first_avail (Avail ),
23872396 Offset = StreamModule :offset (Stream0 ),
23882397 Regs1 = jit_regs :invalidate_reg (Regs0 , Temp ),
2389- case lists : keyfind ( Label , 1 , Labels ) of
2390- {Label , LabelOffset } ->
2398+ case Labels of
2399+ # {Label : = LabelOffset } ->
23912400 Rel = LabelOffset - Offset ,
23922401 I1 = jit_aarch64_asm :adr (Temp , Rel ),
23932402 I2 = jit_aarch64_asm :str (Temp , ? JITSTATE_CONTINUATION ),
23942403 Code = <<I1 /binary , I2 /binary >>,
23952404 Stream1 = StreamModule :append (Stream0 , Code ),
23962405 State # state {stream = Stream1 , regs = Regs1 };
2397- false ->
2406+ _ ->
23982407 I1 = jit_aarch64_asm :adr (Temp , 0 ),
2399- Reloc = {Label , Offset , {adr , Temp }},
2408+ BrEntry = {Offset , {adr , Temp }},
24002409 I2 = jit_aarch64_asm :str (Temp , ? JITSTATE_CONTINUATION ),
24012410 Code = <<I1 /binary , I2 /binary >>,
24022411 Stream1 = StreamModule :append (Stream0 , Code ),
2403- State # state {stream = Stream1 , branches = [Reloc | Branches ], regs = Regs1 }
2412+ ExistingBrs = maps :get (Label , Branches , []),
2413+ State # state {
2414+ stream = Stream1 ,
2415+ branches = Branches #{Label => [BrEntry | ExistingBrs ]},
2416+ regs = Regs1
2417+ }
24042418 end .
24052419
24062420% %-----------------------------------------------------------------------------
@@ -2425,12 +2439,19 @@ set_continuation_to_offset(
24252439 OffsetRef = make_ref (),
24262440 Offset = StreamModule :offset (Stream0 ),
24272441 I1 = jit_aarch64_asm :adr (Temp , 0 ),
2428- Reloc = {OffsetRef , Offset , {adr , Temp }},
2442+ BrEntry = {Offset , {adr , Temp }},
24292443 I2 = jit_aarch64_asm :str (Temp , ? JITSTATE_CONTINUATION ),
24302444 Code = <<I1 /binary , I2 /binary >>,
24312445 Stream1 = StreamModule :append (Stream0 , Code ),
24322446 Regs1 = jit_regs :invalidate_reg (Regs0 , Temp ),
2433- {State # state {stream = Stream1 , branches = [Reloc | Branches ], regs = Regs1 }, OffsetRef }.
2447+ {
2448+ State # state {
2449+ stream = Stream1 ,
2450+ branches = Branches #{OffsetRef => [BrEntry ]},
2451+ regs = Regs1
2452+ },
2453+ OffsetRef
2454+ }.
24342455
24352456% %-----------------------------------------------------------------------------
24362457% % @doc Implement a continuation entry point. On AArch64 this is a nop
@@ -2815,20 +2836,24 @@ call_only_or_schedule_next(
28152836 Stream1 = StreamModule :append (Stream0 , <<I1 /binary , I2 /binary , I3 /binary >>),
28162837 BNEOffset = StreamModule :offset (Stream1 ),
28172838
2818- case lists : keyfind ( Label , 1 , Labels ) of
2819- {Label , LabelOffset } ->
2839+ case Labels of
2840+ # {Label : = LabelOffset } ->
28202841 % Label is already known, emit direct branch with calculated offset
28212842 % Calculate relative offset (must be 4-byte aligned)
28222843 Rel = LabelOffset - BNEOffset ,
28232844 I4 = jit_aarch64_asm :bcc (ne , Rel ),
28242845 Stream2 = StreamModule :append (Stream1 , I4 ),
28252846 State1 = State0 # state {stream = Stream2 };
2826- false ->
2847+ _ ->
28272848 % Label not yet known, emit placeholder and add relocation
28282849 I4 = jit_aarch64_asm :bcc (ne , 0 ),
2829- Reloc1 = {Label , BNEOffset , {bcc , ne }},
2850+ BrEntry = {BNEOffset , {bcc , ne }},
2851+ ExistingBrs = maps :get (Label , Branches , []),
28302852 Stream2 = StreamModule :append (Stream1 , I4 ),
2831- State1 = State0 # state {stream = Stream2 , branches = [Reloc1 | Branches ]}
2853+ State1 = State0 # state {
2854+ stream = Stream2 ,
2855+ branches = Branches #{Label => [BrEntry | ExistingBrs ]}
2856+ }
28322857 end ,
28332858 State2 = set_continuation_to_label (State1 , Label ),
28342859 call_primitive_last (State2 , ? PRIM_SCHEDULE_NEXT_CP , [ctx , jit_state ]).
@@ -2926,7 +2951,7 @@ return_labels_and_lines(
29262951) ->
29272952 SortedLabels = lists :keysort (2 , [
29282953 {Label , LabelOffset }
2929- || {Label , LabelOffset } <- Labels , is_integer (Label )
2954+ || {Label , LabelOffset } <- maps : to_list ( Labels ) , is_integer (Label )
29302955 ]),
29312956
29322957 I1 = jit_aarch64_asm :adr (r0 , 8 ),
@@ -3081,10 +3106,10 @@ add_label(
30813106 ),
30823107
30833108 State # state {
3084- stream = Stream2 , branches = RemainingBranches , labels = [ {Label , LabelOffset } | Labels ]
3109+ stream = Stream2 , branches = RemainingBranches , labels = Labels # {Label => LabelOffset }
30853110 };
30863111add_label (# state {labels = Labels } = State , Label , Offset ) ->
3087- State # state {labels = [ {Label , Offset } | Labels ] }.
3112+ State # state {labels = Labels # {Label => Offset }}.
30883113
30893114- ifdef (JIT_DWARF ).
30903115% %-----------------------------------------------------------------------------
0 commit comments