Skip to content

Commit 80f7f8d

Browse files
committed
* 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
1 parent b664cae commit 80f7f8d

File tree

8 files changed

+60
-13
lines changed

8 files changed

+60
-13
lines changed

ChangeLog

+16
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
Mon May 10 02:58:33 2010 Yusuke Endoh <mame@tsg.ne.jp>
2+
3+
* compile.c (iseq_compile_each), vm_insnhelper.c (vm_invoke_block,
4+
vm_throw): allow "return" and "yield" even in singleton class
5+
definition. based on a patch from wanabe <s.wanabe AT gmail.com>
6+
for "return". [ruby-core:21379] [ruby-dev:40975]
7+
8+
* insns.def (defineclass): ditto (straightforwardly push block ptr,
9+
instead of dfp ptr with special flag).
10+
11+
* vm_core.h (RUBY_VM_CLASS_SPECIAL_P): ditto (no longer needed).
12+
13+
* proc.c (proc_new): ditto (remove handling for special flag).
14+
15+
* bootstraptest/test_jump.rb: add tests for above.
16+
117
Mon May 10 02:29:51 2010 Yusuke Endoh <mame@tsg.ne.jp>
218

319
* cont.c (fiber_switch): raise FiberError when returning to dead

bootstraptest/test_jump.rb

+24
Original file line numberDiff line numberDiff line change
@@ -282,3 +282,27 @@ def m
282282
break
283283
end
284284
}, '[ruby-core:28172]'
285+
286+
assert_equal "true", %q{
287+
class Object
288+
def return_eigenclass
289+
class << self
290+
return self
291+
end
292+
end
293+
end
294+
s = "foo"
295+
s.return_eigenclass == class << s; self; end
296+
}, '[ruby-core:21379]'
297+
298+
assert_equal "true", %q{
299+
class Object
300+
def yield_eigenclass
301+
class << self
302+
yield self
303+
end
304+
end
305+
end
306+
s = "foo"
307+
s.yield_eigenclass {|c| c == class << s; self; end }
308+
}, '[ruby-dev:40975]'

compile.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -4225,7 +4225,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
42254225
rb_iseq_t *is = iseq;
42264226

42274227
if (is) {
4228-
if (is->type == ISEQ_TYPE_TOP || is->type == ISEQ_TYPE_CLASS) {
4228+
if (is->type == ISEQ_TYPE_TOP) {
42294229
COMPILE_ERROR((ERROR_ARGS "Invalid return"));
42304230
}
42314231
else {
@@ -4265,7 +4265,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped)
42654265
unsigned long flag = 0;
42664266

42674267
INIT_ANCHOR(args);
4268-
if (iseq->type == ISEQ_TYPE_TOP || iseq->type == ISEQ_TYPE_CLASS) {
4268+
if (iseq->type == ISEQ_TYPE_TOP) {
42694269
COMPILE_ERROR((ERROR_ARGS "Invalid yield"));
42704270
}
42714271

insns.def

+1-1
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,7 @@ defineclass
953953

954954
/* enter scope */
955955
vm_push_frame(th, class_iseq,
956-
VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_DFP() | 0x02,
956+
VM_FRAME_MAGIC_CLASS, klass, (VALUE) GET_BLOCK_PTR(),
957957
class_iseq->iseq_encoded, GET_SP(), 0,
958958
class_iseq->local_size);
959959
RESTORE_REGS();

proc.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -375,16 +375,14 @@ proc_new(VALUE klass, int is_lambda)
375375
rb_control_frame_t *cfp = th->cfp;
376376
rb_block_t *block;
377377

378-
if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0 &&
379-
!RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) {
378+
if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0) {
380379

381380
block = GC_GUARDED_PTR_REF(cfp->lfp[0]);
382381
}
383382
else {
384383
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
385384

386-
if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0 &&
387-
!RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) {
385+
if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0) {
388386

389387
block = GC_GUARDED_PTR_REF(cfp->lfp[0]);
390388

vm.c

-2
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,6 @@ rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass)
477477
}
478478

479479
if (GC_GUARDED_PTR_REF(cfp->lfp[0])) {
480-
if (!RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) {
481480
rb_proc_t *p;
482481

483482
blockprocval = vm_make_proc_from_block(
@@ -486,7 +485,6 @@ rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass)
486485
GetProcPtr(blockprocval, p);
487486
*cfp->lfp = GC_GUARDED_PTR(&p->block);
488487
}
489-
}
490488

491489
envval = rb_vm_make_env_object(th, cfp);
492490

vm_core.h

-2
Original file line numberDiff line numberDiff line change
@@ -597,8 +597,6 @@ typedef rb_control_frame_t *
597597
#define RUBY_VM_NORMAL_ISEQ_P(ptr) \
598598
(ptr && !RUBY_VM_IFUNC_P(ptr))
599599

600-
#define RUBY_VM_CLASS_SPECIAL_P(ptr) (((VALUE)(ptr)) & 0x02)
601-
602600
#define RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp) ((rb_block_t *)(&(cfp)->self))
603601
#define RUBY_VM_GET_CFP_FROM_BLOCK_PTR(b) \
604602
((rb_control_frame_t *)((VALUE *)(b) - 5))

vm_insnhelper.c

+15-2
Original file line numberDiff line numberDiff line change
@@ -913,8 +913,9 @@ vm_invoke_block(rb_thread_t *th, rb_control_frame_t *reg_cfp, rb_num_t num, rb_n
913913
const rb_block_t *block = GET_BLOCK_PTR();
914914
rb_iseq_t *iseq;
915915
int argc = (int)num;
916+
int type = GET_ISEQ()->local_iseq->type;
916917

917-
if (GET_ISEQ()->local_iseq->type != ISEQ_TYPE_METHOD || block == 0) {
918+
if ((type != ISEQ_TYPE_METHOD && type != ISEQ_TYPE_CLASS) || block == 0) {
918919
rb_vm_localjump_error("no block given (yield)", Qnil, 0);
919920
}
920921
iseq = block->iseq;
@@ -1434,6 +1435,11 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
14341435

14351436
search_parent:
14361437
if (cfp->iseq->type != ISEQ_TYPE_BLOCK) {
1438+
if (cfp->iseq->type == ISEQ_TYPE_CLASS) {
1439+
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
1440+
dfp = cfp->dfp;
1441+
goto search_parent;
1442+
}
14371443
dfp = GC_GUARDED_PTR_REF((VALUE *) *dfp);
14381444
base_iseq = base_iseq->parent_iseq;
14391445

@@ -1499,10 +1505,17 @@ vm_throw(rb_thread_t *th, rb_control_frame_t *reg_cfp,
14991505
else if (state == TAG_RETURN) {
15001506
rb_control_frame_t *cfp = GET_CFP();
15011507
VALUE *dfp = GET_DFP();
1502-
VALUE * const lfp = GET_LFP();
1508+
VALUE *lfp = GET_LFP();
15031509

15041510
/* check orphan and get dfp */
15051511
while ((VALUE *) cfp < th->stack + th->stack_size) {
1512+
if (!lfp) {
1513+
lfp = cfp->lfp;
1514+
}
1515+
if (cfp->dfp == lfp && cfp->iseq->type == ISEQ_TYPE_CLASS) {
1516+
lfp = 0;
1517+
}
1518+
15061519
if (cfp->lfp == lfp) {
15071520
if (VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_LAMBDA) {
15081521
VALUE *tdfp = dfp;

0 commit comments

Comments
 (0)