Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion .github/workflows/zjit-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ jobs:
rustup install ${{ matrix.rust_version }} --profile minimal
rustup default ${{ matrix.rust_version }}

- uses: taiki-e/install-action@b6b84cf49ebfe0176417bdce007c624f0db37f20 # v2.86.2
- uses: taiki-e/install-action@5b4d68e2e660441203ab128a23676f1e4faf1532 # v2.86.3
with:
tool: nextest@0.9
if: ${{ matrix.test_task == 'zjit-check' }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/zjit-ubuntu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ jobs:
ruby-version: '3.1'
bundler: none

- uses: taiki-e/install-action@b6b84cf49ebfe0176417bdce007c624f0db37f20 # v2.86.2
- uses: taiki-e/install-action@5b4d68e2e660441203ab128a23676f1e4faf1532 # v2.86.3
with:
tool: nextest@0.9
if: ${{ matrix.test_task == 'zjit-check' }}
Expand Down
2 changes: 1 addition & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ They are still available on rubygems.org and can be installed with
* 0.6.3 to [v0.6.4][pp-v0.6.4]
* prism 1.9.0
* 1.7.0 to [v1.8.0][prism-v1.8.0], [v1.8.1][prism-v1.8.1], [v1.9.0][prism-v1.9.0]
* psych 5.4.0
* psych 5.5.0
* 5.3.1 to [v5.4.0][psych-v5.4.0]
* resolv 0.7.1
* 0.7.0 to [v0.7.1][resolv-v0.7.1]
Expand Down
31 changes: 21 additions & 10 deletions compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,17 +628,28 @@ setup_branch(const rb_code_location_t *loc, const char *type, VALUE structure, V
}

static VALUE
decl_branch_base(rb_iseq_t *iseq, VALUE key, const rb_code_location_t *loc, const char *type)
decl_branch_base(rb_iseq_t *iseq, int node_id, const rb_code_location_t *loc, const char *type)
{
if (!branch_coverage_valid_p(iseq, loc->beg_pos.lineno)) return Qundef;

/*
* if !structure[node]
* structure[node] = [type, first_lineno, first_column, last_lineno, last_column, branches = {}]
* A branch base is keyed by [source_hash (in two halves), node_id, first_lineno],
* which identifies the branch node stably even across (re-)evals against
* the same path.
*
* if !structure[key]
* structure[key] = [type, first_lineno, first_column, last_lineno, last_column, branches = {}]
* else
* branches = structure[node][5]
* branches = structure[key][5]
* end
*/
uint64_t source_hash = ISEQ_BODY(iseq)->source_hash;
VALUE key = rb_ary_new_from_args(4,
ULONG2NUM((unsigned long)(source_hash >> 32)),
ULONG2NUM((unsigned long)(source_hash & 0xffffffff)),
INT2FIX(node_id),
INT2FIX(loc->beg_pos.lineno));
rb_ary_freeze(key);

VALUE structure = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 0);
VALUE branch_base = rb_hash_aref(structure, key);
Expand Down Expand Up @@ -7082,7 +7093,7 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int
ADD_SEQ(ret, cond_seq);

if (then_label->refcnt && else_label->refcnt) {
branches = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), type == NODE_IF ? "if" : "unless");
branches = decl_branch_base(iseq, nd_node_id(node), nd_code_loc(node), type == NODE_IF ? "if" : "unless");
}

if (then_label->refcnt) {
Expand Down Expand Up @@ -7162,7 +7173,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod

CHECK(COMPILE(head, "case base", RNODE_CASE(node)->nd_head));

branches = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), "case");
branches = decl_branch_base(iseq, nd_node_id(node), nd_code_loc(node), "case");

node = RNODE_CASE(node)->nd_body;
EXPECT_NODE("NODE_CASE", node, NODE_WHEN, COMPILE_NG);
Expand Down Expand Up @@ -7267,7 +7278,7 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
VALUE branches = Qfalse;
int branch_id = 0;

branches = decl_branch_base(iseq, PTR2NUM(orig_node), nd_code_loc(orig_node), "case");
branches = decl_branch_base(iseq, nd_node_id(orig_node), nd_code_loc(orig_node), "case");

INIT_ANCHOR(body_seq);
endlabel = NEW_LABEL(nd_line(node));
Expand Down Expand Up @@ -8266,7 +8277,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no
INIT_ANCHOR(body_seq);
INIT_ANCHOR(cond_seq);

branches = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), "case");
branches = decl_branch_base(iseq, nd_node_id(node), nd_code_loc(node), "case");

node = RNODE_CASE3(node)->nd_body;
EXPECT_NODE("NODE_CASE3", node, NODE_IN, COMPILE_NG);
Expand Down Expand Up @@ -8470,7 +8481,7 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in
if (tmp_label) ADD_LABEL(ret, tmp_label);

ADD_LABEL(ret, redo_label);
branches = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), type == NODE_WHILE ? "while" : "until");
branches = decl_branch_base(iseq, nd_node_id(node), nd_code_loc(node), type == NODE_WHILE ? "while" : "until");

const NODE *const coverage_node = RNODE_WHILE(node)->nd_body ? RNODE_WHILE(node)->nd_body : node;
add_trace_branch_coverage(
Expand Down Expand Up @@ -9113,7 +9124,7 @@ qcall_branch_start(rb_iseq_t *iseq, LINK_ANCHOR *const recv, VALUE *branches, co
LABEL *else_label = NEW_LABEL(nd_line(line_node));
VALUE br = 0;

br = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), "&.");
br = decl_branch_base(iseq, nd_node_id(node), nd_code_loc(node), "&.");
*branches = br;
ADD_INSN(recv, line_node, dup);
ADD_INSNL(recv, line_node, branchnil, else_label);
Expand Down
2 changes: 1 addition & 1 deletion ext/psych/lib/psych/versions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

module Psych
# The version of Psych you are using
VERSION = '5.4.0'
VERSION = '5.5.0'

if RUBY_ENGINE == 'jruby'
DEFAULT_SNAKEYAML_VERSION = '2.10'.freeze
Expand Down
3 changes: 0 additions & 3 deletions ext/psych/lib/psych/visitors/to_ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -445,9 +445,6 @@ def deduplicate key
end
end

def merge_key hash, key, val
end

def revive klass, node
s = register(node, klass.allocate)
init_with(s, revive_hash({}, node, true), node)
Expand Down
3 changes: 0 additions & 3 deletions ext/psych/lib/psych/visitors/yaml_tree.rb
Original file line number Diff line number Diff line change
Expand Up @@ -496,9 +496,6 @@ def visit_hash_subclass o
end
end

def dump_list o
end

def dump_exception o, msg
tag = ['!ruby/exception', o.class.name].join ':'

Expand Down
91 changes: 75 additions & 16 deletions ext/psych/psych_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,28 @@ static int io_reader(void * data, unsigned char *buf, size_t size, size_t *read)
return 1;
}

/* The parser calls back into Ruby for every event, so a handler can call
* Psych::Parser#parse again on the same object. parse() reinitialises the
* parser it is handed, which would pull the input out from under the loop
* still driving it, so keep a flag to reject a reentrant call. */
typedef struct {
yaml_parser_t yaml_parser;
int parsing;
} psych_parser_t;

static void dealloc(void * ptr)
{
yaml_parser_t * parser;
psych_parser_t * parser;

parser = (yaml_parser_t *)ptr;
yaml_parser_delete(parser);
parser = (psych_parser_t *)ptr;
yaml_parser_delete(&parser->yaml_parser);
xfree(parser);
}

#if 0
static size_t memsize(const void *ptr)
{
const yaml_parser_t *parser = ptr;
const psych_parser_t *parser = ptr;
/* TODO: calculate parser's size */
return 0;
}
Expand All @@ -81,10 +90,10 @@ static const rb_data_type_t psych_parser_type = {

static VALUE allocate(VALUE klass)
{
yaml_parser_t * parser;
VALUE obj = TypedData_Make_Struct(klass, yaml_parser_t, &psych_parser_type, parser);
psych_parser_t * parser;
VALUE obj = TypedData_Make_Struct(klass, psych_parser_t, &psych_parser_type, parser);

yaml_parser_initialize(parser);
yaml_parser_initialize(&parser->yaml_parser);

return obj;
}
Expand Down Expand Up @@ -257,18 +266,29 @@ static VALUE protected_event_location(VALUE pointer)
return rb_funcall3(args[0], id_event_location, 4, args + 1);
}

static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
struct parse_args {
psych_parser_t * psych_parser;
VALUE self;
VALUE handler;
VALUE yaml;
VALUE path;
};

static VALUE parse_body(VALUE ptr)
{
yaml_parser_t * parser;
struct parse_args * pargs = (struct parse_args *)ptr;
yaml_parser_t * parser = &pargs->psych_parser->yaml_parser;
VALUE self = pargs->self;
VALUE handler = pargs->handler;
VALUE yaml = pargs->yaml;
VALUE path = pargs->path;
yaml_event_t event;
int done = 0;
int state = 0;
int parser_encoding = YAML_ANY_ENCODING;
int encoding = rb_utf8_encindex();
rb_encoding * internal_enc = rb_default_internal_encoding();

TypedData_Get_Struct(self, yaml_parser_t, &psych_parser_type, parser);

yaml_parser_delete(parser);
yaml_parser_initialize(parser);

Expand Down Expand Up @@ -312,6 +332,10 @@ static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
event_args[3] = end_line;
event_args[4] = end_column;
rb_protect(protected_event_location, (VALUE)event_args, &state);
if (state) {
yaml_event_delete(&event);
rb_jump_tag(state);
}

switch(event.type) {
case YAML_STREAM_START_EVENT:
Expand Down Expand Up @@ -496,7 +520,11 @@ static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
rb_protect(protected_end_mapping, handler, &state);
break;
case YAML_NO_EVENT:
/* Once libyaml has produced the stream end, every later call
* succeeds with a zeroed event and YAML_STREAM_END_EVENT can no
* longer be reached. Stop rather than loop forever. */
rb_protect(protected_empty, handler, &state);
done = 1;
break;
case YAML_STREAM_END_EVENT:
rb_protect(protected_end_stream, handler, &state);
Expand All @@ -510,6 +538,37 @@ static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
return self;
}

static VALUE parse_ensure(VALUE ptr)
{
psych_parser_t * parser = (psych_parser_t *)ptr;

parser->parsing = 0;

return Qnil;
}

static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path)
{
psych_parser_t * parser;
struct parse_args pargs;

TypedData_Get_Struct(self, psych_parser_t, &psych_parser_type, parser);

if (parser->parsing) {
rb_raise(rb_const_get(mPsych, rb_intern("Exception")),
"parser is already parsing, it cannot be reused from a handler callback");
}
parser->parsing = 1;

pargs.psych_parser = parser;
pargs.self = self;
pargs.handler = handler;
pargs.yaml = yaml;
pargs.path = path;

return rb_ensure(parse_body, (VALUE)&pargs, parse_ensure, (VALUE)parser);
}

/*
* call-seq:
* parser.mark # => #<Psych::Parser::Mark>
Expand All @@ -521,13 +580,13 @@ static VALUE mark(VALUE self)
{
VALUE mark_klass;
VALUE args[3];
yaml_parser_t * parser;
psych_parser_t * parser;

TypedData_Get_Struct(self, yaml_parser_t, &psych_parser_type, parser);
TypedData_Get_Struct(self, psych_parser_t, &psych_parser_type, parser);
mark_klass = rb_const_get_at(cPsychParser, rb_intern("Mark"));
args[0] = SIZET2NUM(parser->mark.index);
args[1] = SIZET2NUM(parser->mark.line);
args[2] = SIZET2NUM(parser->mark.column);
args[0] = SIZET2NUM(parser->yaml_parser.mark.index);
args[1] = SIZET2NUM(parser->yaml_parser.mark.line);
args[2] = SIZET2NUM(parser->yaml_parser.mark.column);

return rb_class_new_instance(3, args, mark_klass);
}
Expand Down
Loading