summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-02-04 19:17:33 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2007-02-04 19:17:33 +0000
commit72f2d2a00d8ae3861a15ca92bf9322951a22b6cf (patch)
tree3f74f159fcc7abf2e87ff7295e6400651a26a8c4
parent71364da03fcae2e0fb7b2641b6ac1e507ee03da6 (diff)
* parse.y (rb_compose_ivar2): function to create a new ivar2
symbol from a symbol and a class. back-ported from matzruby. * parse.y (rb_decompose_ivar2): reverse function of rb_compose_ivar2(). * marshal.c (w_symbol): support class local instance variables. * marshal.c (r_object0): ditto. * compile.c (defined_expr): ditto. * compile.c (iseq_compile_each): ditto. * insns.def: add two new instructions: getinstancevariable2 and setinstancevariable2. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11630 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog19
-rw-r--r--compile.c22
-rw-r--r--gc.c2
-rw-r--r--insns.def38
-rw-r--r--intern.h3
-rw-r--r--iseq.c4
-rw-r--r--marshal.c66
-rw-r--r--node.h4
-rw-r--r--parse.y97
-rw-r--r--string.c28
-rw-r--r--vm.c2
-rw-r--r--vm_macro.def6
-rw-r--r--yarvcore.h17
13 files changed, 281 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 5cea64c200..ec4e9acdce 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -14,6 +14,25 @@ Sun Feb 4 02:22:59 2007 Akinori MUSHA <knu@iDaemons.org>
* lib/cgi.rb (CGI::QueryExtension::read_multipart): Remove a debug
print.
+Sat Feb 3 23:51:58 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (rb_compose_ivar2): function to create a new ivar2
+ symbol from a symbol and a class. back-ported from matzruby.
+
+ * parse.y (rb_decompose_ivar2): reverse function of
+ rb_compose_ivar2().
+
+ * marshal.c (w_symbol): support class local instance variables.
+
+ * marshal.c (r_object0): ditto.
+
+ * compile.c (defined_expr): ditto.
+
+ * compile.c (iseq_compile_each): ditto.
+
+ * insns.def: add two new instructions: getinstancevariable2 and
+ setinstancevariable2.
+
Sat Feb 3 23:21:13 2007 Yukihiro Matsumoto <matz@ruby-lang.org>
* insns.def (setclassvariable): remove unnecessary operand.
diff --git a/compile.c b/compile.c
index 5455bd7034..54a806ed99 100644
--- a/compile.c
+++ b/compile.c
@@ -2345,6 +2345,11 @@ defined_expr(yarv_iseq_t *iseq, LINK_ANCHOR *ret,
ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_IVAR),
ID2SYM(node->nd_vid), needstr);
return 1;
+ case NODE_IVAR2:
+ ADD_INSN(ret, nd_line(node), putnil);
+ ADD_INSN3(ret, nd_line(node), defined, INT2FIX(DEFINED_IVAR2),
+ ID2SYM(node->nd_vid), needstr);
+ return 1;
case NODE_GVAR:
ADD_INSN(ret, nd_line(node), putnil);
@@ -3327,6 +3332,15 @@ iseq_compile_each(yarv_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
ID2SYM(node->nd_vid));
break;
}
+ case NODE_IASGN2:{
+ COMPILE(ret, "lvalue", node->nd_value);
+ if (!poped) {
+ ADD_INSN(ret, nd_line(node), dup);
+ }
+ ADD_INSN1(ret, nd_line(node), setinstancevariable2,
+ ID2SYM(node->nd_vid));
+ break;
+ }
case NODE_CDECL:{
COMPILE(ret, "lvalue", node->nd_value);
@@ -3903,6 +3917,14 @@ iseq_compile_each(yarv_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
}
break;
}
+ case NODE_IVAR2:{
+ debugi("nd_vid", node->nd_vid);
+ if (!poped) {
+ ADD_INSN1(ret, nd_line(node), getinstancevariable2,
+ ID2SYM(node->nd_vid));
+ }
+ break;
+ }
case NODE_CONST:{
debugi("nd_vid", node->nd_vid);
diff --git a/gc.c b/gc.c
index 6174d2f420..bf8e29def2 100644
--- a/gc.c
+++ b/gc.c
@@ -896,6 +896,7 @@ gc_mark_children(VALUE ptr, int lev)
case NODE_DASGN:
case NODE_DASGN_CURR:
case NODE_IASGN:
+ case NODE_IASGN2:
case NODE_CVASGN:
case NODE_COLON3:
case NODE_OPT_N:
@@ -935,6 +936,7 @@ gc_mark_children(VALUE ptr, int lev)
case NODE_LVAR:
case NODE_DVAR:
case NODE_IVAR:
+ case NODE_IVAR2:
case NODE_CVAR:
case NODE_NTH_REF:
case NODE_BACK_REF:
diff --git a/insns.def b/insns.def
index 99401cc395..b84d07f290 100644
--- a/insns.def
+++ b/insns.def
@@ -188,6 +188,22 @@ getinstancevariable
/**
@c variable
+ @e get class local instance variable id of obj.
+ @j obj のクラスローカルインスタンス変数 id を得る。
+ */
+DEFINE_INSN
+getinstancevariable2
+(ID id)
+()
+(VALUE val)
+{
+ /* need to cache composed id */
+ id = rb_compose_ivar2(id, eval_get_cvar_base(th, GET_ISEQ()));
+ val = rb_ivar_get(GET_SELF(), id);
+}
+
+/**
+ @c variable
@e set instance variable id of obj as val.
@j obj のインスタンス変数を val にする。
*/
@@ -202,6 +218,22 @@ setinstancevariable
/**
@c variable
+ @e set class local instance variable id of obj as val.
+ @j obj のクラスローカルインスタンス変数を val にする。
+ */
+DEFINE_INSN
+setinstancevariable2
+(ID id)
+(VALUE val)
+()
+{
+ /* need to cache composed id */
+ id = rb_compose_ivar2(id, eval_get_cvar_base(th, GET_ISEQ()));
+ rb_ivar_set(GET_SELF(), id, val);
+}
+
+/**
+ @c variable
@e get class variable id of klass as val.
@j klass のクラス変数 id を得る。
*/
@@ -901,6 +933,12 @@ defined
expr_type = "instance-variable";
}
break;
+ case DEFINED_IVAR2:
+ klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss;
+ if (rb_ivar_defined(GET_SELF(), rb_compose_ivar2(SYM2ID(obj), klass))) {
+ expr_type = "class local instance-variable";
+ }
+ break;
case DEFINED_GVAR:
if (rb_gvar_defined((struct global_entry *)(obj & ~1))) {
expr_type = "global-variable";
diff --git a/intern.h b/intern.h
index ad8c6b42d6..b3fd3cb0ce 100644
--- a/intern.h
+++ b/intern.h
@@ -398,6 +398,7 @@ ID rb_id_attrset(ID);
void rb_gc_mark_parser(void);
int rb_is_const_id(ID);
int rb_is_instance_id(ID);
+int rb_is_instance2_id(ID);
int rb_is_class_id(ID);
int rb_is_local_id(ID);
int rb_is_junk_id(ID);
@@ -409,6 +410,8 @@ void rb_backref_set(VALUE);
VALUE rb_lastline_get(void);
void rb_lastline_set(VALUE);
VALUE rb_sym_all_symbols(void);
+ID rb_compose_ivar2(ID, VALUE);
+ID rb_decompose_ivar2(ID, VALUE*);
/* process.c */
struct rb_exec_arg {
int argc;
diff --git a/iseq.c b/iseq.c
index 0b53f0b830..9932491d1c 100644
--- a/iseq.c
+++ b/iseq.c
@@ -863,6 +863,8 @@ node_name(int node)
return "NODE_GASGN";
case NODE_IASGN:
return "NODE_IASGN";
+ case NODE_IASGN2:
+ return "NODE_IASGN2";
case NODE_CDECL:
return "NODE_CDECL";
case NODE_CVASGN:
@@ -905,6 +907,8 @@ node_name(int node)
return "NODE_GVAR";
case NODE_IVAR:
return "NODE_IVAR";
+ case NODE_IVAR2:
+ return "NODE_IVAR2";
case NODE_CONST:
return "NODE_CONST";
case NODE_CVAR:
diff --git a/marshal.c b/marshal.c
index 950a1b31d1..1d8b5afa80 100644
--- a/marshal.c
+++ b/marshal.c
@@ -47,7 +47,7 @@ shortlen(long len, BDIGIT *ds)
#endif
#define MARSHAL_MAJOR 4
-#define MARSHAL_MINOR 8
+#define MARSHAL_MINOR 9
#define TYPE_NIL '0'
#define TYPE_TRUE 'T'
@@ -73,6 +73,7 @@ shortlen(long len, BDIGIT *ds)
#define TYPE_MODULE 'm'
#define TYPE_SYMBOL ':'
+#define TYPE_SYMBOL2 ','
#define TYPE_SYMLINK ';'
#define TYPE_IVAR 'I'
@@ -304,7 +305,7 @@ w_float(double d, struct dump_arg *arg)
static void
w_symbol(ID id, struct dump_arg *arg)
{
- const char *sym = rb_id2name(id);
+ const char *sym;
st_data_t num;
if (st_lookup(arg->symbols, id, &num)) {
@@ -312,8 +313,22 @@ w_symbol(ID id, struct dump_arg *arg)
w_long((long)num, arg);
}
else {
- w_byte(TYPE_SYMBOL, arg);
- w_bytes(sym, strlen(sym), arg);
+ if (rb_is_instance2_id(id)) {
+ VALUE klass;
+ volatile VALUE path;
+
+ id = rb_decompose_ivar2(id, &klass);
+ path = class2path(klass);
+ w_byte(TYPE_SYMBOL2, arg);
+ sym = rb_id2name(id);
+ w_bytes(sym, strlen(sym), arg);
+ w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg);
+ }
+ else {
+ sym = rb_id2name(id);
+ w_byte(TYPE_SYMBOL, arg);
+ w_bytes(sym, strlen(sym), arg);
+ }
st_add_direct(arg->symbols, id, arg->symbols->num_entries);
}
}
@@ -360,12 +375,14 @@ w_extended(VALUE klass, struct dump_arg *arg, int check)
static void
w_class(char type, VALUE obj, struct dump_arg *arg, int check)
{
+ volatile VALUE p;
char *path;
VALUE klass = CLASS_OF(obj);
w_extended(klass, arg, check);
w_byte(type, arg);
- path = RSTRING_PTR(class2path(rb_class_real(klass)));
+ p = class2path(rb_class_real(klass));
+ path = RSTRING_PTR(p);
w_unique(path, arg);
}
@@ -490,7 +507,7 @@ w_object(VALUE obj, struct dump_arg *arg, int limit)
}
w_byte(TYPE_CLASS, arg);
{
- VALUE path = class2path(obj);
+ volatile VALUE path = class2path(obj);
w_bytes(RSTRING_PTR(path), RSTRING_LEN(path), arg);
}
break;
@@ -738,7 +755,9 @@ struct load_arg {
int taint;
};
+static VALUE r_entry(VALUE v, struct load_arg *arg);
static VALUE r_object(struct load_arg *arg);
+static VALUE path2class(const char *path);
static int
r_byte(struct load_arg *arg)
@@ -855,10 +874,24 @@ r_symlink(struct load_arg *arg)
static ID
r_symreal(struct load_arg *arg)
{
- ID id;
volatile VALUE s = r_bytes(arg);
+ ID id = rb_intern(RSTRING_PTR(s));
+
+ st_insert(arg->symbols, arg->symbols->num_entries, id);
+
+ return id;
+}
+
+static ID
+r_symivar2(struct load_arg *arg)
+{
+ volatile VALUE s = r_bytes(arg);
+ ID id = rb_intern(RSTRING_PTR(s));
+ VALUE klass;
- id = rb_intern(RSTRING_PTR(s));
+ s = r_bytes(arg);
+ klass = r_entry(path2class(RSTRING_PTR(s)), arg);
+ id = rb_compose_ivar2(id, klass);
st_insert(arg->symbols, arg->symbols->num_entries, id);
return id;
@@ -867,10 +900,19 @@ r_symreal(struct load_arg *arg)
static ID
r_symbol(struct load_arg *arg)
{
- if (r_byte(arg) == TYPE_SYMLINK) {
+ int type;
+
+ switch ((type = r_byte(arg))) {
+ case TYPE_SYMBOL:
+ return r_symreal(arg);
+ case TYPE_SYMBOL2:
+ return r_symivar2(arg);
+ case TYPE_SYMLINK:
return r_symlink(arg);
+ default:
+ rb_raise(rb_eArgError, "dump format error(0x%x)", type);
+ break;
}
- return r_symreal(arg);
}
static const char*
@@ -1274,6 +1316,10 @@ r_object0(struct load_arg *arg, int *ivp, VALUE extmod)
v = ID2SYM(r_symreal(arg));
break;
+ case TYPE_SYMBOL2:
+ v = ID2SYM(r_symivar2(arg));
+ break;
+
case TYPE_SYMLINK:
v = ID2SYM(r_symlink(arg));
break;
diff --git a/node.h b/node.h
index 7deab9646d..453f59f47a 100644
--- a/node.h
+++ b/node.h
@@ -48,6 +48,7 @@ enum node_type {
NODE_DASGN_CURR,
NODE_GASGN,
NODE_IASGN,
+ NODE_IASGN2,
NODE_CDECL,
NODE_CVASGN,
NODE_CVDECL,
@@ -70,6 +71,7 @@ enum node_type {
NODE_DVAR,
NODE_GVAR,
NODE_IVAR,
+ NODE_IVAR2,
NODE_CONST,
NODE_CVAR,
NODE_NTH_REF,
@@ -282,6 +284,7 @@ typedef struct RNode {
#define NEW_DASGN(v,val) NEW_NODE(NODE_DASGN,v,val,0)
#define NEW_DASGN_CURR(v,val) NEW_NODE(NODE_DASGN_CURR,v,val,0)
#define NEW_IASGN(v,val) NEW_NODE(NODE_IASGN,v,val,0)
+#define NEW_IASGN2(v,val) NEW_NODE(NODE_IASGN2,v,val,0)
#define NEW_CDECL(v,val,path) NEW_NODE(NODE_CDECL,v,val,path)
#define NEW_CVASGN(v,val) NEW_NODE(NODE_CVASGN,v,val,0)
#define NEW_CVDECL(v,val) NEW_NODE(NODE_CVDECL,v,val,0)
@@ -294,6 +297,7 @@ typedef struct RNode {
#define NEW_LVAR(v) NEW_NODE(NODE_LVAR,v,0,local_cnt(v))
#define NEW_DVAR(v) NEW_NODE(NODE_DVAR,v,0,0)
#define NEW_IVAR(v) NEW_NODE(NODE_IVAR,v,0,0)
+#define NEW_IVAR2(v) NEW_NODE(NODE_IVAR2,v,0,0)
#define NEW_CONST(v) NEW_NODE(NODE_CONST,v,0,0)
#define NEW_CVAR(v) NEW_NODE(NODE_CVAR,v,0,0)
#define NEW_NTH_REF(n) NEW_NODE(NODE_NTH_REF,0,n,local_cnt('~'))
diff --git a/parse.y b/parse.y
index 49094f92ef..3f783af352 100644
--- a/parse.y
+++ b/parse.y
@@ -35,19 +35,21 @@
#define ID_SCOPE_SHIFT 3
#define ID_SCOPE_MASK 0x07
-#define ID_LOCAL 0x01
-#define ID_INSTANCE 0x02
-#define ID_GLOBAL 0x03
-#define ID_ATTRSET 0x04
-#define ID_CONST 0x05
-#define ID_CLASS 0x06
-#define ID_JUNK 0x07
-#define ID_INTERNAL ID_JUNK
+#define ID_LOCAL 0x00
+#define ID_INSTANCE 0x01
+#define ID_INSTANCE2 0x02
+#define ID_GLOBAL 0x03
+#define ID_ATTRSET 0x04
+#define ID_CONST 0x05
+#define ID_CLASS 0x06
+#define ID_JUNK 0x07
+#define ID_INTERNAL ID_JUNK
#define is_notop_id(id) ((id)>tLAST_TOKEN)
#define is_local_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
#define is_global_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
#define is_instance_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
+#define is_instance2_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE2)
#define is_attrset_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
#define is_const_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
#define is_class_id(id) (is_notop_id(id)&&((id)&ID_SCOPE_MASK)==ID_CLASS)
@@ -7245,6 +7247,9 @@ gettable_gen(struct parser_params *parser, ID id)
else if (is_instance_id(id)) {
return NEW_IVAR(id);
}
+ else if (is_instance2_id(id)) {
+ return NEW_IVAR2(id);
+ }
else if (is_const_id(id)) {
return NEW_CONST(id);
}
@@ -7298,6 +7303,9 @@ assignable_gen(struct parser_params *parser, ID id, NODE *val)
else if (is_instance_id(id)) {
return NEW_IASGN(id, val);
}
+ else if (is_instance2_id(id)) {
+ return NEW_IASGN2(id, val);
+ }
else if (is_const_id(id)) {
if (in_def || in_single)
yyerror("dynamic constant assignment");
@@ -7432,6 +7440,7 @@ node_assign_gen(struct parser_params *parser, NODE *lhs, NODE *rhs)
switch (nd_type(lhs)) {
case NODE_GASGN:
case NODE_IASGN:
+ case NODE_IASGN2:
case NODE_LASGN:
case NODE_DASGN:
case NODE_DASGN_CURR:
@@ -8319,6 +8328,8 @@ static struct symbols {
ID last_id;
st_table *sym_id;
st_table *id_str;
+ st_table *ivar2_id;
+ st_table *id_ivar2;
VALUE op_sym[tLAST_TOKEN];
} global_symbols = {tLAST_TOKEN};
@@ -8327,11 +8338,38 @@ static struct st_hash_type symhash = {
rb_str_hash,
};
+struct ivar2_key {
+ ID id;
+ VALUE klass;
+};
+
+static int
+ivar2_cmp(struct ivar2_key *key1, struct ivar2_key *key2)
+{
+ if (key1->id == key2->id && key1->klass == key2->klass) {
+ return 0;
+ }
+ return 1;
+}
+
+static int
+ivar2_hash(struct ivar2_key *key)
+{
+ return (key->id << 8) ^ (key->klass >> 2);
+}
+
+static struct st_hash_type ivar2_hash_type = {
+ ivar2_cmp,
+ ivar2_hash,
+};
+
void
Init_sym(void)
{
global_symbols.sym_id = st_init_table_with_size(&symhash, 1000);
global_symbols.id_str = st_init_numtable_with_size(1000);
+ global_symbols.ivar2_id = st_init_table_with_size(&ivar2_hash_type, 1000);
+ global_symbols.id_ivar2 = st_init_numtable_with_size(1000);
}
void
@@ -8466,6 +8504,9 @@ rb_intern2(const char *name, long len)
m++;
id |= ID_CLASS;
}
+ else if (name[1] == '_') {
+ id |= ID_INSTANCE2;
+ }
else {
id |= ID_INSTANCE;
}
@@ -8527,6 +8568,39 @@ rb_intern(const char *name)
return rb_intern2(name, strlen(name));
}
+ID
+rb_compose_ivar2(ID oid, VALUE klass)
+{
+ struct ivar2_key key, *kp;
+ ID id;
+
+ key.id = oid;
+ key.klass = klass;
+ if (st_lookup(global_symbols.ivar2_id, (st_data_t)&key, (st_data_t *)&id))
+ return id;
+
+ kp = ALLOC_N(struct ivar2_key, 1);
+ kp->id = oid; kp->klass = klass;
+ id = ID_INSTANCE2;
+ id |= ++global_symbols.last_id << ID_SCOPE_SHIFT;
+ st_add_direct(global_symbols.ivar2_id, (st_data_t)kp, (st_data_t)id);
+ st_add_direct(global_symbols.id_ivar2, (st_data_t)id, (st_data_t)kp);
+ return id;
+}
+
+ID
+rb_decompose_ivar2(ID id, VALUE *klassp)
+{
+ struct ivar2_key *kp;
+ ID oid;
+
+ if (!st_lookup(global_symbols.id_ivar2, (st_data_t)id, (st_data_t *)&kp)) {
+ return id;
+ }
+ if (klassp) *klassp = kp->klass;
+ return kp->id;
+}
+
VALUE
rb_id2str(ID id)
{
@@ -8636,6 +8710,13 @@ rb_is_instance_id(ID id)
}
int
+rb_is_instance2_id(ID id)
+{
+ if (is_instance2_id(id)) return Qtrue;
+ return Qfalse;
+}
+
+int
rb_is_local_id(ID id)
{
if (is_local_id(id)) return Qtrue;
diff --git a/string.c b/string.c
index faacf95428..89e88544c9 100644
--- a/string.c
+++ b/string.c
@@ -4690,6 +4690,9 @@ sym_inspect(VALUE sym)
VALUE str, klass = Qundef;
ID id = SYM2ID(sym);
+ if (rb_is_instance2_id(id)) {
+ id = rb_decompose_ivar2(id, &klass);
+ }
sym = rb_id2str(id);
str = rb_str_new(0, RSTRING_LEN(sym)+1);
RSTRING_PTR(str)[0] = ':';
@@ -4723,6 +4726,9 @@ rb_sym_to_s(VALUE sym)
{
ID id = SYM2ID(sym);
+ if (rb_is_instance2_id(id)) {
+ id = rb_decompose_ivar2(id, 0);
+ }
return str_new3(rb_cString, rb_id2str(id));
}
@@ -4868,6 +4874,27 @@ rb_to_id(VALUE name)
return id;
}
+static VALUE
+sym_div(VALUE sym, VALUE klass)
+{
+ ID id = SYM2ID(sym);
+
+ if (!rb_is_instance2_id(id)) {
+ rb_raise(rb_eArgError, "symbol %s should be local instance variable",
+ rb_id2name(id));
+ }
+ switch (TYPE(klass)) {
+ case T_CLASS:
+ case T_MODULE:
+ break;
+ default:
+ rb_check_type(klass, T_CLASS);
+ break;
+ }
+ id = rb_compose_ivar2(id, klass);
+ return ID2SYM(id);
+}
+
/*
* A <code>String</code> object holds and manipulates an arbitrary sequence of
* bytes, typically representing characters. String objects may be created
@@ -5008,6 +5035,7 @@ Init_String(void)
rb_define_singleton_method(rb_cSymbol, "all_symbols", rb_sym_all_symbols, 0); /* in parse.y */
rb_define_singleton_method(rb_cSymbol, "intern", rb_sym_s_intern, 1);
+ rb_define_method(rb_cSymbol, "/", sym_div, 1);
rb_define_method(rb_cSymbol, "==", sym_equal, 1);
rb_define_method(rb_cSymbol, "to_i", sym_to_i, 0);
rb_define_method(rb_cSymbol, "inspect", sym_inspect, 0);
diff --git a/vm.c b/vm.c
index 3da1f53486..720aefe79b 100644
--- a/vm.c
+++ b/vm.c
@@ -504,7 +504,7 @@ th_call0(yarv_thread_t *th, VALUE klass, VALUE recv,
val = rb_ivar_set(recv, body->nd_vid, argv[0]);
break;
}
- case NODE_IVAR:{
+ case NODE_IVAR: {
if (argc != 0) {
rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)",
argc);
diff --git a/vm_macro.def b/vm_macro.def
index 8a2eb83dbb..e08fb14938 100644
--- a/vm_macro.def
+++ b/vm_macro.def
@@ -293,6 +293,12 @@ MACRO macro_eval_invoke_method(recv, klass, id, num, mn, blockptr)
POP();
break;
}
+ case NODE_IVAR2:{
+ ID vid = rb_compose_ivar2(node->nd_vid, mn->nd_clss);
+ val = rb_ivar_get(recv, vid);
+ POP();
+ break;
+ }
case NODE_BMETHOD:{
VALUE *argv = GET_SP() - num;
val = th_invoke_bmethod(th, id, node->nd_cval,
diff --git a/yarvcore.h b/yarvcore.h
index 8db6b8a7ab..f2c76b2f68 100644
--- a/yarvcore.h
+++ b/yarvcore.h
@@ -585,14 +585,15 @@ typedef VALUE CDHASH;
/* defined? */
#define DEFINED_IVAR INT2FIX(1)
-#define DEFINED_GVAR INT2FIX(2)
-#define DEFINED_CVAR INT2FIX(3)
-#define DEFINED_CONST INT2FIX(4)
-#define DEFINED_METHOD INT2FIX(5)
-#define DEFINED_YIELD INT2FIX(6)
-#define DEFINED_REF INT2FIX(7)
-#define DEFINED_ZSUPER INT2FIX(8)
-#define DEFINED_FUNC INT2FIX(9)
+#define DEFINED_IVAR2 INT2FIX(2)
+#define DEFINED_GVAR INT2FIX(3)
+#define DEFINED_CVAR INT2FIX(4)
+#define DEFINED_CONST INT2FIX(5)
+#define DEFINED_METHOD INT2FIX(6)
+#define DEFINED_YIELD INT2FIX(7)
+#define DEFINED_REF INT2FIX(8)
+#define DEFINED_ZSUPER INT2FIX(9)
+#define DEFINED_FUNC INT2FIX(10)
/* VM related object allocate functions */
/* TODO: should be static functions */