Skip to content

Commit d315ac8

Browse files
authored
Merge pull request #689 from casperisfine/parser-escape
parser.rl: parse_string implement a fast path
2 parents 94d679f + 96bd97c commit d315ac8

File tree

2 files changed

+140
-65
lines changed

2 files changed

+140
-65
lines changed

ext/json/ext/parser/parser.c

+94-51
Original file line numberDiff line numberDiff line change
@@ -2302,6 +2302,26 @@ static inline VALUE build_string(const char *start, const char *end, bool intern
23022302
return result;
23032303
}
23042304

2305+
static VALUE json_string_fastpath(JSON_Parser *json, char *string, char *stringEnd, bool is_name, bool intern, bool symbolize)
2306+
{
2307+
size_t bufferSize = stringEnd - string;
2308+
2309+
if (is_name) {
2310+
VALUE cached_key;
2311+
if (RB_UNLIKELY(symbolize)) {
2312+
cached_key = rsymbol_cache_fetch(&json->name_cache, string, bufferSize);
2313+
} else {
2314+
cached_key = rstring_cache_fetch(&json->name_cache, string, bufferSize);
2315+
}
2316+
2317+
if (RB_LIKELY(cached_key)) {
2318+
return cached_key;
2319+
}
2320+
}
2321+
2322+
return build_string(string, stringEnd, intern, symbolize);
2323+
}
2324+
23052325
static VALUE json_string_unescape(JSON_Parser *json, char *string, char *stringEnd, bool is_name, bool intern, bool symbolize)
23062326
{
23072327
size_t bufferSize = stringEnd - string;
@@ -2323,7 +2343,7 @@ static VALUE json_string_unescape(JSON_Parser *json, char *string, char *stringE
23232343
}
23242344

23252345
pe = memchr(p, '\\', bufferSize);
2326-
if (RB_LIKELY(pe == NULL)) {
2346+
if (RB_UNLIKELY(pe == NULL)) {
23272347
return build_string(string, stringEnd, intern, symbolize);
23282348
}
23292349

@@ -2424,15 +2444,15 @@ static VALUE json_string_unescape(JSON_Parser *json, char *string, char *stringE
24242444
}
24252445

24262446

2427-
#line 2428 "parser.c"
2447+
#line 2448 "parser.c"
24282448
enum {JSON_string_start = 1};
2429-
enum {JSON_string_first_final = 8};
2449+
enum {JSON_string_first_final = 9};
24302450
enum {JSON_string_error = 0};
24312451

24322452
enum {JSON_string_en_main = 1};
24332453

24342454

2435-
#line 1019 "parser.rl"
2455+
#line 1051 "parser.rl"
24362456

24372457

24382458
static int
@@ -2453,15 +2473,15 @@ static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *resu
24532473
VALUE match_string;
24542474

24552475

2456-
#line 2457 "parser.c"
2476+
#line 2477 "parser.c"
24572477
{
24582478
cs = JSON_string_start;
24592479
}
24602480

2461-
#line 1039 "parser.rl"
2481+
#line 1071 "parser.rl"
24622482
json->memo = p;
24632483

2464-
#line 2465 "parser.c"
2484+
#line 2485 "parser.c"
24652485
{
24662486
if ( p == pe )
24672487
goto _test_eof;
@@ -2486,47 +2506,56 @@ case 2:
24862506
goto st0;
24872507
goto st2;
24882508
tr2:
2489-
#line 1006 "parser.rl"
2509+
#line 1033 "parser.rl"
2510+
{
2511+
*result = json_string_fastpath(json, json->memo + 1, p, json->parsing_name, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
2512+
{p = (( p + 1))-1;}
2513+
p--;
2514+
{p++; cs = 9; goto _out;}
2515+
}
2516+
#line 1026 "parser.rl"
24902517
{
24912518
*result = json_string_unescape(json, json->memo + 1, p, json->parsing_name, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
2492-
if (NIL_P(*result)) {
2493-
p--;
2494-
{p++; cs = 8; goto _out;}
2495-
} else {
2496-
{p = (( p + 1))-1;}
2497-
}
2519+
{p = (( p + 1))-1;}
2520+
p--;
2521+
{p++; cs = 9; goto _out;}
24982522
}
2499-
#line 1016 "parser.rl"
2500-
{ p--; {p++; cs = 8; goto _out;} }
2501-
goto st8;
2502-
st8:
2523+
goto st9;
2524+
tr6:
2525+
#line 1026 "parser.rl"
2526+
{
2527+
*result = json_string_unescape(json, json->memo + 1, p, json->parsing_name, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names);
2528+
{p = (( p + 1))-1;}
2529+
p--;
2530+
{p++; cs = 9; goto _out;}
2531+
}
2532+
goto st9;
2533+
st9:
25032534
if ( ++p == pe )
2504-
goto _test_eof8;
2505-
case 8:
2506-
#line 2507 "parser.c"
2535+
goto _test_eof9;
2536+
case 9:
2537+
#line 2538 "parser.c"
25072538
goto st0;
25082539
st3:
25092540
if ( ++p == pe )
25102541
goto _test_eof3;
25112542
case 3:
25122543
if ( (*p) == 117 )
2513-
goto st4;
2544+
goto st5;
25142545
if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 )
25152546
goto st0;
2516-
goto st2;
2547+
goto st4;
25172548
st4:
25182549
if ( ++p == pe )
25192550
goto _test_eof4;
25202551
case 4:
2521-
if ( (*p) < 65 ) {
2522-
if ( 48 <= (*p) && (*p) <= 57 )
2523-
goto st5;
2524-
} else if ( (*p) > 70 ) {
2525-
if ( 97 <= (*p) && (*p) <= 102 )
2526-
goto st5;
2527-
} else
2528-
goto st5;
2529-
goto st0;
2552+
switch( (*p) ) {
2553+
case 34: goto tr6;
2554+
case 92: goto st3;
2555+
}
2556+
if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 )
2557+
goto st0;
2558+
goto st4;
25302559
st5:
25312560
if ( ++p == pe )
25322561
goto _test_eof5;
@@ -2559,27 +2588,41 @@ case 6:
25592588
case 7:
25602589
if ( (*p) < 65 ) {
25612590
if ( 48 <= (*p) && (*p) <= 57 )
2562-
goto st2;
2591+
goto st8;
2592+
} else if ( (*p) > 70 ) {
2593+
if ( 97 <= (*p) && (*p) <= 102 )
2594+
goto st8;
2595+
} else
2596+
goto st8;
2597+
goto st0;
2598+
st8:
2599+
if ( ++p == pe )
2600+
goto _test_eof8;
2601+
case 8:
2602+
if ( (*p) < 65 ) {
2603+
if ( 48 <= (*p) && (*p) <= 57 )
2604+
goto st4;
25632605
} else if ( (*p) > 70 ) {
25642606
if ( 97 <= (*p) && (*p) <= 102 )
2565-
goto st2;
2607+
goto st4;
25662608
} else
2567-
goto st2;
2609+
goto st4;
25682610
goto st0;
25692611
}
25702612
_test_eof2: cs = 2; goto _test_eof;
2571-
_test_eof8: cs = 8; goto _test_eof;
2613+
_test_eof9: cs = 9; goto _test_eof;
25722614
_test_eof3: cs = 3; goto _test_eof;
25732615
_test_eof4: cs = 4; goto _test_eof;
25742616
_test_eof5: cs = 5; goto _test_eof;
25752617
_test_eof6: cs = 6; goto _test_eof;
25762618
_test_eof7: cs = 7; goto _test_eof;
2619+
_test_eof8: cs = 8; goto _test_eof;
25772620

25782621
_test_eof: {}
25792622
_out: {}
25802623
}
25812624

2582-
#line 1041 "parser.rl"
2625+
#line 1073 "parser.rl"
25832626

25842627
if (json->create_additions && RTEST(match_string = json->match_string)) {
25852628
VALUE klass;
@@ -2732,15 +2775,15 @@ static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self)
27322775
}
27332776

27342777

2735-
#line 2736 "parser.c"
2778+
#line 2779 "parser.c"
27362779
enum {JSON_start = 1};
27372780
enum {JSON_first_final = 10};
27382781
enum {JSON_error = 0};
27392782

27402783
enum {JSON_en_main = 1};
27412784

27422785

2743-
#line 1207 "parser.rl"
2786+
#line 1239 "parser.rl"
27442787

27452788

27462789
/*
@@ -2769,16 +2812,16 @@ static VALUE cParser_parse(VALUE self)
27692812
json->stack = &stack;
27702813

27712814

2772-
#line 2773 "parser.c"
2815+
#line 2816 "parser.c"
27732816
{
27742817
cs = JSON_start;
27752818
}
27762819

2777-
#line 1235 "parser.rl"
2820+
#line 1267 "parser.rl"
27782821
p = json->source;
27792822
pe = p + json->len;
27802823

2781-
#line 2782 "parser.c"
2824+
#line 2825 "parser.c"
27822825
{
27832826
if ( p == pe )
27842827
goto _test_eof;
@@ -2812,7 +2855,7 @@ case 1:
28122855
cs = 0;
28132856
goto _out;
28142857
tr2:
2815-
#line 1199 "parser.rl"
2858+
#line 1231 "parser.rl"
28162859
{
28172860
char *np = JSON_parse_value(json, p, pe, &result, 0);
28182861
if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
@@ -2822,7 +2865,7 @@ cs = 0;
28222865
if ( ++p == pe )
28232866
goto _test_eof10;
28242867
case 10:
2825-
#line 2826 "parser.c"
2868+
#line 2869 "parser.c"
28262869
switch( (*p) ) {
28272870
case 13: goto st10;
28282871
case 32: goto st10;
@@ -2911,7 +2954,7 @@ case 9:
29112954
_out: {}
29122955
}
29132956

2914-
#line 1238 "parser.rl"
2957+
#line 1270 "parser.rl"
29152958

29162959
if (json->stack_handle) {
29172960
rvalue_stack_eagerly_release(json->stack_handle);
@@ -2947,16 +2990,16 @@ static VALUE cParser_m_parse(VALUE klass, VALUE source, VALUE opts)
29472990
json->stack = &stack;
29482991

29492992

2950-
#line 2951 "parser.c"
2993+
#line 2994 "parser.c"
29512994
{
29522995
cs = JSON_start;
29532996
}
29542997

2955-
#line 1273 "parser.rl"
2998+
#line 1305 "parser.rl"
29562999
p = json->source;
29573000
pe = p + json->len;
29583001

2959-
#line 2960 "parser.c"
3002+
#line 3003 "parser.c"
29603003
{
29613004
if ( p == pe )
29623005
goto _test_eof;
@@ -2990,7 +3033,7 @@ case 1:
29903033
cs = 0;
29913034
goto _out;
29923035
tr2:
2993-
#line 1199 "parser.rl"
3036+
#line 1231 "parser.rl"
29943037
{
29953038
char *np = JSON_parse_value(json, p, pe, &result, 0);
29963039
if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;}
@@ -3000,7 +3043,7 @@ cs = 0;
30003043
if ( ++p == pe )
30013044
goto _test_eof10;
30023045
case 10:
3003-
#line 3004 "parser.c"
3046+
#line 3047 "parser.c"
30043047
switch( (*p) ) {
30053048
case 13: goto st10;
30063049
case 32: goto st10;
@@ -3089,7 +3132,7 @@ case 9:
30893132
_out: {}
30903133
}
30913134

3092-
#line 1276 "parser.rl"
3135+
#line 1308 "parser.rl"
30933136

30943137
if (json->stack_handle) {
30953138
rvalue_stack_eagerly_release(json->stack_handle);

0 commit comments

Comments
 (0)