Skip to content

Commit 9153fb7

Browse files
authored
Optimize Plug.Conn.Utils.validate_utf8!/3 (#1311)
1 parent 82a3dbe commit 9153fb7

1 file changed

Lines changed: 24 additions & 5 deletions

File tree

lib/plug/conn/utils.ex

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -286,25 +286,44 @@ defmodule Plug.Conn.Utils do
286286
do: stripped
287287
end
288288

289+
# 56-bit SWAR guard: all 7 bytes are ASCII (< 128)
290+
defguardp ascii_swar?(w)
291+
when Bitwise.band(w, 0x80808080808080) == 0
292+
289293
@doc """
290294
Validates the given binary is valid UTF-8.
291295
"""
292296
@spec validate_utf8!(binary, module, binary) :: :ok | no_return
293297
def validate_utf8!(binary, exception, context)
294298

295299
def validate_utf8!(<<binary::binary>>, exception, context) do
296-
do_validate_utf8!(binary, exception, context)
300+
if byte_size(binary) < 12 do
301+
do_validate_utf8_small!(binary, exception, context)
302+
else
303+
do_validate_utf8_swar!(binary, exception, context)
304+
end
305+
end
306+
307+
# SWAR loop
308+
defp do_validate_utf8_swar!(<<w::56, b, rest::bits>>, exception, context)
309+
when b <= 127 and ascii_swar?(w) do
310+
do_validate_utf8_swar!(rest, exception, context)
311+
end
312+
313+
defp do_validate_utf8_swar!(rest, exception, context) do
314+
do_validate_utf8_small!(rest, exception, context)
297315
end
298316

299-
defp do_validate_utf8!(<<_::utf8, rest::bits>>, exception, context) do
300-
do_validate_utf8!(rest, exception, context)
317+
# Small loop (identical to original character loop)
318+
defp do_validate_utf8_small!(<<_::utf8, rest::bits>>, exception, context) do
319+
do_validate_utf8_small!(rest, exception, context)
301320
end
302321

303-
defp do_validate_utf8!(<<byte, _::bits>>, exception, context) do
322+
defp do_validate_utf8_small!(<<byte, _::bits>>, exception, context) do
304323
raise exception, "invalid UTF-8 on #{context}, got byte #{byte}"
305324
end
306325

307-
defp do_validate_utf8!(<<>>, _exception, _context) do
326+
defp do_validate_utf8_small!(<<>>, _exception, _context) do
308327
:ok
309328
end
310329

0 commit comments

Comments
 (0)