Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 20 additions & 13 deletions ext/json/ext/parser/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,8 @@ static rvalue_stack *rvalue_stack_grow(rvalue_stack *stack, VALUE *handle, rvalu

static VALUE rvalue_stack_push(rvalue_stack *stack, VALUE value, VALUE *handle, rvalue_stack **stack_ref)
{
JSON_ASSERT(stack->type != RVALUE_STACK_STACK_ALLOCATED || handle);

if (RB_UNLIKELY(stack->head >= stack->capa)) {
stack = rvalue_stack_grow(stack, handle, stack_ref);
}
Expand Down Expand Up @@ -431,6 +433,7 @@ typedef struct JSON_ParserStateStruct {
int in_array;
int current_nesting;
unsigned int emitted_deprecations;
VALUE parser;
} JSON_ParserState;

static json_frame_stack *json_frame_stack_spill(json_frame_stack *old_stack, VALUE *handle, json_frame_stack **stack_ref);
Expand All @@ -451,6 +454,9 @@ static json_frame_stack *json_frame_stack_grow(json_frame_stack *stack, VALUE *h
static json_frame *json_frame_stack_push(JSON_ParserState *state, json_frame frame)
{
json_frame_stack *stack = state->frames;

JSON_ASSERT(stack->type != RVALUE_STACK_STACK_ALLOCATED || state->frame_stack_handle);

if (RB_UNLIKELY(stack->head >= stack->capa)) {
stack = json_frame_stack_grow(stack, state->frame_stack_handle, &state->frames);
}
Expand Down Expand Up @@ -665,8 +671,8 @@ static VALUE parse_error_new(JSON_ParserState *state, VALUE message, long line,
VALUE exc = rb_exc_new_str(eParserError, message);
rb_ivar_set(exc, i_at_line, LONG2NUM(line));
rb_ivar_set(exc, i_at_column, LONG2NUM(column));
if (eos && state->value_stack_handle) {
rb_ivar_set(exc, i_at_eos, *state->value_stack_handle);
if (eos && state->parser) {
rb_ivar_set(exc, i_at_eos, state->parser);
}
return exc;
}
Expand Down Expand Up @@ -2166,6 +2172,7 @@ static void JSON_ResumableParser_mark(void *ptr)
rvalue_stack_mark(&parser->value_stack);
rvalue_cache_mark(&parser->state.name_cache);
rb_gc_mark(parser->buffer); // pin the buffer
rb_gc_mark_movable(parser->state.parser);
}

static void JSON_ResumableParser_free(void *ptr)
Expand Down Expand Up @@ -2200,6 +2207,7 @@ static void JSON_ResumableParser_compact(void *ptr)
rvalue_stack_compact(&parser->value_stack);
rvalue_cache_compact(&parser->state.name_cache);
parser->buffer = rb_gc_location(parser->buffer);
parser->state.parser = rb_gc_location(parser->state.parser);
}

static const rb_data_type_t JSON_ResumableParser_type = {
Expand All @@ -2221,6 +2229,7 @@ static VALUE cResumableParser_allocate(VALUE klass)
JSON_ResumableParser *parser;
VALUE obj = TypedData_Make_Struct(klass, JSON_ResumableParser, &JSON_ResumableParser_type, parser);
parser->state.in_array++;
parser->state.parser = obj;
return obj;
}

Expand Down Expand Up @@ -2286,7 +2295,7 @@ static VALUE cResumableParser_initialize(int argc, VALUE *argv, VALUE self)
return self;
}

static JSON_ResumableParser *ResumableParser_acquire(VALUE *self, bool lock);
static JSON_ResumableParser *ResumableParser_acquire(VALUE self, bool lock);

/*
* call-seq: self << string -> self
Expand All @@ -2297,7 +2306,7 @@ static VALUE cResumableParser_feed(VALUE self, VALUE str)
{
rb_check_frozen(self);

JSON_ResumableParser *parser = ResumableParser_acquire(&self, false);
JSON_ResumableParser *parser = ResumableParser_acquire(self, false);

str = convert_encoding(str);
if (!RSTRING_LEN(str)) {
Expand Down Expand Up @@ -2355,9 +2364,9 @@ static VALUE json_parse_any_resumable_safe(VALUE _args)
return (VALUE)json_parse_any(args->state, args->config, true);
}

static JSON_ResumableParser *ResumableParser_acquire(VALUE *self, bool lock)
static JSON_ResumableParser *ResumableParser_acquire(VALUE self, bool lock)
{
JSON_ResumableParser *parser = cResumableParser_get(*self);
JSON_ResumableParser *parser = cResumableParser_get(self);

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

Expand All @@ -2390,7 +2397,7 @@ static JSON_ResumableParser *ResumableParser_acquire(VALUE *self, bool lock)
*/
static VALUE cResumableParser_parse(VALUE self)
{
JSON_ResumableParser *parser = ResumableParser_acquire(&self, true);
JSON_ResumableParser *parser = ResumableParser_acquire(self, true);
if (!parser->buffer) {
parser->in_use = false;
return Qfalse;
Expand Down Expand Up @@ -2443,7 +2450,7 @@ static VALUE cResumableParser_parse(VALUE self)
*/
static VALUE cResumableParser_value_p(VALUE self)
{
JSON_ResumableParser *parser = ResumableParser_acquire(&self, false);
JSON_ResumableParser *parser = ResumableParser_acquire(self, false);

if (parser->value_stack.head > 0) {
json_frame *frame = json_frame_stack_peek(&parser->frames);
Expand All @@ -2467,7 +2474,7 @@ static VALUE cResumableParser_value_p(VALUE self)
*/
static VALUE cResumableParser_value(VALUE self)
{
JSON_ResumableParser *parser = ResumableParser_acquire(&self, false);
JSON_ResumableParser *parser = ResumableParser_acquire(self, false);

if (parser->frames.head > 0) {
json_frame *frame = json_frame_stack_peek(&parser->frames);
Expand All @@ -2489,7 +2496,7 @@ static VALUE cResumableParser_value(VALUE self)
*/
static VALUE cResumableParser_clear(VALUE self)
{
JSON_ResumableParser *parser = ResumableParser_acquire(&self, false);
JSON_ResumableParser *parser = ResumableParser_acquire(self, false);
parser->buffer = 0;
parser->frames.head = 0;
parser->value_stack.head = 0;
Expand Down Expand Up @@ -2581,7 +2588,7 @@ static VALUE cResumableParser_partial_value_body(VALUE self)
*/
static VALUE cResumableParser_partial_value(VALUE self)
{
JSON_ResumableParser *parser = ResumableParser_acquire(&self, true);
JSON_ResumableParser *parser = ResumableParser_acquire(self, true);

int status;
VALUE result = rb_protect(cResumableParser_partial_value_body, self, &status);
Expand Down
Loading