mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* fix namespace issue on singleton class expressions. [Bug #10943]
* vm_core.h, method.h: remove rb_iseq_t::cref_stack. CREF is stored to rb_method_definition_t::body.iseq_body.cref. * vm_insnhelper.c: modify SVAR usage. When calling ISEQ type method, push CREF information onto method frame, SVAR located place. Before this fix, SVAR is simply nil. After this patch, CREF (or NULL == Qfalse for not iseq methods) is stored at the method invocation. When SVAR is requierd, then put NODE_IF onto SVAR location, and NDOE_IF::nd_reserved points CREF itself. * vm.c (vm_cref_new, vm_cref_dump, vm_cref_new_toplevel): added. * vm_insnhelper.c (vm_push_frame): accept CREF. * method.h, vm_method.c (rb_add_method_iseq): added. This function accepts iseq and CREF. * class.c (clone_method): use rb_add_method_iseq(). * gc.c (mark_method_entry): mark method_entry::body.iseq_body.cref. * iseq.c: remove CREF related codes. * insns.def (getinlinecache/setinlinecache): CREF should be cache key because a different CREF has a different namespace. * node.c (rb_gc_mark_node): mark NODE_IF::nd_reserved for SVAR. * proc.c: catch up changes. * struct.c: ditto. * insns.def: ditto. * vm_args.c (raise_argument_error): ditto. * vm_eval.c: ditto. * test/ruby/test_class.rb: add a test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@49874 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
e0f5a6ab48
commit
d84f9b1694
16 changed files with 378 additions and 131 deletions
46
ChangeLog
46
ChangeLog
|
@ -1,3 +1,49 @@
|
||||||
|
Fri Mar 6 20:18:38 2015 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
|
* fix namespace issue on singleton class expressions. [Bug #10943]
|
||||||
|
|
||||||
|
* vm_core.h, method.h: remove rb_iseq_t::cref_stack. CREF is stored
|
||||||
|
to rb_method_definition_t::body.iseq_body.cref.
|
||||||
|
|
||||||
|
* vm_insnhelper.c: modify SVAR usage.
|
||||||
|
When calling ISEQ type method, push CREF information onto method
|
||||||
|
frame, SVAR located place. Before this fix, SVAR is simply nil.
|
||||||
|
After this patch, CREF (or NULL == Qfalse for not iseq methods)
|
||||||
|
is stored at the method invocation.
|
||||||
|
|
||||||
|
When SVAR is requierd, then put NODE_IF onto SVAR location,
|
||||||
|
and NDOE_IF::nd_reserved points CREF itself.
|
||||||
|
|
||||||
|
* vm.c (vm_cref_new, vm_cref_dump, vm_cref_new_toplevel): added.
|
||||||
|
|
||||||
|
* vm_insnhelper.c (vm_push_frame): accept CREF.
|
||||||
|
|
||||||
|
* method.h, vm_method.c (rb_add_method_iseq): added. This function
|
||||||
|
accepts iseq and CREF.
|
||||||
|
|
||||||
|
* class.c (clone_method): use rb_add_method_iseq().
|
||||||
|
|
||||||
|
* gc.c (mark_method_entry): mark method_entry::body.iseq_body.cref.
|
||||||
|
|
||||||
|
* iseq.c: remove CREF related codes.
|
||||||
|
|
||||||
|
* insns.def (getinlinecache/setinlinecache): CREF should be cache key
|
||||||
|
because a different CREF has a different namespace.
|
||||||
|
|
||||||
|
* node.c (rb_gc_mark_node): mark NODE_IF::nd_reserved for SVAR.
|
||||||
|
|
||||||
|
* proc.c: catch up changes.
|
||||||
|
|
||||||
|
* struct.c: ditto.
|
||||||
|
|
||||||
|
* insns.def: ditto.
|
||||||
|
|
||||||
|
* vm_args.c (raise_argument_error): ditto.
|
||||||
|
|
||||||
|
* vm_eval.c: ditto.
|
||||||
|
|
||||||
|
* test/ruby/test_class.rb: add a test.
|
||||||
|
|
||||||
Fri Mar 6 18:19:13 2015 Koichi Sasada <ko1@atdot.net>
|
Fri Mar 6 18:19:13 2015 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* test/webrick/test_filehandler.rb: on vboxsf (on VirtualBox
|
* test/webrick/test_filehandler.rb: on vboxsf (on VirtualBox
|
||||||
|
|
7
class.c
7
class.c
|
@ -247,11 +247,10 @@ clone_method(VALUE klass, ID mid, const rb_method_entry_t *me)
|
||||||
if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) {
|
if (me->def && me->def->type == VM_METHOD_TYPE_ISEQ) {
|
||||||
rb_iseq_t *iseq;
|
rb_iseq_t *iseq;
|
||||||
NODE *new_cref;
|
NODE *new_cref;
|
||||||
newiseqval = rb_iseq_clone(me->def->body.iseq->self, klass);
|
newiseqval = rb_iseq_clone(me->def->body.iseq_body.iseq->self, klass);
|
||||||
GetISeqPtr(newiseqval, iseq);
|
GetISeqPtr(newiseqval, iseq);
|
||||||
rb_vm_rewrite_cref_stack(me->def->body.iseq->cref_stack, me->klass, klass, &new_cref);
|
rb_vm_rewrite_cref_stack(me->def->body.iseq_body.cref, me->klass, klass, &new_cref);
|
||||||
RB_OBJ_WRITE(iseq->self, &iseq->cref_stack, new_cref);
|
rb_add_method_iseq(klass, mid, iseq, new_cref, me->flag);
|
||||||
rb_add_method(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, me->flag);
|
|
||||||
RB_GC_GUARD(newiseqval);
|
RB_GC_GUARD(newiseqval);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
5
gc.c
5
gc.c
|
@ -3786,11 +3786,14 @@ mark_method_entry(rb_objspace_t *objspace, const rb_method_entry_t *me)
|
||||||
const rb_method_definition_t *def = me->def;
|
const rb_method_definition_t *def = me->def;
|
||||||
|
|
||||||
gc_mark(objspace, me->klass);
|
gc_mark(objspace, me->klass);
|
||||||
|
|
||||||
again:
|
again:
|
||||||
if (!def) return;
|
if (!def) return;
|
||||||
|
|
||||||
switch (def->type) {
|
switch (def->type) {
|
||||||
case VM_METHOD_TYPE_ISEQ:
|
case VM_METHOD_TYPE_ISEQ:
|
||||||
gc_mark(objspace, def->body.iseq->self);
|
gc_mark(objspace, def->body.iseq_body.iseq->self);
|
||||||
|
gc_mark(objspace, (VALUE)def->body.iseq_body.cref);
|
||||||
break;
|
break;
|
||||||
case VM_METHOD_TYPE_BMETHOD:
|
case VM_METHOD_TYPE_BMETHOD:
|
||||||
gc_mark(objspace, def->body.proc);
|
gc_mark(objspace, def->body.proc);
|
||||||
|
|
27
insns.def
27
insns.def
|
@ -159,7 +159,7 @@ getclassvariable
|
||||||
()
|
()
|
||||||
(VALUE val)
|
(VALUE val)
|
||||||
{
|
{
|
||||||
NODE *cref = rb_vm_get_cref(GET_ISEQ(), GET_EP());
|
NODE *cref = rb_vm_get_cref(GET_EP());
|
||||||
val = rb_cvar_get(vm_get_cvar_base(cref, GET_CFP()), id);
|
val = rb_cvar_get(vm_get_cvar_base(cref, GET_CFP()), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ setclassvariable
|
||||||
(VALUE val)
|
(VALUE val)
|
||||||
()
|
()
|
||||||
{
|
{
|
||||||
NODE *cref = rb_vm_get_cref(GET_ISEQ(), GET_EP());
|
NODE *cref = rb_vm_get_cref(GET_EP());
|
||||||
rb_cvar_set(vm_get_cvar_base(cref, GET_CFP()), id, val);
|
rb_cvar_set(vm_get_cvar_base(cref, GET_CFP()), id, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ getconstant
|
||||||
(VALUE klass)
|
(VALUE klass)
|
||||||
(VALUE val)
|
(VALUE val)
|
||||||
{
|
{
|
||||||
val = vm_get_ev_const(th, GET_ISEQ(), klass, id, 0);
|
val = vm_get_ev_const(th, klass, id, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -318,10 +318,10 @@ putspecialobject
|
||||||
val = rb_mRubyVMFrozenCore;
|
val = rb_mRubyVMFrozenCore;
|
||||||
break;
|
break;
|
||||||
case VM_SPECIAL_OBJECT_CBASE:
|
case VM_SPECIAL_OBJECT_CBASE:
|
||||||
val = vm_get_cbase(GET_ISEQ(), GET_EP());
|
val = vm_get_cbase(GET_EP());
|
||||||
break;
|
break;
|
||||||
case VM_SPECIAL_OBJECT_CONST_BASE:
|
case VM_SPECIAL_OBJECT_CONST_BASE:
|
||||||
val = vm_get_const_base(GET_ISEQ(), GET_EP());
|
val = vm_get_const_base(GET_EP());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rb_bug("putspecialobject insn: unknown value_type");
|
rb_bug("putspecialobject insn: unknown value_type");
|
||||||
|
@ -730,7 +730,7 @@ defined
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DEFINED_IVAR2:
|
case DEFINED_IVAR2:
|
||||||
klass = vm_get_cbase(GET_ISEQ(), GET_EP());
|
klass = vm_get_cbase(GET_EP());
|
||||||
break;
|
break;
|
||||||
case DEFINED_GVAR:
|
case DEFINED_GVAR:
|
||||||
if (rb_gvar_defined(rb_global_entry(SYM2ID(obj)))) {
|
if (rb_gvar_defined(rb_global_entry(SYM2ID(obj)))) {
|
||||||
|
@ -738,7 +738,7 @@ defined
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DEFINED_CVAR: {
|
case DEFINED_CVAR: {
|
||||||
NODE *cref = rb_vm_get_cref(GET_ISEQ(), GET_EP());
|
NODE *cref = rb_vm_get_cref(GET_EP());
|
||||||
klass = vm_get_cvar_base(cref, GET_CFP());
|
klass = vm_get_cvar_base(cref, GET_CFP());
|
||||||
if (rb_cvar_defined(klass, SYM2ID(obj))) {
|
if (rb_cvar_defined(klass, SYM2ID(obj))) {
|
||||||
expr_type = DEFINED_CVAR;
|
expr_type = DEFINED_CVAR;
|
||||||
|
@ -747,7 +747,7 @@ defined
|
||||||
}
|
}
|
||||||
case DEFINED_CONST:
|
case DEFINED_CONST:
|
||||||
klass = v;
|
klass = v;
|
||||||
if (vm_get_ev_const(th, GET_ISEQ(), klass, SYM2ID(obj), 1)) {
|
if (vm_get_ev_const(th, klass, SYM2ID(obj), 1)) {
|
||||||
expr_type = DEFINED_CONST;
|
expr_type = DEFINED_CONST;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1013,13 +1013,14 @@ defineclass
|
||||||
rb_bug("unknown defineclass type: %d", (int)type);
|
rb_bug("unknown defineclass type: %d", (int)type);
|
||||||
}
|
}
|
||||||
|
|
||||||
COPY_CREF(class_iseq->cref_stack, vm_cref_push(th, klass, NOEX_PUBLIC, NULL));
|
|
||||||
|
|
||||||
/* enter scope */
|
/* enter scope */
|
||||||
vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS,
|
vm_push_frame(th, class_iseq, VM_FRAME_MAGIC_CLASS,
|
||||||
klass, 0, VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()),
|
klass, 0,
|
||||||
|
VM_ENVVAL_BLOCK_PTR(GET_BLOCK_PTR()),
|
||||||
|
vm_cref_push(th, klass, NOEX_PUBLIC, NULL),
|
||||||
class_iseq->iseq_encoded, GET_SP(),
|
class_iseq->iseq_encoded, GET_SP(),
|
||||||
class_iseq->local_size, 0, class_iseq->stack_max);
|
class_iseq->local_size, 0, class_iseq->stack_max);
|
||||||
|
|
||||||
RESTORE_REGS();
|
RESTORE_REGS();
|
||||||
NEXT_INSN();
|
NEXT_INSN();
|
||||||
}
|
}
|
||||||
|
@ -1241,7 +1242,8 @@ getinlinecache
|
||||||
()
|
()
|
||||||
(VALUE val)
|
(VALUE val)
|
||||||
{
|
{
|
||||||
if (ic->ic_serial == GET_GLOBAL_CONSTANT_STATE()) {
|
if (ic->ic_serial == GET_GLOBAL_CONSTANT_STATE() &&
|
||||||
|
ic->ic_cref == rb_vm_get_cref(GET_EP())) {
|
||||||
val = ic->ic_value.value;
|
val = ic->ic_value.value;
|
||||||
JUMP(dst);
|
JUMP(dst);
|
||||||
}
|
}
|
||||||
|
@ -1267,6 +1269,7 @@ setinlinecache
|
||||||
}
|
}
|
||||||
ic->ic_value.value = val;
|
ic->ic_value.value = val;
|
||||||
ic->ic_serial = GET_GLOBAL_CONSTANT_STATE() - ruby_vm_const_missing_count;
|
ic->ic_serial = GET_GLOBAL_CONSTANT_STATE() - ruby_vm_const_missing_count;
|
||||||
|
ic->ic_cref = rb_vm_get_cref(GET_EP());
|
||||||
ruby_vm_const_missing_count = 0;
|
ruby_vm_const_missing_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
25
iseq.c
25
iseq.c
|
@ -121,7 +121,6 @@ iseq_mark(void *ptr)
|
||||||
RUBY_MARK_UNLESS_NULL(iseq->location.path);
|
RUBY_MARK_UNLESS_NULL(iseq->location.path);
|
||||||
RUBY_MARK_UNLESS_NULL(iseq->location.absolute_path);
|
RUBY_MARK_UNLESS_NULL(iseq->location.absolute_path);
|
||||||
|
|
||||||
RUBY_MARK_UNLESS_NULL((VALUE)iseq->cref_stack);
|
|
||||||
RUBY_MARK_UNLESS_NULL(iseq->klass);
|
RUBY_MARK_UNLESS_NULL(iseq->klass);
|
||||||
RUBY_MARK_UNLESS_NULL(iseq->coverage);
|
RUBY_MARK_UNLESS_NULL(iseq->coverage);
|
||||||
RUBY_MARK_UNLESS_NULL(iseq->orig);
|
RUBY_MARK_UNLESS_NULL(iseq->orig);
|
||||||
|
@ -213,38 +212,21 @@ iseq_location_setup(rb_iseq_t *iseq, VALUE path, VALUE absolute_path, VALUE name
|
||||||
return loc;
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ISEQ_SET_CREF(iseq, cref) RB_OBJ_WRITE((iseq)->self, &(iseq)->cref_stack, (cref))
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_relation(rb_iseq_t *iseq, const VALUE parent)
|
set_relation(rb_iseq_t *iseq, const VALUE parent)
|
||||||
{
|
{
|
||||||
const VALUE type = iseq->type;
|
const VALUE type = iseq->type;
|
||||||
rb_thread_t *th = GET_THREAD();
|
|
||||||
rb_iseq_t *piseq;
|
rb_iseq_t *piseq;
|
||||||
|
|
||||||
/* set class nest stack */
|
/* set class nest stack */
|
||||||
if (type == ISEQ_TYPE_TOP) {
|
if (type == ISEQ_TYPE_TOP) {
|
||||||
/* toplevel is private */
|
|
||||||
RB_OBJ_WRITE(iseq->self, &iseq->cref_stack, NEW_CREF(rb_cObject));
|
|
||||||
iseq->cref_stack->nd_refinements = Qnil;
|
|
||||||
iseq->cref_stack->nd_visi = NOEX_PRIVATE;
|
|
||||||
if (th->top_wrapper) {
|
|
||||||
NODE *cref = NEW_CREF(th->top_wrapper);
|
|
||||||
cref->nd_refinements = Qnil;
|
|
||||||
cref->nd_visi = NOEX_PRIVATE;
|
|
||||||
RB_OBJ_WRITE(cref, &cref->nd_next, iseq->cref_stack);
|
|
||||||
ISEQ_SET_CREF(iseq, cref);
|
|
||||||
}
|
|
||||||
iseq->local_iseq = iseq;
|
iseq->local_iseq = iseq;
|
||||||
}
|
}
|
||||||
else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
|
else if (type == ISEQ_TYPE_METHOD || type == ISEQ_TYPE_CLASS) {
|
||||||
ISEQ_SET_CREF(iseq, NEW_CREF(0)); /* place holder */
|
|
||||||
iseq->cref_stack->nd_refinements = Qnil;
|
|
||||||
iseq->local_iseq = iseq;
|
iseq->local_iseq = iseq;
|
||||||
}
|
}
|
||||||
else if (RTEST(parent)) {
|
else if (RTEST(parent)) {
|
||||||
GetISeqPtr(parent, piseq);
|
GetISeqPtr(parent, piseq);
|
||||||
ISEQ_SET_CREF(iseq, piseq->cref_stack);
|
|
||||||
iseq->local_iseq = piseq->local_iseq;
|
iseq->local_iseq = piseq->local_iseq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1973,13 +1955,8 @@ rb_iseq_clone(VALUE iseqval, VALUE newcbase)
|
||||||
if (iseq0->local_iseq == iseq0) {
|
if (iseq0->local_iseq == iseq0) {
|
||||||
iseq1->local_iseq = iseq1;
|
iseq1->local_iseq = iseq1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newcbase) {
|
if (newcbase) {
|
||||||
ISEQ_SET_CREF(iseq1, NEW_CREF(newcbase));
|
|
||||||
RB_OBJ_WRITE(iseq1->cref_stack, &iseq1->cref_stack->nd_refinements, iseq0->cref_stack->nd_refinements);
|
|
||||||
iseq1->cref_stack->nd_visi = iseq0->cref_stack->nd_visi;
|
|
||||||
if (iseq0->cref_stack->nd_next) {
|
|
||||||
RB_OBJ_WRITE(iseq1->cref_stack, &iseq1->cref_stack->nd_next, iseq0->cref_stack->nd_next);
|
|
||||||
}
|
|
||||||
RB_OBJ_WRITE(iseq1->self, &iseq1->klass, newcbase);
|
RB_OBJ_WRITE(iseq1->self, &iseq1->klass, newcbase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
method.h
6
method.h
|
@ -12,6 +12,7 @@
|
||||||
#define METHOD_H
|
#define METHOD_H
|
||||||
|
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
#ifndef END_OF_ENUMERATION
|
#ifndef END_OF_ENUMERATION
|
||||||
# if defined(__GNUC__) &&! defined(__STRICT_ANSI__)
|
# if defined(__GNUC__) &&! defined(__STRICT_ANSI__)
|
||||||
|
@ -79,8 +80,12 @@ typedef struct rb_method_definition_struct {
|
||||||
rb_method_type_t type; /* method type */
|
rb_method_type_t type; /* method type */
|
||||||
int alias_count;
|
int alias_count;
|
||||||
ID original_id;
|
ID original_id;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
struct {
|
||||||
rb_iseq_t *const iseq; /* should be mark */
|
rb_iseq_t *const iseq; /* should be mark */
|
||||||
|
NODE *cref;
|
||||||
|
} iseq_body;
|
||||||
rb_method_cfunc_t cfunc;
|
rb_method_cfunc_t cfunc;
|
||||||
rb_method_attr_t attr;
|
rb_method_attr_t attr;
|
||||||
const VALUE proc; /* should be mark */
|
const VALUE proc; /* should be mark */
|
||||||
|
@ -113,6 +118,7 @@ struct unlinked_method_entry_list_entry {
|
||||||
UNDEFINED_METHOD_ENTRY_P((def)->body.orig_me))
|
UNDEFINED_METHOD_ENTRY_P((def)->body.orig_me))
|
||||||
|
|
||||||
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex);
|
void rb_add_method_cfunc(VALUE klass, ID mid, VALUE (*func)(ANYARGS), int argc, rb_method_flag_t noex);
|
||||||
|
void rb_add_method_iseq(VALUE klass, ID mid, rb_iseq_t *iseq, NODE *cref, rb_method_flag_t noex);
|
||||||
rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_flag_t noex);
|
rb_method_entry_t *rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *option, rb_method_flag_t noex);
|
||||||
rb_method_entry_t *rb_method_entry(VALUE klass, ID id, VALUE *define_class_ptr);
|
rb_method_entry_t *rb_method_entry(VALUE klass, ID id, VALUE *define_class_ptr);
|
||||||
rb_method_entry_t *rb_method_entry_at(VALUE obj, ID id);
|
rb_method_entry_t *rb_method_entry_at(VALUE obj, ID id);
|
||||||
|
|
1
node.c
1
node.c
|
@ -947,6 +947,7 @@ rb_gc_mark_node(NODE *obj)
|
||||||
{
|
{
|
||||||
switch (nd_type(obj)) {
|
switch (nd_type(obj)) {
|
||||||
case NODE_IF: /* 1,2,3 */
|
case NODE_IF: /* 1,2,3 */
|
||||||
|
rb_gc_mark(obj->nd_refinements); /* use as SVAR */
|
||||||
case NODE_FOR:
|
case NODE_FOR:
|
||||||
case NODE_ITER:
|
case NODE_ITER:
|
||||||
case NODE_WHEN:
|
case NODE_WHEN:
|
||||||
|
|
20
proc.c
20
proc.c
|
@ -1208,7 +1208,6 @@ mnew_internal(rb_method_entry_t *me, VALUE defined_class, VALUE klass,
|
||||||
def->type = VM_METHOD_TYPE_MISSING;
|
def->type = VM_METHOD_TYPE_MISSING;
|
||||||
def->original_id = id;
|
def->original_id = id;
|
||||||
def->alias_count = 0;
|
def->alias_count = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
data->ume = ALLOC(struct unlinked_method_entry_list_entry);
|
data->ume = ALLOC(struct unlinked_method_entry_list_entry);
|
||||||
data->me->def->alias_count++;
|
data->me->def->alias_count++;
|
||||||
|
@ -2025,7 +2024,7 @@ rb_method_entry_min_max_arity(const rb_method_entry_t *me, int *max)
|
||||||
case VM_METHOD_TYPE_BMETHOD:
|
case VM_METHOD_TYPE_BMETHOD:
|
||||||
return rb_proc_min_max_arity(def->body.proc, max);
|
return rb_proc_min_max_arity(def->body.proc, max);
|
||||||
case VM_METHOD_TYPE_ISEQ: {
|
case VM_METHOD_TYPE_ISEQ: {
|
||||||
rb_iseq_t *iseq = def->body.iseq;
|
rb_iseq_t *iseq = def->body.iseq_body.iseq;
|
||||||
return rb_iseq_min_max_arity(iseq, max);
|
return rb_iseq_min_max_arity(iseq, max);
|
||||||
}
|
}
|
||||||
case VM_METHOD_TYPE_UNDEF:
|
case VM_METHOD_TYPE_UNDEF:
|
||||||
|
@ -2162,12 +2161,24 @@ method_get_iseq(rb_method_definition_t *def)
|
||||||
case VM_METHOD_TYPE_BMETHOD:
|
case VM_METHOD_TYPE_BMETHOD:
|
||||||
return get_proc_iseq(def->body.proc, 0);
|
return get_proc_iseq(def->body.proc, 0);
|
||||||
case VM_METHOD_TYPE_ISEQ:
|
case VM_METHOD_TYPE_ISEQ:
|
||||||
return def->body.iseq;
|
return def->body.iseq_body.iseq;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NODE *
|
||||||
|
method_get_cref(rb_method_definition_t *def)
|
||||||
|
{
|
||||||
|
switch (def->type) {
|
||||||
|
case VM_METHOD_TYPE_ISEQ:
|
||||||
|
return def->body.iseq_body.cref;
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
rb_iseq_t *
|
rb_iseq_t *
|
||||||
rb_method_get_iseq(VALUE method)
|
rb_method_get_iseq(VALUE method)
|
||||||
{
|
{
|
||||||
|
@ -2376,6 +2387,7 @@ method_proc(VALUE method)
|
||||||
env->block.self = meth->recv;
|
env->block.self = meth->recv;
|
||||||
env->block.klass = meth->defined_class;
|
env->block.klass = meth->defined_class;
|
||||||
env->block.iseq = method_get_iseq(meth->me->def);
|
env->block.iseq = method_get_iseq(meth->me->def);
|
||||||
|
env->block.ep[-1] = (VALUE)method_get_cref(meth->me->def);
|
||||||
return procval;
|
return procval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
struct.c
4
struct.c
|
@ -179,7 +179,7 @@ define_aref_method(VALUE nstr, VALUE name, VALUE off)
|
||||||
VALUE iseqval = rb_method_for_self_aref(name, off, rb_vm_opt_struct_aref);
|
VALUE iseqval = rb_method_for_self_aref(name, off, rb_vm_opt_struct_aref);
|
||||||
rb_iseq_t *iseq = DATA_PTR(iseqval);
|
rb_iseq_t *iseq = DATA_PTR(iseqval);
|
||||||
|
|
||||||
rb_add_method(nstr, SYM2ID(name), VM_METHOD_TYPE_ISEQ, iseq, NOEX_PUBLIC);
|
rb_add_method_iseq(nstr, SYM2ID(name), iseq, NULL, NOEX_PUBLIC);
|
||||||
RB_GC_GUARD(iseqval);
|
RB_GC_GUARD(iseqval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ define_aset_method(VALUE nstr, VALUE name, VALUE off)
|
||||||
VALUE iseqval = rb_method_for_self_aset(name, off, rb_vm_opt_struct_aset);
|
VALUE iseqval = rb_method_for_self_aset(name, off, rb_vm_opt_struct_aset);
|
||||||
rb_iseq_t *iseq = DATA_PTR(iseqval);
|
rb_iseq_t *iseq = DATA_PTR(iseqval);
|
||||||
|
|
||||||
rb_add_method(nstr, SYM2ID(name), VM_METHOD_TYPE_ISEQ, iseq, NOEX_PUBLIC);
|
rb_add_method_iseq(nstr, SYM2ID(name), iseq, NULL, NOEX_PUBLIC);
|
||||||
RB_GC_GUARD(iseqval);
|
RB_GC_GUARD(iseqval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -399,4 +399,124 @@ class TestClass < Test::Unit::TestCase
|
||||||
def c.f; end
|
def c.f; end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_singleton_class_should_has_own_namespace
|
||||||
|
# CONST in singleton class
|
||||||
|
objs = []
|
||||||
|
$i = 0
|
||||||
|
|
||||||
|
2.times{
|
||||||
|
objs << obj = Object.new
|
||||||
|
class << obj
|
||||||
|
CONST = ($i += 1)
|
||||||
|
def foo
|
||||||
|
CONST
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
assert_equal(1, objs[0].foo, '[Bug #10943]')
|
||||||
|
assert_equal(2, objs[1].foo, '[Bug #10943]')
|
||||||
|
|
||||||
|
# CONST in block in singleton class
|
||||||
|
objs = []
|
||||||
|
$i = 0
|
||||||
|
|
||||||
|
2.times{
|
||||||
|
objs << obj = Object.new
|
||||||
|
class << obj
|
||||||
|
1.times{
|
||||||
|
CONST = ($i += 1)
|
||||||
|
}
|
||||||
|
def foo
|
||||||
|
[nil].map{
|
||||||
|
CONST
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
assert_equal([1], objs[0].foo, '[Bug #10943]')
|
||||||
|
assert_equal([2], objs[1].foo, '[Bug #10943]')
|
||||||
|
|
||||||
|
# class def in singleton class
|
||||||
|
objs = []
|
||||||
|
$xs = []
|
||||||
|
$i = 0
|
||||||
|
|
||||||
|
2.times{
|
||||||
|
objs << obj = Object.new
|
||||||
|
class << obj
|
||||||
|
CONST = ($i += 1)
|
||||||
|
class X
|
||||||
|
$xs << self
|
||||||
|
CONST = ($i += 1)
|
||||||
|
def foo
|
||||||
|
CONST
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def x
|
||||||
|
X
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
assert_not_equal($xs[0], $xs[1], '[Bug #10943]')
|
||||||
|
assert_not_equal(objs[0].x, objs[1].x, '[Bug #10943]')
|
||||||
|
assert_equal(2, $xs[0]::CONST, '[Bug #10943]')
|
||||||
|
assert_equal(2, $xs[0].new.foo, '[Bug #10943]')
|
||||||
|
assert_equal(4, $xs[1]::CONST, '[Bug #10943]')
|
||||||
|
assert_equal(4, $xs[1].new.foo, '[Bug #10943]')
|
||||||
|
|
||||||
|
# class def in block in singleton class
|
||||||
|
objs = []
|
||||||
|
$xs = []
|
||||||
|
$i = 0
|
||||||
|
|
||||||
|
2.times{
|
||||||
|
objs << obj = Object.new
|
||||||
|
class << obj
|
||||||
|
1.times{
|
||||||
|
CONST = ($i += 1)
|
||||||
|
}
|
||||||
|
1.times{
|
||||||
|
class X
|
||||||
|
$xs << self
|
||||||
|
CONST = ($i += 1)
|
||||||
|
def foo
|
||||||
|
CONST
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def x
|
||||||
|
X
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
}
|
||||||
|
assert_not_equal($xs[0], $xs[1], '[Bug #10943]')
|
||||||
|
assert_not_equal(objs[0].x, objs[1].x, '[Bug #10943]')
|
||||||
|
assert_equal(2, $xs[0]::CONST, '[Bug #10943]')
|
||||||
|
assert_equal(2, $xs[0].new.foo, '[Bug #10943]')
|
||||||
|
assert_equal(4, $xs[1]::CONST, '[Bug #10943]')
|
||||||
|
assert_equal(4, $xs[1].new.foo, '[Bug #10943]')
|
||||||
|
|
||||||
|
# method def in singleton class
|
||||||
|
ms = []
|
||||||
|
ps = $test_singleton_class_shared_cref_ps = []
|
||||||
|
2.times{
|
||||||
|
ms << Module.new do
|
||||||
|
class << self
|
||||||
|
$test_singleton_class_shared_cref_ps << Proc.new{
|
||||||
|
def xyzzy
|
||||||
|
self
|
||||||
|
end
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
ps.each{|p| p.call} # define xyzzy methods for each singleton classes
|
||||||
|
ms.each{|m|
|
||||||
|
assert_equal(m, m.xyzzy, "Bug #10871")
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
74
vm.c
74
vm.c
|
@ -79,6 +79,39 @@ rb_vm_control_frame_block_ptr(const rb_control_frame_t *cfp)
|
||||||
return VM_CF_BLOCK_PTR(cfp);
|
return VM_CF_BLOCK_PTR(cfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NODE *
|
||||||
|
vm_cref_new(VALUE klass, long visi, NODE *prev_cref)
|
||||||
|
{
|
||||||
|
NODE *cref = NEW_CREF(klass);
|
||||||
|
cref->nd_refinements = Qnil;
|
||||||
|
cref->nd_visi = visi;
|
||||||
|
cref->nd_next = prev_cref;
|
||||||
|
return cref;
|
||||||
|
}
|
||||||
|
|
||||||
|
static NODE *
|
||||||
|
vm_cref_new_toplevel(rb_thread_t *th)
|
||||||
|
{
|
||||||
|
NODE *cref = vm_cref_new(rb_cObject, NOEX_PRIVATE /* toplevel visibility is private */, NULL);
|
||||||
|
|
||||||
|
if (th->top_wrapper) {
|
||||||
|
cref = vm_cref_new(th->top_wrapper, NOEX_PRIVATE, cref);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cref;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vm_cref_dump(const char *mesg, const NODE *cref)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "vm_cref_dump: %s (%p)\n", mesg, cref);
|
||||||
|
|
||||||
|
while (cref) {
|
||||||
|
fprintf(stderr, "= cref| klass: %s\n", RSTRING_PTR(rb_class_path(cref->nd_clss)));
|
||||||
|
cref = cref->nd_next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if VM_COLLECT_USAGE_DETAILS
|
#if VM_COLLECT_USAGE_DETAILS
|
||||||
static void vm_collect_usage_operand(int insn, int n, VALUE op);
|
static void vm_collect_usage_operand(int insn, int n, VALUE op);
|
||||||
static void vm_collect_usage_insn(int insn);
|
static void vm_collect_usage_insn(int insn);
|
||||||
|
@ -211,7 +244,9 @@ vm_set_top_stack(rb_thread_t * th, VALUE iseqval)
|
||||||
|
|
||||||
/* for return */
|
/* for return */
|
||||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
|
vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
|
||||||
th->top_self, rb_cObject, VM_ENVVAL_BLOCK_PTR(0),
|
th->top_self, rb_cObject,
|
||||||
|
VM_ENVVAL_BLOCK_PTR(0),
|
||||||
|
vm_cref_new_toplevel(th),
|
||||||
iseq->iseq_encoded, th->cfp->sp, iseq->local_size, 0, iseq->stack_max);
|
iseq->iseq_encoded, th->cfp->sp, iseq->local_size, 0, iseq->stack_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,12 +258,10 @@ vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref, rb_block_t
|
||||||
|
|
||||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL | VM_FRAME_FLAG_FINISH,
|
vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL | VM_FRAME_FLAG_FINISH,
|
||||||
base_block->self, base_block->klass,
|
base_block->self, base_block->klass,
|
||||||
VM_ENVVAL_PREV_EP_PTR(base_block->ep), iseq->iseq_encoded,
|
VM_ENVVAL_PREV_EP_PTR(base_block->ep),
|
||||||
|
cref,
|
||||||
|
iseq->iseq_encoded,
|
||||||
th->cfp->sp, iseq->local_size, 0, iseq->stack_max);
|
th->cfp->sp, iseq->local_size, 0, iseq->stack_max);
|
||||||
|
|
||||||
if (cref) {
|
|
||||||
th->cfp->ep[-1] = (VALUE)cref;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -790,6 +823,7 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
|
||||||
vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH | VM_FRAME_FLAG_BMETHOD,
|
vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH | VM_FRAME_FLAG_BMETHOD,
|
||||||
self, defined_class,
|
self, defined_class,
|
||||||
VM_ENVVAL_PREV_EP_PTR(block->ep),
|
VM_ENVVAL_PREV_EP_PTR(block->ep),
|
||||||
|
cref,
|
||||||
iseq->iseq_encoded + opt_pc,
|
iseq->iseq_encoded + opt_pc,
|
||||||
cfp->sp + arg_size, iseq->local_size - arg_size,
|
cfp->sp + arg_size, iseq->local_size - arg_size,
|
||||||
me, iseq->stack_max);
|
me, iseq->stack_max);
|
||||||
|
@ -801,15 +835,12 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
|
||||||
vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH,
|
vm_push_frame(th, iseq, type | VM_FRAME_FLAG_FINISH,
|
||||||
self, defined_class,
|
self, defined_class,
|
||||||
VM_ENVVAL_PREV_EP_PTR(block->ep),
|
VM_ENVVAL_PREV_EP_PTR(block->ep),
|
||||||
|
cref,
|
||||||
iseq->iseq_encoded + opt_pc,
|
iseq->iseq_encoded + opt_pc,
|
||||||
cfp->sp + arg_size, iseq->local_size - arg_size,
|
cfp->sp + arg_size, iseq->local_size - arg_size,
|
||||||
0, iseq->stack_max);
|
0, iseq->stack_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cref) {
|
|
||||||
th->cfp->ep[-1] = (VALUE)cref;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = vm_exec(th);
|
ret = vm_exec(th);
|
||||||
|
|
||||||
if (me) {
|
if (me) {
|
||||||
|
@ -1017,7 +1048,8 @@ rb_vm_cref(void)
|
||||||
if (cfp == 0) {
|
if (cfp == 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return rb_vm_get_cref(cfp->iseq, cfp->ep);
|
|
||||||
|
return rb_vm_get_cref(cfp->ep);
|
||||||
}
|
}
|
||||||
|
|
||||||
const NODE *
|
const NODE *
|
||||||
|
@ -1027,7 +1059,7 @@ rb_vm_cref_in_context(VALUE self, VALUE cbase)
|
||||||
const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
|
const rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);
|
||||||
const NODE *cref;
|
const NODE *cref;
|
||||||
if (cfp->self != self) return NULL;
|
if (cfp->self != self) return NULL;
|
||||||
cref = rb_vm_get_cref(cfp->iseq, cfp->ep);
|
cref = rb_vm_get_cref(cfp->ep);
|
||||||
if (cref->nd_clss != cbase) return NULL;
|
if (cref->nd_clss != cbase) return NULL;
|
||||||
return cref;
|
return cref;
|
||||||
}
|
}
|
||||||
|
@ -1053,7 +1085,7 @@ rb_vm_cbase(void)
|
||||||
if (cfp == 0) {
|
if (cfp == 0) {
|
||||||
rb_raise(rb_eRuntimeError, "Can't call on top of Fiber or Thread");
|
rb_raise(rb_eRuntimeError, "Can't call on top of Fiber or Thread");
|
||||||
}
|
}
|
||||||
return vm_get_cbase(cfp->iseq, cfp->ep);
|
return vm_get_cbase(cfp->ep);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* jump */
|
/* jump */
|
||||||
|
@ -1594,6 +1626,7 @@ vm_exec(rb_thread_t *th)
|
||||||
vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_RESCUE,
|
vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_RESCUE,
|
||||||
cfp->self, cfp->klass,
|
cfp->self, cfp->klass,
|
||||||
VM_ENVVAL_PREV_EP_PTR(cfp->ep),
|
VM_ENVVAL_PREV_EP_PTR(cfp->ep),
|
||||||
|
NULL,
|
||||||
catch_iseq->iseq_encoded,
|
catch_iseq->iseq_encoded,
|
||||||
cfp->sp + 1 /* push value */,
|
cfp->sp + 1 /* push value */,
|
||||||
catch_iseq->local_size - 1,
|
catch_iseq->local_size - 1,
|
||||||
|
@ -1745,7 +1778,8 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg,
|
||||||
VALUE val;
|
VALUE val;
|
||||||
|
|
||||||
vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
|
vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
|
||||||
recv, CLASS_OF(recv), VM_ENVVAL_BLOCK_PTR(blockptr), 0, reg_cfp->sp, 1, 0, 0);
|
recv, CLASS_OF(recv), VM_ENVVAL_BLOCK_PTR(blockptr), vm_cref_new_toplevel(th),
|
||||||
|
0, reg_cfp->sp, 1, 0, 0);
|
||||||
|
|
||||||
val = (*func)(arg);
|
val = (*func)(arg);
|
||||||
|
|
||||||
|
@ -2183,7 +2217,9 @@ th_init(rb_thread_t *th, VALUE self)
|
||||||
th->cfp = (void *)(th->stack + th->stack_size);
|
th->cfp = (void *)(th->stack + th->stack_size);
|
||||||
|
|
||||||
vm_push_frame(th, 0 /* dummy iseq */, VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
|
vm_push_frame(th, 0 /* dummy iseq */, VM_FRAME_MAGIC_TOP | VM_FRAME_FLAG_FINISH,
|
||||||
Qnil /* dummy self */, Qnil /* dummy klass */, VM_ENVVAL_BLOCK_PTR(0), 0 /* dummy pc */, th->stack, 1, 0, 0);
|
Qnil /* dummy self */, Qnil /* dummy klass */, VM_ENVVAL_BLOCK_PTR(0),
|
||||||
|
NULL /* dummy cref */,
|
||||||
|
0 /* dummy pc */, th->stack, 1, 0, 0);
|
||||||
|
|
||||||
th->status = THREAD_RUNNABLE;
|
th->status = THREAD_RUNNABLE;
|
||||||
th->errinfo = Qnil;
|
th->errinfo = Qnil;
|
||||||
|
@ -2250,15 +2286,13 @@ vm_define_method(rb_thread_t *th, VALUE obj, ID id, VALUE iseqval,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dup */
|
/* dup */
|
||||||
COPY_CREF(miseq->cref_stack, cref);
|
|
||||||
miseq->cref_stack->nd_visi = NOEX_PUBLIC;
|
|
||||||
RB_OBJ_WRITE(miseq->self, &miseq->klass, klass);
|
RB_OBJ_WRITE(miseq->self, &miseq->klass, klass);
|
||||||
miseq->defined_method_id = id;
|
miseq->defined_method_id = id;
|
||||||
rb_add_method(klass, id, VM_METHOD_TYPE_ISEQ, miseq, noex);
|
rb_add_method_iseq(klass, id, miseq, cref, noex);
|
||||||
|
|
||||||
if (!is_singleton && noex == NOEX_MODFUNC) {
|
if (!is_singleton && noex == NOEX_MODFUNC) {
|
||||||
klass = rb_singleton_class(klass);
|
klass = rb_singleton_class(klass);
|
||||||
rb_add_method(klass, id, VM_METHOD_TYPE_ISEQ, miseq, NOEX_PUBLIC);
|
rb_add_method_iseq(klass, id, miseq, cref, NOEX_PUBLIC);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2745,6 +2779,8 @@ Init_VM(void)
|
||||||
th->cfp->self = th->top_self;
|
th->cfp->self = th->top_self;
|
||||||
th->cfp->klass = Qnil;
|
th->cfp->klass = Qnil;
|
||||||
|
|
||||||
|
th->cfp->ep[-1] = (VALUE)vm_cref_new(rb_cObject, NOEX_PRIVATE, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The Binding of the top level scope
|
* The Binding of the top level scope
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -675,7 +675,7 @@ raise_argument_error(rb_thread_t *th, const rb_iseq_t *iseq, const VALUE exc)
|
||||||
VALUE at;
|
VALUE at;
|
||||||
|
|
||||||
if (iseq) {
|
if (iseq) {
|
||||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, Qnil /* self */, Qnil /* klass */, Qnil /* specval*/,
|
vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, Qnil /* self */, Qnil /* klass */, Qnil /* specval*/, NULL /* cref */,
|
||||||
iseq->iseq_encoded, th->cfp->sp, 0 /* local_size */, 0 /* me */, 0 /* stack_max */);
|
iseq->iseq_encoded, th->cfp->sp, 0 /* local_size */, 0 /* me */, 0 /* stack_max */);
|
||||||
at = rb_vm_backtrace_object();
|
at = rb_vm_backtrace_object();
|
||||||
vm_pop_frame(th);
|
vm_pop_frame(th);
|
||||||
|
|
13
vm_core.h
13
vm_core.h
|
@ -117,6 +117,7 @@ typedef struct rb_compile_option_struct rb_compile_option_t;
|
||||||
|
|
||||||
struct iseq_inline_cache_entry {
|
struct iseq_inline_cache_entry {
|
||||||
rb_serial_t ic_serial;
|
rb_serial_t ic_serial;
|
||||||
|
NODE *ic_cref;
|
||||||
union {
|
union {
|
||||||
size_t index;
|
size_t index;
|
||||||
VALUE value;
|
VALUE value;
|
||||||
|
@ -322,17 +323,6 @@ struct rb_iseq_struct {
|
||||||
|
|
||||||
VALUE self;
|
VALUE self;
|
||||||
const VALUE orig; /* non-NULL if its data have origin */
|
const VALUE orig; /* non-NULL if its data have origin */
|
||||||
|
|
||||||
/* block inlining */
|
|
||||||
/*
|
|
||||||
* NODE *node;
|
|
||||||
* void *special_block_builder;
|
|
||||||
* void *cached_special_block_builder;
|
|
||||||
* VALUE cached_special_block;
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* klass/module nest information stack (cref) */
|
|
||||||
NODE * const cref_stack;
|
|
||||||
const VALUE klass;
|
const VALUE klass;
|
||||||
|
|
||||||
/* misc */
|
/* misc */
|
||||||
|
@ -416,7 +406,6 @@ typedef struct rb_vm_struct {
|
||||||
|
|
||||||
/* object management */
|
/* object management */
|
||||||
VALUE mark_object_ary;
|
VALUE mark_object_ary;
|
||||||
|
|
||||||
const VALUE special_exceptions[ruby_special_error_count];
|
const VALUE special_exceptions[ruby_special_error_count];
|
||||||
|
|
||||||
/* load */
|
/* load */
|
||||||
|
|
|
@ -119,7 +119,8 @@ vm_call0_cfunc_with_frame(rb_thread_t* th, rb_call_info_t *ci, const VALUE *argv
|
||||||
rb_control_frame_t *reg_cfp = th->cfp;
|
rb_control_frame_t *reg_cfp = th->cfp;
|
||||||
|
|
||||||
vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv, defined_class,
|
vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv, defined_class,
|
||||||
VM_ENVVAL_BLOCK_PTR(blockptr), 0, reg_cfp->sp, 1, me, 0);
|
VM_ENVVAL_BLOCK_PTR(blockptr), NULL /* cref */,
|
||||||
|
0, reg_cfp->sp, 1, me, 0);
|
||||||
|
|
||||||
if (len >= 0) rb_check_arity(argc, len, len);
|
if (len >= 0) rb_check_arity(argc, len, len);
|
||||||
|
|
||||||
|
@ -1306,13 +1307,13 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *const cref_arg,
|
||||||
|
|
||||||
if (!cref && base_block->iseq) {
|
if (!cref && base_block->iseq) {
|
||||||
if (NIL_P(scope)) {
|
if (NIL_P(scope)) {
|
||||||
orig_cref = rb_vm_get_cref(base_block->iseq, base_block->ep);
|
orig_cref = rb_vm_get_cref(base_block->ep);
|
||||||
cref = NEW_CREF(Qnil);
|
cref = NEW_CREF(Qnil);
|
||||||
crefval = (VALUE) cref;
|
crefval = (VALUE) cref;
|
||||||
COPY_CREF(cref, orig_cref);
|
COPY_CREF(cref, orig_cref);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cref = rb_vm_get_cref(base_block->iseq, base_block->ep);
|
cref = rb_vm_get_cref(base_block->ep);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vm_set_eval_stack(th, iseqval, cref, base_block);
|
vm_set_eval_stack(th, iseqval, cref, base_block);
|
||||||
|
|
100
vm_insnhelper.c
100
vm_insnhelper.c
|
@ -46,6 +46,7 @@ vm_push_frame(rb_thread_t *th,
|
||||||
VALUE self,
|
VALUE self,
|
||||||
VALUE klass,
|
VALUE klass,
|
||||||
VALUE specval,
|
VALUE specval,
|
||||||
|
const NODE *cref,
|
||||||
const VALUE *pc,
|
const VALUE *pc,
|
||||||
VALUE *sp,
|
VALUE *sp,
|
||||||
int local_size,
|
int local_size,
|
||||||
|
@ -68,7 +69,8 @@ vm_push_frame(rb_thread_t *th,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set special val */
|
/* set special val */
|
||||||
*sp = specval;
|
sp[-1] = (VALUE)cref;
|
||||||
|
sp[ 0] = specval;
|
||||||
|
|
||||||
/* setup vm control frame stack */
|
/* setup vm control frame stack */
|
||||||
|
|
||||||
|
@ -161,6 +163,7 @@ lep_svar_get(rb_thread_t *th, const VALUE *lep, rb_num_t key)
|
||||||
const NODE * const svar = *svar_place;
|
const NODE * const svar = *svar_place;
|
||||||
|
|
||||||
if (NIL_P((VALUE)svar)) return Qnil;
|
if (NIL_P((VALUE)svar)) return Qnil;
|
||||||
|
if (nd_type(svar) == NODE_CREF) return Qnil;
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case VM_SVAR_LASTLINE:
|
case VM_SVAR_LASTLINE:
|
||||||
|
@ -188,6 +191,12 @@ lep_svar_set(rb_thread_t *th, VALUE *lep, rb_num_t key, VALUE val)
|
||||||
|
|
||||||
if (NIL_P((VALUE)svar)) {
|
if (NIL_P((VALUE)svar)) {
|
||||||
svar = *svar_place = NEW_IF(Qnil, Qnil, Qnil);
|
svar = *svar_place = NEW_IF(Qnil, Qnil, Qnil);
|
||||||
|
svar->nd_reserved = Qfalse;
|
||||||
|
}
|
||||||
|
else if (nd_type(svar) == NODE_CREF) {
|
||||||
|
NODE *cref = svar;
|
||||||
|
svar = *svar_place = NEW_IF(Qnil, Qnil, Qnil);
|
||||||
|
svar->nd_reserved = (VALUE)cref;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
@ -245,28 +254,42 @@ vm_getspecial(rb_thread_t *th, VALUE *lep, rb_num_t key, rb_num_t type)
|
||||||
}
|
}
|
||||||
|
|
||||||
static NODE *
|
static NODE *
|
||||||
vm_get_cref0(const rb_iseq_t *iseq, const VALUE *ep)
|
ep_cref(const VALUE *ep)
|
||||||
{
|
{
|
||||||
while (1) {
|
const VALUE svar = ep[-1];
|
||||||
if (VM_EP_LEP_P(ep)) {
|
|
||||||
if (!RUBY_VM_NORMAL_ISEQ_P(iseq)) return NULL;
|
if (!svar) {
|
||||||
return iseq->cref_stack;
|
return NULL;
|
||||||
}
|
}
|
||||||
else if (ep[-1] != Qnil) {
|
else if (nd_type(svar) == NODE_CREF) {
|
||||||
|
return (NODE *)svar;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (NODE *)((NODE *)svar)->nd_reserved;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static NODE *
|
||||||
|
vm_get_cref0(const VALUE *ep)
|
||||||
|
{
|
||||||
|
while (!VM_EP_LEP_P(ep)) {
|
||||||
|
if (ep[-1]) {
|
||||||
return (NODE *)ep[-1];
|
return (NODE *)ep[-1];
|
||||||
}
|
}
|
||||||
ep = VM_EP_PREV_EP(ep);
|
ep = VM_EP_PREV_EP(ep);
|
||||||
}
|
}
|
||||||
|
return ep_cref(ep);
|
||||||
}
|
}
|
||||||
|
|
||||||
NODE *
|
NODE *
|
||||||
rb_vm_get_cref(const rb_iseq_t *iseq, const VALUE *ep)
|
rb_vm_get_cref(const VALUE *ep)
|
||||||
{
|
{
|
||||||
NODE *cref = vm_get_cref0(iseq, ep);
|
NODE *cref = vm_get_cref0(ep);
|
||||||
|
|
||||||
if (cref == 0) {
|
if (cref == 0) {
|
||||||
rb_bug("rb_vm_get_cref: unreachable");
|
rb_bug("rb_vm_get_cref: unreachable");
|
||||||
}
|
}
|
||||||
|
|
||||||
return cref;
|
return cref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,6 +297,7 @@ void
|
||||||
rb_vm_rewrite_cref_stack(NODE *node, VALUE old_klass, VALUE new_klass, NODE **new_cref_ptr)
|
rb_vm_rewrite_cref_stack(NODE *node, VALUE old_klass, VALUE new_klass, NODE **new_cref_ptr)
|
||||||
{
|
{
|
||||||
NODE *new_node;
|
NODE *new_node;
|
||||||
|
|
||||||
while (node) {
|
while (node) {
|
||||||
if (node->nd_clss == old_klass) {
|
if (node->nd_clss == old_klass) {
|
||||||
new_node = NEW_CREF(new_klass);
|
new_node = NEW_CREF(new_klass);
|
||||||
|
@ -294,17 +318,21 @@ rb_vm_rewrite_cref_stack(NODE *node, VALUE old_klass, VALUE new_klass, NODE **ne
|
||||||
static NODE *
|
static NODE *
|
||||||
vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
|
vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
|
||||||
{
|
{
|
||||||
rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
|
NODE *prev_cref = NULL;
|
||||||
NODE *cref = NEW_CREF(klass);
|
NODE *cref = NULL;
|
||||||
cref->nd_refinements = Qnil;
|
|
||||||
cref->nd_visi = noex;
|
|
||||||
|
|
||||||
if (blockptr) {
|
if (blockptr) {
|
||||||
RB_OBJ_WRITE(cref, &cref->nd_next, vm_get_cref0(blockptr->iseq, blockptr->ep));
|
prev_cref = vm_get_cref0(blockptr->ep);
|
||||||
}
|
}
|
||||||
else if (cfp) {
|
else {
|
||||||
RB_OBJ_WRITE(cref, &cref->nd_next, vm_get_cref0(cfp->iseq, cfp->ep));
|
rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
|
||||||
|
|
||||||
|
if (cfp) {
|
||||||
|
prev_cref = vm_get_cref0(cfp->ep);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
cref = vm_cref_new(klass, noex, prev_cref);
|
||||||
|
|
||||||
/* TODO: why cref->nd_next is 1? */
|
/* TODO: why cref->nd_next is 1? */
|
||||||
if (cref->nd_next && cref->nd_next != (void *) 1 &&
|
if (cref->nd_next && cref->nd_next != (void *) 1 &&
|
||||||
!NIL_P(cref->nd_next->nd_refinements)) {
|
!NIL_P(cref->nd_next->nd_refinements)) {
|
||||||
|
@ -315,9 +343,9 @@ vm_cref_push(rb_thread_t *th, VALUE klass, int noex, rb_block_t *blockptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
vm_get_cbase(const rb_iseq_t *iseq, const VALUE *ep)
|
vm_get_cbase(const VALUE *ep)
|
||||||
{
|
{
|
||||||
NODE *cref = rb_vm_get_cref(iseq, ep);
|
NODE *cref = rb_vm_get_cref(ep);
|
||||||
VALUE klass = Qundef;
|
VALUE klass = Qundef;
|
||||||
|
|
||||||
while (cref) {
|
while (cref) {
|
||||||
|
@ -331,9 +359,9 @@ vm_get_cbase(const rb_iseq_t *iseq, const VALUE *ep)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
vm_get_const_base(const rb_iseq_t *iseq, const VALUE *ep)
|
vm_get_const_base(const VALUE *ep)
|
||||||
{
|
{
|
||||||
NODE *cref = rb_vm_get_cref(iseq, ep);
|
NODE *cref = rb_vm_get_cref(ep);
|
||||||
VALUE klass = Qundef;
|
VALUE klass = Qundef;
|
||||||
|
|
||||||
while (cref) {
|
while (cref) {
|
||||||
|
@ -373,14 +401,13 @@ vm_get_iclass(rb_control_frame_t *cfp, VALUE klass)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
|
vm_get_ev_const(rb_thread_t *th, VALUE orig_klass, ID id, int is_defined)
|
||||||
VALUE orig_klass, ID id, int is_defined)
|
|
||||||
{
|
{
|
||||||
VALUE val;
|
VALUE val;
|
||||||
|
|
||||||
if (orig_klass == Qnil) {
|
if (orig_klass == Qnil) {
|
||||||
/* in current lexical scope */
|
/* in current lexical scope */
|
||||||
const NODE *root_cref = rb_vm_get_cref(iseq, th->cfp->ep);
|
const NODE *root_cref = rb_vm_get_cref(th->cfp->ep);
|
||||||
const NODE *cref;
|
const NODE *cref;
|
||||||
VALUE klass = orig_klass;
|
VALUE klass = orig_klass;
|
||||||
|
|
||||||
|
@ -1128,7 +1155,7 @@ vm_callee_setup_arg(rb_thread_t *th, rb_call_info_t *ci, const rb_iseq_t *iseq,
|
||||||
static VALUE
|
static VALUE
|
||||||
vm_call_iseq_setup(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
|
vm_call_iseq_setup(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
|
||||||
{
|
{
|
||||||
vm_callee_setup_arg(th, ci, ci->me->def->body.iseq, cfp->sp - ci->argc);
|
vm_callee_setup_arg(th, ci, ci->me->def->body.iseq_body.iseq, cfp->sp - ci->argc);
|
||||||
return vm_call_iseq_setup_2(th, cfp, ci);
|
return vm_call_iseq_setup_2(th, cfp, ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1148,7 +1175,7 @@ vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info
|
||||||
{
|
{
|
||||||
int i, local_size;
|
int i, local_size;
|
||||||
VALUE *argv = cfp->sp - ci->argc;
|
VALUE *argv = cfp->sp - ci->argc;
|
||||||
rb_iseq_t *iseq = ci->me->def->body.iseq;
|
rb_iseq_t *iseq = ci->me->def->body.iseq_body.iseq;
|
||||||
VALUE *sp = argv + iseq->param.size;
|
VALUE *sp = argv + iseq->param.size;
|
||||||
|
|
||||||
/* clear local variables (arg_size...local_size) */
|
/* clear local variables (arg_size...local_size) */
|
||||||
|
@ -1157,7 +1184,7 @@ vm_call_iseq_setup_normal(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info
|
||||||
}
|
}
|
||||||
|
|
||||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, ci->recv, ci->defined_class,
|
vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD, ci->recv, ci->defined_class,
|
||||||
VM_ENVVAL_BLOCK_PTR(ci->blockptr),
|
VM_ENVVAL_BLOCK_PTR(ci->blockptr), ci->me->def->body.iseq_body.cref,
|
||||||
iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me, iseq->stack_max);
|
iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me, iseq->stack_max);
|
||||||
|
|
||||||
cfp->sp = argv - 1 /* recv */;
|
cfp->sp = argv - 1 /* recv */;
|
||||||
|
@ -1169,7 +1196,7 @@ vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_in
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
VALUE *argv = cfp->sp - ci->argc;
|
VALUE *argv = cfp->sp - ci->argc;
|
||||||
rb_iseq_t *iseq = ci->me->def->body.iseq;
|
rb_iseq_t *iseq = ci->me->def->body.iseq_body.iseq;
|
||||||
VALUE *src_argv = argv;
|
VALUE *src_argv = argv;
|
||||||
VALUE *sp_orig, *sp;
|
VALUE *sp_orig, *sp;
|
||||||
VALUE finish_flag = VM_FRAME_TYPE_FINISH_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
|
VALUE finish_flag = VM_FRAME_TYPE_FINISH_P(cfp) ? VM_FRAME_FLAG_FINISH : 0;
|
||||||
|
@ -1195,7 +1222,8 @@ vm_call_iseq_setup_tailcall(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_in
|
||||||
}
|
}
|
||||||
|
|
||||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag,
|
vm_push_frame(th, iseq, VM_FRAME_MAGIC_METHOD | finish_flag,
|
||||||
ci->recv, ci->defined_class, VM_ENVVAL_BLOCK_PTR(ci->blockptr),
|
ci->recv, ci->defined_class,
|
||||||
|
VM_ENVVAL_BLOCK_PTR(ci->blockptr), ci->me->def->body.iseq_body.cref,
|
||||||
iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me, iseq->stack_max);
|
iseq->iseq_encoded + ci->aux.opt_pc, sp, 0, ci->me, iseq->stack_max);
|
||||||
|
|
||||||
cfp->sp = sp_orig;
|
cfp->sp = sp_orig;
|
||||||
|
@ -1377,7 +1405,8 @@ vm_call_cfunc_with_frame(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_i
|
||||||
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass, Qundef);
|
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, me->called_id, me->klass, Qundef);
|
||||||
|
|
||||||
vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv, defined_class,
|
vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, recv, defined_class,
|
||||||
VM_ENVVAL_BLOCK_PTR(blockptr), 0, th->cfp->sp, 1, me, 0);
|
VM_ENVVAL_BLOCK_PTR(blockptr), NULL /* cref */,
|
||||||
|
0, th->cfp->sp, 1, me, 0);
|
||||||
|
|
||||||
if (len >= 0) rb_check_arity(argc, len, len);
|
if (len >= 0) rb_check_arity(argc, len, len);
|
||||||
|
|
||||||
|
@ -1465,7 +1494,8 @@ vm_call_cfunc_push_frame(rb_thread_t *th)
|
||||||
th->passed_ci = 0;
|
th->passed_ci = 0;
|
||||||
|
|
||||||
vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, ci->recv, ci->defined_class,
|
vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC, ci->recv, ci->defined_class,
|
||||||
VM_ENVVAL_BLOCK_PTR(ci->blockptr), 0, th->cfp->sp + ci->aux.inc_sp, 1, me);
|
VM_ENVVAL_BLOCK_PTR(ci->blockptr), NULL /* cref */,
|
||||||
|
0, th->cfp->sp + ci->aux.inc_sp, 1, me);
|
||||||
|
|
||||||
if (ci->call != vm_call_general) {
|
if (ci->call != vm_call_general) {
|
||||||
ci->call = vm_call_cfunc_with_frame;
|
ci->call = vm_call_cfunc_with_frame;
|
||||||
|
@ -1754,7 +1784,7 @@ vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp, rb_call_info_t *ci)
|
||||||
case VM_METHOD_TYPE_UNDEF:
|
case VM_METHOD_TYPE_UNDEF:
|
||||||
break;
|
break;
|
||||||
case VM_METHOD_TYPE_REFINED:{
|
case VM_METHOD_TYPE_REFINED:{
|
||||||
NODE *cref = rb_vm_get_cref(cfp->iseq, cfp->ep);
|
NODE *cref = rb_vm_get_cref(cfp->ep);
|
||||||
VALUE refinements = cref ? cref->nd_refinements : Qnil;
|
VALUE refinements = cref ? cref->nd_refinements : Qnil;
|
||||||
VALUE refinement, defined_class;
|
VALUE refinement, defined_class;
|
||||||
rb_method_entry_t *me;
|
rb_method_entry_t *me;
|
||||||
|
@ -1983,7 +2013,7 @@ vm_search_super_method(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_inf
|
||||||
iseq = iseq->parent_iseq;
|
iseq = iseq->parent_iseq;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ci->me && ci->me->def->type == VM_METHOD_TYPE_ISEQ && ci->me->def->body.iseq == iseq) {
|
if (ci->me && ci->me->def->type == VM_METHOD_TYPE_ISEQ && ci->me->def->body.iseq_body.iseq == iseq) {
|
||||||
ci->klass = RCLASS_SUPER(ci->defined_class);
|
ci->klass = RCLASS_SUPER(ci->defined_class);
|
||||||
ci->me = rb_method_entry(ci->klass, ci->mid, &ci->defined_class);
|
ci->me = rb_method_entry(ci->klass, ci->mid, &ci->defined_class);
|
||||||
}
|
}
|
||||||
|
@ -2039,8 +2069,8 @@ vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block,
|
||||||
|
|
||||||
vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC,
|
vm_push_frame(th, (rb_iseq_t *)ifunc, VM_FRAME_MAGIC_IFUNC,
|
||||||
self, defined_class,
|
self, defined_class,
|
||||||
VM_ENVVAL_PREV_EP_PTR(block->ep), 0,
|
VM_ENVVAL_PREV_EP_PTR(block->ep), NULL /* cref */,
|
||||||
th->cfp->sp, 1, th->passed_bmethod_me, 0);
|
0, th->cfp->sp, 1, th->passed_bmethod_me, 0);
|
||||||
|
|
||||||
val = (*ifunc->nd_cfnc) (arg, ifunc->nd_tval, argc, argv, blockarg);
|
val = (*ifunc->nd_cfnc) (arg, ifunc->nd_tval, argc, argv, blockarg);
|
||||||
|
|
||||||
|
@ -2095,7 +2125,7 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_call_info_t *ci
|
||||||
is_lambda ? VM_FRAME_MAGIC_LAMBDA : VM_FRAME_MAGIC_BLOCK,
|
is_lambda ? VM_FRAME_MAGIC_LAMBDA : VM_FRAME_MAGIC_BLOCK,
|
||||||
block->self,
|
block->self,
|
||||||
block->klass,
|
block->klass,
|
||||||
VM_ENVVAL_PREV_EP_PTR(block->ep),
|
VM_ENVVAL_PREV_EP_PTR(block->ep), NULL /* cref */,
|
||||||
iseq->iseq_encoded + opt_pc,
|
iseq->iseq_encoded + opt_pc,
|
||||||
rsp + arg_size,
|
rsp + arg_size,
|
||||||
iseq->local_size - arg_size, 0, iseq->stack_max);
|
iseq->local_size - arg_size, 0, iseq->stack_max);
|
||||||
|
|
46
vm_method.c
46
vm_method.c
|
@ -245,8 +245,7 @@ rb_add_refined_method_entry(VALUE refined_class, ID mid)
|
||||||
rb_clear_method_cache_by_class(refined_class);
|
rb_clear_method_cache_by_class(refined_class);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0,
|
rb_add_method(refined_class, mid, VM_METHOD_TYPE_REFINED, 0, NOEX_PUBLIC);
|
||||||
NOEX_PUBLIC);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +324,7 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
|
||||||
rb_warning("method redefined; discarding old %"PRIsVALUE, rb_id2str(mid));
|
rb_warning("method redefined; discarding old %"PRIsVALUE, rb_id2str(mid));
|
||||||
switch (old_def->type) {
|
switch (old_def->type) {
|
||||||
case VM_METHOD_TYPE_ISEQ:
|
case VM_METHOD_TYPE_ISEQ:
|
||||||
iseq = old_def->body.iseq;
|
iseq = old_def->body.iseq_body.iseq;
|
||||||
break;
|
break;
|
||||||
case VM_METHOD_TYPE_BMETHOD:
|
case VM_METHOD_TYPE_BMETHOD:
|
||||||
iseq = rb_proc_get_iseq(old_def->body.proc, 0);
|
iseq = rb_proc_get_iseq(old_def->body.proc, 0);
|
||||||
|
@ -359,7 +358,8 @@ rb_method_entry_make(VALUE klass, ID mid, rb_method_type_t type,
|
||||||
|
|
||||||
switch(def->type) {
|
switch(def->type) {
|
||||||
case VM_METHOD_TYPE_ISEQ:
|
case VM_METHOD_TYPE_ISEQ:
|
||||||
RB_OBJ_WRITTEN(klass, Qundef, def->body.iseq->self);
|
RB_OBJ_WRITTEN(klass, Qundef, def->body.iseq_body.iseq->self);
|
||||||
|
RB_OBJ_WRITTEN(klass, Qundef, def->body.iseq_body.cref);
|
||||||
break;
|
break;
|
||||||
case VM_METHOD_TYPE_IVAR:
|
case VM_METHOD_TYPE_IVAR:
|
||||||
RB_OBJ_WRITTEN(klass, Qundef, def->body.attr.location);
|
RB_OBJ_WRITTEN(klass, Qundef, def->body.attr.location);
|
||||||
|
@ -447,27 +447,40 @@ setup_method_cfunc_struct(rb_method_cfunc_t *cfunc, VALUE (*func)(), int argc)
|
||||||
}
|
}
|
||||||
|
|
||||||
rb_method_entry_t *
|
rb_method_entry_t *
|
||||||
rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex)
|
rb_add_method0(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex, NODE *cref)
|
||||||
{
|
{
|
||||||
rb_thread_t *th;
|
rb_thread_t *th;
|
||||||
rb_control_frame_t *cfp;
|
rb_control_frame_t *cfp;
|
||||||
int line;
|
int line;
|
||||||
rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, 0, noex, klass);
|
rb_method_entry_t *me = rb_method_entry_make(klass, mid, type, 0, noex, klass);
|
||||||
rb_method_definition_t *def = ALLOC(rb_method_definition_t);
|
rb_method_definition_t *def = ALLOC(rb_method_definition_t);
|
||||||
|
|
||||||
if (me->def && me->def->type == VM_METHOD_TYPE_REFINED) {
|
if (me->def && me->def->type == VM_METHOD_TYPE_REFINED) {
|
||||||
me->def->body.orig_me->def = def;
|
me->def->body.orig_me->def = def;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
me->def = def;
|
me->def = def;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0 && cref) vm_cref_dump("rb_add_method0", cref);
|
||||||
|
|
||||||
def->type = type;
|
def->type = type;
|
||||||
def->original_id = mid;
|
def->original_id = mid;
|
||||||
def->alias_count = 0;
|
def->alias_count = 0;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case VM_METHOD_TYPE_ISEQ: {
|
case VM_METHOD_TYPE_ISEQ: {
|
||||||
rb_iseq_t *iseq = (rb_iseq_t *)opts;
|
rb_iseq_t *iseq = (rb_iseq_t *)opts;
|
||||||
*(rb_iseq_t **)&def->body.iseq = iseq;
|
NODE *private_cref;
|
||||||
RB_OBJ_WRITTEN(klass, Qundef, iseq->self);
|
|
||||||
|
*(rb_iseq_t **)&def->body.iseq_body.iseq = iseq;
|
||||||
|
RB_OBJ_WRITTEN(klass, Qundef, iseq->self); /* should be set iseq before newobj */
|
||||||
|
def->body.iseq_body.cref = NULL;
|
||||||
|
|
||||||
|
private_cref = vm_cref_new_toplevel(GET_THREAD()); /* TODO: CREF should be shared with other methods */
|
||||||
|
if (cref) COPY_CREF(private_cref, cref);
|
||||||
|
private_cref->nd_visi = NOEX_PUBLIC;
|
||||||
|
RB_OBJ_WRITE(klass, &def->body.iseq_body.cref, private_cref);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VM_METHOD_TYPE_CFUNC:
|
case VM_METHOD_TYPE_CFUNC:
|
||||||
|
@ -511,13 +524,24 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_
|
||||||
return me;
|
return me;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rb_method_entry_t *
|
||||||
|
rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex)
|
||||||
|
{
|
||||||
|
return rb_add_method0(klass, mid, type, opts, noex, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
rb_add_method_iseq(VALUE klass, ID mid, rb_iseq_t *iseq, NODE *cref, rb_method_flag_t noex)
|
||||||
|
{
|
||||||
|
rb_add_method0(klass, mid, VM_METHOD_TYPE_ISEQ, iseq, noex, cref);
|
||||||
|
}
|
||||||
|
|
||||||
static rb_method_entry_t *
|
static rb_method_entry_t *
|
||||||
method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me,
|
method_entry_set(VALUE klass, ID mid, const rb_method_entry_t *me,
|
||||||
rb_method_flag_t noex, VALUE defined_class)
|
rb_method_flag_t noex, VALUE defined_class)
|
||||||
{
|
{
|
||||||
rb_method_type_t type = me->def ? me->def->type : VM_METHOD_TYPE_UNDEF;
|
rb_method_type_t type = me->def ? me->def->type : VM_METHOD_TYPE_UNDEF;
|
||||||
rb_method_entry_t *newme = rb_method_entry_make(klass, mid, type, me->def, noex,
|
rb_method_entry_t *newme = rb_method_entry_make(klass, mid, type, me->def, noex, defined_class);
|
||||||
defined_class);
|
|
||||||
method_added(klass, mid);
|
method_added(klass, mid);
|
||||||
return newme;
|
return newme;
|
||||||
}
|
}
|
||||||
|
@ -1195,7 +1219,7 @@ rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_defini
|
||||||
}
|
}
|
||||||
switch (d1->type) {
|
switch (d1->type) {
|
||||||
case VM_METHOD_TYPE_ISEQ:
|
case VM_METHOD_TYPE_ISEQ:
|
||||||
return d1->body.iseq == d2->body.iseq;
|
return d1->body.iseq_body.iseq == d2->body.iseq_body.iseq;
|
||||||
case VM_METHOD_TYPE_CFUNC:
|
case VM_METHOD_TYPE_CFUNC:
|
||||||
return
|
return
|
||||||
d1->body.cfunc.func == d2->body.cfunc.func &&
|
d1->body.cfunc.func == d2->body.cfunc.func &&
|
||||||
|
@ -1226,7 +1250,7 @@ rb_hash_method_definition(st_index_t hash, const rb_method_definition_t *def)
|
||||||
hash = rb_hash_uint(hash, def->type);
|
hash = rb_hash_uint(hash, def->type);
|
||||||
switch (def->type) {
|
switch (def->type) {
|
||||||
case VM_METHOD_TYPE_ISEQ:
|
case VM_METHOD_TYPE_ISEQ:
|
||||||
return rb_hash_uint(hash, (st_index_t)def->body.iseq);
|
return rb_hash_uint(hash, (st_index_t)def->body.iseq_body.iseq);
|
||||||
case VM_METHOD_TYPE_CFUNC:
|
case VM_METHOD_TYPE_CFUNC:
|
||||||
hash = rb_hash_uint(hash, (st_index_t)def->body.cfunc.func);
|
hash = rb_hash_uint(hash, (st_index_t)def->body.cfunc.func);
|
||||||
return rb_hash_uint(hash, def->body.cfunc.argc);
|
return rb_hash_uint(hash, def->body.cfunc.argc);
|
||||||
|
|
Loading…
Add table
Reference in a new issue