Skip to content

Commit 1fc369e

Browse files
rerobikazherczeg
authored andcommitted
Use binary search for keyword checking (#2584)
This patch improves keyword searching during identifier parsing. JerryScript-DCO-1.0-Signed-off-by: Robert Fancsik [email protected]
1 parent 7f17210 commit 1fc369e

File tree

1 file changed

+71
-52
lines changed

1 file changed

+71
-52
lines changed

jerry-core/parser/js/js-lexer.c

Lines changed: 71 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -309,37 +309,35 @@ typedef struct
309309
* Keyword defines
310310
*/
311311
#define LEXER_KEYWORD(name, type) { (const uint8_t *) (name), (type) }
312-
#define LEXER_KEYWORD_END() { (const uint8_t *) NULL, LEXER_EOS }
312+
#define LEXER_KEYWORD_LIST_LENGTH(name) (const uint8_t) (sizeof ((name)) / sizeof ((name)[0]))
313313
/** @} */
314314

315315
/**
316316
* Keywords with 2 characters.
317317
*/
318-
static const keyword_string_t keyword_length_2[4] =
318+
static const keyword_string_t keywords_with_length_2[] =
319319
{
320320
LEXER_KEYWORD ("do", LEXER_KEYW_DO),
321321
LEXER_KEYWORD ("if", LEXER_KEYW_IF),
322322
LEXER_KEYWORD ("in", LEXER_KEYW_IN),
323-
LEXER_KEYWORD_END ()
324323
};
325324

326325
/**
327326
* Keywords with 3 characters.
328327
*/
329-
static const keyword_string_t keyword_length_3[6] =
328+
static const keyword_string_t keywords_with_length_3[] =
330329
{
331330
LEXER_KEYWORD ("for", LEXER_KEYW_FOR),
332331
LEXER_KEYWORD ("let", LEXER_KEYW_LET),
333332
LEXER_KEYWORD ("new", LEXER_KEYW_NEW),
334333
LEXER_KEYWORD ("try", LEXER_KEYW_TRY),
335334
LEXER_KEYWORD ("var", LEXER_KEYW_VAR),
336-
LEXER_KEYWORD_END ()
337335
};
338336

339337
/**
340338
* Keywords with 4 characters.
341339
*/
342-
static const keyword_string_t keyword_length_4[9] =
340+
static const keyword_string_t keywords_with_length_4[] =
343341
{
344342
LEXER_KEYWORD ("case", LEXER_KEYW_CASE),
345343
LEXER_KEYWORD ("else", LEXER_KEYW_ELSE),
@@ -349,22 +347,12 @@ static const keyword_string_t keyword_length_4[9] =
349347
LEXER_KEYWORD ("true", LEXER_LIT_TRUE),
350348
LEXER_KEYWORD ("void", LEXER_KEYW_VOID),
351349
LEXER_KEYWORD ("with", LEXER_KEYW_WITH),
352-
LEXER_KEYWORD_END ()
353350
};
354351

355-
#ifndef CONFIG_DISABLE_ES2015
356-
/**
357-
* Number of keywords with 5 characters.
358-
*/
359-
#define KEYWORD_LENGTH_COUNT 11
360-
#else /* CONFIG_DISABLE_ES2015 */
361-
#define KEYWORD_LENGTH_COUNT 10
362-
#endif /* !CONFIG_DISABLE_ES2015 */
363-
364352
/**
365353
* Keywords with 5 characters.
366354
*/
367-
static const keyword_string_t keyword_length_5[KEYWORD_LENGTH_COUNT] =
355+
static const keyword_string_t keywords_with_length_5[] =
368356
{
369357
#ifndef CONFIG_DISABLE_ES2015
370358
LEXER_KEYWORD ("await", LEXER_KEYW_AWAIT),
@@ -378,13 +366,12 @@ static const keyword_string_t keyword_length_5[KEYWORD_LENGTH_COUNT] =
378366
LEXER_KEYWORD ("throw", LEXER_KEYW_THROW),
379367
LEXER_KEYWORD ("while", LEXER_KEYW_WHILE),
380368
LEXER_KEYWORD ("yield", LEXER_KEYW_YIELD),
381-
LEXER_KEYWORD_END ()
382369
};
383370

384371
/**
385372
* Keywords with 6 characters.
386373
*/
387-
static const keyword_string_t keyword_length_6[9] =
374+
static const keyword_string_t keywords_with_length_6[] =
388375
{
389376
LEXER_KEYWORD ("delete", LEXER_KEYW_DELETE),
390377
LEXER_KEYWORD ("export", LEXER_KEYW_EXPORT),
@@ -394,71 +381,82 @@ static const keyword_string_t keyword_length_6[9] =
394381
LEXER_KEYWORD ("static", LEXER_KEYW_STATIC),
395382
LEXER_KEYWORD ("switch", LEXER_KEYW_SWITCH),
396383
LEXER_KEYWORD ("typeof", LEXER_KEYW_TYPEOF),
397-
LEXER_KEYWORD_END ()
398384
};
399385

400386
/**
401387
* Keywords with 7 characters.
402388
*/
403-
static const keyword_string_t keyword_length_7[6] =
389+
static const keyword_string_t keywords_with_length_7[] =
404390
{
405391
LEXER_KEYWORD ("default", LEXER_KEYW_DEFAULT),
406392
LEXER_KEYWORD ("extends", LEXER_KEYW_EXTENDS),
407393
LEXER_KEYWORD ("finally", LEXER_KEYW_FINALLY),
408394
LEXER_KEYWORD ("package", LEXER_KEYW_PACKAGE),
409395
LEXER_KEYWORD ("private", LEXER_KEYW_PRIVATE),
410-
LEXER_KEYWORD_END ()
411396
};
412397

413398
/**
414399
* Keywords with 8 characters.
415400
*/
416-
static const keyword_string_t keyword_length_8[4] =
401+
static const keyword_string_t keywords_with_length_8[] =
417402
{
418403
LEXER_KEYWORD ("continue", LEXER_KEYW_CONTINUE),
419404
LEXER_KEYWORD ("debugger", LEXER_KEYW_DEBUGGER),
420405
LEXER_KEYWORD ("function", LEXER_KEYW_FUNCTION),
421-
LEXER_KEYWORD_END ()
422406
};
423407

424408
/**
425409
* Keywords with 9 characters.
426410
*/
427-
static const keyword_string_t keyword_length_9[3] =
411+
static const keyword_string_t keywords_with_length_9[] =
428412
{
429413
LEXER_KEYWORD ("interface", LEXER_KEYW_INTERFACE),
430414
LEXER_KEYWORD ("protected", LEXER_KEYW_PROTECTED),
431-
LEXER_KEYWORD_END ()
432415
};
433416

434417
/**
435418
* Keywords with 10 characters.
436419
*/
437-
static const keyword_string_t keyword_length_10[3] =
420+
static const keyword_string_t keywords_with_length_10[] =
438421
{
439422
LEXER_KEYWORD ("implements", LEXER_KEYW_IMPLEMENTS),
440423
LEXER_KEYWORD ("instanceof", LEXER_KEYW_INSTANCEOF),
441-
LEXER_KEYWORD_END ()
442424
};
443425

444426
/**
445-
* List to the keywords.
427+
* List of the keyword groups.
428+
*/
429+
static const keyword_string_t * const keyword_strings_list[] =
430+
{
431+
keywords_with_length_2,
432+
keywords_with_length_3,
433+
keywords_with_length_4,
434+
keywords_with_length_5,
435+
keywords_with_length_6,
436+
keywords_with_length_7,
437+
keywords_with_length_8,
438+
keywords_with_length_9,
439+
keywords_with_length_10
440+
};
441+
442+
/**
443+
* List of the keyword groups length.
446444
*/
447-
static const keyword_string_t * const keyword_string_list[9] =
445+
static const uint8_t keyword_lengths_list[] =
448446
{
449-
keyword_length_2,
450-
keyword_length_3,
451-
keyword_length_4,
452-
keyword_length_5,
453-
keyword_length_6,
454-
keyword_length_7,
455-
keyword_length_8,
456-
keyword_length_9,
457-
keyword_length_10
447+
LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_2),
448+
LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_3),
449+
LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_4),
450+
LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_5),
451+
LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_6),
452+
LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_7),
453+
LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_8),
454+
LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_9),
455+
LEXER_KEYWORD_LIST_LENGTH (keywords_with_length_10)
458456
};
459457

460458
#undef LEXER_KEYWORD
461-
#undef LEXER_KEYWORD_END
459+
#undef LEXER_KEYWORD_LIST_LENGTH
462460

463461
/**
464462
* Parse identifier.
@@ -551,31 +549,52 @@ lexer_parse_identifier (parser_context_t *context_p, /**< context */
551549
&& !context_p->token.lit_location.has_escape
552550
&& (length >= 2 && length <= 10))
553551
{
554-
const keyword_string_t *keyword_p = keyword_string_list[length - 2];
552+
const keyword_string_t *keyword_list_p = keyword_strings_list[length - 2];
553+
554+
int start = 0;
555+
int end = keyword_lengths_list[length - 2];
556+
int middle = end / 2;
555557

556558
do
557559
{
558-
if (ident_start_p[0] == keyword_p->keyword_p[0]
559-
&& ident_start_p[1] == keyword_p->keyword_p[1]
560-
&& memcmp (ident_start_p, keyword_p->keyword_p, length) == 0)
560+
const keyword_string_t *keyword_p = keyword_list_p + middle;
561+
int compare_result = ident_start_p[0] - keyword_p->keyword_p[0];
562+
563+
if (compare_result == 0)
561564
{
562-
if (keyword_p->type >= LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD)
565+
compare_result = memcmp (ident_start_p, keyword_p->keyword_p, length);
566+
567+
if (compare_result == 0)
563568
{
564-
if (context_p->status_flags & PARSER_IS_STRICT)
569+
if (JERRY_UNLIKELY (keyword_p->type >= LEXER_FIRST_FUTURE_STRICT_RESERVED_WORD))
565570
{
566-
parser_raise_error (context_p, PARSER_ERR_STRICT_IDENT_NOT_ALLOWED);
571+
if (context_p->status_flags & PARSER_IS_STRICT)
572+
{
573+
parser_raise_error (context_p, PARSER_ERR_STRICT_IDENT_NOT_ALLOWED);
574+
}
575+
576+
context_p->token.literal_is_reserved = true;
577+
break;
567578
}
568579

569-
context_p->token.literal_is_reserved = true;
580+
context_p->token.type = (uint8_t) keyword_p->type;
570581
break;
571582
}
583+
}
572584

573-
context_p->token.type = (uint8_t) keyword_p->type;
574-
break;
585+
if (compare_result > 0)
586+
{
587+
start = middle + 1;
588+
}
589+
else
590+
{
591+
JERRY_ASSERT (compare_result < 0);
592+
end = middle;
575593
}
576-
keyword_p++;
594+
595+
middle = (start + end) / 2;
577596
}
578-
while (keyword_p->type != LEXER_EOS);
597+
while (start < end);
579598
}
580599

581600
if (context_p->token.type == LEXER_LITERAL)

0 commit comments

Comments
 (0)