* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
VM value stack frame of block contains cref information. (dfp[-1] points CREF) * compile.c, eval_intern.h, eval_method.c, load.c, proc.c, vm_dump.h, vm_core.h: ditto. * include/ruby/ruby.h, gc.c: remove T_VALUES because of above changes. * bootstraptest/test_eval.rb, test_knownbug.rb: move solved test. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@16468 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
2e5e857a0b
commit
385f0e8af6
14
ChangeLog
14
ChangeLog
@ -1,3 +1,17 @@
|
|||||||
|
Mon May 19 11:32:47 2008 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
|
* vm.c, insns.def, eval.c, vm_insnhelper.c: fix CREF handling.
|
||||||
|
VM value stack frame of block contains cref information.
|
||||||
|
(dfp[-1] points CREF)
|
||||||
|
|
||||||
|
* compile.c, eval_intern.h, eval_method.c, load.c, proc.c,
|
||||||
|
vm_dump.h, vm_core.h: ditto.
|
||||||
|
|
||||||
|
* include/ruby/ruby.h, gc.c: remove T_VALUES because of above
|
||||||
|
changes.
|
||||||
|
|
||||||
|
* bootstraptest/test_eval.rb, test_knownbug.rb: move solved test.
|
||||||
|
|
||||||
Sun May 18 22:26:51 2008 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
Sun May 18 22:26:51 2008 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
||||||
|
|
||||||
* lib/webrick/httpservlet/filehandler.rb: should normalize path
|
* lib/webrick/httpservlet/filehandler.rb: should normalize path
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
def m
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
|
||||||
|
i=0
|
||||||
|
while i<800000 # benchmark loop 2
|
||||||
|
i+=1
|
||||||
|
m; m; m; m; m; m; m; m;
|
||||||
|
end
|
@ -208,3 +208,22 @@ assert_normal_exit %q{
|
|||||||
end
|
end
|
||||||
Foo.add_method
|
Foo.add_method
|
||||||
}, '[ruby-core:14556] reported by Frederick Cheung'
|
}, '[ruby-core:14556] reported by Frederick Cheung'
|
||||||
|
|
||||||
|
assert_equal 'ok', %q{
|
||||||
|
class Module
|
||||||
|
def my_module_eval(&block)
|
||||||
|
module_eval(&block)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
class String
|
||||||
|
Integer.my_module_eval do
|
||||||
|
def hoge; end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if Integer.instance_methods(false).map{|m|m.to_sym}.include?(:hoge) &&
|
||||||
|
!String.instance_methods(false).map{|m|m.to_sym}.include?(:hoge)
|
||||||
|
:ok
|
||||||
|
else
|
||||||
|
:ng
|
||||||
|
end
|
||||||
|
}, "[ruby-dev:34236]"
|
||||||
|
@ -136,26 +136,6 @@ assert_equal 'ok', %q{
|
|||||||
end
|
end
|
||||||
}, '[ruby-core:16010]'
|
}, '[ruby-core:16010]'
|
||||||
|
|
||||||
|
|
||||||
assert_equal 'ok', %q{
|
|
||||||
class Module
|
|
||||||
def my_module_eval(&block)
|
|
||||||
module_eval(&block)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
class String
|
|
||||||
Integer.my_module_eval do
|
|
||||||
def hoge; end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if Integer.instance_methods(false).map{|m|m.to_sym}.include?(:hoge) &&
|
|
||||||
!String.instance_methods(false).map{|m|m.to_sym}.include?(:hoge)
|
|
||||||
:ok
|
|
||||||
else
|
|
||||||
:ng
|
|
||||||
end
|
|
||||||
}, "[ruby-dev:34236]"
|
|
||||||
|
|
||||||
assert_equal 'ok', %q{
|
assert_equal 'ok', %q{
|
||||||
def m
|
def m
|
||||||
t = Thread.new { while true do // =~ "" end }
|
t = Thread.new { while true do // =~ "" end }
|
||||||
|
35
compile.c
35
compile.c
@ -280,7 +280,7 @@ iseq_compile(VALUE self, NODE *node)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (iseq->type == ISEQ_TYPE_RESCUE || iseq->type == ISEQ_TYPE_ENSURE) {
|
if (iseq->type == ISEQ_TYPE_RESCUE || iseq->type == ISEQ_TYPE_ENSURE) {
|
||||||
ADD_INSN2(ret, 0, getdynamic, INT2FIX(1), INT2FIX(0));
|
ADD_INSN2(ret, 0, getdynamic, INT2FIX(2), INT2FIX(0));
|
||||||
ADD_INSN1(ret, 0, throw, INT2FIX(0) /* continue throw */ );
|
ADD_INSN1(ret, 0, throw, INT2FIX(0) /* continue throw */ );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -771,7 +771,8 @@ iseq_set_exception_local_table(rb_iseq_t *iseq)
|
|||||||
id_dollar_bang = rb_intern("#$!");
|
id_dollar_bang = rb_intern("#$!");
|
||||||
}
|
}
|
||||||
iseq->local_table = (ID *)ALLOC_N(ID *, 1);
|
iseq->local_table = (ID *)ALLOC_N(ID *, 1);
|
||||||
iseq->local_table_size = iseq->local_size = 1;
|
iseq->local_table_size = 1;
|
||||||
|
iseq->local_size = iseq->local_table_size + 1;
|
||||||
iseq->local_table[0] = id_dollar_bang;
|
iseq->local_table[0] = id_dollar_bang;
|
||||||
return COMPILE_OK;
|
return COMPILE_OK;
|
||||||
}
|
}
|
||||||
@ -992,12 +993,14 @@ iseq_set_local_table(rb_iseq_t *iseq, ID *tbl)
|
|||||||
}
|
}
|
||||||
|
|
||||||
iseq->local_size = iseq->local_table_size = size;
|
iseq->local_size = iseq->local_table_size = size;
|
||||||
|
iseq->local_size += 1;
|
||||||
if (iseq->type == ISEQ_TYPE_METHOD ||
|
/*
|
||||||
iseq->type == ISEQ_TYPE_CLASS ||
|
if (lfp == dfp ) { // top, class, method
|
||||||
iseq->type == ISEQ_TYPE_TOP) {
|
dfp[-1]: svar
|
||||||
iseq->local_size += 1 /* svar */;
|
else { // block
|
||||||
|
dfp[-1]: cref
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
debugs("iseq_set_local_table: %d, %d\n", iseq->local_size, iseq->local_table_size);
|
debugs("iseq_set_local_table: %d, %d\n", iseq->local_size, iseq->local_table_size);
|
||||||
return COMPILE_OK;
|
return COMPILE_OK;
|
||||||
@ -3264,8 +3267,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||||||
case NODE_ARRAY:
|
case NODE_ARRAY:
|
||||||
while (narg) {
|
while (narg) {
|
||||||
COMPILE(ret, "rescue arg", narg->nd_head);
|
COMPILE(ret, "rescue arg", narg->nd_head);
|
||||||
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1),
|
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
|
||||||
INT2FIX(0));
|
|
||||||
ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1));
|
ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1));
|
||||||
ADD_INSNL(ret, nd_line(node), branchif, label_hit);
|
ADD_INSNL(ret, nd_line(node), branchif, label_hit);
|
||||||
narg = narg->nd_next;
|
narg = narg->nd_next;
|
||||||
@ -3274,8 +3276,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||||||
case NODE_SPLAT:
|
case NODE_SPLAT:
|
||||||
case NODE_ARGSCAT:
|
case NODE_ARGSCAT:
|
||||||
case NODE_ARGSPUSH:
|
case NODE_ARGSPUSH:
|
||||||
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1),
|
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
|
||||||
INT2FIX(0));
|
|
||||||
COMPILE(ret, "rescue/cond splat", narg);
|
COMPILE(ret, "rescue/cond splat", narg);
|
||||||
ADD_INSN1(ret, nd_line(node), checkincludearray, Qtrue);
|
ADD_INSN1(ret, nd_line(node), checkincludearray, Qtrue);
|
||||||
ADD_INSN(ret, nd_line(node), swap);
|
ADD_INSN(ret, nd_line(node), swap);
|
||||||
@ -3290,8 +3291,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||||||
else {
|
else {
|
||||||
ADD_INSN1(ret, nd_line(node), putobject,
|
ADD_INSN1(ret, nd_line(node), putobject,
|
||||||
rb_eStandardError);
|
rb_eStandardError);
|
||||||
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1),
|
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
|
||||||
INT2FIX(0));
|
|
||||||
ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1));
|
ADD_SEND(ret, nd_line(node), ID2SYM(idEqq), INT2FIX(1));
|
||||||
ADD_INSNL(ret, nd_line(node), branchif, label_hit);
|
ADD_INSNL(ret, nd_line(node), branchif, label_hit);
|
||||||
}
|
}
|
||||||
@ -4012,8 +4012,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||||||
if (idx < 0) {
|
if (idx < 0) {
|
||||||
rb_bug("unknown dvar (%s)", rb_id2name(node->nd_vid));
|
rb_bug("unknown dvar (%s)", rb_id2name(node->nd_vid));
|
||||||
}
|
}
|
||||||
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(ls - idx),
|
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(ls - idx), INT2FIX(lv));
|
||||||
INT2FIX(lv));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4485,8 +4484,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||||||
case NODE_ERRINFO:{
|
case NODE_ERRINFO:{
|
||||||
if (!poped) {
|
if (!poped) {
|
||||||
if (iseq->type == ISEQ_TYPE_RESCUE) {
|
if (iseq->type == ISEQ_TYPE_RESCUE) {
|
||||||
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1),
|
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(0));
|
||||||
INT2FIX(0));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rb_iseq_t *ip = iseq;
|
rb_iseq_t *ip = iseq;
|
||||||
@ -4499,8 +4497,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
|
|||||||
level++;
|
level++;
|
||||||
}
|
}
|
||||||
if (ip) {
|
if (ip) {
|
||||||
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(1),
|
ADD_INSN2(ret, nd_line(node), getdynamic, INT2FIX(2), INT2FIX(level));
|
||||||
INT2FIX(level));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ADD_INSN(ret, nd_line(node), putnil);
|
ADD_INSN(ret, nd_line(node), putnil);
|
||||||
|
141
eval.c
141
eval.c
@ -32,7 +32,7 @@ VALUE sysstack_error;
|
|||||||
|
|
||||||
static VALUE exception_error;
|
static VALUE exception_error;
|
||||||
|
|
||||||
static VALUE eval(VALUE, VALUE, VALUE, const char *, int);
|
static VALUE eval_string(VALUE, VALUE, VALUE, const char *, int);
|
||||||
|
|
||||||
static inline VALUE rb_yield_0(int argc, VALUE *argv);
|
static inline VALUE rb_yield_0(int argc, VALUE *argv);
|
||||||
static VALUE rb_call(VALUE, VALUE, ID, int, const VALUE *, int);
|
static VALUE rb_call(VALUE, VALUE, ID, int, const VALUE *, int);
|
||||||
@ -264,7 +264,7 @@ ruby_run_node(void *n)
|
|||||||
VALUE
|
VALUE
|
||||||
rb_eval_string(const char *str)
|
rb_eval_string(const char *str)
|
||||||
{
|
{
|
||||||
return eval(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1);
|
return eval_string(rb_vm_top_self(), rb_str_new2(str), Qnil, "(eval)", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
@ -329,7 +329,7 @@ rb_eval_cmd(VALUE cmd, VALUE arg, int level)
|
|||||||
|
|
||||||
PUSH_TAG();
|
PUSH_TAG();
|
||||||
if ((state = EXEC_TAG()) == 0) {
|
if ((state = EXEC_TAG()) == 0) {
|
||||||
val = eval(rb_vm_top_self(), cmd, Qnil, 0, 0);
|
val = eval_string(rb_vm_top_self(), cmd, Qnil, 0, 0);
|
||||||
}
|
}
|
||||||
POP_TAG();
|
POP_TAG();
|
||||||
|
|
||||||
@ -884,11 +884,12 @@ rb_iterator_p()
|
|||||||
|
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_f_block_given_p()
|
rb_f_block_given_p(void)
|
||||||
{
|
{
|
||||||
rb_thread_t *th = GET_THREAD();
|
rb_thread_t *th = GET_THREAD();
|
||||||
rb_control_frame_t *cfp = th->cfp;
|
rb_control_frame_t *cfp = th->cfp;
|
||||||
cfp = vm_get_ruby_level_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
|
cfp = vm_get_ruby_level_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
|
||||||
|
|
||||||
if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
|
if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
|
||||||
return Qtrue;
|
return Qtrue;
|
||||||
}
|
}
|
||||||
@ -1681,7 +1682,7 @@ rb_frame_self(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
|
eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *file, int line)
|
||||||
{
|
{
|
||||||
int state;
|
int state;
|
||||||
VALUE result = Qundef;
|
VALUE result = Qundef;
|
||||||
@ -1689,7 +1690,7 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
|
|||||||
rb_binding_t *bind = 0;
|
rb_binding_t *bind = 0;
|
||||||
rb_thread_t *th = GET_THREAD();
|
rb_thread_t *th = GET_THREAD();
|
||||||
rb_env_t *env = NULL;
|
rb_env_t *env = NULL;
|
||||||
NODE *stored_cref_stack = 0;
|
rb_block_t block;
|
||||||
|
|
||||||
if (file == 0) {
|
if (file == 0) {
|
||||||
file = rb_sourcefile();
|
file = rb_sourcefile();
|
||||||
@ -1705,7 +1706,6 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
|
|||||||
if (rb_obj_is_kind_of(scope, rb_cBinding)) {
|
if (rb_obj_is_kind_of(scope, rb_cBinding)) {
|
||||||
GetBindingPtr(scope, bind);
|
GetBindingPtr(scope, bind);
|
||||||
envval = bind->env;
|
envval = bind->env;
|
||||||
stored_cref_stack = bind->cref_stack;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rb_raise(rb_eTypeError,
|
rb_raise(rb_eTypeError,
|
||||||
@ -1717,7 +1717,9 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
||||||
th->base_block = RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
|
block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
|
||||||
|
th->base_block = █
|
||||||
|
th->base_block->self = self;
|
||||||
th->base_block->iseq = cfp->iseq; /* TODO */
|
th->base_block->iseq = cfp->iseq; /* TODO */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1725,7 +1727,8 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
|
|||||||
th->parse_in_eval++;
|
th->parse_in_eval++;
|
||||||
iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line));
|
iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line));
|
||||||
th->parse_in_eval--;
|
th->parse_in_eval--;
|
||||||
rb_vm_set_eval_stack(th, iseqval);
|
|
||||||
|
rb_vm_set_eval_stack(th, iseqval, cref);
|
||||||
th->base_block = 0;
|
th->base_block = 0;
|
||||||
|
|
||||||
if (0) { /* for debug */
|
if (0) { /* for debug */
|
||||||
@ -1739,22 +1742,12 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
|
|||||||
bind->env = vm_make_env_object(th, th->cfp);
|
bind->env = vm_make_env_object(th, th->cfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* push tag */
|
|
||||||
if (stored_cref_stack) {
|
|
||||||
stored_cref_stack =
|
|
||||||
vm_set_special_cref(th, env->block.lfp, stored_cref_stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* kick */
|
/* kick */
|
||||||
CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
|
CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
|
||||||
result = vm_eval_body(th);
|
result = vm_eval_body(th);
|
||||||
}
|
}
|
||||||
POP_TAG();
|
POP_TAG();
|
||||||
|
|
||||||
if (stored_cref_stack) {
|
|
||||||
vm_set_special_cref(th, env->block.lfp, stored_cref_stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state) {
|
if (state) {
|
||||||
if (state == TAG_RAISE) {
|
if (state == TAG_RAISE) {
|
||||||
VALUE errinfo = th->errinfo;
|
VALUE errinfo = th->errinfo;
|
||||||
@ -1779,6 +1772,12 @@ eval(VALUE self, VALUE src, VALUE scope, const char *file, int line)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
eval_string(VALUE self, VALUE src, VALUE scope, const char *file, int line)
|
||||||
|
{
|
||||||
|
return eval_string_with_cref(self, src, scope, 0, file, line);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* eval(string [, binding [, filename [,lineno]]]) => obj
|
* eval(string [, binding [, filename [,lineno]]]) => obj
|
||||||
@ -1825,90 +1824,36 @@ rb_f_eval(int argc, VALUE *argv, VALUE self)
|
|||||||
|
|
||||||
if (!NIL_P(vfile))
|
if (!NIL_P(vfile))
|
||||||
file = RSTRING_PTR(vfile);
|
file = RSTRING_PTR(vfile);
|
||||||
return eval(self, src, scope, file, line);
|
return eval_string(self, src, scope, file, line);
|
||||||
}
|
|
||||||
|
|
||||||
VALUE vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key);
|
|
||||||
void vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, VALUE val);
|
|
||||||
|
|
||||||
/* function to call func under the specified class/module context */
|
|
||||||
static VALUE
|
|
||||||
exec_under(VALUE (*func) (VALUE), VALUE under, VALUE self, VALUE args)
|
|
||||||
{
|
|
||||||
VALUE val = Qnil; /* OK */
|
|
||||||
rb_thread_t *th = GET_THREAD();
|
|
||||||
rb_control_frame_t *cfp = th->cfp;
|
|
||||||
rb_control_frame_t *pcfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
|
||||||
VALUE stored_self = pcfp->self;
|
|
||||||
NODE *stored_cref = 0;
|
|
||||||
|
|
||||||
rb_block_t block;
|
|
||||||
rb_block_t *blockptr;
|
|
||||||
int state;
|
|
||||||
|
|
||||||
/* replace environment */
|
|
||||||
pcfp->self = self;
|
|
||||||
if ((blockptr = GC_GUARDED_PTR_REF(*th->cfp->lfp)) != 0) {
|
|
||||||
/* copy block info */
|
|
||||||
/* TODO: why? */
|
|
||||||
block = *blockptr;
|
|
||||||
block.self = self;
|
|
||||||
*th->cfp->lfp = GC_GUARDED_PTR(&block);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
|
||||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
|
||||||
}
|
|
||||||
|
|
||||||
stored_cref = (NODE *)vm_cfp_svar_get(th, cfp, 2);
|
|
||||||
vm_cfp_svar_set(th, cfp, 2, (VALUE)vm_cref_push(th, under, NOEX_PUBLIC));
|
|
||||||
|
|
||||||
PUSH_TAG();
|
|
||||||
if ((state = EXEC_TAG()) == 0) {
|
|
||||||
val = (*func) (args);
|
|
||||||
}
|
|
||||||
POP_TAG();
|
|
||||||
|
|
||||||
/* restore environment */
|
|
||||||
vm_cfp_svar_set(th, cfp, 2, (VALUE)stored_cref);
|
|
||||||
pcfp->self = stored_self;
|
|
||||||
|
|
||||||
if (state) {
|
|
||||||
JUMP_TAG(state);
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
yield_under_i(VALUE arg)
|
|
||||||
{
|
|
||||||
if (arg == Qundef) {
|
|
||||||
return rb_yield_0(0, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return rb_yield_0(RARRAY_LEN(arg), RARRAY_PTR(arg));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* block eval under the class/module context */
|
/* block eval under the class/module context */
|
||||||
static VALUE
|
static VALUE
|
||||||
yield_under(VALUE under, VALUE self, VALUE values)
|
yield_under(VALUE under, VALUE self, VALUE values)
|
||||||
{
|
{
|
||||||
return exec_under(yield_under_i, under, self, values);
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
rb_block_t block, *blockptr;
|
||||||
|
NODE *cref = vm_cref_push(th, under, NOEX_PUBLIC);
|
||||||
|
|
||||||
|
if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
|
||||||
|
block = *blockptr;
|
||||||
|
block.self = self;
|
||||||
|
th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
if (values == Qundef) {
|
||||||
eval_under_i(VALUE arg)
|
return vm_yield_with_cref(th, 0, 0, cref);
|
||||||
{
|
}
|
||||||
VALUE *args = (VALUE *)arg;
|
else {
|
||||||
return eval(args[0], args[1], Qnil, (char *)args[2], (int)args[3]);
|
return vm_yield_with_cref(th, RARRAY_LEN(values), RARRAY_PTR(values), cref);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* string eval under the class/module context */
|
/* string eval under the class/module context */
|
||||||
static VALUE
|
static VALUE
|
||||||
eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
|
eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
|
||||||
{
|
{
|
||||||
VALUE args[4];
|
NODE *cref = vm_cref_push(GET_THREAD(), under, NOEX_PUBLIC);
|
||||||
|
|
||||||
if (rb_safe_level() >= 4) {
|
if (rb_safe_level() >= 4) {
|
||||||
StringValue(src);
|
StringValue(src);
|
||||||
@ -1916,11 +1861,8 @@ eval_under(VALUE under, VALUE self, VALUE src, const char *file, int line)
|
|||||||
else {
|
else {
|
||||||
SafeStringValue(src);
|
SafeStringValue(src);
|
||||||
}
|
}
|
||||||
args[0] = self;
|
|
||||||
args[1] = src;
|
return eval_string_with_cref(self, src, Qnil, cref, file, line);
|
||||||
args[2] = (VALUE)file;
|
|
||||||
args[3] = (VALUE)line;
|
|
||||||
return exec_under(eval_under_i, under, self, (VALUE)args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
@ -1928,8 +1870,7 @@ specific_eval(int argc, VALUE *argv, VALUE klass, VALUE self)
|
|||||||
{
|
{
|
||||||
if (rb_block_given_p()) {
|
if (rb_block_given_p()) {
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)",
|
rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", argc);
|
||||||
argc);
|
|
||||||
}
|
}
|
||||||
return yield_under(klass, self, Qundef);
|
return yield_under(klass, self, Qundef);
|
||||||
}
|
}
|
||||||
@ -2499,12 +2440,12 @@ errinfo_place(void)
|
|||||||
while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
|
while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
|
||||||
if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
||||||
if (cfp->iseq->type == ISEQ_TYPE_RESCUE) {
|
if (cfp->iseq->type == ISEQ_TYPE_RESCUE) {
|
||||||
return &cfp->dfp[-1];
|
return &cfp->dfp[-2];
|
||||||
}
|
}
|
||||||
else if (cfp->iseq->type == ISEQ_TYPE_ENSURE &&
|
else if (cfp->iseq->type == ISEQ_TYPE_ENSURE &&
|
||||||
TYPE(cfp->dfp[-1]) != T_NODE &&
|
TYPE(cfp->dfp[-2]) != T_NODE &&
|
||||||
!FIXNUM_P(cfp->dfp[-1])) {
|
!FIXNUM_P(cfp->dfp[-2])) {
|
||||||
return &cfp->dfp[-1];
|
return &cfp->dfp[-2];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||||
|
@ -225,11 +225,12 @@ NORETURN(void rb_print_undef(VALUE, ID, int));
|
|||||||
NORETURN(void vm_localjump_error(const char *, VALUE, int));
|
NORETURN(void vm_localjump_error(const char *, VALUE, int));
|
||||||
NORETURN(void vm_jump_tag_but_local_jump(int, VALUE));
|
NORETURN(void vm_jump_tag_but_local_jump(int, VALUE));
|
||||||
|
|
||||||
NODE *vm_get_cref(rb_thread_t *th, rb_iseq_t *iseq, rb_control_frame_t *cfp);
|
|
||||||
NODE *vm_cref_push(rb_thread_t *th, VALUE, int);
|
NODE *vm_cref_push(rb_thread_t *th, VALUE, int);
|
||||||
NODE *vm_set_special_cref(rb_thread_t *th, VALUE *lfp, NODE * cref_stack);
|
NODE *vm_set_special_cref(rb_thread_t *th, VALUE *lfp, NODE * cref_stack);
|
||||||
VALUE vm_make_jump_tag_but_local_jump(int state, VALUE val);
|
VALUE vm_make_jump_tag_but_local_jump(int state, VALUE val);
|
||||||
|
|
||||||
|
NODE *ruby_cref(void);
|
||||||
|
|
||||||
static rb_control_frame_t *
|
static rb_control_frame_t *
|
||||||
vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
|
vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
|
||||||
{
|
{
|
||||||
@ -242,22 +243,12 @@ vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline NODE *
|
|
||||||
ruby_cref()
|
|
||||||
{
|
|
||||||
rb_thread_t *th = GET_THREAD();
|
|
||||||
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
|
||||||
return vm_get_cref(th, cfp->iseq, cfp);
|
|
||||||
}
|
|
||||||
|
|
||||||
VALUE vm_get_cbase(rb_thread_t *th);
|
|
||||||
VALUE rb_obj_is_proc(VALUE);
|
VALUE rb_obj_is_proc(VALUE);
|
||||||
void rb_vm_check_redefinition_opt_method(NODE *node);
|
void rb_vm_check_redefinition_opt_method(NODE *node);
|
||||||
VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, rb_block_t *blockptr, VALUE filename);
|
VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, rb_block_t *blockptr, VALUE filename);
|
||||||
void rb_thread_terminate_all(void);
|
void rb_thread_terminate_all(void);
|
||||||
void rb_vm_set_eval_stack(rb_thread_t *, VALUE iseq);
|
void rb_vm_set_eval_stack(rb_thread_t *, VALUE iseq, NODE *cref);
|
||||||
VALUE rb_vm_top_self();
|
VALUE rb_vm_top_self();
|
||||||
|
VALUE rb_vm_cbase(void);
|
||||||
#define ruby_cbase() vm_get_cbase(GET_THREAD())
|
|
||||||
|
|
||||||
#endif /* RUBY_EVAL_INTERN_H */
|
#endif /* RUBY_EVAL_INTERN_H */
|
||||||
|
@ -463,7 +463,7 @@ rb_undef(VALUE klass, ID id)
|
|||||||
VALUE origin;
|
VALUE origin;
|
||||||
NODE *body;
|
NODE *body;
|
||||||
|
|
||||||
if (ruby_cbase() == rb_cObject && klass == rb_cObject) {
|
if (rb_vm_cbase() == rb_cObject && klass == rb_cObject) {
|
||||||
rb_secure(4);
|
rb_secure(4);
|
||||||
}
|
}
|
||||||
if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
|
if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
|
||||||
|
15
gc.c
15
gc.c
@ -1280,15 +1280,6 @@ gc_mark_children(rb_objspace_t *objspace, VALUE ptr, int lev)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_VALUES:
|
|
||||||
{
|
|
||||||
rb_gc_mark(RVALUES(obj)->v1);
|
|
||||||
rb_gc_mark(RVALUES(obj)->v2);
|
|
||||||
ptr = RVALUES(obj)->v3;
|
|
||||||
goto again;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
rb_bug("rb_gc_mark(): unknown data type 0x%lx(%p) %s",
|
rb_bug("rb_gc_mark(): unknown data type 0x%lx(%p) %s",
|
||||||
obj->as.basic.flags & T_MASK, obj,
|
obj->as.basic.flags & T_MASK, obj,
|
||||||
@ -1531,8 +1522,6 @@ obj_free(rb_objspace_t *objspace, VALUE obj)
|
|||||||
|
|
||||||
case T_FLOAT:
|
case T_FLOAT:
|
||||||
break;
|
break;
|
||||||
case T_VALUES:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_BIGNUM:
|
case T_BIGNUM:
|
||||||
if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) {
|
if (!(RBASIC(obj)->flags & RBIGNUM_EMBED_FLAG) && RBIGNUM_DIGITS(obj)) {
|
||||||
@ -1878,7 +1867,6 @@ os_obj_of(rb_objspace_t *objspace, VALUE of)
|
|||||||
case T_NONE:
|
case T_NONE:
|
||||||
case T_ICLASS:
|
case T_ICLASS:
|
||||||
case T_NODE:
|
case T_NODE:
|
||||||
case T_VALUES:
|
|
||||||
continue;
|
continue;
|
||||||
case T_CLASS:
|
case T_CLASS:
|
||||||
if (FL_TEST(p, FL_SINGLETON)) continue;
|
if (FL_TEST(p, FL_SINGLETON)) continue;
|
||||||
@ -2175,7 +2163,7 @@ id2ref(VALUE obj, VALUE objid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!is_pointer_to_heap(objspace, (void *)ptr) ||
|
if (!is_pointer_to_heap(objspace, (void *)ptr) ||
|
||||||
BUILTIN_TYPE(ptr) >= T_VALUES || BUILTIN_TYPE(ptr) == T_ICLASS) {
|
BUILTIN_TYPE(ptr) > T_FIXNUM || BUILTIN_TYPE(ptr) == T_ICLASS) {
|
||||||
rb_raise(rb_eRangeError, "%p is not id value", p0);
|
rb_raise(rb_eRangeError, "%p is not id value", p0);
|
||||||
}
|
}
|
||||||
if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) {
|
if (BUILTIN_TYPE(ptr) == 0 || RBASIC(ptr)->klass == 0) {
|
||||||
@ -2334,7 +2322,6 @@ count_objects(int argc, VALUE *argv, VALUE os)
|
|||||||
COUNT_TYPE(T_FALSE);
|
COUNT_TYPE(T_FALSE);
|
||||||
COUNT_TYPE(T_SYMBOL);
|
COUNT_TYPE(T_SYMBOL);
|
||||||
COUNT_TYPE(T_FIXNUM);
|
COUNT_TYPE(T_FIXNUM);
|
||||||
COUNT_TYPE(T_VALUES);
|
|
||||||
COUNT_TYPE(T_UNDEF);
|
COUNT_TYPE(T_UNDEF);
|
||||||
COUNT_TYPE(T_NODE);
|
COUNT_TYPE(T_NODE);
|
||||||
COUNT_TYPE(T_ICLASS);
|
COUNT_TYPE(T_ICLASS);
|
||||||
|
@ -262,7 +262,6 @@ enum ruby_value_type {
|
|||||||
RUBY_T_SYMBOL = 0x14,
|
RUBY_T_SYMBOL = 0x14,
|
||||||
RUBY_T_FIXNUM = 0x15,
|
RUBY_T_FIXNUM = 0x15,
|
||||||
|
|
||||||
RUBY_T_VALUES = 0x1a,
|
|
||||||
RUBY_T_UNDEF = 0x1b,
|
RUBY_T_UNDEF = 0x1b,
|
||||||
RUBY_T_NODE = 0x1c,
|
RUBY_T_NODE = 0x1c,
|
||||||
RUBY_T_ICLASS = 0x1d,
|
RUBY_T_ICLASS = 0x1d,
|
||||||
@ -292,7 +291,6 @@ enum ruby_value_type {
|
|||||||
#define T_SYMBOL RUBY_T_SYMBOL
|
#define T_SYMBOL RUBY_T_SYMBOL
|
||||||
#define T_RATIONAL RUBY_T_RATIONAL
|
#define T_RATIONAL RUBY_T_RATIONAL
|
||||||
#define T_COMPLEX RUBY_T_COMPLEX
|
#define T_COMPLEX RUBY_T_COMPLEX
|
||||||
#define T_VALUES RUBY_T_VALUES
|
|
||||||
#define T_UNDEF RUBY_T_UNDEF
|
#define T_UNDEF RUBY_T_UNDEF
|
||||||
#define T_NODE RUBY_T_NODE
|
#define T_NODE RUBY_T_NODE
|
||||||
#define T_MASK RUBY_T_MASK
|
#define T_MASK RUBY_T_MASK
|
||||||
@ -438,13 +436,6 @@ struct RObject {
|
|||||||
RCLASS_IV_INDEX_TBL(rb_obj_class(o)) : \
|
RCLASS_IV_INDEX_TBL(rb_obj_class(o)) : \
|
||||||
ROBJECT(o)->as.heap.iv_index_tbl)
|
ROBJECT(o)->as.heap.iv_index_tbl)
|
||||||
|
|
||||||
struct RValues {
|
|
||||||
struct RBasic basic;
|
|
||||||
VALUE v1;
|
|
||||||
VALUE v2;
|
|
||||||
VALUE v3;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
VALUE super;
|
VALUE super;
|
||||||
struct st_table *iv_tbl;
|
struct st_table *iv_tbl;
|
||||||
@ -654,7 +645,6 @@ struct RBignum {
|
|||||||
#define RFILE(obj) (R_CAST(RFile)(obj))
|
#define RFILE(obj) (R_CAST(RFile)(obj))
|
||||||
#define RRATIONAL(obj) (R_CAST(RRational)(obj))
|
#define RRATIONAL(obj) (R_CAST(RRational)(obj))
|
||||||
#define RCOMPLEX(obj) (R_CAST(RComplex)(obj))
|
#define RCOMPLEX(obj) (R_CAST(RComplex)(obj))
|
||||||
#define RVALUES(obj) (R_CAST(RValues)(obj))
|
|
||||||
|
|
||||||
#define FL_SINGLETON FL_USER0
|
#define FL_SINGLETON FL_USER0
|
||||||
#define FL_MARK (((VALUE)1)<<5)
|
#define FL_MARK (((VALUE)1)<<5)
|
||||||
|
20
insns.def
20
insns.def
@ -183,7 +183,8 @@ getclassvariable
|
|||||||
()
|
()
|
||||||
(VALUE val)
|
(VALUE val)
|
||||||
{
|
{
|
||||||
val = rb_cvar_get(vm_get_cvar_base(th, GET_ISEQ()), id);
|
NODE *cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||||
|
val = rb_cvar_get(vm_get_cvar_base(cref), id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -197,7 +198,8 @@ setclassvariable
|
|||||||
(VALUE val)
|
(VALUE val)
|
||||||
()
|
()
|
||||||
{
|
{
|
||||||
rb_cvar_set(vm_get_cvar_base(th, GET_ISEQ()), id, val);
|
NODE *cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||||
|
rb_cvar_set(vm_get_cvar_base(cref), id, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -317,7 +319,7 @@ putcbase
|
|||||||
()
|
()
|
||||||
(VALUE val)
|
(VALUE val)
|
||||||
{
|
{
|
||||||
val = vm_get_cbase(th);
|
val = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -723,8 +725,8 @@ definemethod
|
|||||||
(VALUE obj)
|
(VALUE obj)
|
||||||
()
|
()
|
||||||
{
|
{
|
||||||
vm_define_method(th, obj, id, body, is_singleton,
|
NODE *cref = vm_get_cref(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||||
get_cref(GET_ISEQ(), GET_LFP()));
|
vm_define_method(th, obj, id, body, is_singleton, cref);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -744,7 +746,7 @@ alias
|
|||||||
rb_alias_variable(SYM2ID(sym1), SYM2ID(sym2));
|
rb_alias_variable(SYM2ID(sym1), SYM2ID(sym2));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss;
|
klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||||
rb_alias(klass, SYM2ID(sym1), SYM2ID(sym2));
|
rb_alias(klass, SYM2ID(sym1), SYM2ID(sym2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -760,7 +762,7 @@ undef
|
|||||||
(VALUE sym)
|
(VALUE sym)
|
||||||
()
|
()
|
||||||
{
|
{
|
||||||
VALUE klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss;
|
VALUE klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||||
rb_undef(klass, SYM2ID(sym));
|
rb_undef(klass, SYM2ID(sym));
|
||||||
INC_VM_STATE_VERSION();
|
INC_VM_STATE_VERSION();
|
||||||
}
|
}
|
||||||
@ -787,7 +789,7 @@ defined
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DEFINED_IVAR2:
|
case DEFINED_IVAR2:
|
||||||
klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss;
|
klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||||
break;
|
break;
|
||||||
case DEFINED_GVAR:
|
case DEFINED_GVAR:
|
||||||
if (rb_gvar_defined((struct global_entry *)(obj & ~1))) {
|
if (rb_gvar_defined((struct global_entry *)(obj & ~1))) {
|
||||||
@ -795,7 +797,7 @@ defined
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DEFINED_CVAR:
|
case DEFINED_CVAR:
|
||||||
klass = get_cref(GET_ISEQ(), GET_LFP())->nd_clss;
|
klass = vm_get_cbase(GET_ISEQ(), GET_LFP(), GET_DFP());
|
||||||
if (rb_cvar_defined(klass, SYM2ID(obj))) {
|
if (rb_cvar_defined(klass, SYM2ID(obj))) {
|
||||||
expr_type = "class variable";
|
expr_type = "class variable";
|
||||||
}
|
}
|
||||||
|
6
load.c
6
load.c
@ -650,7 +650,7 @@ rb_mod_autoload_p(VALUE mod, VALUE sym)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
|
rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
|
||||||
{
|
{
|
||||||
VALUE klass = ruby_cbase();
|
VALUE klass = rb_vm_cbase();
|
||||||
if (NIL_P(klass)) {
|
if (NIL_P(klass)) {
|
||||||
rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
|
rb_raise(rb_eTypeError, "Can not set autoload on singleton class");
|
||||||
}
|
}
|
||||||
@ -664,8 +664,8 @@ rb_f_autoload(VALUE obj, VALUE sym, VALUE file)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_f_autoload_p(VALUE obj, VALUE sym)
|
rb_f_autoload_p(VALUE obj, VALUE sym)
|
||||||
{
|
{
|
||||||
/* use ruby_cbase() as same as rb_f_autoload. */
|
/* use rb_vm_cbase() as same as rb_f_autoload. */
|
||||||
VALUE klass = ruby_cbase();
|
VALUE klass = rb_vm_cbase();
|
||||||
if (NIL_P(klass)) {
|
if (NIL_P(klass)) {
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
6
proc.c
6
proc.c
@ -50,7 +50,6 @@ proc_mark(void *ptr)
|
|||||||
proc = ptr;
|
proc = ptr;
|
||||||
RUBY_MARK_UNLESS_NULL(proc->envval);
|
RUBY_MARK_UNLESS_NULL(proc->envval);
|
||||||
RUBY_MARK_UNLESS_NULL(proc->blockprocval);
|
RUBY_MARK_UNLESS_NULL(proc->blockprocval);
|
||||||
RUBY_MARK_UNLESS_NULL((VALUE)proc->special_cref_stack);
|
|
||||||
RUBY_MARK_UNLESS_NULL(proc->block.proc);
|
RUBY_MARK_UNLESS_NULL(proc->block.proc);
|
||||||
RUBY_MARK_UNLESS_NULL(proc->block.self);
|
RUBY_MARK_UNLESS_NULL(proc->block.self);
|
||||||
if (proc->block.iseq && RUBY_VM_IFUNC_P(proc->block.iseq)) {
|
if (proc->block.iseq && RUBY_VM_IFUNC_P(proc->block.iseq)) {
|
||||||
@ -94,7 +93,6 @@ proc_dup(VALUE self)
|
|||||||
dst->block.proc = procval;
|
dst->block.proc = procval;
|
||||||
dst->envval = src->envval;
|
dst->envval = src->envval;
|
||||||
dst->safe_level = dst->safe_level;
|
dst->safe_level = dst->safe_level;
|
||||||
dst->special_cref_stack = src->special_cref_stack;
|
|
||||||
dst->is_lambda = src->is_lambda;
|
dst->is_lambda = src->is_lambda;
|
||||||
|
|
||||||
return procval;
|
return procval;
|
||||||
@ -241,7 +239,6 @@ binding_mark(void *ptr)
|
|||||||
if (ptr) {
|
if (ptr) {
|
||||||
bind = ptr;
|
bind = ptr;
|
||||||
RUBY_MARK_UNLESS_NULL(bind->env);
|
RUBY_MARK_UNLESS_NULL(bind->env);
|
||||||
RUBY_MARK_UNLESS_NULL((VALUE)bind->cref_stack);
|
|
||||||
}
|
}
|
||||||
RUBY_MARK_LEAVE("binding");
|
RUBY_MARK_LEAVE("binding");
|
||||||
}
|
}
|
||||||
@ -264,7 +261,6 @@ binding_dup(VALUE self)
|
|||||||
GetBindingPtr(self, src);
|
GetBindingPtr(self, src);
|
||||||
GetBindingPtr(bindval, dst);
|
GetBindingPtr(bindval, dst);
|
||||||
dst->env = src->env;
|
dst->env = src->env;
|
||||||
dst->cref_stack = src->cref_stack;
|
|
||||||
return bindval;
|
return bindval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,7 +282,6 @@ rb_binding_new(void)
|
|||||||
|
|
||||||
GetBindingPtr(bindval, bind);
|
GetBindingPtr(bindval, bind);
|
||||||
bind->env = vm_make_env_object(th, cfp);
|
bind->env = vm_make_env_object(th, cfp);
|
||||||
bind->cref_stack = ruby_cref();
|
|
||||||
return bindval;
|
return bindval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1587,7 +1582,6 @@ proc_binding(VALUE self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bind->env = proc->envval;
|
bind->env = proc->envval;
|
||||||
bind->cref_stack = proc->special_cref_stack;
|
|
||||||
return bindval;
|
return bindval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#define RUBY_VERSION "1.9.0"
|
#define RUBY_VERSION "1.9.0"
|
||||||
#define RUBY_RELEASE_DATE "2008-05-18"
|
#define RUBY_RELEASE_DATE "2008-05-19"
|
||||||
#define RUBY_VERSION_CODE 190
|
#define RUBY_VERSION_CODE 190
|
||||||
#define RUBY_RELEASE_CODE 20080518
|
#define RUBY_RELEASE_CODE 20080519
|
||||||
#define RUBY_PATCHLEVEL 0
|
#define RUBY_PATCHLEVEL 0
|
||||||
|
|
||||||
#define RUBY_VERSION_MAJOR 1
|
#define RUBY_VERSION_MAJOR 1
|
||||||
@ -9,7 +9,7 @@
|
|||||||
#define RUBY_VERSION_TEENY 0
|
#define RUBY_VERSION_TEENY 0
|
||||||
#define RUBY_RELEASE_YEAR 2008
|
#define RUBY_RELEASE_YEAR 2008
|
||||||
#define RUBY_RELEASE_MONTH 5
|
#define RUBY_RELEASE_MONTH 5
|
||||||
#define RUBY_RELEASE_DAY 18
|
#define RUBY_RELEASE_DAY 19
|
||||||
|
|
||||||
#ifdef RUBY_EXTERN
|
#ifdef RUBY_EXTERN
|
||||||
RUBY_EXTERN const char ruby_version[];
|
RUBY_EXTERN const char ruby_version[];
|
||||||
@ -46,7 +46,7 @@ RUBY_EXTERN const char ruby_copyright[];
|
|||||||
|
|
||||||
# define RUBY_DESCRIPTION \
|
# define RUBY_DESCRIPTION \
|
||||||
"ruby "RUBY_VERSION \
|
"ruby "RUBY_VERSION \
|
||||||
" ("RUBY_RELEASE_DATE" " \
|
"2008-05-19" \
|
||||||
RUBY_RELEASE_STR" " \
|
RUBY_RELEASE_STR" " \
|
||||||
STRINGIZE(RUBY_RELEASE_NUM)") " \
|
STRINGIZE(RUBY_RELEASE_NUM)") " \
|
||||||
"["RUBY_PLATFORM"]"
|
"["RUBY_PLATFORM"]"
|
||||||
|
130
vm.c
130
vm.c
@ -79,7 +79,7 @@ rb_vm_set_top_stack(rb_thread_t *th, VALUE iseqval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
rb_vm_set_eval_stack(rb_thread_t *th, VALUE iseqval)
|
rb_vm_set_eval_stack(rb_thread_t *th, VALUE iseqval, NODE *cref)
|
||||||
{
|
{
|
||||||
rb_iseq_t *iseq;
|
rb_iseq_t *iseq;
|
||||||
rb_block_t *block = th->base_block;
|
rb_block_t *block = th->base_block;
|
||||||
@ -90,6 +90,10 @@ rb_vm_set_eval_stack(rb_thread_t *th, VALUE iseqval)
|
|||||||
vm_push_frame(th, iseq, FRAME_MAGIC_EVAL, block->self,
|
vm_push_frame(th, iseq, FRAME_MAGIC_EVAL, block->self,
|
||||||
GC_GUARDED_PTR(block->dfp), iseq->iseq_encoded,
|
GC_GUARDED_PTR(block->dfp), iseq->iseq_encoded,
|
||||||
th->cfp->sp, block->lfp, iseq->local_size);
|
th->cfp->sp, block->lfp, iseq->local_size);
|
||||||
|
|
||||||
|
if (cref) {
|
||||||
|
th->cfp->dfp[-1] = (VALUE)cref;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Env */
|
/* Env */
|
||||||
@ -263,12 +267,6 @@ vm_make_env_each(rb_thread_t *th, rb_control_frame_t *cfp,
|
|||||||
env->block.dfp = cfp->dfp;
|
env->block.dfp = cfp->dfp;
|
||||||
env->block.iseq = cfp->iseq;
|
env->block.iseq = cfp->iseq;
|
||||||
|
|
||||||
if (VMDEBUG &&
|
|
||||||
(!(cfp->lfp[-1] == Qnil ||
|
|
||||||
BUILTIN_TYPE(cfp->lfp[-1]) == T_VALUES))) {
|
|
||||||
rb_bug("invalid svar");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
if (!RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
||||||
/* TODO */
|
/* TODO */
|
||||||
env->block.iseq = 0;
|
env->block.iseq = 0;
|
||||||
@ -389,7 +387,6 @@ vm_make_proc(rb_thread_t *th,
|
|||||||
proc->block.proc = procval;
|
proc->block.proc = procval;
|
||||||
proc->envval = envval;
|
proc->envval = envval;
|
||||||
proc->safe_level = th->safe_level;
|
proc->safe_level = th->safe_level;
|
||||||
proc->special_cref_stack = lfp_get_special_cref(block->lfp);
|
|
||||||
|
|
||||||
if (VMDEBUG) {
|
if (VMDEBUG) {
|
||||||
if (th->stack < block->dfp && block->dfp < th->stack + th->stack_size) {
|
if (th->stack < block->dfp && block->dfp < th->stack + th->stack_size) {
|
||||||
@ -540,8 +537,8 @@ rb_call_super(int argc, const VALUE *argv)
|
|||||||
/* C -> Ruby: block */
|
/* C -> Ruby: block */
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self,
|
invoke_block_from_c(rb_thread_t *th, rb_block_t *block, VALUE self,
|
||||||
int argc, VALUE *argv, rb_block_t *blockptr)
|
int argc, VALUE *argv, rb_block_t *blockptr, NODE *cref)
|
||||||
{
|
{
|
||||||
VALUE val;
|
VALUE val;
|
||||||
if (BUILTIN_TYPE(block->iseq) != T_NODE) {
|
if (BUILTIN_TYPE(block->iseq) != T_NODE) {
|
||||||
@ -566,6 +563,7 @@ invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self,
|
|||||||
self, GC_GUARDED_PTR(block->dfp),
|
self, GC_GUARDED_PTR(block->dfp),
|
||||||
iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, block->lfp,
|
iseq->iseq_encoded + opt_pc, cfp->sp + arg_size, block->lfp,
|
||||||
iseq->local_size - arg_size);
|
iseq->local_size - arg_size);
|
||||||
|
th->cfp->dfp[-1] = (VALUE)cref;
|
||||||
|
|
||||||
val = vm_eval_body(th);
|
val = vm_eval_body(th);
|
||||||
}
|
}
|
||||||
@ -576,7 +574,7 @@ invoke_block(rb_thread_t *th, rb_block_t *block, VALUE self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
vm_yield(rb_thread_t *th, int argc, VALUE *argv)
|
vm_yield_with_cref(rb_thread_t *th, int argc, VALUE *argv, NODE *cref)
|
||||||
{
|
{
|
||||||
rb_block_t *block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
|
rb_block_t *block = GC_GUARDED_PTR_REF(th->cfp->lfp[0]);
|
||||||
|
|
||||||
@ -584,7 +582,13 @@ vm_yield(rb_thread_t *th, int argc, VALUE *argv)
|
|||||||
vm_localjump_error("no block given", Qnil, 0);
|
vm_localjump_error("no block given", Qnil, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return invoke_block(th, block, block->self, argc, argv, 0);
|
return invoke_block_from_c(th, block, block->self, argc, argv, 0, cref);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
vm_yield(rb_thread_t *th, int argc, VALUE *argv)
|
||||||
|
{
|
||||||
|
return vm_yield_with_cref(th, argc, argv, (NODE *)Qnil);
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
@ -594,14 +598,12 @@ vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc,
|
|||||||
VALUE val = Qundef;
|
VALUE val = Qundef;
|
||||||
int state;
|
int state;
|
||||||
volatile int stored_safe = th->safe_level;
|
volatile int stored_safe = th->safe_level;
|
||||||
volatile NODE *stored_special_cref_stack =
|
|
||||||
lfp_set_special_cref(proc->block.lfp, proc->special_cref_stack);
|
|
||||||
rb_control_frame_t * volatile cfp = th->cfp;
|
rb_control_frame_t * volatile cfp = th->cfp;
|
||||||
|
|
||||||
TH_PUSH_TAG(th);
|
TH_PUSH_TAG(th);
|
||||||
if ((state = EXEC_TAG()) == 0) {
|
if ((state = EXEC_TAG()) == 0) {
|
||||||
th->safe_level = proc->safe_level;
|
th->safe_level = proc->safe_level;
|
||||||
val = invoke_block(th, &proc->block, self, argc, argv, blockptr);
|
val = invoke_block_from_c(th, &proc->block, self, argc, argv, blockptr, (NODE *)Qnil);
|
||||||
}
|
}
|
||||||
TH_POP_TAG();
|
TH_POP_TAG();
|
||||||
|
|
||||||
@ -609,8 +611,6 @@ vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc,
|
|||||||
th->safe_level = stored_safe;
|
th->safe_level = stored_safe;
|
||||||
}
|
}
|
||||||
|
|
||||||
lfp_set_special_cref(proc->block.lfp, (NODE*)stored_special_cref_stack);
|
|
||||||
|
|
||||||
if (state) {
|
if (state) {
|
||||||
if (state == TAG_RETURN && proc->is_lambda) {
|
if (state == TAG_RETURN && proc->is_lambda) {
|
||||||
VALUE err = th->errinfo;
|
VALUE err = th->errinfo;
|
||||||
@ -773,8 +773,6 @@ vm_backtrace(rb_thread_t *th, int lev)
|
|||||||
return ary;
|
return ary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cref */
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
check_svar(void)
|
check_svar(void)
|
||||||
{
|
{
|
||||||
@ -783,7 +781,7 @@ check_svar(void)
|
|||||||
while ((void *)(cfp + 1) < (void *)(th->stack + th->stack_size)) {
|
while ((void *)(cfp + 1) < (void *)(th->stack + th->stack_size)) {
|
||||||
/* printf("cfp: %p\n", cfp->type); */
|
/* printf("cfp: %p\n", cfp->type); */
|
||||||
if (cfp->lfp && cfp->lfp[-1] != Qnil &&
|
if (cfp->lfp && cfp->lfp[-1] != Qnil &&
|
||||||
TYPE(cfp->lfp[-1]) != T_VALUES) {
|
TYPE(cfp->lfp[-1]) != T_NODE) {
|
||||||
/* dp(cfp->lfp[-1]); */
|
/* dp(cfp->lfp[-1]); */
|
||||||
rb_bug("!!!invalid svar!!!");
|
rb_bug("!!!invalid svar!!!");
|
||||||
}
|
}
|
||||||
@ -791,30 +789,12 @@ check_svar(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static NODE *
|
|
||||||
lfp_set_special_cref(VALUE *lfp, NODE * cref)
|
|
||||||
{
|
|
||||||
struct RValues *values = (void *) lfp[-1];
|
|
||||||
NODE *old_cref;
|
|
||||||
|
|
||||||
if (VMDEBUG) {
|
|
||||||
check_svar();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cref == 0 && ((VALUE)values == Qnil || values->basic.klass == 0)) {
|
|
||||||
old_cref = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
old_cref = (NODE *)lfp_svar_get(GET_THREAD(), lfp, 2);
|
|
||||||
lfp_svar_set(GET_THREAD(), lfp, 2, (VALUE)cref);
|
|
||||||
}
|
|
||||||
return old_cref;
|
|
||||||
}
|
|
||||||
|
|
||||||
NODE *
|
NODE *
|
||||||
vm_set_special_cref(rb_thread_t *th, VALUE *lfp, NODE * cref_stack)
|
ruby_cref(void)
|
||||||
{
|
{
|
||||||
return lfp_set_special_cref(lfp, cref_stack);
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
||||||
|
return vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -829,12 +809,6 @@ debug_cref(NODE *cref)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NODE *
|
|
||||||
vm_get_cref(rb_thread_t *th, rb_iseq_t *iseq, rb_control_frame_t *cfp)
|
|
||||||
{
|
|
||||||
return get_cref(iseq, cfp->lfp);
|
|
||||||
}
|
|
||||||
|
|
||||||
NODE *
|
NODE *
|
||||||
vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
|
vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
|
||||||
{
|
{
|
||||||
@ -842,16 +816,15 @@ vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
|
|||||||
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
||||||
|
|
||||||
cref->nd_file = 0;
|
cref->nd_file = 0;
|
||||||
cref->nd_next = get_cref(cfp->iseq, cfp->lfp);
|
cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
|
||||||
cref->nd_visi = noex;
|
cref->nd_visi = noex;
|
||||||
return cref;
|
return cref;
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
static inline VALUE
|
||||||
vm_get_cbase(rb_thread_t *th)
|
vm_get_cbase(rb_iseq_t *iseq, VALUE *lfp, VALUE *dfp)
|
||||||
{
|
{
|
||||||
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
NODE *cref = vm_get_cref(iseq, lfp, dfp);
|
||||||
NODE *cref = get_cref(cfp->iseq, cfp->lfp);
|
|
||||||
VALUE klass = Qundef;
|
VALUE klass = Qundef;
|
||||||
|
|
||||||
while (cref) {
|
while (cref) {
|
||||||
@ -860,9 +833,18 @@ vm_get_cbase(rb_thread_t *th)
|
|||||||
}
|
}
|
||||||
cref = cref->nd_next;
|
cref = cref->nd_next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return klass;
|
return klass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_vm_cbase(void)
|
||||||
|
{
|
||||||
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
||||||
|
return vm_get_cbase(cfp->iseq, cfp->lfp, cfp->dfp);
|
||||||
|
}
|
||||||
|
|
||||||
/* jump */
|
/* jump */
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
@ -1038,16 +1020,16 @@ vm_init_redefined_flag(void)
|
|||||||
C1 : pushed by send insn (CFUNC)
|
C1 : pushed by send insn (CFUNC)
|
||||||
|
|
||||||
struct CONTROL_FRAME {
|
struct CONTROL_FRAME {
|
||||||
VALUE *pc; // cfp[0]
|
VALUE *pc; // cfp[0], program counter
|
||||||
VALUE *sp; // cfp[1]
|
VALUE *sp; // cfp[1], stack pointer
|
||||||
VALUE *bp; // cfp[2]
|
VALUE *bp; // cfp[2], base pointer
|
||||||
rb_iseq_t *iseq; // cfp[3]
|
rb_iseq_t *iseq; // cfp[3], iseq
|
||||||
VALUE flag; // cfp[4]
|
VALUE flag; // cfp[4], magic
|
||||||
VALUE self; // cfp[5]
|
VALUE self; // cfp[5], self
|
||||||
VALUE *lfp; // cfp[6]
|
VALUE *lfp; // cfp[6], local frame pointer
|
||||||
VALUE *dfp; // cfp[7]
|
VALUE *dfp; // cfp[7], dynamic frame pointer
|
||||||
rb_iseq_t * block_iseq; // cfp[8]
|
rb_iseq_t * block_iseq; // cfp[8], block iseq
|
||||||
VALUE proc; // cfp[9] always 0
|
VALUE proc; // cfp[9], always 0
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BLOCK {
|
struct BLOCK {
|
||||||
@ -1055,15 +1037,11 @@ vm_init_redefined_flag(void)
|
|||||||
VALUE *lfp;
|
VALUE *lfp;
|
||||||
VALUE *dfp;
|
VALUE *dfp;
|
||||||
rb_iseq_t *block_iseq;
|
rb_iseq_t *block_iseq;
|
||||||
};
|
VALUE proc;
|
||||||
|
|
||||||
struct PROC {
|
|
||||||
VALUE proc_sig = 0;
|
|
||||||
struct BLOCK;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct METHOD_CONTROL_FRAME {
|
struct METHOD_CONTROL_FRAME {
|
||||||
struct CONTROL_FRAME;
|
rb_control_frame_t frame;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct METHOD_FRAME {
|
struct METHOD_FRAME {
|
||||||
@ -1073,12 +1051,13 @@ vm_init_redefined_flag(void)
|
|||||||
VALUE param0;
|
VALUE param0;
|
||||||
...
|
...
|
||||||
VALUE paramN;
|
VALUE paramN;
|
||||||
|
VALUE cref;
|
||||||
VALUE special; // lfp [1]
|
VALUE special; // lfp [1]
|
||||||
struct block_object *block_ptr | 0x01; // lfp [0]
|
struct block_object *block_ptr | 0x01; // lfp [0]
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BLOCK_CONTROL_FRAME {
|
struct BLOCK_CONTROL_FRAME {
|
||||||
struct STACK_FRAME;
|
rb_control_frame_t frame;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BLOCK_FRAME {
|
struct BLOCK_FRAME {
|
||||||
@ -1088,17 +1067,19 @@ vm_init_redefined_flag(void)
|
|||||||
VALUE param0;
|
VALUE param0;
|
||||||
...
|
...
|
||||||
VALUE paramN;
|
VALUE paramN;
|
||||||
|
VALUE cref;
|
||||||
VALUE *(prev_ptr | 0x01); // DFP[0]
|
VALUE *(prev_ptr | 0x01); // DFP[0]
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CLASS_CONTROL_FRAME {
|
struct CLASS_CONTROL_FRAME {
|
||||||
struct STACK_FRAME;
|
rb_control_frame_t frame;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CLASS_FRAME {
|
struct CLASS_FRAME {
|
||||||
VALUE param0;
|
VALUE param0;
|
||||||
...
|
...
|
||||||
VALUE paramN;
|
VALUE paramN;
|
||||||
|
VALUE cref;
|
||||||
VALUE prev_dfp; // for frame jump
|
VALUE prev_dfp; // for frame jump
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1125,11 +1106,6 @@ vm_init_redefined_flag(void)
|
|||||||
VALUE *dfp; // lfp
|
VALUE *dfp; // lfp
|
||||||
rb_iseq_t * block_iseq; // 0
|
rb_iseq_t * block_iseq; // 0
|
||||||
};
|
};
|
||||||
|
|
||||||
struct C_METHDO_FRAME{
|
|
||||||
VALUE block_ptr;
|
|
||||||
VALUE special;
|
|
||||||
};
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -1315,7 +1291,7 @@ vm_eval_body(rb_thread_t *th)
|
|||||||
cfp->sp[0] = err;
|
cfp->sp[0] = err;
|
||||||
vm_push_frame(th, catch_iseq, FRAME_MAGIC_BLOCK,
|
vm_push_frame(th, catch_iseq, FRAME_MAGIC_BLOCK,
|
||||||
cfp->self, (VALUE)cfp->dfp, catch_iseq->iseq_encoded,
|
cfp->self, (VALUE)cfp->dfp, catch_iseq->iseq_encoded,
|
||||||
cfp->sp + 1, cfp->lfp, catch_iseq->local_size - 1);
|
cfp->sp + 1 /* push value */, cfp->lfp, catch_iseq->local_size - 1);
|
||||||
|
|
||||||
state = 0;
|
state = 0;
|
||||||
th->errinfo = Qnil;
|
th->errinfo = Qnil;
|
||||||
|
@ -497,8 +497,6 @@ typedef struct {
|
|||||||
int safe_level;
|
int safe_level;
|
||||||
int is_from_method;
|
int is_from_method;
|
||||||
int is_lambda;
|
int is_lambda;
|
||||||
|
|
||||||
NODE *special_cref_stack;
|
|
||||||
} rb_proc_t;
|
} rb_proc_t;
|
||||||
|
|
||||||
#define GetEnvPtr(obj, ptr) \
|
#define GetEnvPtr(obj, ptr) \
|
||||||
@ -517,7 +515,6 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
VALUE env;
|
VALUE env;
|
||||||
NODE *cref_stack;
|
|
||||||
} rb_binding_t;
|
} rb_binding_t;
|
||||||
|
|
||||||
|
|
||||||
@ -614,6 +611,7 @@ VALUE vm_make_env_object(rb_thread_t *th, rb_control_frame_t *cfp);
|
|||||||
VALUE vm_backtrace(rb_thread_t *, int);
|
VALUE vm_backtrace(rb_thread_t *, int);
|
||||||
|
|
||||||
VALUE vm_yield(rb_thread_t *th, int argc, VALUE *argv);
|
VALUE vm_yield(rb_thread_t *th, int argc, VALUE *argv);
|
||||||
|
VALUE vm_yield_with_cref(rb_thread_t *th, int argc, VALUE *argv, NODE *cref);
|
||||||
VALUE vm_call0(rb_thread_t *th, VALUE klass, VALUE recv, VALUE id, ID oid,
|
VALUE vm_call0(rb_thread_t *th, VALUE klass, VALUE recv, VALUE id, ID oid,
|
||||||
int argc, const VALUE *argv, NODE *body, int nosuper);
|
int argc, const VALUE *argv, NODE *body, int nosuper);
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||||||
void
|
void
|
||||||
vm_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp)
|
vm_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 1
|
||||||
VALUE *sp = cfp->sp, *bp = cfp->bp;
|
VALUE *sp = cfp->sp, *bp = cfp->bp;
|
||||||
VALUE *lfp = cfp->lfp;
|
VALUE *lfp = cfp->lfp;
|
||||||
VALUE *dfp = cfp->dfp;
|
VALUE *dfp = cfp->dfp;
|
||||||
@ -174,6 +174,13 @@ vm_stack_dump_raw(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||||||
fprintf(stderr, "---------------------------\n");
|
fprintf(stderr, "---------------------------\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vm_stack_dump_raw_current(void)
|
||||||
|
{
|
||||||
|
rb_thread_t *th = GET_THREAD();
|
||||||
|
vm_stack_dump_raw(th, th->cfp);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
env_dump_raw(rb_env_t *env, VALUE *lfp, VALUE *dfp)
|
env_dump_raw(rb_env_t *env, VALUE *lfp, VALUE *dfp)
|
||||||
{
|
{
|
||||||
|
109
vm_insnhelper.c
109
vm_insnhelper.c
@ -29,6 +29,8 @@ vm_push_frame(rb_thread_t *th, rb_iseq_t *iseq, VALUE type,
|
|||||||
rb_control_frame_t *cfp;
|
rb_control_frame_t *cfp;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* setup vm value stack */
|
||||||
|
|
||||||
/* nil initialize */
|
/* nil initialize */
|
||||||
for (i=0; i < local_size; i++) {
|
for (i=0; i < local_size; i++) {
|
||||||
*sp = Qnil;
|
*sp = Qnil;
|
||||||
@ -43,6 +45,8 @@ vm_push_frame(rb_thread_t *th, rb_iseq_t *iseq, VALUE type,
|
|||||||
lfp = sp;
|
lfp = sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* setup vm control frame stack */
|
||||||
|
|
||||||
cfp = th->cfp = th->cfp - 1;
|
cfp = th->cfp = th->cfp - 1;
|
||||||
cfp->pc = pc;
|
cfp->pc = pc;
|
||||||
cfp->sp = sp + 1;
|
cfp->sp = sp + 1;
|
||||||
@ -827,45 +831,24 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cref */
|
/* svar */
|
||||||
|
|
||||||
static NODE *
|
static inline NODE *
|
||||||
lfp_get_special_cref(VALUE *lfp)
|
|
||||||
{
|
|
||||||
struct RValues *values;
|
|
||||||
if (((VALUE)(values = (void *)lfp[-1])) != Qnil && values->basic.klass) {
|
|
||||||
return (NODE *)values->basic.klass;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct RValues *
|
|
||||||
new_value(void)
|
|
||||||
{
|
|
||||||
struct RValues *val = RVALUES(rb_newobj());
|
|
||||||
OBJSETUP(val, 0, T_VALUES);
|
|
||||||
val->v1 = val->v2 = val->v3 = Qnil;
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct RValues *
|
|
||||||
lfp_svar_place(rb_thread_t *th, VALUE *lfp)
|
lfp_svar_place(rb_thread_t *th, VALUE *lfp)
|
||||||
{
|
{
|
||||||
struct RValues *svar;
|
NODE *svar;
|
||||||
|
|
||||||
if (th->local_lfp != lfp) {
|
if (th->local_lfp != lfp) {
|
||||||
svar = (struct RValues *)lfp[-1];
|
svar = (NODE *)lfp[-1];
|
||||||
if ((VALUE)svar == Qnil) {
|
if ((VALUE)svar == Qnil) {
|
||||||
svar = new_value();
|
svar = NEW_IF(Qnil, Qnil, Qnil);
|
||||||
lfp[-1] = (VALUE)svar;
|
lfp[-1] = (VALUE)svar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
svar = (struct RValues *)th->local_svar;
|
svar = (NODE *)th->local_svar;
|
||||||
if ((VALUE)svar == Qnil) {
|
if ((VALUE)svar == Qnil) {
|
||||||
svar = new_value();
|
svar = NEW_IF(Qnil, Qnil, Qnil);
|
||||||
th->local_svar = (VALUE)svar;
|
th->local_svar = (VALUE)svar;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -875,17 +858,15 @@ lfp_svar_place(rb_thread_t *th, VALUE *lfp)
|
|||||||
static VALUE
|
static VALUE
|
||||||
lfp_svar_get(rb_thread_t *th, VALUE *lfp, VALUE key)
|
lfp_svar_get(rb_thread_t *th, VALUE *lfp, VALUE key)
|
||||||
{
|
{
|
||||||
struct RValues *svar = lfp_svar_place(th, lfp);
|
NODE *svar = lfp_svar_place(th, lfp);
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 0:
|
case 0:
|
||||||
return svar->v1;
|
return svar->u1.value;
|
||||||
case 1:
|
case 1:
|
||||||
return svar->v2;
|
return svar->u2.value;
|
||||||
case 2:
|
|
||||||
return svar->basic.klass;
|
|
||||||
default: {
|
default: {
|
||||||
VALUE hash = svar->v3;
|
VALUE hash = svar->u3.value;
|
||||||
|
|
||||||
if (hash == Qnil) {
|
if (hash == Qnil) {
|
||||||
return Qnil;
|
return Qnil;
|
||||||
@ -900,45 +881,26 @@ lfp_svar_get(rb_thread_t *th, VALUE *lfp, VALUE key)
|
|||||||
static void
|
static void
|
||||||
lfp_svar_set(rb_thread_t *th, VALUE *lfp, VALUE key, VALUE val)
|
lfp_svar_set(rb_thread_t *th, VALUE *lfp, VALUE key, VALUE val)
|
||||||
{
|
{
|
||||||
struct RValues *svar = lfp_svar_place(th, lfp);
|
NODE *svar = lfp_svar_place(th, lfp);
|
||||||
|
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 0:
|
case 0:
|
||||||
svar->v1 = val;
|
svar->u1.value = val;
|
||||||
return;
|
return;
|
||||||
case 1:
|
case 1:
|
||||||
svar->v2 = val;
|
svar->u2.value = val;
|
||||||
return;
|
|
||||||
case 2:
|
|
||||||
svar->basic.klass = val;
|
|
||||||
return;
|
return;
|
||||||
default: {
|
default: {
|
||||||
VALUE hash = svar->v3;
|
VALUE hash = svar->u3.value;
|
||||||
|
|
||||||
if (hash == Qnil) {
|
if (hash == Qnil) {
|
||||||
svar->v3 = hash = rb_hash_new();
|
svar->u3.value = hash = rb_hash_new();
|
||||||
}
|
}
|
||||||
rb_hash_aset(hash, key, val);
|
rb_hash_aset(hash, key, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static NODE *
|
|
||||||
get_cref(rb_iseq_t *iseq, VALUE *lfp)
|
|
||||||
{
|
|
||||||
NODE *cref;
|
|
||||||
if ((cref = lfp_get_special_cref(lfp)) != 0) {
|
|
||||||
/* */
|
|
||||||
}
|
|
||||||
else if ((cref = iseq->cref_stack) != 0) {
|
|
||||||
/* */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rb_bug("get_cref: unreachable");
|
|
||||||
}
|
|
||||||
return cref;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
vm_getspecial(rb_thread_t *th, VALUE *lfp, VALUE key, rb_num_t type)
|
vm_getspecial(rb_thread_t *th, VALUE *lfp, VALUE key, rb_num_t type)
|
||||||
{
|
{
|
||||||
@ -976,6 +938,30 @@ vm_getspecial(rb_thread_t *th, VALUE *lfp, VALUE key, rb_num_t type)
|
|||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NODE *
|
||||||
|
vm_get_cref(rb_iseq_t *iseq, const VALUE * const lfp, const VALUE *dfp)
|
||||||
|
{
|
||||||
|
NODE *cref = 0;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (lfp == dfp) {
|
||||||
|
cref = iseq->cref_stack;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (dfp[-1] != Qnil) {
|
||||||
|
cref = (NODE *)dfp[-1];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dfp = GET_PREV_DFP(dfp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cref == 0) {
|
||||||
|
rb_bug("vm_get_cref: unreachable");
|
||||||
|
}
|
||||||
|
return cref;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
vm_check_if_namespace(VALUE klass)
|
vm_check_if_namespace(VALUE klass)
|
||||||
{
|
{
|
||||||
@ -997,7 +983,7 @@ vm_get_ev_const(rb_thread_t *th, rb_iseq_t *iseq,
|
|||||||
|
|
||||||
if (klass == Qnil) {
|
if (klass == Qnil) {
|
||||||
/* in current lexical scope */
|
/* in current lexical scope */
|
||||||
NODE *root_cref = get_cref(iseq, th->cfp->lfp);
|
NODE *root_cref = vm_get_cref(iseq, th->cfp->lfp, th->cfp->dfp);
|
||||||
NODE *cref = root_cref;
|
NODE *cref = root_cref;
|
||||||
|
|
||||||
while (cref && cref->nd_next) {
|
while (cref && cref->nd_next) {
|
||||||
@ -1054,9 +1040,8 @@ vm_get_ev_const(rb_thread_t *th, rb_iseq_t *iseq,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline VALUE
|
static inline VALUE
|
||||||
vm_get_cvar_base(rb_thread_t *th, rb_iseq_t *iseq)
|
vm_get_cvar_base(NODE *cref)
|
||||||
{
|
{
|
||||||
NODE *cref = get_cref(iseq, th->cfp->lfp);
|
|
||||||
VALUE klass = Qnil;
|
VALUE klass = Qnil;
|
||||||
|
|
||||||
if (cref) {
|
if (cref) {
|
||||||
@ -1076,8 +1061,8 @@ vm_define_method(rb_thread_t *th, VALUE obj,
|
|||||||
ID id, rb_iseq_t *miseq, rb_num_t is_singleton, NODE *cref)
|
ID id, rb_iseq_t *miseq, rb_num_t is_singleton, NODE *cref)
|
||||||
{
|
{
|
||||||
NODE *newbody;
|
NODE *newbody;
|
||||||
int noex = cref->nd_visi;
|
|
||||||
VALUE klass = cref->nd_clss;
|
VALUE klass = cref->nd_clss;
|
||||||
|
int noex = cref->nd_visi;
|
||||||
|
|
||||||
if (is_singleton) {
|
if (is_singleton) {
|
||||||
if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
|
if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user