Skip to content

Commit 004a5c1

Browse files
committed
Refactor ResumableParser
Stop updating stack handles, we don't actually need them as we're starting heap allocated. Add an assertion to prove it. Use a dedicated field for storing the parser reference to be used for marking EOS errors. Also stop marking EOS errors when not in resumable mode.
1 parent 3650e2b commit 004a5c1

1 file changed

Lines changed: 20 additions & 13 deletions

File tree

ext/json/ext/parser/parser.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ static rvalue_stack *rvalue_stack_grow(rvalue_stack *stack, VALUE *handle, rvalu
233233

234234
static VALUE rvalue_stack_push(rvalue_stack *stack, VALUE value, VALUE *handle, rvalue_stack **stack_ref)
235235
{
236+
JSON_ASSERT(stack->type != RVALUE_STACK_STACK_ALLOCATED || handle);
237+
236238
if (RB_UNLIKELY(stack->head >= stack->capa)) {
237239
stack = rvalue_stack_grow(stack, handle, stack_ref);
238240
}
@@ -431,6 +433,7 @@ typedef struct JSON_ParserStateStruct {
431433
int in_array;
432434
int current_nesting;
433435
unsigned int emitted_deprecations;
436+
VALUE parser;
434437
} JSON_ParserState;
435438

436439
static json_frame_stack *json_frame_stack_spill(json_frame_stack *old_stack, VALUE *handle, json_frame_stack **stack_ref);
@@ -451,6 +454,9 @@ static json_frame_stack *json_frame_stack_grow(json_frame_stack *stack, VALUE *h
451454
static json_frame *json_frame_stack_push(JSON_ParserState *state, json_frame frame)
452455
{
453456
json_frame_stack *stack = state->frames;
457+
458+
JSON_ASSERT(stack->type != RVALUE_STACK_STACK_ALLOCATED || state->frame_stack_handle);
459+
454460
if (RB_UNLIKELY(stack->head >= stack->capa)) {
455461
stack = json_frame_stack_grow(stack, state->frame_stack_handle, &state->frames);
456462
}
@@ -665,8 +671,8 @@ static VALUE parse_error_new(JSON_ParserState *state, VALUE message, long line,
665671
VALUE exc = rb_exc_new_str(eParserError, message);
666672
rb_ivar_set(exc, i_at_line, LONG2NUM(line));
667673
rb_ivar_set(exc, i_at_column, LONG2NUM(column));
668-
if (eos && state->value_stack_handle) {
669-
rb_ivar_set(exc, i_at_eos, *state->value_stack_handle);
674+
if (eos && state->parser) {
675+
rb_ivar_set(exc, i_at_eos, state->parser);
670676
}
671677
return exc;
672678
}
@@ -2166,6 +2172,7 @@ static void JSON_ResumableParser_mark(void *ptr)
21662172
rvalue_stack_mark(&parser->value_stack);
21672173
rvalue_cache_mark(&parser->state.name_cache);
21682174
rb_gc_mark(parser->buffer); // pin the buffer
2175+
rb_gc_mark_movable(parser->state.parser);
21692176
}
21702177

21712178
static void JSON_ResumableParser_free(void *ptr)
@@ -2200,6 +2207,7 @@ static void JSON_ResumableParser_compact(void *ptr)
22002207
rvalue_stack_compact(&parser->value_stack);
22012208
rvalue_cache_compact(&parser->state.name_cache);
22022209
parser->buffer = rb_gc_location(parser->buffer);
2210+
parser->state.parser = rb_gc_location(parser->state.parser);
22032211
}
22042212

22052213
static const rb_data_type_t JSON_ResumableParser_type = {
@@ -2221,6 +2229,7 @@ static VALUE cResumableParser_allocate(VALUE klass)
22212229
JSON_ResumableParser *parser;
22222230
VALUE obj = TypedData_Make_Struct(klass, JSON_ResumableParser, &JSON_ResumableParser_type, parser);
22232231
parser->state.in_array++;
2232+
parser->state.parser = obj;
22242233
return obj;
22252234
}
22262235

@@ -2286,7 +2295,7 @@ static VALUE cResumableParser_initialize(int argc, VALUE *argv, VALUE self)
22862295
return self;
22872296
}
22882297

2289-
static JSON_ResumableParser *ResumableParser_acquire(VALUE *self, bool lock);
2298+
static JSON_ResumableParser *ResumableParser_acquire(VALUE self, bool lock);
22902299

22912300
/*
22922301
* call-seq: self << string -> self
@@ -2297,7 +2306,7 @@ static VALUE cResumableParser_feed(VALUE self, VALUE str)
22972306
{
22982307
rb_check_frozen(self);
22992308

2300-
JSON_ResumableParser *parser = ResumableParser_acquire(&self, false);
2309+
JSON_ResumableParser *parser = ResumableParser_acquire(self, false);
23012310

23022311
str = convert_encoding(str);
23032312
if (!RSTRING_LEN(str)) {
@@ -2355,9 +2364,9 @@ static VALUE json_parse_any_resumable_safe(VALUE _args)
23552364
return (VALUE)json_parse_any(args->state, args->config, true);
23562365
}
23572366

2358-
static JSON_ResumableParser *ResumableParser_acquire(VALUE *self, bool lock)
2367+
static JSON_ResumableParser *ResumableParser_acquire(VALUE self, bool lock)
23592368
{
2360-
JSON_ResumableParser *parser = cResumableParser_get(*self);
2369+
JSON_ResumableParser *parser = cResumableParser_get(self);
23612370

23622371
if (parser->in_use) {
23632372
rb_raise(rb_eArgError, "ResumableParser can't be used recursively");
@@ -2370,8 +2379,6 @@ static JSON_ResumableParser *ResumableParser_acquire(VALUE *self, bool lock)
23702379
// self may have moved, so we need to update all pointers
23712380
// Investigate: We might be better off keeping JSON_ParserState on the stack
23722381
// and only persist what we need.
2373-
parser->state.value_stack_handle = self;
2374-
parser->state.frame_stack_handle = self;
23752382
parser->state.value_stack = &parser->value_stack;
23762383
parser->state.frames = &parser->frames;
23772384

@@ -2390,7 +2397,7 @@ static JSON_ResumableParser *ResumableParser_acquire(VALUE *self, bool lock)
23902397
*/
23912398
static VALUE cResumableParser_parse(VALUE self)
23922399
{
2393-
JSON_ResumableParser *parser = ResumableParser_acquire(&self, true);
2400+
JSON_ResumableParser *parser = ResumableParser_acquire(self, true);
23942401
if (!parser->buffer) {
23952402
parser->in_use = false;
23962403
return Qfalse;
@@ -2443,7 +2450,7 @@ static VALUE cResumableParser_parse(VALUE self)
24432450
*/
24442451
static VALUE cResumableParser_value_p(VALUE self)
24452452
{
2446-
JSON_ResumableParser *parser = ResumableParser_acquire(&self, false);
2453+
JSON_ResumableParser *parser = ResumableParser_acquire(self, false);
24472454

24482455
if (parser->value_stack.head > 0) {
24492456
json_frame *frame = json_frame_stack_peek(&parser->frames);
@@ -2467,7 +2474,7 @@ static VALUE cResumableParser_value_p(VALUE self)
24672474
*/
24682475
static VALUE cResumableParser_value(VALUE self)
24692476
{
2470-
JSON_ResumableParser *parser = ResumableParser_acquire(&self, false);
2477+
JSON_ResumableParser *parser = ResumableParser_acquire(self, false);
24712478

24722479
if (parser->frames.head > 0) {
24732480
json_frame *frame = json_frame_stack_peek(&parser->frames);
@@ -2489,7 +2496,7 @@ static VALUE cResumableParser_value(VALUE self)
24892496
*/
24902497
static VALUE cResumableParser_clear(VALUE self)
24912498
{
2492-
JSON_ResumableParser *parser = ResumableParser_acquire(&self, false);
2499+
JSON_ResumableParser *parser = ResumableParser_acquire(self, false);
24932500
parser->buffer = 0;
24942501
parser->frames.head = 0;
24952502
parser->value_stack.head = 0;
@@ -2581,7 +2588,7 @@ static VALUE cResumableParser_partial_value_body(VALUE self)
25812588
*/
25822589
static VALUE cResumableParser_partial_value(VALUE self)
25832590
{
2584-
JSON_ResumableParser *parser = ResumableParser_acquire(&self, true);
2591+
JSON_ResumableParser *parser = ResumableParser_acquire(self, true);
25852592

25862593
int status;
25872594
VALUE result = rb_protect(cResumableParser_partial_value_body, self, &status);

0 commit comments

Comments
 (0)