136136 branches :: [{non_neg_integer (), non_neg_integer (), non_neg_integer ()}],
137137 jump_table_start :: non_neg_integer (),
138138 available_regs :: [aarch64_register ()],
139- used_regs :: [ aarch64_register ()] ,
139+ used_regs :: jit_regs : regs () ,
140140 labels :: [{integer () | reference (), integer ()}],
141141 variant :: non_neg_integer ()
142142}).
@@ -238,7 +238,7 @@ new(Variant, StreamModule, Stream) ->
238238 jump_table_start = 0 ,
239239 offset = StreamModule :offset (Stream ),
240240 available_regs = ? AVAILABLE_REGS ,
241- used_regs = [] ,
241+ used_regs = jit_regs : new () ,
242242 labels = [],
243243 variant = Variant
244244 }.
@@ -293,7 +293,7 @@ debugger(#state{stream_module = StreamModule, stream = Stream0} = State) ->
293293% % @return The list of used registers
294294% %-----------------------------------------------------------------------------
295295-spec used_regs (state ()) -> [aarch64_register ()].
296- used_regs (# state {used_regs = Used }) -> Used .
296+ used_regs (# state {used_regs = Used }) -> lists : sort ( jit_regs : to_list ( Used )) .
297297
298298% %-----------------------------------------------------------------------------
299299% % @doc Return the list of currently available native scratch registers. This
@@ -343,7 +343,7 @@ free_native_register(State, _Other) ->
343343% %-----------------------------------------------------------------------------
344344-spec assert_all_native_free (state ()) -> ok .
345345assert_all_native_free (# state {
346- available_regs = ? AVAILABLE_REGS , used_regs = []
346+ available_regs = ? AVAILABLE_REGS , used_regs = #{}
347347}) ->
348348 ok .
349349
@@ -508,7 +508,7 @@ call_primitive_last(
508508 ArgsRegs = args_regs (Args ),
509509 ScratchRegs = ? AVAILABLE_REGS -- ArgsRegs -- ParamRegs ,
510510 [Temp | AvailableRegs1 ] = ScratchRegs ,
511- UsedRegs = ? AVAILABLE_REGS -- AvailableRegs1 ,
511+ UsedRegs = jit_regs : from_list ( ? AVAILABLE_REGS -- AvailableRegs1 ) ,
512512 PrepCall =
513513 case Primitive of
514514 0 ->
@@ -526,7 +526,7 @@ call_primitive_last(
526526 # state {stream = Stream2 } = State1 ,
527527 Call = jit_aarch64_asm :br (Temp ),
528528 Stream3 = StreamModule :append (Stream2 , Call ),
529- State1 # state {stream = Stream3 , available_regs = ? AVAILABLE_REGS , used_regs = [] }.
529+ State1 # state {stream = Stream3 , available_regs = ? AVAILABLE_REGS , used_regs = jit_regs : new () }.
530530
531531% %-----------------------------------------------------------------------------
532532% % @doc Emit a return of a value if it's not equal to ctx.
@@ -634,7 +634,7 @@ jump_to_continuation(
634634 Code = <<I1 /binary , I2 /binary , I3 /binary >>,
635635 Stream1 = StreamModule :append (Stream0 , Code ),
636636 % Free all registers since this is a tail jump
637- State # state {stream = Stream1 , available_regs = ? AVAILABLE_REGS , used_regs = [] }.
637+ State # state {stream = Stream1 , available_regs = ? AVAILABLE_REGS , used_regs = jit_regs : new () }.
638638
639639% % @private
640640-spec rewrite_branch_instruction (
@@ -1064,22 +1064,24 @@ if_block_free_reg(Reg, State0) when ?IS_GPR(Reg) ->
10641064 State0 .
10651065
10661066% % @private
1067- -spec merge_used_regs (state (), [aarch64_register ()]) -> state ().
1068- merge_used_regs (# state {used_regs = UR0 , available_regs = AvR0 } = State , [
1069- Reg | T
1070- ]) ->
1071- case lists :member (Reg , UR0 ) of
1072- true ->
1073- merge_used_regs (State , T );
1074- false ->
1075- AvR1 = lists :delete (Reg , AvR0 ),
1076- UR1 = [Reg | UR0 ],
1077- merge_used_regs (
1078- State # state {used_regs = UR1 , available_regs = AvR1 }, T
1079- )
1080- end ;
1081- merge_used_regs (State , []) ->
1082- State .
1067+ -spec merge_used_regs (state (), jit_regs :regs ()) -> state ().
1068+ merge_used_regs (State , OtherRegs ) ->
1069+ maps :fold (
1070+ fun (Reg , _ , AccState ) ->
1071+ # state {used_regs = UR , available_regs = AvR } = AccState ,
1072+ case jit_regs :is_used (UR , Reg ) of
1073+ true ->
1074+ AccState ;
1075+ false ->
1076+ AccState # state {
1077+ used_regs = jit_regs :add (UR , Reg ),
1078+ available_regs = lists :delete (Reg , AvR )
1079+ }
1080+ end
1081+ end ,
1082+ State ,
1083+ OtherRegs
1084+ ).
10831085
10841086% %-----------------------------------------------------------------------------
10851087% % @doc Emit a shift register right by a fixed number of bits, effectively
@@ -1111,7 +1113,10 @@ shift_right(
11111113->
11121114 I = jit_aarch64_asm :lsr (ResultReg , Reg , Shift ),
11131115 Stream1 = StreamModule :append (Stream0 , I ),
1114- {State # state {stream = Stream1 , available_regs = T , used_regs = [ResultReg | UR ]}, ResultReg }.
1116+ {
1117+ State # state {stream = Stream1 , available_regs = T , used_regs = jit_regs :add (UR , ResultReg )},
1118+ ResultReg
1119+ }.
11151120
11161121% %-----------------------------------------------------------------------------
11171122% % @doc Emit a shift register left by a fixed number of bits, effectively
@@ -1159,8 +1164,9 @@ call_func_ptr(
11591164 end ,
11601165 [FuncPtrTuple | Args ]
11611166 ),
1162- UsedRegs1 = UsedRegs0 -- FreeRegs ,
1163- SavedRegs = [? LR_REG , ? CTX_REG , ? JITSTATE_REG , ? NATIVE_INTERFACE_REG | UsedRegs1 ],
1167+ UsedRegs1 = jit_regs :without (UsedRegs0 , FreeRegs ),
1168+ UsedRegsList = [R || R <- lists :reverse (? AVAILABLE_REGS ), jit_regs :is_used (UsedRegs1 , R )],
1169+ SavedRegs = [? LR_REG , ? CTX_REG , ? JITSTATE_REG , ? NATIVE_INTERFACE_REG | UsedRegsList ],
11641170 {SavedRegsOdd , Stream1 } = push_registers (SavedRegs , StreamModule , Stream0 ),
11651171
11661172 % Set up arguments following AArch64 calling convention
@@ -1201,9 +1207,8 @@ call_func_ptr(
12011207
12021208 Stream6 = pop_registers (SavedRegsOdd , lists :reverse (SavedRegs ), StreamModule , Stream5 ),
12031209
1204- AvailableRegs2 = lists :delete (ResultReg , AvailableRegs1 ),
1205- AvailableRegs3 = ? AVAILABLE_REGS -- (? AVAILABLE_REGS -- AvailableRegs2 ),
1206- UsedRegs2 = [ResultReg | UsedRegs1 ],
1210+ UsedRegs2 = jit_regs :add (UsedRegs1 , ResultReg ),
1211+ AvailableRegs3 = jit_regs :available (? AVAILABLE_REGS , UsedRegs2 ),
12071212 {
12081213 State1 # state {
12091214 stream = Stream6 ,
@@ -1244,7 +1249,13 @@ set_args(
12441249 ParamRegs = parameter_regs (Args ),
12451250 ArgsRegs = args_regs (Args ),
12461251 AvailableScratchGP =
1247- ? SCRATCH_REGS -- ParamRegs -- ArgsRegs -- UsedRegs ,
1252+ [
1253+ R
1254+ || R <- ? SCRATCH_REGS ,
1255+ not lists :member (R , ParamRegs ),
1256+ not lists :member (R , ArgsRegs ),
1257+ not jit_regs :is_used (UsedRegs , R )
1258+ ],
12481259 Offset = StreamModule :offset (Stream0 ),
12491260 Args1 = [
12501261 case Arg of
@@ -1257,17 +1268,22 @@ set_args(
12571268 Stream1 = StreamModule :append (Stream0 , SetArgsCode ),
12581269 NewUsedRegs = lists :foldl (
12591270 fun
1260- ({free , {ptr , Reg }}, AccUsed ) -> lists : delete ( Reg , AccUsed );
1261- ({free , Reg }, AccUsed ) -> lists : delete ( Reg , AccUsed );
1271+ ({free , {ptr , Reg }}, AccUsed ) -> jit_regs : remove ( AccUsed , Reg );
1272+ ({free , Reg }, AccUsed ) -> jit_regs : remove ( AccUsed , Reg );
12621273 (_ , AccUsed ) -> AccUsed
12631274 end ,
12641275 UsedRegs ,
12651276 Args
12661277 ),
12671278 State0 # state {
12681279 stream = Stream1 ,
1269- available_regs = ? AVAILABLE_REGS -- ParamRegs -- NewUsedRegs ,
1270- used_regs = ParamRegs ++ (NewUsedRegs -- ParamRegs )
1280+ available_regs = [
1281+ R
1282+ || R <- ? AVAILABLE_REGS ,
1283+ not lists :member (R , ParamRegs ),
1284+ not jit_regs :is_used (NewUsedRegs , R )
1285+ ],
1286+ used_regs = jit_regs :merge (NewUsedRegs , ParamRegs )
12711287 }.
12721288
12731289% % @private
@@ -1628,7 +1644,9 @@ get_array_element(
16281644 Stream1 = StreamModule :append (Stream0 , <<I1 /binary >>),
16291645 {
16301646 State # state {
1631- stream = Stream1 , available_regs = AvailableT , used_regs = [ElemReg | UsedRegs0 ]
1647+ stream = Stream1 ,
1648+ available_regs = AvailableT ,
1649+ used_regs = jit_regs :add (UsedRegs0 , ElemReg )
16321650 },
16331651 ElemReg
16341652 }.
@@ -1743,7 +1761,10 @@ move_to_native_register(
17431761) ->
17441762 I1 = jit_aarch64_asm :ldr (Reg , ? CP ),
17451763 Stream1 = StreamModule :append (Stream0 , I1 ),
1746- {State # state {stream = Stream1 , used_regs = [Reg | Used ], available_regs = AvailT }, Reg };
1764+ {
1765+ State # state {stream = Stream1 , used_regs = jit_regs :add (Used , Reg ), available_regs = AvailT },
1766+ Reg
1767+ };
17471768move_to_native_register (State , Reg ) when is_atom (Reg ) ->
17481769 {State , Reg };
17491770move_to_native_register (
@@ -1765,7 +1786,10 @@ move_to_native_register(
17651786->
17661787 I1 = jit_aarch64_asm :mov (Reg , Imm ),
17671788 Stream1 = StreamModule :append (Stream0 , I1 ),
1768- {State # state {stream = Stream1 , used_regs = [Reg | Used ], available_regs = AvailT }, Reg };
1789+ {
1790+ State # state {stream = Stream1 , used_regs = jit_regs :add (Used , Reg ), available_regs = AvailT },
1791+ Reg
1792+ };
17691793move_to_native_register (
17701794 # state {
17711795 stream_module = StreamModule ,
@@ -1777,7 +1801,10 @@ move_to_native_register(
17771801) ->
17781802 I1 = jit_aarch64_asm :ldr (Reg , ? X_REG (? MAX_REG )),
17791803 Stream1 = StreamModule :append (Stream0 , I1 ),
1780- {State # state {stream = Stream1 , used_regs = [Reg | Used ], available_regs = AvailT }, Reg };
1804+ {
1805+ State # state {stream = Stream1 , used_regs = jit_regs :add (Used , Reg ), available_regs = AvailT },
1806+ Reg
1807+ };
17811808move_to_native_register (
17821809 # state {
17831810 stream_module = StreamModule ,
@@ -1791,7 +1818,10 @@ move_to_native_register(
17911818->
17921819 I1 = jit_aarch64_asm :ldr (Reg , ? X_REG (X )),
17931820 Stream1 = StreamModule :append (Stream0 , I1 ),
1794- {State # state {stream = Stream1 , used_regs = [Reg | Used ], available_regs = AvailT }, Reg };
1821+ {
1822+ State # state {stream = Stream1 , used_regs = jit_regs :add (Used , Reg ), available_regs = AvailT },
1823+ Reg
1824+ };
17951825move_to_native_register (
17961826 # state {
17971827 stream_module = StreamModule ,
@@ -1805,7 +1835,10 @@ move_to_native_register(
18051835 I2 = jit_aarch64_asm :ldr (Reg , {Reg , Y * ? WORD_SIZE }),
18061836 Code = <<I1 /binary , I2 /binary >>,
18071837 Stream1 = StreamModule :append (Stream0 , Code ),
1808- {State # state {stream = Stream1 , available_regs = AvailT , used_regs = [Reg | Used ]}, Reg }.
1838+ {
1839+ State # state {stream = Stream1 , available_regs = AvailT , used_regs = jit_regs :add (Used , Reg )},
1840+ Reg
1841+ }.
18091842
18101843% %-----------------------------------------------------------------------------
18111844% % @doc Move a value (integer, vm register, pointer or native register) to a
@@ -1873,7 +1906,12 @@ copy_to_native_register(
18731906) when is_atom (Reg ) ->
18741907 I1 = jit_aarch64_asm :mov (SaveReg , Reg ),
18751908 Stream1 = StreamModule :append (Stream0 , I1 ),
1876- {State # state {stream = Stream1 , available_regs = AvailT , used_regs = [SaveReg | Used ]}, SaveReg };
1909+ {
1910+ State # state {
1911+ stream = Stream1 , available_regs = AvailT , used_regs = jit_regs :add (Used , SaveReg )
1912+ },
1913+ SaveReg
1914+ };
18771915copy_to_native_register (
18781916 # state {
18791917 stream_module = StreamModule ,
@@ -1885,7 +1923,12 @@ copy_to_native_register(
18851923) when is_atom (Reg ) ->
18861924 I1 = jit_aarch64_asm :ldr (SaveReg , {Reg , 0 }),
18871925 Stream1 = StreamModule :append (Stream0 , I1 ),
1888- {State # state {stream = Stream1 , available_regs = AvailT , used_regs = [SaveReg | Used ]}, SaveReg };
1926+ {
1927+ State # state {
1928+ stream = Stream1 , available_regs = AvailT , used_regs = jit_regs :add (Used , SaveReg )
1929+ },
1930+ SaveReg
1931+ };
18891932copy_to_native_register (State , Reg ) ->
18901933 move_to_native_register (State , Reg ).
18911934
@@ -2024,7 +2067,9 @@ get_module_index(
20242067 Code = <<I1 /binary , I2 /binary >>,
20252068 Stream1 = StreamModule :append (Stream0 , Code ),
20262069 {
2027- State # state {stream = Stream1 , available_regs = AvailableT , used_regs = [Reg | UsedRegs0 ]},
2070+ State # state {
2071+ stream = Stream1 , available_regs = AvailableT , used_regs = jit_regs :add (UsedRegs0 , Reg )
2072+ },
20282073 Reg
20292074 }.
20302075
@@ -2073,7 +2118,11 @@ and_(
20732118 Val
20742119) ->
20752120 NewState = op_imm (
2076- State # state {available_regs = T , used_regs = [ResultReg | UR ]}, and_ , ResultReg , Reg , Val
2121+ State # state {available_regs = T , used_regs = jit_regs :add (UR , ResultReg )},
2122+ and_ ,
2123+ ResultReg ,
2124+ Reg ,
2125+ Val
20772126 ),
20782127 {NewState , ResultReg }.
20792128
@@ -2395,22 +2444,12 @@ return_labels_and_lines(
23952444% % @private
23962445- spec free_reg ([aarch64_register ()], [aarch64_register ()], aarch64_register ()) ->
23972446 {[aarch64_register ()], [aarch64_register ()]}.
2398- free_reg (AvailableRegs0 , UsedRegs0 , Reg ) when ? IS_GPR (Reg ) ->
2399- AvailableRegs1 = free_reg0 ( ? AVAILABLE_REGS , AvailableRegs0 , Reg , [] ),
2400- true = lists : member ( Reg , UsedRegs0 ),
2401- UsedRegs1 = lists : delete ( Reg , UsedRegs0 ),
2447+ free_reg (_AvailableRegs0 , UsedRegs0 , Reg ) when ? IS_GPR (Reg ) ->
2448+ true = jit_regs : is_used ( UsedRegs0 , Reg ),
2449+ UsedRegs1 = jit_regs : remove ( UsedRegs0 , Reg ),
2450+ AvailableRegs1 = jit_regs : available ( ? AVAILABLE_REGS , UsedRegs1 ),
24022451 {AvailableRegs1 , UsedRegs1 }.
24032452
2404- % % @private
2405- - spec free_reg0 ([aarch64_register ()], [aarch64_register ()], aarch64_register (), [aarch64_register ()]) ->
2406- [aarch64_register ()].
2407- free_reg0 ([Reg | _SortedT ], PrevRegs0 , Reg , Acc ) ->
2408- lists :reverse (Acc , [Reg | PrevRegs0 ]);
2409- free_reg0 ([PrevReg | SortedT ], [PrevReg | PrevT ], Reg , Acc ) ->
2410- free_reg0 (SortedT , PrevT , Reg , [PrevReg | Acc ]);
2411- free_reg0 ([_Other | SortedT ], PrevRegs , Reg , Acc ) ->
2412- free_reg0 (SortedT , PrevRegs , Reg , Acc ).
2413-
24142453% % @private
24152454- spec args_regs ([arg ()]) -> [aarch64_register () | imm ].
24162455args_regs (Args ) ->
0 commit comments