Mercurial > hg > nginx-quic
comparison src/event/quic/ngx_event_quic_transport.c @ 8441:81d491f0dc8c quic
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.
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Sat, 22 May 2021 18:40:45 +0300 |
parents | 515ac3c8435c |
children | 4715f3e669f1 |
comparison
equal
deleted
inserted
replaced
8440:557dc6a06ba6 | 8441:81d491f0dc8c |
---|---|
63 #define ngx_quic_write_uint16_aligned(p, s) \ | 63 #define ngx_quic_write_uint16_aligned(p, s) \ |
64 (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t)) | 64 (*(uint16_t *) (p) = htons((uint16_t) (s)), (p) + sizeof(uint16_t)) |
65 | 65 |
66 #define ngx_quic_write_uint32_aligned(p, s) \ | 66 #define ngx_quic_write_uint32_aligned(p, s) \ |
67 (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t)) | 67 (*(uint32_t *) (p) = htonl((uint32_t) (s)), (p) + sizeof(uint32_t)) |
68 | |
69 #define ngx_quic_build_int_set(p, value, len, bits) \ | |
70 (*(p)++ = ((value >> ((len) * 8)) & 0xff) | ((bits) << 6)) | |
68 | 71 |
69 #define NGX_QUIC_VERSION(c) (0xff000000 + (c)) | 72 #define NGX_QUIC_VERSION(c) (0xff000000 + (c)) |
70 | 73 |
71 | 74 |
72 static u_char *ngx_quic_parse_int(u_char *pos, u_char *end, uint64_t *out); | 75 static u_char *ngx_quic_parse_int(u_char *pos, u_char *end, uint64_t *out); |
242 | 245 |
243 return pos + len; | 246 return pos + len; |
244 } | 247 } |
245 | 248 |
246 | 249 |
247 static ngx_uint_t | 250 static ngx_inline ngx_uint_t |
248 ngx_quic_varint_len(uint64_t value) | 251 ngx_quic_varint_len(uint64_t value) |
249 { | 252 { |
250 ngx_uint_t bits; | 253 if (value < (1 << 6)) { |
251 | 254 return 1; |
252 bits = 0; | 255 } |
253 while (value >> ((8 << bits) - 2)) { | 256 |
254 bits++; | 257 if (value < (1 << 14)) { |
255 } | 258 return 2; |
256 | 259 } |
257 return 1 << bits; | 260 |
258 } | 261 if (value < (1 << 30)) { |
259 | 262 return 4; |
260 | 263 } |
261 static void | 264 |
265 return 8; | |
266 } | |
267 | |
268 | |
269 static ngx_inline void | |
262 ngx_quic_build_int(u_char **pos, uint64_t value) | 270 ngx_quic_build_int(u_char **pos, uint64_t value) |
263 { | 271 { |
264 u_char *p; | 272 u_char *p; |
265 ngx_uint_t bits, len; | |
266 | 273 |
267 p = *pos; | 274 p = *pos; |
268 bits = 0; | 275 |
269 | 276 if (value < (1 << 6)) { |
270 while (value >> ((8 << bits) - 2)) { | 277 ngx_quic_build_int_set(p, value, 0, 0); |
271 bits++; | 278 |
272 } | 279 } else if (value < (1 << 14)) { |
273 | 280 ngx_quic_build_int_set(p, value, 1, 1); |
274 len = (1 << bits); | 281 ngx_quic_build_int_set(p, value, 0, 0); |
275 | 282 |
276 while (len--) { | 283 } else if (value < (1 << 30)) { |
277 *p++ = value >> (len * 8); | 284 ngx_quic_build_int_set(p, value, 3, 2); |
278 } | 285 ngx_quic_build_int_set(p, value, 2, 0); |
279 | 286 ngx_quic_build_int_set(p, value, 1, 0); |
280 **pos |= bits << 6; | 287 ngx_quic_build_int_set(p, value, 0, 0); |
288 | |
289 } else { | |
290 ngx_quic_build_int_set(p, value, 7, 3); | |
291 ngx_quic_build_int_set(p, value, 6, 0); | |
292 ngx_quic_build_int_set(p, value, 5, 0); | |
293 ngx_quic_build_int_set(p, value, 4, 0); | |
294 ngx_quic_build_int_set(p, value, 3, 0); | |
295 ngx_quic_build_int_set(p, value, 2, 0); | |
296 ngx_quic_build_int_set(p, value, 1, 0); | |
297 ngx_quic_build_int_set(p, value, 0, 0); | |
298 } | |
299 | |
281 *pos = p; | 300 *pos = p; |
282 } | 301 } |
283 | 302 |
284 | 303 |
285 u_char * | 304 u_char * |