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
5 changes: 5 additions & 0 deletions ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,11 @@ node_locations(VALUE ast_value, const NODE *node)
location_new(&RNODE_IF(node)->if_keyword_loc),
location_new(&RNODE_IF(node)->then_keyword_loc),
location_new(&RNODE_IF(node)->end_keyword_loc));
case NODE_MODULE:
return rb_ary_new_from_args(3,
location_new(nd_code_loc(node)),
location_new(&RNODE_MODULE(node)->module_keyword_loc),
location_new(&RNODE_MODULE(node)->end_keyword_loc));
case NODE_NEXT:
return rb_ary_new_from_args(2,
location_new(nd_code_loc(node)),
Expand Down
2 changes: 1 addition & 1 deletion autogen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ case "$0" in
* ) srcdir="";; # Otherwise
esac

# If install-only is explicitly requested, disbale symlink flags
# If install-only is explicitly requested, disable symlink flags
case " $* " in
*" -i "* | *" --install"* ) symlink_flags="" ;;
* ) symlink_flags="--install --symlink" ;;
Expand Down
12 changes: 12 additions & 0 deletions benchmark/struct_accessor.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
prelude: |
C = Struct.new(:x) do
def initialize(...)
super
@ivar = 42
end

attr_accessor :ivar

class_eval <<-END
def r
#{'x;'*256}
Expand All @@ -15,11 +22,16 @@ prelude: |
m = method(:x=)
#{'m.call(nil);'*256}
end
def r_ivar
#{'ivar;'*256}
end
END
end
C.new(nil) # ensure common shape is known
obj = C.new(nil)
benchmark:
member_reader: "obj.r"
member_writer: "obj.w"
member_reader_method: "obj.rm"
member_writer_method: "obj.wm"
ivar_reader: "obj.r_ivar"
8 changes: 8 additions & 0 deletions depend
Original file line number Diff line number Diff line change
Expand Up @@ -6065,6 +6065,7 @@ hash.$(OBJEXT): $(top_srcdir)/internal/set_table.h
hash.$(OBJEXT): $(top_srcdir)/internal/st.h
hash.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
hash.$(OBJEXT): $(top_srcdir)/internal/string.h
hash.$(OBJEXT): $(top_srcdir)/internal/struct.h
hash.$(OBJEXT): $(top_srcdir)/internal/symbol.h
hash.$(OBJEXT): $(top_srcdir)/internal/thread.h
hash.$(OBJEXT): $(top_srcdir)/internal/time.h
Expand Down Expand Up @@ -6288,6 +6289,7 @@ hash.$(OBJEXT): {$(VPATH)}symbol.h
hash.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
hash.$(OBJEXT): {$(VPATH)}thread_native.h
hash.$(OBJEXT): {$(VPATH)}util.h
hash.$(OBJEXT): {$(VPATH)}variable.h
hash.$(OBJEXT): {$(VPATH)}vm_core.h
hash.$(OBJEXT): {$(VPATH)}vm_debug.h
hash.$(OBJEXT): {$(VPATH)}vm_opts.h
Expand Down Expand Up @@ -12926,6 +12928,7 @@ range.$(OBJEXT): $(top_srcdir)/internal/enumerator.h
range.$(OBJEXT): $(top_srcdir)/internal/error.h
range.$(OBJEXT): $(top_srcdir)/internal/fixnum.h
range.$(OBJEXT): $(top_srcdir)/internal/gc.h
range.$(OBJEXT): $(top_srcdir)/internal/imemo.h
range.$(OBJEXT): $(top_srcdir)/internal/numeric.h
range.$(OBJEXT): $(top_srcdir)/internal/range.h
range.$(OBJEXT): $(top_srcdir)/internal/serial.h
Expand All @@ -12948,6 +12951,7 @@ range.$(OBJEXT): {$(VPATH)}config.h
range.$(OBJEXT): {$(VPATH)}defines.h
range.$(OBJEXT): {$(VPATH)}encoding.h
range.$(OBJEXT): {$(VPATH)}id.h
range.$(OBJEXT): {$(VPATH)}id_table.h
range.$(OBJEXT): {$(VPATH)}intern.h
range.$(OBJEXT): {$(VPATH)}internal.h
range.$(OBJEXT): {$(VPATH)}internal/abi.h
Expand Down Expand Up @@ -15580,6 +15584,7 @@ shape.$(OBJEXT): $(top_srcdir)/internal/serial.h
shape.$(OBJEXT): $(top_srcdir)/internal/set_table.h
shape.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
shape.$(OBJEXT): $(top_srcdir)/internal/string.h
shape.$(OBJEXT): $(top_srcdir)/internal/struct.h
shape.$(OBJEXT): $(top_srcdir)/internal/symbol.h
shape.$(OBJEXT): $(top_srcdir)/internal/variable.h
shape.$(OBJEXT): $(top_srcdir)/internal/vm.h
Expand Down Expand Up @@ -16569,6 +16574,7 @@ string.$(OBJEXT): $(top_srcdir)/internal/serial.h
string.$(OBJEXT): $(top_srcdir)/internal/set_table.h
string.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
string.$(OBJEXT): $(top_srcdir)/internal/string.h
string.$(OBJEXT): $(top_srcdir)/internal/struct.h
string.$(OBJEXT): $(top_srcdir)/internal/transcode.h
string.$(OBJEXT): $(top_srcdir)/internal/variable.h
string.$(OBJEXT): $(top_srcdir)/internal/vm.h
Expand Down Expand Up @@ -16766,6 +16772,7 @@ string.$(OBJEXT): {$(VPATH)}thread.h
string.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h
string.$(OBJEXT): {$(VPATH)}thread_native.h
string.$(OBJEXT): {$(VPATH)}util.h
string.$(OBJEXT): {$(VPATH)}variable.h
string.$(OBJEXT): {$(VPATH)}vm_core.h
string.$(OBJEXT): {$(VPATH)}vm_debug.h
string.$(OBJEXT): {$(VPATH)}vm_opts.h
Expand Down Expand Up @@ -18103,6 +18110,7 @@ variable.$(OBJEXT): $(top_srcdir)/internal/serial.h
variable.$(OBJEXT): $(top_srcdir)/internal/set_table.h
variable.$(OBJEXT): $(top_srcdir)/internal/static_assert.h
variable.$(OBJEXT): $(top_srcdir)/internal/string.h
variable.$(OBJEXT): $(top_srcdir)/internal/struct.h
variable.$(OBJEXT): $(top_srcdir)/internal/symbol.h
variable.$(OBJEXT): $(top_srcdir)/internal/thread.h
variable.$(OBJEXT): $(top_srcdir)/internal/variable.h
Expand Down
13 changes: 13 additions & 0 deletions gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3260,6 +3260,10 @@ rb_gc_mark_children(void *objspace, VALUE obj)
gc_mark_internal(ptr[i]);
}

if (!FL_TEST_RAW(obj, RSTRUCT_GEN_FIELDS)) {
gc_mark_internal(RSTRUCT_FIELDS_OBJ(obj));
}

break;
}

Expand Down Expand Up @@ -4188,6 +4192,15 @@ rb_gc_update_object_references(void *objspace, VALUE obj)
for (i = 0; i < len; i++) {
UPDATE_IF_MOVED(objspace, ptr[i]);
}

if (RSTRUCT_EMBED_LEN(obj)) {
if (!FL_TEST_RAW(obj, RSTRUCT_GEN_FIELDS)) {
UPDATE_IF_MOVED(objspace, ptr[len]);
}
}
else {
UPDATE_IF_MOVED(objspace, RSTRUCT(obj)->as.heap.fields_obj);
}
}
break;
default:
Expand Down
41 changes: 41 additions & 0 deletions internal/struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,23 @@
#include "ruby/internal/stdbool.h" /* for bool */
#include "ruby/ruby.h" /* for struct RBasic */

/* Flags of RStruct
*
* 1-7: RSTRUCT_EMBED_LEN
* If non-zero, the struct is embedded (its contents follow the
* header, rather than being on a separately allocated buffer) and
* these bits are the length of the Struct.
* 8: RSTRUCT_GEN_FIELDS
* The struct is embedded and has no space left to store the
* IMEMO/fields reference. Any ivar this struct may have will be in
* the generic_fields_tbl. This flag doesn't imply the struct has
* ivars.
*/
enum {
RSTRUCT_EMBED_LEN_MASK = RUBY_FL_USER7 | RUBY_FL_USER6 | RUBY_FL_USER5 | RUBY_FL_USER4 |
RUBY_FL_USER3 | RUBY_FL_USER2 | RUBY_FL_USER1,
RSTRUCT_EMBED_LEN_SHIFT = (RUBY_FL_USHIFT+1),
RSTRUCT_GEN_FIELDS = RUBY_FL_USER8,
};

struct RStruct {
Expand All @@ -23,6 +36,7 @@ struct RStruct {
struct {
long len;
const VALUE *ptr;
VALUE fields_obj;
} heap;
/* This is a length 1 array because:
* 1. GCC has a bug that does not optimize C flexible array members
Expand Down Expand Up @@ -116,4 +130,31 @@ RSTRUCT_GET(VALUE st, long k)
return RSTRUCT_CONST_PTR(st)[k];
}

static inline VALUE
RSTRUCT_FIELDS_OBJ(VALUE st)
{
const long embed_len = RSTRUCT_EMBED_LEN(st);
VALUE fields_obj;
if (embed_len) {
RUBY_ASSERT(!FL_TEST_RAW(st, RSTRUCT_GEN_FIELDS));
fields_obj = RSTRUCT_GET(st, embed_len);
}
else {
fields_obj = RSTRUCT(st)->as.heap.fields_obj;
}
return fields_obj;
}

static inline void
RSTRUCT_SET_FIELDS_OBJ(VALUE st, VALUE fields_obj)
{
const long embed_len = RSTRUCT_EMBED_LEN(st);
if (embed_len) {
RUBY_ASSERT(!FL_TEST_RAW(st, RSTRUCT_GEN_FIELDS));
RSTRUCT_SET(st, embed_len, fields_obj);
}
else {
RB_OBJ_WRITE(st, &RSTRUCT(st)->as.heap.fields_obj, fields_obj);
}
}
#endif /* INTERNAL_STRUCT_H */
4 changes: 3 additions & 1 deletion node_dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -1009,8 +1009,10 @@ dump_node(VALUE buf, VALUE indent, int comment, const NODE * node)
ANN("format: module [nd_cpath]; [nd_body]; end");
ANN("example: module M; ..; end");
F_NODE(nd_cpath, RNODE_MODULE, "module path");
LAST_NODE;
F_NODE(nd_body, RNODE_MODULE, "module definition");
F_LOC(module_keyword_loc, RNODE_MODULE);
LAST_NODE;
F_LOC(end_keyword_loc, RNODE_MODULE);
return;

case NODE_SCLASS:
Expand Down
10 changes: 6 additions & 4 deletions parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,7 @@ static rb_node_alias_t *rb_node_alias_new(struct parser_params *p, NODE *nd_1st,
static rb_node_valias_t *rb_node_valias_new(struct parser_params *p, ID nd_alias, ID nd_orig, const YYLTYPE *loc, const YYLTYPE *keyword_loc);
static rb_node_undef_t *rb_node_undef_new(struct parser_params *p, NODE *nd_undef, const YYLTYPE *loc);
static rb_node_class_t *rb_node_class_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, NODE *nd_super, const YYLTYPE *loc, const YYLTYPE *class_keyword_loc, const YYLTYPE *inheritance_operator_loc, const YYLTYPE *end_keyword_loc);
static rb_node_module_t *rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc);
static rb_node_module_t *rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *module_keyword_loc, const YYLTYPE *end_keyword_loc);
static rb_node_sclass_t *rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const YYLTYPE *loc);
static rb_node_colon2_t *rb_node_colon2_new(struct parser_params *p, NODE *nd_head, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc);
static rb_node_colon3_t *rb_node_colon3_new(struct parser_params *p, ID nd_mid, const YYLTYPE *loc, const YYLTYPE *delimiter_loc, const YYLTYPE *name_loc);
Expand Down Expand Up @@ -1253,7 +1253,7 @@ static rb_node_error_t *rb_node_error_new(struct parser_params *p, const YYLTYPE
#define NEW_VALIAS(n,o,loc,k_loc) (NODE *)rb_node_valias_new(p,n,o,loc,k_loc)
#define NEW_UNDEF(i,loc) (NODE *)rb_node_undef_new(p,i,loc)
#define NEW_CLASS(n,b,s,loc,ck_loc,io_loc,ek_loc) (NODE *)rb_node_class_new(p,n,b,s,loc,ck_loc,io_loc,ek_loc)
#define NEW_MODULE(n,b,loc) (NODE *)rb_node_module_new(p,n,b,loc)
#define NEW_MODULE(n,b,loc,mk_loc,ek_loc) (NODE *)rb_node_module_new(p,n,b,loc,mk_loc,ek_loc)
#define NEW_SCLASS(r,b,loc) (NODE *)rb_node_sclass_new(p,r,b,loc)
#define NEW_COLON2(c,i,loc,d_loc,n_loc) (NODE *)rb_node_colon2_new(p,c,i,loc,d_loc,n_loc)
#define NEW_COLON3(i,loc,d_loc,n_loc) (NODE *)rb_node_colon3_new(p,i,loc,d_loc,n_loc)
Expand Down Expand Up @@ -4621,7 +4621,7 @@ primary : inline_primary
bodystmt
k_end
{
$$ = NEW_MODULE($cpath, $bodystmt, &@$);
$$ = NEW_MODULE($cpath, $bodystmt, &@$, &@k_module, &@k_end);
nd_set_line(RNODE_MODULE($$)->nd_body, @k_end.end_pos.lineno);
set_line_body($bodystmt, @cpath.end_pos.lineno);
nd_set_line($$, @cpath.end_pos.lineno);
Expand Down Expand Up @@ -11438,13 +11438,15 @@ rb_node_sclass_new(struct parser_params *p, NODE *nd_recv, NODE *nd_body, const
}

static rb_node_module_t *
rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc)
rb_node_module_new(struct parser_params *p, NODE *nd_cpath, NODE *nd_body, const YYLTYPE *loc, const YYLTYPE *module_keyword_loc, const YYLTYPE *end_keyword_loc)
{
/* Keep the order of node creation */
NODE *scope = NEW_SCOPE(0, nd_body, loc);
rb_node_module_t *n = NODE_NEWNODE(NODE_MODULE, rb_node_module_t, loc);
n->nd_cpath = nd_cpath;
n->nd_body = scope;
n->module_keyword_loc = *module_keyword_loc;
n->end_keyword_loc = *end_keyword_loc;

return n;
}
Expand Down
2 changes: 1 addition & 1 deletion ractor.c
Original file line number Diff line number Diff line change
Expand Up @@ -2302,7 +2302,7 @@ static const rb_data_type_t cross_ractor_require_data_type = {
NULL, // memsize
NULL, // compact
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_DECL_MARKING
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_DECL_MARKING | RUBY_TYPED_EMBEDDABLE
};

static VALUE
Expand Down
4 changes: 3 additions & 1 deletion ractor_sync.c
Original file line number Diff line number Diff line change
Expand Up @@ -1273,7 +1273,7 @@ static const rb_data_type_t ractor_selector_data_type = {
ractor_selector_memsize,
NULL, // update
},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};

static struct ractor_selector *
Expand Down Expand Up @@ -1318,6 +1318,8 @@ ractor_selector_add(VALUE selv, VALUE rpv)
}

st_insert(s->ports, (st_data_t)rpv, (st_data_t)rp);
RB_OBJ_WRITTEN(selv, Qundef, rpv);

return selv;
}

Expand Down
2 changes: 2 additions & 0 deletions rubyparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,8 @@ typedef struct RNode_MODULE {

struct RNode *nd_cpath;
struct RNode *nd_body;
rb_code_location_t module_keyword_loc;
rb_code_location_t end_keyword_loc;
} rb_node_module_t;

typedef struct RNode_SCLASS {
Expand Down
11 changes: 10 additions & 1 deletion struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,13 +811,22 @@ struct_alloc(VALUE klass)
{
long n = num_members(klass);
size_t embedded_size = offsetof(struct RStruct, as.ary) + (sizeof(VALUE) * n);
if (RCLASS_MAX_IV_COUNT(klass) > 0) {
embedded_size += sizeof(VALUE);
}

VALUE flags = T_STRUCT | (RGENGC_WB_PROTECTED_STRUCT ? FL_WB_PROTECTED : 0);

if (n > 0 && rb_gc_size_allocatable_p(embedded_size)) {
flags |= n << RSTRUCT_EMBED_LEN_SHIFT;

NEWOBJ_OF(st, struct RStruct, klass, flags, embedded_size, 0);

if (RCLASS_MAX_IV_COUNT(klass) == 0 && embedded_size == rb_gc_obj_slot_size((VALUE)st)) {
FL_SET_RAW((VALUE)st, RSTRUCT_GEN_FIELDS);
}
else {
RSTRUCT_SET_FIELDS_OBJ((VALUE)st, 0);
}
rb_mem_clear((VALUE *)st->as.ary, n);

return (VALUE)st;
Expand Down
4 changes: 3 additions & 1 deletion symbol.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ typedef struct {
VALUE ids;
} rb_symbols_t;

rb_symbols_t ruby_global_symbols = {tNEXT_ID-1};
rb_symbols_t ruby_global_symbols = {
.next_id = tNEXT_ID,
};

struct sym_set_static_sym_entry {
VALUE sym;
Expand Down
5 changes: 5 additions & 0 deletions test/ruby/test_ast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1491,6 +1491,11 @@ def test_lambda_locations
assert_locations(node.children[-1].locations, [[1, 0, 1, 20], [1, 0, 1, 2], [1, 10, 1, 12], [1, 17, 1, 20]])
end

def test_module_locations
node = ast_parse('module A end')
assert_locations(node.children[-1].locations, [[1, 0, 1, 12], [1, 0, 1, 6], [1, 9, 1, 12]])
end

def test_if_locations
node = ast_parse("if cond then 1 else 2 end")
assert_locations(node.children[-1].locations, [[1, 0, 1, 25], [1, 0, 1, 2], [1, 8, 1, 12], [1, 22, 1, 25]])
Expand Down
49 changes: 49 additions & 0 deletions test/ruby/test_object_id.rb
Original file line number Diff line number Diff line change
Expand Up @@ -252,3 +252,52 @@ def initialize
end;
end
end

class TestObjectIdStruct < TestObjectId
EmbeddedStruct = Struct.new(:embedded_field)

def setup
@obj = EmbeddedStruct.new
end
end

class TestObjectIdStructGenIvar < TestObjectId
GenIvarStruct = Struct.new(:a, :b, :c)

def setup
@obj = GenIvarStruct.new
end
end

class TestObjectIdStructNotEmbed < TestObjectId
MANY_IVS = 80

StructNotEmbed = Struct.new(*MANY_IVS.times.map { |i| :"field_#{i}" })

def setup
@obj = StructNotEmbed.new
end
end

class TestObjectIdStructTooComplex < TestObjectId
StructTooComplex = Struct.new(:a) do
def initialize
@too_complex_obj_id_test = 1
end
end

def setup
if defined?(RubyVM::Shape::SHAPE_MAX_VARIATIONS)
assert_equal 8, RubyVM::Shape::SHAPE_MAX_VARIATIONS
end
8.times do |i|
StructTooComplex.new.instance_variable_set("@TestObjectIdStructTooComplex#{i}", 1)
end
@obj = StructTooComplex.new
@obj.instance_variable_set("@a#{rand(10_000)}", 1)

if defined?(RubyVM::Shape)
assert_predicate(RubyVM::Shape.of(@obj), :too_complex?)
end
end
end
Loading