Skip to content

Commit 4a63be0

Browse files
mscdexevanlucas
authored andcommitted
http: optimize checkIsHttpToken()
This commit both makes checkIsHttpToken() inlinable and extracts the character checking logic to a separate inlinable function so that the main loop can be unrolled a bit. PR-URL: #6570 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Сковорода Никита Андреевич <[email protected]>
1 parent 23a495a commit 4a63be0

File tree

1 file changed

+49
-36
lines changed

1 file changed

+49
-36
lines changed

lib/_http_common.js

+49-36
Original file line numberDiff line numberDiff line change
@@ -232,52 +232,65 @@ exports.httpSocketSetup = httpSocketSetup;
232232
* per the rules defined in RFC 7230
233233
* See https://tools.ietf.org/html/rfc7230#section-3.2.6
234234
*
235+
* Allowed characters in an HTTP token:
236+
* ^_`a-z 94-122
237+
* A-Z 65-90
238+
* - 45
239+
* 0-9 48-57
240+
* ! 33
241+
* #$%&' 35-39
242+
* *+ 42-43
243+
* . 46
244+
* | 124
245+
* ~ 126
246+
*
235247
* This implementation of checkIsHttpToken() loops over the string instead of
236248
* using a regular expression since the former is up to 180% faster with v8 4.9
237249
* depending on the string length (the shorter the string, the larger the
238250
* performance difference)
251+
*
252+
* Additionally, checkIsHttpToken() is currently designed to be inlinable by v8,
253+
* so take care when making changes to the implementation so that the source
254+
* code size does not exceed v8's default max_inlined_source_size setting.
239255
**/
256+
function isValidTokenChar(ch) {
257+
if (ch >= 94 && ch <= 122)
258+
return true;
259+
if (ch >= 65 && ch <= 90)
260+
return true;
261+
if (ch === 45)
262+
return true;
263+
if (ch >= 48 && ch <= 57)
264+
return true;
265+
if (ch === 34 || ch === 40 || ch === 41 || ch === 44)
266+
return false;
267+
if (ch >= 33 && ch <= 46)
268+
return true;
269+
if (ch === 124 || ch === 126)
270+
return true;
271+
return false;
272+
}
240273
function checkIsHttpToken(val) {
241274
if (typeof val !== 'string' || val.length === 0)
242275
return false;
243-
244-
for (var i = 0, len = val.length; i < len; i++) {
245-
var ch = val.charCodeAt(i);
246-
247-
if (ch >= 65 && ch <= 90) // A-Z
248-
continue;
249-
250-
if (ch >= 97 && ch <= 122) // a-z
251-
continue;
252-
253-
// ^ => 94
254-
// _ => 95
255-
// ` => 96
256-
// | => 124
257-
// ~ => 126
258-
if (ch === 94 || ch === 95 || ch === 96 || ch === 124 || ch === 126)
259-
continue;
260-
261-
if (ch >= 48 && ch <= 57) // 0-9
262-
continue;
263-
264-
// ! => 33
265-
// # => 35
266-
// $ => 36
267-
// % => 37
268-
// & => 38
269-
// ' => 39
270-
// * => 42
271-
// + => 43
272-
// - => 45
273-
// . => 46
274-
if (ch >= 33 && ch <= 46) {
275-
if (ch === 34 || ch === 40 || ch === 41 || ch === 44)
276+
if (!isValidTokenChar(val.charCodeAt(0)))
277+
return false;
278+
const len = val.length;
279+
if (len > 1) {
280+
if (!isValidTokenChar(val.charCodeAt(1)))
281+
return false;
282+
if (len > 2) {
283+
if (!isValidTokenChar(val.charCodeAt(2)))
276284
return false;
277-
continue;
285+
if (len > 3) {
286+
if (!isValidTokenChar(val.charCodeAt(3)))
287+
return false;
288+
for (var i = 4; i < len; i++) {
289+
if (!isValidTokenChar(val.charCodeAt(i)))
290+
return false;
291+
}
292+
}
278293
}
279-
280-
return false;
281294
}
282295
return true;
283296
}

0 commit comments

Comments
 (0)