Skip to content

Commit a457077

Browse files
committed
JIT: fix binary matching with large integers on 32 bits
Patterns such as: ```erlang <<"🌑"/utf8, Moons255Str/binary>> = Moons256Str, ``` (as found in test_binary_to_atom) do match a 32 bits integer in a binary. It is typically encoded by compiler with a 31 bits match followed by a 1 bit match, maybe because of some BEAM optimization (?). ``` {bs_start_match4,{atom,no_fail},1,{x,0},{x,1}}. {bs_match,{f,27}, {x,1}, {commands,[{ensure_at_least,32,1}, {'=:=',nil,31,2018494024}, {'=:=',nil,1,1}]}}. ``` In our case, if the pattern value is larger than 28 bits, the `?PRIM_BITSTRING_EXTRACT_INTEGER` primitive will return a boxed integer. On 32 bits platforms, we need to unbox it for comparison. If we confirm the compiler always matches up to 31 bits, we could actually optimize this differently, or maybe squash the two. Signed-off-by: Paul Guyot <[email protected]>
1 parent f6d5d16 commit a457077

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

libs/jit/src/jit.erl

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2974,11 +2974,25 @@ first_pass_bs_match_equal_colon_equal(
29742974
]),
29752975
MSt2 = handle_error_if({Result, '==', 0}, MMod, MSt1),
29762976
MSt3 = cond_jump_to_label({Result, '==', ?FALSE_ATOM}, Fail, MMod, MSt2),
2977-
MSt4 = MMod:shift_right(MSt3, Result, 4),
2978-
MSt5 = cond_jump_to_label({Result, '!=', PatternValue}, Fail, MMod, MSt4),
2979-
MSt6 = MMod:add(MSt5, BSOffsetReg, Size),
2980-
MSt7 = MMod:free_native_registers(MSt6, [Result]),
2981-
{J0 - 3, Rest3, MatchState, BSOffsetReg, MSt7}.
2977+
MSt6 =
2978+
case MMod:word_size() of
2979+
4 when PatternValue bsr 28 > 0 ->
2980+
% PatternValue doesn't match on immediate integer, so unbox Result for comparison
2981+
MMod:if_block(
2982+
MSt3, {Result, '&', ?TERM_PRIMARY_MASK, '!=', ?TERM_PRIMARY_BOXED}, fun(BSt0) ->
2983+
MMod:jump_to_label(BSt0, Fail)
2984+
end
2985+
),
2986+
MSt4 = MMod:and_(MSt3, Result, ?TERM_PRIMARY_CLEAR_MASK),
2987+
{MSt5, IntValue} = MMod:get_array_element(MSt4, {free, Result}, 1),
2988+
cond_jump_to_label({IntValue, '!=', PatternValue}, Fail, MMod, MSt5);
2989+
_ ->
2990+
MSt4 = MMod:shift_right(MSt3, Result, 4),
2991+
cond_jump_to_label({Result, '!=', PatternValue}, Fail, MMod, MSt4)
2992+
end,
2993+
MSt7 = MMod:add(MSt6, BSOffsetReg, Size),
2994+
MSt8 = MMod:free_native_registers(MSt7, [Result]),
2995+
{J0 - 3, Rest3, MatchState, BSOffsetReg, MSt8}.
29822996

29832997
first_pass_bs_match_skip(MatchState, BSOffsetReg, J0, Rest0, MMod, MSt0) ->
29842998
{Stride, Rest1} = decode_literal(Rest0),

0 commit comments

Comments
 (0)