diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-06-22 09:32:56 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-06-22 09:32:56 +0000 |
commit | c4bc9b575898ba352d0fea8289ebcaf8921dacd1 (patch) | |
tree | 5974195d1c0a004072980018cbdfda08b831e727 /iseq.c | |
parent | 471d8d2586d984fd70f6837b117d6f275201204b (diff) | |
download | ruby-c4bc9b575898ba352d0fea8289ebcaf8921dacd1.tar.gz |
* iseq.c, vm_eval.c: set th->base_block properly.
th->base_block is information for (a) parsing, (b) compiling
and (c) setting up the frame to execute the program passed by
`eval' method. For example, (1) parser need to know up-level
variables to detect it is variable or method without paren.
Befor (a), (b) and (c), VM set th->base_block by passed bindng
(or previous frame information). After execute (a), (b) and (c),
VM should clear th->base_block. However, if (a), (b) or (c)
raises an exception, then th->base_block is not cleared.
Problem is that the uncleared value th->balo_block is used for
irrelevant iseq compilation. It causes SEGV or critical error.
I tried to solve this problem: to clear them before exception,
but finally I found out that it is difficult to do it (Ruby
program can be run in many places).
Because of this background, I set th->base_block before
compiling iseq and restore it after compiling.
Basically, th->base_block is dirty hack (similar to global
variable) and this patch is also dirty.
* bootstraptest/test_eval.rb: add a test for above.
* internal.h: remove unused decl.
* iseq.c (rb_iseq_compile_with_option): add base_block parameter.
set th->base_block before compation and restore it after
compilation.
* ruby.c (require_libraries): pass 0 as base_block instead of
setting th->base_block
* tool/compile_prelude.rb (prelude_eval): apply above changes.
* vm.c, vm_eval.c: ditto.
* vm_core.h: add comments.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36179 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'iseq.c')
-rw-r--r-- | iseq.c | 56 |
1 files changed, 41 insertions, 15 deletions
@@ -11,6 +11,7 @@ #include "ruby/ruby.h" #include "internal.h" +#include "eval_intern.h" /* #define RUBY_MARK_FREE_DEBUG 1 */ #include "gc.h" @@ -566,30 +567,55 @@ parse_string(VALUE str, const char *file, int line) } VALUE -rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line, VALUE opt) +rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line, rb_block_t *base_block, VALUE opt) { - rb_compile_option_t option; - const char *fn = StringValueCStr(file); - int ln = NUM2INT(line); - NODE *node = parse_string(StringValue(src), fn, ln); + int state; rb_thread_t *th = GET_THREAD(); - make_compile_option(&option, opt); + rb_block_t *prev_base_block = th->base_block; + VALUE iseqval; + + th->base_block = base_block; + + TH_PUSH_TAG(th); + if ((state = EXEC_TAG()) == 0) { + int ln = NUM2INT(line); + const char *fn = StringValueCStr(file); + NODE *node = parse_string(StringValue(src), fn, ln); + rb_compile_option_t option; + + make_compile_option(&option, opt); - if (th->base_block && th->base_block->iseq) { - return rb_iseq_new_with_opt(node, th->base_block->iseq->location.label, - file, absolute_path, line, th->base_block->iseq->self, - ISEQ_TYPE_EVAL, &option); + if (base_block && base_block->iseq) { + iseqval = rb_iseq_new_with_opt(node, base_block->iseq->location.label, + file, absolute_path, line, base_block->iseq->self, + ISEQ_TYPE_EVAL, &option); + } + else { + iseqval = rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file, absolute_path, line, Qfalse, + ISEQ_TYPE_TOP, &option); + } } - else { - return rb_iseq_new_with_opt(node, rb_str_new2("<compiled>"), file, absolute_path, line, Qfalse, - ISEQ_TYPE_TOP, &option); + TH_POP_TAG(); + + th->base_block = prev_base_block; + + if (state) { + JUMP_TAG(state); } + + return iseqval; } VALUE rb_iseq_compile(VALUE src, VALUE file, VALUE line) { - return rb_iseq_compile_with_option(src, file, Qnil, line, Qnil); + return rb_iseq_compile_with_option(src, file, Qnil, line, 0, Qnil); +} + +VALUE +rb_iseq_compile_on_base(VALUE src, VALUE file, VALUE line, rb_block_t *base_block) +{ + return rb_iseq_compile_with_option(src, file, Qnil, line, base_block, Qnil); } static VALUE @@ -603,7 +629,7 @@ iseq_s_compile(int argc, VALUE *argv, VALUE self) if (NIL_P(file)) file = rb_str_new2("<compiled>"); if (NIL_P(line)) line = INT2FIX(1); - return rb_iseq_compile_with_option(src, file, path, line, opt); + return rb_iseq_compile_with_option(src, file, path, line, 0, opt); } static VALUE |