* include/ruby/ruby.h: introduce new type T_IMEMO.

T_IMEMO is Internal Memo type, internal use only.
  T_IMEMO has same purpose of NODE_MEMO.
  To insert T_IMEMO, type numbers are modified a little.
* internal.h: define struct RIMemo. Each RIMemo objects
  has imemo_type. We can observe it by the imemo_type() function.
* gc.c (rb_imemo_new): added.
* node.h: remove NODE_CREF and NEW_CREF().
* node.c (rb_gc_mark_node): ditto.
* vm.c (vm_cref_new): use rb_imem_new().
* vm_eval.c: ditto.
* vm_eval.c (eval_string_with_cref):
* vm_eval.c (rb_type_str):
* vm_insnhelper.c: use RIMemo objects for CREF.
* ext/objspace/objspace.c: support T_IMEMO.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49932 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
ko1 2015-03-11 10:36:17 +00:00
Родитель 5922c95461
Коммит 0952b43b9b
10 изменённых файлов: 104 добавлений и 27 удалений

Просмотреть файл

@ -1,3 +1,32 @@
Wed Mar 11 19:35:46 2015 Koichi Sasada <ko1@atdot.net>
* include/ruby/ruby.h: introduce new type T_IMEMO.
T_IMEMO is Internal Memo type, internal use only.
T_IMEMO has same purpose of NODE_MEMO.
To insert T_IMEMO, type numbers are modified a little.
* internal.h: define struct RIMemo. Each RIMemo objects
has imemo_type. We can observe it by the imemo_type() function.
* gc.c (rb_imemo_new): added.
* node.h: remove NODE_CREF and NEW_CREF().
* node.c (rb_gc_mark_node): ditto.
* vm.c (vm_cref_new): use rb_imem_new().
* vm_eval.c: ditto.
* vm_eval.c (eval_string_with_cref):
* vm_eval.c (rb_type_str):
* vm_insnhelper.c: use RIMemo objects for CREF.
* ext/objspace/objspace.c: support T_IMEMO.
Wed Mar 11 17:03:20 2015 Koichi Sasada <ko1@atdot.net>
* gc.c: fix memory leak by prepend method.

Просмотреть файл

@ -56,6 +56,7 @@ total_i(void *vstart, void *vend, size_t stride, void *ptr)
if (RBASIC(v)->flags) {
switch (BUILTIN_TYPE(v)) {
case T_NONE:
case T_IMEMO:
case T_ICLASS:
case T_NODE:
case T_ZOMBIE:
@ -166,6 +167,7 @@ type2sym(enum ruby_value_type i)
CASE_TYPE(T_SYMBOL);
CASE_TYPE(T_FIXNUM);
CASE_TYPE(T_UNDEF);
CASE_TYPE(T_IMEMO);
CASE_TYPE(T_NODE);
CASE_TYPE(T_ICLASS);
CASE_TYPE(T_ZOMBIE);
@ -390,7 +392,6 @@ count_nodes(int argc, VALUE *argv, VALUE os)
COUNT_NODE(NODE_SCLASS);
COUNT_NODE(NODE_COLON2);
COUNT_NODE(NODE_COLON3);
COUNT_NODE(NODE_CREF);
COUNT_NODE(NODE_DOT2);
COUNT_NODE(NODE_DOT3);
COUNT_NODE(NODE_FLIP2);

28
gc.c
Просмотреть файл

@ -380,6 +380,9 @@ typedef struct RVALUE {
struct RMatch match;
struct RRational rational;
struct RComplex complex;
union {
rb_cref_t cref;
} imemo;
struct {
struct RBasic basic;
VALUE v1;
@ -1717,12 +1720,19 @@ rb_newobj_of(VALUE klass, VALUE flags)
NODE*
rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
{
VALUE flags = (RGENGC_WB_PROTECTED_NODE_CREF && type == NODE_CREF ? FL_WB_PROTECTED : 0);
VALUE flags = 0;
NODE *n = (NODE *)newobj_of(0, T_NODE | flags, a0, a1, a2);
nd_set_type(n, type);
return n;
}
VALUE
rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0)
{
VALUE flags = T_IMEMO | (type << FL_USHIFT) | FL_WB_PROTECTED;
return newobj_of(v0, flags, v1, v2, v3);
}
VALUE
rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
{
@ -1971,6 +1981,7 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
break;
case T_RATIONAL:
case T_COMPLEX:
case T_IMEMO:
break;
case T_ICLASS:
/* Basically , T_ICLASS shares table with the module */
@ -2181,6 +2192,7 @@ internal_object_p(VALUE obj)
if (p->as.basic.flags) {
switch (BUILTIN_TYPE(p)) {
case T_NONE:
case T_IMEMO:
case T_ICLASS:
case T_NODE:
case T_ZOMBIE:
@ -2917,6 +2929,7 @@ obj_memsize_of(VALUE obj, int use_all_types)
break;
case T_RATIONAL:
case T_COMPLEX:
case T_IMEMO:
break;
case T_FLOAT:
@ -3060,6 +3073,7 @@ count_objects(int argc, VALUE *argv, VALUE os)
COUNT_TYPE(T_FALSE);
COUNT_TYPE(T_SYMBOL);
COUNT_TYPE(T_FIXNUM);
COUNT_TYPE(T_IMEMO);
COUNT_TYPE(T_UNDEF);
COUNT_TYPE(T_NODE);
COUNT_TYPE(T_ICLASS);
@ -4134,6 +4148,17 @@ gc_mark_children(rb_objspace_t *objspace, VALUE obj)
obj = rb_gc_mark_node(&any->as.node);
if (obj) gc_mark(objspace, obj);
return; /* no need to mark class. */
case T_IMEMO:
switch (imemo_type(obj)) {
case imemo_cref:
gc_mark(objspace, RANY(obj)->as.imemo.cref.klass);
gc_mark(objspace, (VALUE)RANY(obj)->as.imemo.cref.next);
gc_mark(objspace, RANY(obj)->as.imemo.cref.refinements);
return;
default:
rb_bug("unreachable");
}
}
gc_mark(objspace, any->as.basic.klass);
@ -8609,6 +8634,7 @@ type_name(int type, VALUE obj)
TYPE_NAME(T_SYMBOL);
TYPE_NAME(T_FIXNUM);
TYPE_NAME(T_UNDEF);
TYPE_NAME(T_IMEMO);
TYPE_NAME(T_NODE);
TYPE_NAME(T_ICLASS);
TYPE_NAME(T_ZOMBIE);

Просмотреть файл

@ -448,11 +448,12 @@ enum ruby_value_type {
RUBY_T_FALSE = 0x13,
RUBY_T_SYMBOL = 0x14,
RUBY_T_FIXNUM = 0x15,
RUBY_T_UNDEF = 0x16,
RUBY_T_UNDEF = 0x1b,
RUBY_T_NODE = 0x1c,
RUBY_T_ICLASS = 0x1d,
RUBY_T_ZOMBIE = 0x1e,
RUBY_T_IMEMO = 0x1a,
RUBY_T_NODE = 0x1b,
RUBY_T_ICLASS = 0x1c,
RUBY_T_ZOMBIE = 0x1d,
RUBY_T_MASK = 0x1f
};
@ -479,6 +480,7 @@ enum ruby_value_type {
#define T_SYMBOL RUBY_T_SYMBOL
#define T_RATIONAL RUBY_T_RATIONAL
#define T_COMPLEX RUBY_T_COMPLEX
#define T_IMEMO RUBY_T_IMEMO
#define T_UNDEF RUBY_T_UNDEF
#define T_NODE RUBY_T_NODE
#define T_ZOMBIE RUBY_T_ZOMBIE

Просмотреть файл

@ -513,15 +513,44 @@ RCLASS_SET_SUPER(VALUE klass, VALUE super)
RB_OBJ_WRITE(klass, &RCLASS(klass)->super, super);
return super;
}
/* IMEMO: Internal memo object */
/* FL_USER0, FL_USER1, FL_USER2: type */
#define FL_IMEMO_MARK_V0 FL_USER6
#define FL_IMEMO_MARK_V1 FL_USER3
#define FL_IMEMO_MARK_V2 FL_USER4
#define FL_IMEMO_MARK_V3 FL_USER5
struct RIMemo {
VALUE flags;
VALUE v0;
VALUE v1;
VALUE v2;
VALUE v3;
};
enum imemo_type {
imemo_none,
imemo_cref,
imemo_mask = 0x07
};
static inline enum imemo_type
imemo_type(VALUE imemo)
{
return (RBASIC(imemo)->flags >> FL_USHIFT) & imemo_mask;
}
VALUE rb_imemo_new(enum imemo_type type, VALUE v1, VALUE v2, VALUE v3, VALUE v0);
/* CREF */
typedef struct rb_cref_struct {
VALUE flags;
VALUE refinements;
VALUE klass;
const VALUE refinements;
const VALUE klass;
VALUE visi;
struct rb_cref_struct *next;
struct rb_cref_struct * const next;
} rb_cref_t;
#define NODE_FL_CREF_PUSHED_BY_EVAL_ (((VALUE)1)<<15)

5
node.c
Просмотреть файл

@ -1069,11 +1069,6 @@ rb_gc_mark_node(NODE *obj)
rb_gc_mark(RNODE(obj)->u2.value);
break;
case NODE_CREF:
rb_gc_mark(CREF_REFINEMENTS((rb_cref_t *)obj));
rb_gc_mark(CREF_CLASS((rb_cref_t *)obj));
return (VALUE)CREF_NEXT((rb_cref_t *)obj);
default: /* unlisted NODE */
rb_gc_mark_maybe(RNODE(obj)->u1.value);
rb_gc_mark_maybe(RNODE(obj)->u2.value);

3
node.h
Просмотреть файл

@ -192,8 +192,6 @@ enum node_type {
#define NODE_COLON2 NODE_COLON2
NODE_COLON3,
#define NODE_COLON3 NODE_COLON3
NODE_CREF,
#define NODE_CREF NODE_CREF
NODE_DOT2,
#define NODE_DOT2 NODE_DOT2
NODE_DOT3,
@ -447,7 +445,6 @@ typedef struct RNode {
#define NEW_MODULE(n,b) NEW_NODE(NODE_MODULE,n,NEW_SCOPE(0,b),0)
#define NEW_COLON2(c,i) NEW_NODE(NODE_COLON2,c,i,0)
#define NEW_COLON3(i) NEW_NODE(NODE_COLON3,0,i,0)
#define NEW_CREF(a) NEW_NODE(NODE_CREF,a,0,0)
#define NEW_DOT2(b,e) NEW_NODE(NODE_DOT2,b,e,0)
#define NEW_DOT3(b,e) NEW_NODE(NODE_DOT3,b,e,0)
#define NEW_SELF() NEW_NODE(NODE_SELF,0,0,0)

5
vm.c
Просмотреть файл

@ -82,10 +82,7 @@ rb_vm_control_frame_block_ptr(const rb_control_frame_t *cfp)
static rb_cref_t *
vm_cref_new(VALUE klass, long visi, const rb_cref_t *prev_cref)
{
rb_cref_t *cref = (rb_cref_t *)NEW_CREF(klass);
CREF_REFINEMENTS_SET(cref, Qnil);
CREF_VISI_SET(cref, visi);
CREF_NEXT_SET(cref, prev_cref);
rb_cref_t *cref = (rb_cref_t *)rb_imemo_new(imemo_cref, klass, visi, (VALUE)prev_cref, Qnil);
return cref;
}

Просмотреть файл

@ -498,6 +498,7 @@ rb_type_str(enum ruby_value_type type)
type_case(T_FALSE)
type_case(T_SYMBOL)
type_case(T_FIXNUM)
type_case(T_IMEMO)
type_case(T_UNDEF)
type_case(T_NODE)
type_case(T_ICLASS)
@ -1308,7 +1309,7 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_
if (!cref && base_block->iseq) {
if (NIL_P(scope)) {
orig_cref = rb_vm_get_cref(base_block->ep);
cref = (rb_cref_t *)NEW_CREF(Qnil);
cref = vm_cref_new(Qnil, 0, NULL);
crefval = (VALUE) cref;
COPY_CREF(cref, orig_cref);
}

Просмотреть файл

@ -163,7 +163,7 @@ lep_svar_get(rb_thread_t *th, const VALUE *lep, rb_num_t key)
const struct SVAR *const svar = *svar_place;
if (NIL_P((VALUE)svar)) return Qnil;
if (nd_type(svar) == NODE_CREF) return Qnil;
if (RB_TYPE_P((VALUE)svar, T_IMEMO) && imemo_type((VALUE)svar) == imemo_cref) return Qnil;
switch (key) {
case VM_SVAR_LASTLINE:
@ -193,7 +193,7 @@ lep_svar_set(rb_thread_t *th, VALUE *lep, rb_num_t key, VALUE val)
svar = *svar_place = (struct SVAR *)NEW_IF(Qnil, Qnil, Qnil);
svar->cref = NULL;
}
else if (nd_type(svar) == NODE_CREF) {
else if (RB_TYPE_P((VALUE)svar, T_IMEMO) && imemo_type((VALUE)svar) == imemo_cref) {
const rb_cref_t *cref = (rb_cref_t *)svar;
svar = *svar_place = (struct SVAR *)NEW_IF(Qnil, Qnil, Qnil);
RB_OBJ_WRITE(svar, &svar->cref, (VALUE)cref);
@ -261,7 +261,7 @@ lep_cref(const VALUE *ep)
if (!svar) {
return NULL;
}
else if (nd_type(svar) == NODE_CREF) {
else if (RB_TYPE_P((VALUE)svar, T_IMEMO) && imemo_type(svar) == imemo_cref) {
return (rb_cref_t *)svar;
}
else {
@ -300,13 +300,13 @@ rb_vm_rewrite_cref_stack(rb_cref_t *node, VALUE old_klass, VALUE new_klass, rb_c
while (node) {
if (CREF_CLASS(node) == old_klass) {
new_node = (rb_cref_t *)NEW_CREF(new_klass);
new_node = vm_cref_new(new_klass, 0, NULL);
COPY_CREF_OMOD(new_node, node);
CREF_NEXT_SET(new_node, CREF_NEXT(node));
*new_cref_ptr = new_node;
return;
}
new_node = (rb_cref_t *)NEW_CREF(CREF_CLASS(node));
new_node = vm_cref_new(CREF_CLASS(node), 0, NULL);
COPY_CREF_OMOD(new_node, node);
node = CREF_NEXT(node);
*new_cref_ptr = new_node;