aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Kandaurov <pluknet@nginx.com>2021-05-22 18:40:45 +0300
committerSergey Kandaurov <pluknet@nginx.com>2021-05-22 18:40:45 +0300
commitf1378601010b8f2857ac7c043ec4ac6d534543bb (patch)
tree85c917a4c5a6c616c192c20bebba25f152ec858a /src
parent66f736391ea5d0bc459c3f389a8cbfbb36fa9c86 (diff)
downloadnginx-f1378601010b8f2857ac7c043ec4ac6d534543bb.tar.gz
nginx-f1378601010b8f2857ac7c043ec4ac6d534543bb.zip
QUIC: unroll and inline ngx_quic_varint_len()/ngx_quic_build_int().
According to profiling, those two are among most frequently called, so inlining is generally useful, and unrolling should help with it. Further, this fixes undefined behaviour seen with invalid values. Inspired by Yu Liu.
Diffstat (limited to 'src')
-rw-r--r--src/event/quic/ngx_event_quic_transport.c53
1 files changed, 36 insertions, 17 deletions
diff --git a/src/event/quic/ngx_event_quic_transport.c b/src/event/quic/ngx_event_quic_transport.c
index 2524223d6..c13155c55 100644
--- a/src/event/quic/ngx_event_quic_transport.c
+++ b/src/event/quic/ngx_event_quic_transport.c
@@ -66,6 +66,9 @@
#define ngx_quic_write_uint32_aligned(p, s) \
(*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t))
+#define ngx_quic_build_int_set(p, value, len, bits) \
+ (*(p)++ = ((value >> ((len) * 8)) & 0xff) | ((bits) << 6))
+
#define NGX_QUIC_VERSION(c) (0xff000000 + (c))
@@ -244,40 +247,56 @@ ngx_quic_copy_bytes(u_char *pos, u_char *end, size_t len, u_char *dst)
}
-static ngx_uint_t
+static ngx_inline ngx_uint_t
ngx_quic_varint_len(uint64_t value)
{
- ngx_uint_t bits;
+ if (value < (1 << 6)) {
+ return 1;
+ }
- bits = 0;
- while (value >> ((8 << bits) - 2)) {
- bits++;
+ if (value < (1 << 14)) {
+ return 2;
}
- return 1 << bits;
+ if (value < (1 << 30)) {
+ return 4;
+ }
+
+ return 8;
}
-static void
+static ngx_inline void
ngx_quic_build_int(u_char **pos, uint64_t value)
{
- u_char *p;
- ngx_uint_t bits, len;
+ u_char *p;
p = *pos;
- bits = 0;
- while (value >> ((8 << bits) - 2)) {
- bits++;
- }
+ if (value < (1 << 6)) {
+ ngx_quic_build_int_set(p, value, 0, 0);
- len = (1 << bits);
+ } else if (value < (1 << 14)) {
+ ngx_quic_build_int_set(p, value, 1, 1);
+ ngx_quic_build_int_set(p, value, 0, 0);
- while (len--) {
- *p++ = value >> (len * 8);
+ } else if (value < (1 << 30)) {
+ ngx_quic_build_int_set(p, value, 3, 2);
+ ngx_quic_build_int_set(p, value, 2, 0);
+ ngx_quic_build_int_set(p, value, 1, 0);
+ ngx_quic_build_int_set(p, value, 0, 0);
+
+ } else {
+ ngx_quic_build_int_set(p, value, 7, 3);
+ ngx_quic_build_int_set(p, value, 6, 0);
+ ngx_quic_build_int_set(p, value, 5, 0);
+ ngx_quic_build_int_set(p, value, 4, 0);
+ ngx_quic_build_int_set(p, value, 3, 0);
+ ngx_quic_build_int_set(p, value, 2, 0);
+ ngx_quic_build_int_set(p, value, 1, 0);
+ ngx_quic_build_int_set(p, value, 0, 0);
}
- **pos |= bits << 6;
*pos = p;
}