summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authormame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-05-09 18:21:39 +0000
committermame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2010-05-09 18:21:39 +0000
commit80f7f8d07e2b3b48c054e5f4c5d2e16ffa9bfc67 (patch)
tree883d4d789458a6bf9008b08e34b84add1bb61476 /vm_insnhelper.c
parentb664caeb785d66bb882fb014f0274eb5c7f23413 (diff)
* compile.c (iseq_compile_each), vm_insnhelper.c (vm_invoke_block,
vm_throw): allow "return" and "yield" even in singleton class definition. based on a patch from wanabe <s.wanabe AT gmail.com> for "return". [ruby-core:21379] [ruby-dev:40975] * insns.def (defineclass): ditto (straightforwardly push block ptr, instead of dfp ptr with special flag). * vm_core.h (RUBY_VM_CLASS_SPECIAL_P): ditto (no longer needed). * proc.c (proc_new): ditto (remove handling for special flag). * bootstraptest/test_jump.rb: add tests for above. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@27714 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 4f041a9465..f1ef50981f 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -913,8 +913,9 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n
const rb_block_t *block = GET_BLOCK_PTR();
rb_iseq_t *iseq;
int argc = (int)num;
+ int type = GET_ISEQ()->local_iseq->type;
- if (GET_ISEQ()->local_iseq->type != ISEQ_TYPE_METHOD || block == 0) {
+ if ((type != ISEQ_TYPE_METHOD && type != ISEQ_TYPE_CLASS) || block == 0) {
rb_vm_localjump_error("no block given (yield)", Qnil, 0);
}
iseq = block->iseq;
@@ -1434,6 +1435,11 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
search_parent:
if (cfp->iseq->type != ISEQ_TYPE_BLOCK) {
+ if (cfp->iseq->type == ISEQ_TYPE_CLASS) {
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
+ dfp = cfp->dfp;
+ goto search_parent;
+ }
dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp);
base_iseq = base_iseq->parent_iseq;
@@ -1499,10 +1505,17 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
else if (state == TAG_RETURN) {
rb_control_frame_t *cfp = GET_CFP();
VALUE *dfp = GET_DFP();
- VALUE * const lfp = GET_LFP();
+ VALUE *lfp = GET_LFP();
/* check orphan and get dfp */
while ((VALUE *) cfp < th->stack + th->stack_size) {
+ if (!lfp) {
+ lfp = cfp->lfp;
+ }
+ if (cfp->dfp == lfp && cfp->iseq->type == ISEQ_TYPE_CLASS) {
+ lfp = 0;
+ }
+
if (cfp->lfp == lfp) {
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
VALUE *tdfp = dfp;