summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog29
-rw-r--r--ext/objspace/objspace.c3
-rw-r--r--gc.c28
-rw-r--r--include/ruby/ruby.h10
-rw-r--r--internal.h35
-rw-r--r--node.c5
-rw-r--r--node.h3
-rw-r--r--vm.c5
-rw-r--r--vm_eval.c3
-rw-r--r--vm_insnhelper.c10
10 files changed, 104 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index df19eb1341..a6342f7ba0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c
index 038461a394..fe07ca84f3 100644
--- a/ext/objspace/objspace.c
+++ b/ext/objspace/objspace.c
@@ -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);
diff --git a/gc.c b/gc.c
index 12721df6ae..a37923baeb 100644
--- a/gc.c
+++ b/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,13 +1720,20 @@ 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)
{
if (klass) Check_Type(klass, T_CLASS);
@@ -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);
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index a35186c949..32a6d23b2e 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -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
diff --git a/internal.h b/internal.h
index 372cf5daba..9172fb1892 100644
--- a/internal.h
+++ b/internal.h
@@ -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)
diff --git a/node.c b/node.c
index 2d33554121..bd20f2d913 100644
--- a/node.c
+++ b/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);
diff --git a/node.h b/node.h
index b41431952d..68241b9b69 100644
--- a/node.h
+++ b/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)
diff --git a/vm.c b/vm.c
index 521809f0d6..07e7dc0ae6 100644
--- a/vm.c
+++ b/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;
}
diff --git a/vm_eval.c b/vm_eval.c
index 0524019e16..294c90e0a2 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -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);
}
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index f5f5634d09..b2481834de 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -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;