mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* vm.c, eval_intern.h (PASS_PASSED_BLOCK):
set a VM_FRAME_FLAG_PASSED flag to skip this frame when searching ruby-level-cfp. * eval.c, eval_intern.h, proc.c: fix to check cfp. if there is no valid ruby-level-cfp, cause RuntimeError exception. [ruby-dev:34128] * vm_core.h, vm_evalbody.c, vm.c, vm_dump.c, vm_insnhelper.c, insns.def: rename FRAME_MAGIC_* to VM_FRAME_MAGIC_*. * KNOWNBUGS.rb, bootstraptest/test*.rb: move solved bugs. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@17084 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
e6697a6405
commit
9e324fdd3e
17 changed files with 242 additions and 191 deletions
15
ChangeLog
15
ChangeLog
|
@ -1,3 +1,18 @@
|
|||
Wed Jun 11 05:53:20 2008 Koichi Sasada <ko1@atdot.net>
|
||||
|
||||
* vm.c, eval_intern.h (PASS_PASSED_BLOCK):
|
||||
set a VM_FRAME_FLAG_PASSED flag to skip this frame when
|
||||
searching ruby-level-cfp.
|
||||
|
||||
* eval.c, eval_intern.h, proc.c: fix to check cfp. if there is
|
||||
no valid ruby-level-cfp, cause RuntimeError exception.
|
||||
[ruby-dev:34128]
|
||||
|
||||
* vm_core.h, vm_evalbody.c, vm.c, vm_dump.c, vm_insnhelper.c,
|
||||
insns.def: rename FRAME_MAGIC_* to VM_FRAME_MAGIC_*.
|
||||
|
||||
* KNOWNBUGS.rb, bootstraptest/test*.rb: move solved bugs.
|
||||
|
||||
Wed Jun 11 05:55:31 2008 Hidetoshi NAGAI <nagai@ai.kyutech.ac.jp>
|
||||
|
||||
* ext/tk/tcltklib.c: SEGV when tcltk-stubs is enabled.
|
||||
|
|
64
KNOWNBUGS.rb
64
KNOWNBUGS.rb
|
@ -29,49 +29,6 @@ assert_equal 'ok', %q{
|
|||
C.new.foo
|
||||
}, '[ruby-core:14813]'
|
||||
|
||||
assert_equal 'ok', %q{
|
||||
a = lambda {|x, y, &b| b }
|
||||
b = a.curry[1]
|
||||
if b.call(2){} == nil
|
||||
:ng
|
||||
else
|
||||
:ok
|
||||
end
|
||||
}, '[ruby-core:15551]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
g = Module.enum_for(:new)
|
||||
loop { g.next }
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
Fiber.new(&Object.method(:class_eval)).resume("foo")
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
Thread.new("foo", &Object.method(:class_eval)).join
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
g = enum_for(:local_variables)
|
||||
loop { g.next }
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
g = enum_for(:block_given?)
|
||||
loop { g.next }
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
g = enum_for(:binding)
|
||||
loop { g.next }
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
g = "abc".enum_for(:scan, /./)
|
||||
loop { g.next }
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_equal %q{[:bar, :foo]}, %q{
|
||||
def foo
|
||||
klass = Class.new do
|
||||
|
@ -84,24 +41,3 @@ assert_equal %q{[:bar, :foo]}, %q{
|
|||
foo
|
||||
}, "[ ruby-Bugs-19304 ]"
|
||||
|
||||
assert_equal 'ok', %q{
|
||||
lambda {
|
||||
break :ok
|
||||
:ng
|
||||
}.call
|
||||
}, '[ruby-dev:34646]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
eval("", method(:proc).call {}.binding)
|
||||
}
|
||||
|
||||
assert_normal_exit %q{
|
||||
a = []
|
||||
100.times {|i| a << i << nil << nil }
|
||||
p a.compact!
|
||||
}
|
||||
|
||||
assert_equal 'ok', %q{
|
||||
a = [false]
|
||||
(a[0] &&= true) == false ? :ok : :ng
|
||||
}, '[ruby-dev:34679]'
|
||||
|
|
|
@ -282,3 +282,7 @@ assert_equal 'ok', %q{
|
|||
:ok
|
||||
end
|
||||
}, '[ruby-core:16796]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
eval("", method(:proc).call {}.binding)
|
||||
}
|
||||
|
|
|
@ -259,3 +259,20 @@ assert_equal %Q{ok\n}, %q{
|
|||
GC.start
|
||||
block.call
|
||||
}, '[ruby-core:14885]'
|
||||
|
||||
assert_equal 'ok', %q{
|
||||
a = lambda {|x, y, &b| b }
|
||||
b = a.curry[1]
|
||||
if b.call(2){} == nil
|
||||
:ng
|
||||
else
|
||||
:ok
|
||||
end
|
||||
}, '[ruby-core:15551]'
|
||||
|
||||
assert_equal 'ok', %q{
|
||||
lambda {
|
||||
break :ok
|
||||
:ng
|
||||
}.call
|
||||
}, '[ruby-dev:34646]'
|
||||
|
|
|
@ -817,3 +817,14 @@ assert_equal 'ok', %q{
|
|||
end
|
||||
}, '[ruby-core:14537]'
|
||||
|
||||
assert_equal 'ok', %q{
|
||||
a = [false]
|
||||
(a[0] &&= true) == false ? :ok : :ng
|
||||
}, '[ruby-dev:34679]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
a = []
|
||||
100.times {|i| a << i << nil << nil }
|
||||
p a.compact!
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# Thread and Fiber
|
||||
|
||||
assert_equal %q{ok}, %q{
|
||||
Thread.new{
|
||||
}.join
|
||||
|
@ -268,3 +270,35 @@ assert_normal_exit %q{
|
|||
at_exit { Fiber.new{}.resume }
|
||||
}
|
||||
|
||||
assert_normal_exit %q{
|
||||
g = enum_for(:local_variables)
|
||||
loop { g.next }
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
g = enum_for(:block_given?)
|
||||
loop { g.next }
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
g = enum_for(:binding)
|
||||
loop { g.next }
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
g = "abc".enum_for(:scan, /./)
|
||||
loop { g.next }
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
g = Module.enum_for(:new)
|
||||
loop { g.next }
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
Fiber.new(&Object.method(:class_eval)).resume("foo")
|
||||
}, '[ruby-dev:34128]'
|
||||
|
||||
assert_normal_exit %q{
|
||||
Thread.new("foo", &Object.method(:class_eval)).join
|
||||
}, '[ruby-dev:34128]'
|
||||
|
|
10
eval.c
10
eval.c
|
@ -17,8 +17,6 @@ VALUE proc_invoke(VALUE, VALUE, VALUE, VALUE);
|
|||
VALUE rb_binding_new(void);
|
||||
NORETURN(void rb_raise_jump(VALUE));
|
||||
|
||||
VALUE rb_f_block_given_p(void);
|
||||
|
||||
ID rb_frame_callee(void);
|
||||
VALUE rb_eLocalJumpError;
|
||||
VALUE rb_eSysStackError;
|
||||
|
@ -586,9 +584,9 @@ rb_f_block_given_p(void)
|
|||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
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_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp));
|
||||
|
||||
if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
|
||||
if (cfp != 0 && GC_GUARDED_PTR_REF(cfp->lfp[0])) {
|
||||
return Qtrue;
|
||||
}
|
||||
else {
|
||||
|
@ -1089,10 +1087,10 @@ rb_f_local_variables(void)
|
|||
VALUE ary = rb_ary_new();
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
rb_control_frame_t *cfp =
|
||||
vm_get_ruby_level_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
|
||||
vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp));
|
||||
int i;
|
||||
|
||||
while (1) {
|
||||
while (cfp) {
|
||||
if (cfp->iseq) {
|
||||
for (i = 0; i < cfp->iseq->local_table_size; i++) {
|
||||
ID lid = cfp->iseq->local_table[i];
|
||||
|
|
|
@ -2,9 +2,15 @@
|
|||
#ifndef RUBY_EVAL_INTERN_H
|
||||
#define RUBY_EVAL_INTERN_H
|
||||
|
||||
#define PASS_PASSED_BLOCK() \
|
||||
(GET_THREAD()->passed_block = \
|
||||
GC_GUARDED_PTR_REF((rb_block_t *)GET_THREAD()->cfp->lfp[0]))
|
||||
#define PASS_PASSED_BLOCK_TH(th) do { \
|
||||
(th)->passed_block = GC_GUARDED_PTR_REF((rb_block_t *)(th)->cfp->lfp[0]); \
|
||||
(th)->cfp->flag |= VM_FRAME_FLAG_PASSED; \
|
||||
} while (0)
|
||||
|
||||
#define PASS_PASSED_BLOCK() do { \
|
||||
rb_thread_t * const __th__ = GET_THREAD(); \
|
||||
PASS_PASSED_BLOCK_TH(__th__); \
|
||||
} while (0)
|
||||
|
||||
#include "ruby/ruby.h"
|
||||
#include "ruby/node.h"
|
||||
|
@ -219,7 +225,7 @@ NORETURN(void vm_jump_tag_but_local_jump(int, VALUE));
|
|||
|
||||
VALUE vm_make_jump_tag_but_local_jump(int state, VALUE val);
|
||||
NODE *vm_cref(void);
|
||||
rb_control_frame_t *vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
|
||||
rb_control_frame_t *vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp);
|
||||
VALUE rb_obj_is_proc(VALUE);
|
||||
VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, const rb_block_t *blockptr, VALUE filename);
|
||||
void rb_thread_terminate_all(void);
|
||||
|
|
|
@ -996,7 +996,7 @@ defineclass
|
|||
|
||||
/* enter scope */
|
||||
vm_push_frame(th, class_iseq,
|
||||
FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
|
||||
VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
|
||||
class_iseq->iseq_encoded, GET_SP(), 0,
|
||||
class_iseq->local_size);
|
||||
RESTORE_REGS();
|
||||
|
|
11
proc.c
11
proc.c
|
@ -275,10 +275,14 @@ VALUE
|
|||
rb_binding_new(void)
|
||||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
|
||||
VALUE bindval = binding_alloc(rb_cBinding);
|
||||
rb_binding_t *bind;
|
||||
|
||||
if (cfp == 0) {
|
||||
rb_raise(rb_eRuntimeError, "Can't create Binding Object on top of Fiber.");
|
||||
}
|
||||
|
||||
GetBindingPtr(bindval, bind);
|
||||
bind->env = vm_make_env_object(th, cfp);
|
||||
return bindval;
|
||||
|
@ -1187,11 +1191,12 @@ rb_method_call(int argc, VALUE *argv, VALUE method)
|
|||
}
|
||||
}
|
||||
if ((state = EXEC_TAG()) == 0) {
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
VALUE rb_vm_call(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
|
||||
int argc, const VALUE *argv, const NODE *body, int nosuper);
|
||||
|
||||
PASS_PASSED_BLOCK();
|
||||
result = rb_vm_call(GET_THREAD(), data->oclass, data->recv, data->id, data->oid,
|
||||
PASS_PASSED_BLOCK_TH(th);
|
||||
result = rb_vm_call(th, data->oclass, data->recv, data->id, data->oid,
|
||||
argc, argv, data->body, 0);
|
||||
}
|
||||
POP_TAG();
|
||||
|
|
97
vm.c
97
vm.c
|
@ -52,7 +52,7 @@ rb_vm_change_state(void)
|
|||
static inline VALUE
|
||||
rb_vm_set_finish_env(rb_thread_t * th)
|
||||
{
|
||||
vm_push_frame(th, 0, FRAME_MAGIC_FINISH,
|
||||
vm_push_frame(th, 0, VM_FRAME_MAGIC_FINISH,
|
||||
Qnil, th->cfp->lfp[0], 0,
|
||||
th->cfp->sp, 0, 1);
|
||||
th->cfp->pc = (VALUE *)&finish_insn_seq[0];
|
||||
|
@ -72,7 +72,7 @@ vm_set_top_stack(rb_thread_t * th, VALUE iseqval)
|
|||
/* for return */
|
||||
rb_vm_set_finish_env(th);
|
||||
|
||||
vm_push_frame(th, iseq, FRAME_MAGIC_TOP,
|
||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_TOP,
|
||||
th->top_self, 0, iseq->iseq_encoded,
|
||||
th->cfp->sp, 0, iseq->local_size);
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref)
|
|||
|
||||
/* for return */
|
||||
rb_vm_set_finish_env(th);
|
||||
vm_push_frame(th, iseq, FRAME_MAGIC_EVAL, block->self,
|
||||
vm_push_frame(th, iseq, VM_FRAME_MAGIC_EVAL, block->self,
|
||||
GC_GUARDED_PTR(block->dfp), iseq->iseq_encoded,
|
||||
th->cfp->sp, block->lfp, iseq->local_size);
|
||||
|
||||
|
@ -95,8 +95,8 @@ vm_set_eval_stack(rb_thread_t * th, VALUE iseqval, const NODE *cref)
|
|||
}
|
||||
}
|
||||
|
||||
rb_control_frame_t *
|
||||
vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
|
||||
static rb_control_frame_t *
|
||||
vm_get_ruby_level_next_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
|
||||
{
|
||||
while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
|
||||
if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
||||
|
@ -107,6 +107,28 @@ vm_get_ruby_level_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
rb_control_frame_t *
|
||||
vm_get_ruby_level_caller_cfp(rb_thread_t *th, rb_control_frame_t *cfp)
|
||||
{
|
||||
if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
||||
return cfp;
|
||||
}
|
||||
|
||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||
|
||||
while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
|
||||
if (RUBY_VM_NORMAL_ISEQ_P(cfp->iseq)) {
|
||||
return cfp;
|
||||
}
|
||||
|
||||
if ((cfp->flag & VM_FRAME_FLAG_PASSED) == 0) {
|
||||
break;
|
||||
}
|
||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Env */
|
||||
|
||||
static void
|
||||
|
@ -322,7 +344,7 @@ vm_make_env_object(rb_thread_t * th, rb_control_frame_t *cfp)
|
|||
{
|
||||
VALUE envval;
|
||||
|
||||
if (VM_FRAME_FLAG(cfp->flag) == FRAME_MAGIC_FINISH) {
|
||||
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_FINISH) {
|
||||
/* for method_missing */
|
||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||
}
|
||||
|
@ -340,7 +362,7 @@ void
|
|||
vm_stack_to_heap(rb_thread_t * const th)
|
||||
{
|
||||
rb_control_frame_t *cfp = th->cfp;
|
||||
while ((cfp = vm_get_ruby_level_cfp(th, cfp)) != 0) {
|
||||
while ((cfp = vm_get_ruby_level_next_cfp(th, cfp)) != 0) {
|
||||
vm_make_env_object(th, cfp);
|
||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||
}
|
||||
|
@ -423,7 +445,8 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
|
|||
const rb_iseq_t *iseq = block->iseq;
|
||||
const rb_control_frame_t *cfp = th->cfp;
|
||||
int i, opt_pc, arg_size = iseq->arg_size;
|
||||
int type = block_proc_is_lambda(block->proc) ? FRAME_MAGIC_LAMBDA : FRAME_MAGIC_BLOCK;
|
||||
int type = block_proc_is_lambda(block->proc) ?
|
||||
VM_FRAME_MAGIC_LAMBDA : VM_FRAME_MAGIC_BLOCK;
|
||||
|
||||
rb_vm_set_finish_env(th);
|
||||
|
||||
|
@ -434,7 +457,7 @@ invoke_block_from_c(rb_thread_t *th, const rb_block_t *block,
|
|||
}
|
||||
|
||||
opt_pc = vm_yield_setup_args(th, iseq, argc, cfp->sp, blockptr,
|
||||
type == FRAME_MAGIC_LAMBDA);
|
||||
type == VM_FRAME_MAGIC_LAMBDA);
|
||||
|
||||
vm_push_frame(th, iseq, type,
|
||||
self, GC_GUARDED_PTR(block->dfp),
|
||||
|
@ -521,22 +544,30 @@ vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, VALUE self,
|
|||
|
||||
/* special variable */
|
||||
|
||||
static rb_control_frame_t *
|
||||
vm_normal_frame(rb_thread_t *th, rb_control_frame_t *cfp)
|
||||
{
|
||||
while (cfp->pc == 0) {
|
||||
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
||||
if (RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return cfp;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
vm_cfp_svar_get(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key)
|
||||
{
|
||||
while (cfp->pc == 0) {
|
||||
cfp++;
|
||||
}
|
||||
return lfp_svar_get(th, cfp->lfp, key);
|
||||
cfp = vm_normal_frame(th, cfp);
|
||||
return lfp_svar_get(th, cfp ? cfp->lfp : 0, key);
|
||||
}
|
||||
|
||||
static void
|
||||
vm_cfp_svar_set(rb_thread_t *th, rb_control_frame_t *cfp, VALUE key, const VALUE val)
|
||||
{
|
||||
while (cfp->pc == 0) {
|
||||
cfp++;
|
||||
}
|
||||
lfp_svar_set(th, cfp->lfp, key, val);
|
||||
cfp = vm_normal_frame(th, cfp);
|
||||
lfp_svar_set(th, cfp ? cfp->lfp : 0, key, val);
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -663,7 +694,7 @@ const char *
|
|||
rb_sourcefile(void)
|
||||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_next_cfp(th, th->cfp);
|
||||
|
||||
if (cfp) {
|
||||
return RSTRING_PTR(cfp->iseq->filename);
|
||||
|
@ -677,7 +708,7 @@ int
|
|||
rb_sourceline(void)
|
||||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_next_cfp(th, th->cfp);
|
||||
|
||||
if (cfp) {
|
||||
return vm_get_sourceline(cfp);
|
||||
|
@ -691,7 +722,7 @@ NODE *
|
|||
vm_cref(void)
|
||||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_next_cfp(th, th->cfp);
|
||||
return vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
|
||||
}
|
||||
|
||||
|
@ -710,12 +741,15 @@ debug_cref(NODE *cref)
|
|||
static NODE *
|
||||
vm_cref_push(rb_thread_t *th, VALUE klass, int noex)
|
||||
{
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
|
||||
NODE *cref = NEW_BLOCK(klass);
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
||||
|
||||
cref->nd_file = 0;
|
||||
cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
|
||||
cref->nd_visi = noex;
|
||||
|
||||
if (cfp) {
|
||||
cref->nd_next = vm_get_cref(cfp->iseq, cfp->lfp, cfp->dfp);
|
||||
}
|
||||
|
||||
return cref;
|
||||
}
|
||||
|
||||
|
@ -739,7 +773,8 @@ VALUE
|
|||
rb_vm_cbase(void)
|
||||
{
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->cfp);
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_next_cfp(th, th->cfp);
|
||||
|
||||
return vm_get_cbase(cfp->iseq, cfp->lfp, cfp->dfp);
|
||||
}
|
||||
|
||||
|
@ -1183,7 +1218,7 @@ vm_eval_body(rb_thread_t *th)
|
|||
|
||||
/* push block frame */
|
||||
cfp->sp[0] = err;
|
||||
vm_push_frame(th, catch_iseq, FRAME_MAGIC_BLOCK,
|
||||
vm_push_frame(th, catch_iseq, VM_FRAME_MAGIC_BLOCK,
|
||||
cfp->self, (VALUE)cfp->dfp, catch_iseq->iseq_encoded,
|
||||
cfp->sp + 1 /* push value */, cfp->lfp, catch_iseq->local_size - 1);
|
||||
|
||||
|
@ -1297,7 +1332,7 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg,
|
|||
volatile VALUE iseqval = rb_iseq_new(0, filename, filename, 0, ISEQ_TYPE_TOP);
|
||||
VALUE val;
|
||||
|
||||
vm_push_frame(th, DATA_PTR(iseqval), FRAME_MAGIC_TOP,
|
||||
vm_push_frame(th, DATA_PTR(iseqval), VM_FRAME_MAGIC_TOP,
|
||||
recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
|
||||
|
||||
val = (*func)(arg);
|
||||
|
@ -1306,14 +1341,6 @@ rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg,
|
|||
return val;
|
||||
}
|
||||
|
||||
int
|
||||
rb_vm_cfunc_funcall_p(const rb_control_frame_t *cfp)
|
||||
{
|
||||
if (vm_cfunc_flags(cfp) & (VM_CALL_FCALL_BIT | VM_CALL_VCALL_BIT))
|
||||
return Qtrue;
|
||||
return Qfalse;
|
||||
}
|
||||
|
||||
/* vm */
|
||||
|
||||
static void
|
||||
|
@ -1548,7 +1575,7 @@ th_init2(rb_thread_t *th)
|
|||
|
||||
th->cfp = (void *)(th->stack + th->stack_size);
|
||||
|
||||
vm_push_frame(th, 0, FRAME_MAGIC_TOP, Qnil, 0, 0,
|
||||
vm_push_frame(th, 0, VM_FRAME_MAGIC_TOP, Qnil, 0, 0,
|
||||
th->stack, 0, 1);
|
||||
|
||||
th->status = THREAD_RUNNABLE;
|
||||
|
|
21
vm.h
21
vm.h
|
@ -219,27 +219,6 @@ default: \
|
|||
(!((th)->stack < (env) && (env) < ((th)->stack + (th)->stack_size)))
|
||||
#define ENV_VAL(env) ((env)[1])
|
||||
|
||||
#define FRAME_MAGIC_METHOD 0x11
|
||||
#define FRAME_MAGIC_BLOCK 0x21
|
||||
#define FRAME_MAGIC_CLASS 0x31
|
||||
#define FRAME_MAGIC_TOP 0x41
|
||||
#define FRAME_MAGIC_FINISH 0x51
|
||||
#define FRAME_MAGIC_CFUNC 0x61
|
||||
#define FRAME_MAGIC_PROC 0x71
|
||||
#define FRAME_MAGIC_IFUNC 0x81
|
||||
#define FRAME_MAGIC_EVAL 0x91
|
||||
#define FRAME_MAGIC_LAMBDA 0xa1
|
||||
#define FRAME_MAGIC_MASK_BITS 8
|
||||
#define FRAME_MAGIC_MASK (~(~0<<FRAME_MAGIC_MASK_BITS))
|
||||
|
||||
#define VM_FRAME_FLAG(type) ((VALUE)((type) & FRAME_MAGIC_MASK))
|
||||
|
||||
#define VM_FRAME_TYPE(cfp) \
|
||||
((cfp)->flag & FRAME_MAGIC_MASK)
|
||||
|
||||
#define RUBYVM_CFUNC_FRAME_P(cfp) \
|
||||
(VM_FRAME_TYPE(cfp) == FRAME_MAGIC_CFUNC)
|
||||
|
||||
#if OPT_CALL_THREADED_CODE
|
||||
#define THROW_EXCEPTION(exc) do { \
|
||||
th->errinfo = (VALUE)(exc); \
|
||||
|
|
23
vm_core.h
23
vm_core.h
|
@ -539,6 +539,29 @@ typedef struct {
|
|||
#define VM_CALL_SUPER_BIT (0x01 << 7)
|
||||
#define VM_CALL_SEND_BIT (0x01 << 8)
|
||||
|
||||
#define VM_FRAME_MAGIC_METHOD 0x11
|
||||
#define VM_FRAME_MAGIC_BLOCK 0x21
|
||||
#define VM_FRAME_MAGIC_CLASS 0x31
|
||||
#define VM_FRAME_MAGIC_TOP 0x41
|
||||
#define VM_FRAME_MAGIC_FINISH 0x51
|
||||
#define VM_FRAME_MAGIC_CFUNC 0x61
|
||||
#define VM_FRAME_MAGIC_PROC 0x71
|
||||
#define VM_FRAME_MAGIC_IFUNC 0x81
|
||||
#define VM_FRAME_MAGIC_EVAL 0x91
|
||||
#define VM_FRAME_MAGIC_LAMBDA 0xa1
|
||||
#define VM_FRAME_MAGIC_MASK_BITS 8
|
||||
#define VM_FRAME_MAGIC_MASK (~(~0<<VM_FRAME_MAGIC_MASK_BITS))
|
||||
|
||||
#define VM_FRAME_TYPE(cfp) ((cfp)->flag & VM_FRAME_MAGIC_MASK)
|
||||
|
||||
/* other frame flag */
|
||||
#define VM_FRAME_FLAG_PASSED 0x0100
|
||||
|
||||
|
||||
#define RUBYVM_CFUNC_FRAME_P(cfp) \
|
||||
(VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC)
|
||||
|
||||
|
||||
/* inline (method|const) cache */
|
||||
#define NEW_INLINE_CACHE_ENTRY() NEW_WHILE(Qundef, 0, 0)
|
||||
#define ic_class u1.value
|
||||
|
|
42
vm_dump.c
42
vm_dump.c
|
@ -46,34 +46,34 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||
}
|
||||
|
||||
switch (VM_FRAME_TYPE(cfp)) {
|
||||
case FRAME_MAGIC_TOP:
|
||||
case VM_FRAME_MAGIC_TOP:
|
||||
magic = "TOP";
|
||||
break;
|
||||
case FRAME_MAGIC_METHOD:
|
||||
case VM_FRAME_MAGIC_METHOD:
|
||||
magic = "METHOD";
|
||||
break;
|
||||
case FRAME_MAGIC_CLASS:
|
||||
case VM_FRAME_MAGIC_CLASS:
|
||||
magic = "CLASS";
|
||||
break;
|
||||
case FRAME_MAGIC_BLOCK:
|
||||
case VM_FRAME_MAGIC_BLOCK:
|
||||
magic = "BLOCK";
|
||||
break;
|
||||
case FRAME_MAGIC_FINISH:
|
||||
case VM_FRAME_MAGIC_FINISH:
|
||||
magic = "FINISH";
|
||||
break;
|
||||
case FRAME_MAGIC_CFUNC:
|
||||
case VM_FRAME_MAGIC_CFUNC:
|
||||
magic = "CFUNC";
|
||||
break;
|
||||
case FRAME_MAGIC_PROC:
|
||||
case VM_FRAME_MAGIC_PROC:
|
||||
magic = "PROC";
|
||||
break;
|
||||
case FRAME_MAGIC_LAMBDA:
|
||||
case VM_FRAME_MAGIC_LAMBDA:
|
||||
magic = "LAMBDA";
|
||||
break;
|
||||
case FRAME_MAGIC_IFUNC:
|
||||
case VM_FRAME_MAGIC_IFUNC:
|
||||
magic = "IFUNC";
|
||||
break;
|
||||
case FRAME_MAGIC_EVAL:
|
||||
case VM_FRAME_MAGIC_EVAL:
|
||||
magic = "EVAL";
|
||||
break;
|
||||
case 0:
|
||||
|
@ -271,15 +271,15 @@ stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||
|
||||
/* stack trace header */
|
||||
|
||||
if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_METHOD ||
|
||||
VM_FRAME_TYPE(cfp) == FRAME_MAGIC_TOP ||
|
||||
VM_FRAME_TYPE(cfp) == FRAME_MAGIC_BLOCK ||
|
||||
VM_FRAME_TYPE(cfp) == FRAME_MAGIC_CLASS ||
|
||||
VM_FRAME_TYPE(cfp) == FRAME_MAGIC_PROC ||
|
||||
VM_FRAME_TYPE(cfp) == FRAME_MAGIC_LAMBDA ||
|
||||
VM_FRAME_TYPE(cfp) == FRAME_MAGIC_CFUNC ||
|
||||
VM_FRAME_TYPE(cfp) == FRAME_MAGIC_IFUNC ||
|
||||
VM_FRAME_TYPE(cfp) == FRAME_MAGIC_EVAL) {
|
||||
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_METHOD ||
|
||||
VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_TOP ||
|
||||
VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_BLOCK ||
|
||||
VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CLASS ||
|
||||
VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_PROC ||
|
||||
VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA ||
|
||||
VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC ||
|
||||
VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_IFUNC ||
|
||||
VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_EVAL) {
|
||||
|
||||
VALUE *ptr = dfp - local_size;
|
||||
|
||||
|
@ -312,7 +312,7 @@ stack_dump_each(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||
ptr - th->stack);
|
||||
}
|
||||
}
|
||||
else if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_FINISH) {
|
||||
else if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_FINISH) {
|
||||
if ((th)->stack + (th)->stack_size > (VALUE *)(cfp + 2)) {
|
||||
stack_dump_each(th, cfp + 1);
|
||||
}
|
||||
|
@ -362,7 +362,7 @@ debug_print_pre(rb_thread_t *th, rb_control_frame_t *cfp)
|
|||
{
|
||||
rb_iseq_t *iseq = cfp->iseq;
|
||||
|
||||
if (iseq != 0 && VM_FRAME_TYPE(cfp) != FRAME_MAGIC_FINISH) {
|
||||
if (iseq != 0 && VM_FRAME_TYPE(cfp) != VM_FRAME_MAGIC_FINISH) {
|
||||
VALUE *seq = iseq->iseq;
|
||||
int pc = cfp->pc - iseq->iseq_encoded;
|
||||
|
||||
|
|
22
vm_eval.c
22
vm_eval.c
|
@ -66,7 +66,7 @@ vm_call0(rb_thread_t * th, VALUE klass, VALUE recv, VALUE id, ID oid,
|
|||
{
|
||||
rb_control_frame_t *reg_cfp = th->cfp;
|
||||
rb_control_frame_t *cfp =
|
||||
vm_push_frame(th, 0, FRAME_MAGIC_CFUNC,
|
||||
vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
|
||||
recv, (VALUE)blockptr, 0, reg_cfp->sp, 0, 1);
|
||||
|
||||
cfp->method_id = id;
|
||||
|
@ -412,13 +412,15 @@ send_internal(int argc, VALUE *argv, VALUE recv, int scope)
|
|||
{
|
||||
VALUE vid;
|
||||
VALUE self = RUBY_VM_PREVIOUS_CONTROL_FRAME(GET_THREAD()->cfp)->self;
|
||||
rb_thread_t *th = GET_THREAD();
|
||||
|
||||
if (argc == 0) {
|
||||
rb_raise(rb_eArgError, "no method name given");
|
||||
}
|
||||
|
||||
vid = *argv++; argc--;
|
||||
PASS_PASSED_BLOCK();
|
||||
PASS_PASSED_BLOCK_TH(th);
|
||||
|
||||
return rb_call0(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, scope, self);
|
||||
}
|
||||
|
||||
|
@ -687,11 +689,17 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char
|
|||
th->base_block = &env->block;
|
||||
}
|
||||
else {
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_cfp(th, th->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 */
|
||||
rb_control_frame_t *cfp = vm_get_ruby_level_caller_cfp(th, th->cfp);
|
||||
|
||||
if (cfp != 0) {
|
||||
block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
|
||||
th->base_block = █
|
||||
th->base_block->self = self;
|
||||
th->base_block->iseq = cfp->iseq; /* TODO */
|
||||
}
|
||||
else {
|
||||
rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
|
||||
}
|
||||
}
|
||||
|
||||
/* make eval iseq */
|
||||
|
|
|
@ -131,7 +131,7 @@ vm_eval(rb_thread_t *th, VALUE initial)
|
|||
}
|
||||
}
|
||||
|
||||
if (VM_FRAME_TYPE(th->cfp) != FRAME_MAGIC_FINISH) {
|
||||
if (VM_FRAME_TYPE(th->cfp) != VM_FRAME_MAGIC_FINISH) {
|
||||
rb_bug("cfp consistency error");
|
||||
}
|
||||
|
||||
|
|
|
@ -367,7 +367,7 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|||
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_CALL, recv, id, klass);
|
||||
{
|
||||
rb_control_frame_t *cfp =
|
||||
vm_push_frame(th, 0, FRAME_MAGIC_CFUNC | (flag << FRAME_MAGIC_MASK_BITS),
|
||||
vm_push_frame(th, 0, VM_FRAME_MAGIC_CFUNC,
|
||||
recv, (VALUE) blockptr, 0, reg_cfp->sp, 0, 1);
|
||||
|
||||
cfp->method_id = id;
|
||||
|
@ -380,6 +380,7 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|||
if (reg_cfp != th->cfp + 1) {
|
||||
rb_bug("cfp consistency error - send");
|
||||
}
|
||||
|
||||
vm_pop_frame(th);
|
||||
}
|
||||
EXEC_EVENT_HOOK(th, RUBY_EVENT_C_RETURN, recv, id, klass);
|
||||
|
@ -387,14 +388,6 @@ vm_call_cfunc(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|||
return val;
|
||||
}
|
||||
|
||||
static inline int
|
||||
vm_cfunc_flags(const rb_control_frame_t *cfp)
|
||||
{
|
||||
if (RUBYVM_CFUNC_FRAME_P(cfp))
|
||||
return cfp->flag >> FRAME_MAGIC_MASK_BITS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline VALUE
|
||||
vm_call_bmethod(rb_thread_t *th, ID id, VALUE procval, VALUE recv,
|
||||
VALUE klass, int argc, VALUE *argv, rb_block_t *blockptr)
|
||||
|
@ -455,7 +448,7 @@ vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
|
|||
}
|
||||
|
||||
vm_push_frame(th, iseq,
|
||||
FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
|
||||
VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
|
||||
iseq->iseq_encoded + opt_pc, sp, 0, 0);
|
||||
|
||||
cfp->sp = rsp - 1 /* recv */;
|
||||
|
@ -478,7 +471,7 @@ vm_setup_method(rb_thread_t *th, rb_control_frame_t *cfp,
|
|||
}
|
||||
|
||||
vm_push_frame(th, iseq,
|
||||
FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
|
||||
VM_FRAME_MAGIC_METHOD, recv, (VALUE) blockptr,
|
||||
iseq->iseq_encoded + opt_pc, sp, 0, 0);
|
||||
}
|
||||
}
|
||||
|
@ -675,7 +668,7 @@ vm_yield_with_cfunc(rb_thread_t *th, const rb_block_t *block,
|
|||
blockarg = Qnil;
|
||||
}
|
||||
|
||||
vm_push_frame(th, 0, FRAME_MAGIC_IFUNC,
|
||||
vm_push_frame(th, 0, VM_FRAME_MAGIC_IFUNC,
|
||||
self, (VALUE)block->dfp,
|
||||
0, th->cfp->sp, block->lfp, 1);
|
||||
|
||||
|
@ -831,7 +824,7 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n
|
|||
block_proc_is_lambda(block->proc));
|
||||
|
||||
vm_push_frame(th, iseq,
|
||||
FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp,
|
||||
VM_FRAME_MAGIC_BLOCK, block->self, (VALUE) block->dfp,
|
||||
iseq->iseq_encoded + opt_pc, rsp + arg_size, block->lfp,
|
||||
iseq->local_size - arg_size);
|
||||
|
||||
|
@ -849,23 +842,18 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n
|
|||
static inline NODE *
|
||||
lfp_svar_place(rb_thread_t *th, VALUE *lfp)
|
||||
{
|
||||
NODE *svar;
|
||||
VALUE *svar;
|
||||
|
||||
if (th->local_lfp != lfp) {
|
||||
svar = (NODE *)lfp[-1];
|
||||
if ((VALUE)svar == Qnil) {
|
||||
svar = NEW_IF(Qnil, Qnil, Qnil);
|
||||
lfp[-1] = (VALUE)svar;
|
||||
}
|
||||
if (lfp && th->local_lfp != lfp) {
|
||||
svar = &lfp[-1];
|
||||
}
|
||||
else {
|
||||
svar = (NODE *)th->local_svar;
|
||||
if ((VALUE)svar == Qnil) {
|
||||
svar = NEW_IF(Qnil, Qnil, Qnil);
|
||||
th->local_svar = (VALUE)svar;
|
||||
}
|
||||
svar = &th->local_svar;
|
||||
}
|
||||
return svar;
|
||||
if (NIL_P(*svar)) {
|
||||
*svar = (VALUE)NEW_IF(Qnil, Qnil, Qnil);
|
||||
}
|
||||
return (NODE *)*svar;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
|
@ -1238,7 +1226,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|||
rb_bug("VM (throw): can't find break base.");
|
||||
}
|
||||
|
||||
if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_LAMBDA) {
|
||||
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
|
||||
/* lambda{... break ...} */
|
||||
is_orphan = 0;
|
||||
pt = GET_LFP();
|
||||
|
@ -1297,7 +1285,7 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
|
|||
*/
|
||||
while ((VALUE *) cfp < th->stack + th->stack_size) {
|
||||
if (GET_DFP() == dfp) {
|
||||
if (VM_FRAME_TYPE(cfp) == FRAME_MAGIC_LAMBDA) {
|
||||
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
|
||||
/* in lambda */
|
||||
is_orphan = 0;
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue