summaryrefslogtreecommitdiff
path: root/iseq.c
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-06-22 09:32:56 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2012-06-22 09:32:56 +0000
commitc4bc9b575898ba352d0fea8289ebcaf8921dacd1 (patch)
tree5974195d1c0a004072980018cbdfda08b831e727 /iseq.c
parent471d8d2586d984fd70f6837b117d6f275201204b (diff)
* 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.c56
1 files changed, 41 insertions, 15 deletions
diff --git a/iseq.c b/iseq.c
index 91597c3e69..890c6b248c 100644
--- a/iseq.c
+++ b/iseq.c
@@ -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